mp: Migrate to shared version of mp library

This commit is contained in:
MerryMage 2020-04-04 00:59:27 +01:00
parent 66fa4a0b54
commit 81fcb4e537
23 changed files with 92 additions and 575 deletions

View file

@ -18,3 +18,7 @@ endif()
add_library(catch INTERFACE) add_library(catch INTERFACE)
target_include_directories(catch INTERFACE target_include_directories(catch INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/catch>) $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/catch>)
add_library(mp INTERFACE)
target_include_directories(mp INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/mp/include>)

View file

@ -57,23 +57,12 @@ add_library(dynarmic
common/iterator_util.h common/iterator_util.h
common/llvm_disassemble.cpp common/llvm_disassemble.cpp
common/llvm_disassemble.h common/llvm_disassemble.h
common/lut_from_list.h
common/macro_util.h common/macro_util.h
common/math_util.cpp common/math_util.cpp
common/math_util.h common/math_util.h
common/memory_pool.cpp common/memory_pool.cpp
common/memory_pool.h common/memory_pool.h
common/mp/append.h
common/mp/bind.h
common/mp/cartesian_product.h
common/mp/concat.h
common/mp/fapply.h
common/mp/fmap.h
common/mp/function_info.h
common/mp/list.h
common/mp/lut.h
common/mp/to_tuple.h
common/mp/vlift.h
common/mp/vllift.h
common/safe_ops.h common/safe_ops.h
common/scope_exit.h common/scope_exit.h
common/string_util.h common/string_util.h
@ -289,6 +278,7 @@ target_link_libraries(dynarmic
PRIVATE PRIVATE
boost boost
fmt::fmt fmt::fmt
mp
xbyak xbyak
$<$<BOOL:DYNARMIC_USE_LLVM>:${llvm_libs}> $<$<BOOL:DYNARMIC_USE_LLVM>:${llvm_libs}>
) )

View file

@ -9,10 +9,11 @@
#include <cstring> #include <cstring>
#include <utility> #include <utility>
#include <mp/traits/function_info.h>
#include "backend/x64/callback.h" #include "backend/x64/callback.h"
#include "common/cast_util.h" #include "common/cast_util.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/mp/function_info.h"
namespace Dynarmic { namespace Dynarmic {
namespace BackendX64 { namespace BackendX64 {
@ -32,18 +33,18 @@ struct ThunkBuilder<R(C::*)(Args...), mfp> {
} // namespace impl } // namespace impl
template<auto mfp> template<auto mfp>
ArgCallback DevirtualizeGeneric(Common::mp::class_type_t<decltype(mfp)>* this_) { ArgCallback DevirtualizeGeneric(mp::class_type<decltype(mfp)>* this_) {
return ArgCallback{&impl::ThunkBuilder<decltype(mfp), mfp>::Thunk, reinterpret_cast<u64>(this_)}; return ArgCallback{&impl::ThunkBuilder<decltype(mfp), mfp>::Thunk, reinterpret_cast<u64>(this_)};
} }
template<auto mfp> template<auto mfp>
ArgCallback DevirtualizeWindows(Common::mp::class_type_t<decltype(mfp)>* this_) { ArgCallback DevirtualizeWindows(mp::class_type<decltype(mfp)>* this_) {
static_assert(sizeof(mfp) == 8); static_assert(sizeof(mfp) == 8);
return ArgCallback{Common::BitCast<u64>(mfp), reinterpret_cast<u64>(this_)}; return ArgCallback{Common::BitCast<u64>(mfp), reinterpret_cast<u64>(this_)};
} }
template<auto mfp> template<auto mfp>
ArgCallback DevirtualizeItanium(Common::mp::class_type_t<decltype(mfp)>* this_) { ArgCallback DevirtualizeItanium(mp::class_type<decltype(mfp)>* this_) {
struct MemberFunctionPointer { struct MemberFunctionPointer {
/// For a non-virtual function, this is a simple function pointer. /// For a non-virtual function, this is a simple function pointer.
/// For a virtual function, it is (1 + virtual table offset in bytes). /// For a virtual function, it is (1 + virtual table offset in bytes).
@ -65,7 +66,7 @@ ArgCallback DevirtualizeItanium(Common::mp::class_type_t<decltype(mfp)>* this_)
} }
template<auto mfp> template<auto mfp>
ArgCallback Devirtualize(Common::mp::class_type_t<decltype(mfp)>* this_) { ArgCallback Devirtualize(mp::class_type<decltype(mfp)>* this_) {
#if defined(__APPLE__) || defined(linux) || defined(__linux) || defined(__linux__) #if defined(__APPLE__) || defined(linux) || defined(__linux) || defined(__linux__)
return DevirtualizeItanium<mfp>(this_); return DevirtualizeItanium<mfp>(this_);
#elif defined(__MINGW64__) #elif defined(__MINGW64__)

View file

@ -8,6 +8,13 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <mp/metavalue/lift_value.h>
#include <mp/traits/integer_of_size.h>
#include <mp/typelist/cartesian_product.h>
#include <mp/typelist/lift_sequence.h>
#include <mp/typelist/list.h>
#include <mp/typelist/lower_to_tuple.h>
#include "backend/x64/abi.h" #include "backend/x64/abi.h"
#include "backend/x64/block_of_code.h" #include "backend/x64/block_of_code.h"
#include "backend/x64/emit_x64.h" #include "backend/x64/emit_x64.h"
@ -18,20 +25,13 @@
#include "common/fp/info.h" #include "common/fp/info.h"
#include "common/fp/op.h" #include "common/fp/op.h"
#include "common/fp/rounding_mode.h" #include "common/fp/rounding_mode.h"
#include "common/mp/cartesian_product.h" #include "common/lut_from_list.h"
#include "common/mp/integer.h"
#include "common/mp/list.h"
#include "common/mp/lut.h"
#include "common/mp/to_tuple.h"
#include "common/mp/vlift.h"
#include "common/mp/vllift.h"
#include "frontend/ir/basic_block.h" #include "frontend/ir/basic_block.h"
#include "frontend/ir/microinstruction.h" #include "frontend/ir/microinstruction.h"
namespace Dynarmic::BackendX64 { namespace Dynarmic::BackendX64 {
using namespace Xbyak::util; using namespace Xbyak::util;
namespace mp = Dynarmic::Common::mp;
namespace { namespace {
@ -845,28 +845,28 @@ static void EmitFPRound(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, siz
return; return;
} }
using fsize_list = mp::list<mp::vlift<size_t(16)>, using fsize_list = mp::list<mp::lift_value<size_t(16)>,
mp::vlift<size_t(32)>, mp::lift_value<size_t(32)>,
mp::vlift<size_t(64)>>; mp::lift_value<size_t(64)>>;
using rounding_list = mp::list< using rounding_list = mp::list<
std::integral_constant<FP::RoundingMode, FP::RoundingMode::ToNearest_TieEven>, mp::lift_value<FP::RoundingMode::ToNearest_TieEven>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsPlusInfinity>, mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsMinusInfinity>, mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsZero>, mp::lift_value<FP::RoundingMode::TowardsZero>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::ToNearest_TieAwayFromZero> mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>
>; >;
using exact_list = mp::list<mp::vlift<true>, mp::vlift<false>>; using exact_list = mp::list<std::true_type, std::false_type>;
using key_type = std::tuple<size_t, FP::RoundingMode, bool>; using key_type = std::tuple<size_t, FP::RoundingMode, bool>;
using value_type = u64(*)(u64, FP::FPSR&, FP::FPCR); using value_type = u64(*)(u64, FP::FPSR&, FP::FPCR);
static const auto lut = mp::GenerateLookupTableFromList<key_type, value_type>( static const auto lut = Common::GenerateLookupTableFromList<key_type, value_type>(
[](auto args) { [](auto args) {
return std::pair<key_type, value_type>{ return std::pair<key_type, value_type>{
mp::to_tuple<decltype(args)>, mp::lower_to_tuple_v<decltype(args)>,
static_cast<value_type>( static_cast<value_type>(
[](u64 input, FP::FPSR& fpsr, FP::FPCR fpcr) { [](u64 input, FP::FPSR& fpsr, FP::FPCR fpcr) {
constexpr auto t = mp::to_tuple<decltype(args)>; constexpr auto t = mp::lower_to_tuple_v<decltype(args)>;
constexpr size_t fsize = std::get<0>(t); constexpr size_t fsize = std::get<0>(t);
constexpr FP::RoundingMode rounding_mode = std::get<1>(t); constexpr FP::RoundingMode rounding_mode = std::get<1>(t);
constexpr bool exact = std::get<2>(t); constexpr bool exact = std::get<2>(t);
@ -1279,25 +1279,25 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
} }
} }
using fbits_list = mp::vllift<std::make_index_sequence<isize + 1>>; using fbits_list = mp::lift_sequence<std::make_index_sequence<isize + 1>>;
using rounding_list = mp::list< using rounding_list = mp::list<
std::integral_constant<FP::RoundingMode, FP::RoundingMode::ToNearest_TieEven>, mp::lift_value<FP::RoundingMode::ToNearest_TieEven>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsPlusInfinity>, mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsMinusInfinity>, mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsZero>, mp::lift_value<FP::RoundingMode::TowardsZero>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::ToNearest_TieAwayFromZero> mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>
>; >;
using key_type = std::tuple<size_t, FP::RoundingMode>; using key_type = std::tuple<size_t, FP::RoundingMode>;
using value_type = u64(*)(u64, FP::FPSR&, FP::FPCR); using value_type = u64(*)(u64, FP::FPSR&, FP::FPCR);
static const auto lut = mp::GenerateLookupTableFromList<key_type, value_type>( static const auto lut = Common::GenerateLookupTableFromList<key_type, value_type>(
[](auto args) { [](auto args) {
return std::pair<key_type, value_type>{ return std::pair<key_type, value_type>{
mp::to_tuple<decltype(args)>, mp::lower_to_tuple_v<decltype(args)>,
static_cast<value_type>( static_cast<value_type>(
[](u64 input, FP::FPSR& fpsr, FP::FPCR fpcr) { [](u64 input, FP::FPSR& fpsr, FP::FPCR fpcr) {
constexpr auto t = mp::to_tuple<decltype(args)>; constexpr auto t = mp::lower_to_tuple_v<decltype(args)>;
constexpr size_t fbits = std::get<0>(t); constexpr size_t fbits = std::get<0>(t);
constexpr FP::RoundingMode rounding_mode = std::get<1>(t); constexpr FP::RoundingMode rounding_mode = std::get<1>(t);
using FPT = mp::unsigned_integer_of_size<fsize>; using FPT = mp::unsigned_integer_of_size<fsize>;

View file

@ -6,12 +6,13 @@
#include <limits> #include <limits>
#include <mp/traits/integer_of_size.h>
#include "backend/x64/block_of_code.h" #include "backend/x64/block_of_code.h"
#include "backend/x64/emit_x64.h" #include "backend/x64/emit_x64.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/bit_util.h" #include "common/bit_util.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/mp/integer.h"
#include "frontend/ir/basic_block.h" #include "frontend/ir/basic_block.h"
#include "frontend/ir/microinstruction.h" #include "frontend/ir/microinstruction.h"
#include "frontend/ir/opcodes.h" #include "frontend/ir/opcodes.h"
@ -19,7 +20,6 @@
namespace Dynarmic::BackendX64 { namespace Dynarmic::BackendX64 {
using namespace Xbyak::util; using namespace Xbyak::util;
namespace mp = Dynarmic::Common::mp;
namespace { namespace {

View file

@ -9,6 +9,8 @@
#include <cstdlib> #include <cstdlib>
#include <type_traits> #include <type_traits>
#include <mp/traits/function_info.h>
#include "backend/x64/abi.h" #include "backend/x64/abi.h"
#include "backend/x64/block_of_code.h" #include "backend/x64/block_of_code.h"
#include "backend/x64/emit_x64.h" #include "backend/x64/emit_x64.h"
@ -16,7 +18,6 @@
#include "common/bit_util.h" #include "common/bit_util.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/math_util.h" #include "common/math_util.h"
#include "common/mp/function_info.h"
#include "frontend/ir/basic_block.h" #include "frontend/ir/basic_block.h"
#include "frontend/ir/microinstruction.h" #include "frontend/ir/microinstruction.h"
#include "frontend/ir/opcodes.h" #include "frontend/ir/opcodes.h"
@ -24,7 +25,6 @@
namespace Dynarmic::BackendX64 { namespace Dynarmic::BackendX64 {
using namespace Xbyak::util; using namespace Xbyak::util;
namespace mp = Common::mp;
template <typename Function> template <typename Function>
static void EmitVectorOperation(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) { static void EmitVectorOperation(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) {
@ -52,7 +52,7 @@ static void EmitAVXVectorOperation(BlockOfCode& code, EmitContext& ctx, IR::Inst
template <typename Lambda> template <typename Lambda>
static void EmitOneArgumentFallback(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Lambda lambda) { static void EmitOneArgumentFallback(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Lambda lambda) {
const auto fn = static_cast<mp::equivalent_function_type_t<Lambda>*>(lambda); const auto fn = static_cast<mp::equivalent_function_type<Lambda>*>(lambda);
constexpr u32 stack_space = 2 * 16; constexpr u32 stack_space = 2 * 16;
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Xmm arg1 = ctx.reg_alloc.UseXmm(args[0]); const Xbyak::Xmm arg1 = ctx.reg_alloc.UseXmm(args[0]);
@ -75,7 +75,7 @@ static void EmitOneArgumentFallback(BlockOfCode& code, EmitContext& ctx, IR::Ins
template <typename Lambda> template <typename Lambda>
static void EmitOneArgumentFallbackWithSaturation(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Lambda lambda) { static void EmitOneArgumentFallbackWithSaturation(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Lambda lambda) {
const auto fn = static_cast<mp::equivalent_function_type_t<Lambda>*>(lambda); const auto fn = static_cast<mp::equivalent_function_type<Lambda>*>(lambda);
constexpr u32 stack_space = 2 * 16; constexpr u32 stack_space = 2 * 16;
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Xmm arg1 = ctx.reg_alloc.UseXmm(args[0]); const Xbyak::Xmm arg1 = ctx.reg_alloc.UseXmm(args[0]);
@ -100,7 +100,7 @@ static void EmitOneArgumentFallbackWithSaturation(BlockOfCode& code, EmitContext
template <typename Lambda> template <typename Lambda>
static void EmitTwoArgumentFallbackWithSaturation(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Lambda lambda) { static void EmitTwoArgumentFallbackWithSaturation(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Lambda lambda) {
const auto fn = static_cast<mp::equivalent_function_type_t<Lambda>*>(lambda); const auto fn = static_cast<mp::equivalent_function_type<Lambda>*>(lambda);
constexpr u32 stack_space = 3 * 16; constexpr u32 stack_space = 3 * 16;
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Xmm arg1 = ctx.reg_alloc.UseXmm(args[0]); const Xbyak::Xmm arg1 = ctx.reg_alloc.UseXmm(args[0]);
@ -128,7 +128,7 @@ static void EmitTwoArgumentFallbackWithSaturation(BlockOfCode& code, EmitContext
template <typename Lambda> template <typename Lambda>
static void EmitTwoArgumentFallback(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Lambda lambda) { static void EmitTwoArgumentFallback(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Lambda lambda) {
const auto fn = static_cast<mp::equivalent_function_type_t<Lambda>*>(lambda); const auto fn = static_cast<mp::equivalent_function_type<Lambda>*>(lambda);
constexpr u32 stack_space = 3 * 16; constexpr u32 stack_space = 3 * 16;
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Xmm arg1 = ctx.reg_alloc.UseXmm(args[0]); const Xbyak::Xmm arg1 = ctx.reg_alloc.UseXmm(args[0]);

View file

@ -10,6 +10,14 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <mp/metavalue/lift_value.h>
#include <mp/traits/function_info.h>
#include <mp/traits/integer_of_size.h>
#include <mp/typelist/cartesian_product.h>
#include <mp/typelist/lift_sequence.h>
#include <mp/typelist/list.h>
#include <mp/typelist/lower_to_tuple.h>
#include "backend/x64/abi.h" #include "backend/x64/abi.h"
#include "backend/x64/block_of_code.h" #include "backend/x64/block_of_code.h"
#include "backend/x64/emit_x64.h" #include "backend/x64/emit_x64.h"
@ -18,21 +26,13 @@
#include "common/fp/info.h" #include "common/fp/info.h"
#include "common/fp/op.h" #include "common/fp/op.h"
#include "common/fp/util.h" #include "common/fp/util.h"
#include "common/mp/cartesian_product.h" #include "common/lut_from_list.h"
#include "common/mp/function_info.h"
#include "common/mp/integer.h"
#include "common/mp/list.h"
#include "common/mp/lut.h"
#include "common/mp/to_tuple.h"
#include "common/mp/vlift.h"
#include "common/mp/vllift.h"
#include "frontend/ir/basic_block.h" #include "frontend/ir/basic_block.h"
#include "frontend/ir/microinstruction.h" #include "frontend/ir/microinstruction.h"
namespace Dynarmic::BackendX64 { namespace Dynarmic::BackendX64 {
using namespace Xbyak::util; using namespace Xbyak::util;
namespace mp = Common::mp;
namespace { namespace {
@ -361,7 +361,7 @@ void EmitThreeOpVectorOperation(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
template<typename Lambda> template<typename Lambda>
void EmitTwoOpFallback(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Lambda lambda) { void EmitTwoOpFallback(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Lambda lambda) {
const auto fn = static_cast<mp::equivalent_function_type_t<Lambda>*>(lambda); const auto fn = static_cast<mp::equivalent_function_type<Lambda>*>(lambda);
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Xmm arg1 = ctx.reg_alloc.UseXmm(args[0]); const Xbyak::Xmm arg1 = ctx.reg_alloc.UseXmm(args[0]);
@ -387,7 +387,7 @@ void EmitTwoOpFallback(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Lamb
template<typename Lambda> template<typename Lambda>
void EmitThreeOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbyak::Xmm result, Xbyak::Xmm arg1, Xbyak::Xmm arg2, Lambda lambda) { void EmitThreeOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbyak::Xmm result, Xbyak::Xmm arg1, Xbyak::Xmm arg2, Lambda lambda) {
const auto fn = static_cast<mp::equivalent_function_type_t<Lambda>*>(lambda); const auto fn = static_cast<mp::equivalent_function_type<Lambda>*>(lambda);
#ifdef _WIN32 #ifdef _WIN32
constexpr u32 stack_space = 4 * 16; constexpr u32 stack_space = 4 * 16;
@ -437,7 +437,7 @@ void EmitThreeOpFallback(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, La
template<typename Lambda> template<typename Lambda>
void EmitFourOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbyak::Xmm result, Xbyak::Xmm arg1, Xbyak::Xmm arg2, Xbyak::Xmm arg3, Lambda lambda) { void EmitFourOpFallbackWithoutRegAlloc(BlockOfCode& code, EmitContext& ctx, Xbyak::Xmm result, Xbyak::Xmm arg1, Xbyak::Xmm arg2, Xbyak::Xmm arg3, Lambda lambda) {
const auto fn = static_cast<mp::equivalent_function_type_t<Lambda>*>(lambda); const auto fn = static_cast<mp::equivalent_function_type<Lambda>*>(lambda);
#ifdef _WIN32 #ifdef _WIN32
constexpr u32 stack_space = 5 * 16; constexpr u32 stack_space = 5 * 16;
@ -1205,25 +1205,26 @@ void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
} }
using rounding_list = mp::list< using rounding_list = mp::list<
std::integral_constant<FP::RoundingMode, FP::RoundingMode::ToNearest_TieEven>, mp::lift_value<FP::RoundingMode::ToNearest_TieEven>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsPlusInfinity>, mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsMinusInfinity>, mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsZero>, mp::lift_value<FP::RoundingMode::TowardsZero>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::ToNearest_TieAwayFromZero> mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>
>; >;
using exact_list = mp::list<mp::vlift<true>, mp::vlift<false>>; using exact_list = mp::list<std::true_type, std::false_type>;
using key_type = std::tuple<FP::RoundingMode, bool>; using key_type = std::tuple<FP::RoundingMode, bool>;
using value_type = void(*)(VectorArray<FPT>&, const VectorArray<FPT>&, FP::FPCR, FP::FPSR&); using value_type = void(*)(VectorArray<FPT>&, const VectorArray<FPT>&, FP::FPCR, FP::FPSR&);
static const auto lut = mp::GenerateLookupTableFromList<key_type, value_type>( static const auto lut = Common::GenerateLookupTableFromList<key_type, value_type>(
[](auto arg) { [](auto arg) {
return std::pair<key_type, value_type>{ return std::pair<key_type, value_type>{
mp::to_tuple<decltype(arg)>, mp::lower_to_tuple_v<decltype(arg)>,
static_cast<value_type>( static_cast<value_type>(
[](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) { [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
constexpr FP::RoundingMode rounding_mode = std::get<0>(mp::to_tuple<decltype(arg)>); constexpr auto t = mp::lower_to_tuple_v<decltype(arg)>;
constexpr bool exact = std::get<1>(mp::to_tuple<decltype(arg)>); constexpr FP::RoundingMode rounding_mode = std::get<0>(t);
constexpr bool exact = std::get<1>(t);
for (size_t i = 0; i < output.size(); ++i) { for (size_t i = 0; i < output.size(); ++i) {
output[i] = static_cast<FPT>(FP::FPRoundInt<FPT>(input[i], fpcr, rounding_mode, exact, fpsr)); output[i] = static_cast<FPT>(FP::FPRoundInt<FPT>(input[i], fpcr, rounding_mode, exact, fpsr));
@ -1465,26 +1466,27 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
} }
} }
using fbits_list = mp::vllift<std::make_index_sequence<fsize + 1>>; using fbits_list = mp::lift_sequence<std::make_index_sequence<fsize + 1>>;
using rounding_list = mp::list< using rounding_list = mp::list<
std::integral_constant<FP::RoundingMode, FP::RoundingMode::ToNearest_TieEven>, mp::lift_value<FP::RoundingMode::ToNearest_TieEven>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsPlusInfinity>, mp::lift_value<FP::RoundingMode::TowardsPlusInfinity>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsMinusInfinity>, mp::lift_value<FP::RoundingMode::TowardsMinusInfinity>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::TowardsZero>, mp::lift_value<FP::RoundingMode::TowardsZero>,
std::integral_constant<FP::RoundingMode, FP::RoundingMode::ToNearest_TieAwayFromZero> mp::lift_value<FP::RoundingMode::ToNearest_TieAwayFromZero>
>; >;
using key_type = std::tuple<size_t, FP::RoundingMode>; using key_type = std::tuple<size_t, FP::RoundingMode>;
using value_type = void(*)(VectorArray<FPT>&, const VectorArray<FPT>&, FP::FPCR, FP::FPSR&); using value_type = void(*)(VectorArray<FPT>&, const VectorArray<FPT>&, FP::FPCR, FP::FPSR&);
static const auto lut = mp::GenerateLookupTableFromList<key_type, value_type>( static const auto lut = Common::GenerateLookupTableFromList<key_type, value_type>(
[](auto arg) { [](auto arg) {
return std::pair<key_type, value_type>{ return std::pair<key_type, value_type>{
mp::to_tuple<decltype(arg)>, mp::lower_to_tuple_v<decltype(arg)>,
static_cast<value_type>( static_cast<value_type>(
[](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) { [](VectorArray<FPT>& output, const VectorArray<FPT>& input, FP::FPCR fpcr, FP::FPSR& fpsr) {
constexpr size_t fbits = std::get<0>(mp::to_tuple<decltype(arg)>); constexpr auto t = mp::lower_to_tuple_v<decltype(arg)>;
constexpr FP::RoundingMode rounding_mode = std::get<1>(mp::to_tuple<decltype(arg)>); constexpr size_t fbits = std::get<0>(t);
constexpr FP::RoundingMode rounding_mode = std::get<1>(t);
for (size_t i = 0; i < output.size(); ++i) { for (size_t i = 0; i < output.size(); ++i) {
output[i] = static_cast<FPT>(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr)); output[i] = static_cast<FPT>(FP::FPToFixed<FPT>(fsize, input[i], fbits, unsigned_, fpcr, rounding_mode, fpsr));

View file

@ -8,16 +8,15 @@
#include <array> #include <array>
#include <map> #include <map>
#include <type_traits>
#include "common/mp/list.h" #include <mp/typelist/list.h>
namespace Dynarmic::Common::mp { namespace Dynarmic::Common {
template <typename KeyT, typename ValueT, typename Function, typename ...Values> template <typename KeyT, typename ValueT, typename Function, typename ...Values>
inline auto GenerateLookupTableFromList(Function f, list<Values...>) { inline auto GenerateLookupTableFromList(Function f, mp::list<Values...>) {
static const std::array<std::pair<KeyT, ValueT>, sizeof...(Values)> pair_array{f(Values{})...}; static const std::array<std::pair<KeyT, ValueT>, sizeof...(Values)> pair_array{f(Values{})...};
return std::map<KeyT, ValueT>(pair_array.begin(), pair_array.end()); return std::map<KeyT, ValueT>(pair_array.begin(), pair_array.end());
} }
} // namespace Dynarmic::Common::mp } // namespace Dynarmic::Common

View file

@ -1,27 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
namespace Dynarmic::Common::mp {
namespace detail {
template<class... L>
struct append_impl;
template<template<class...> class LT, class... T1, class... T2>
struct append_impl<LT<T1...>, T2...> {
using type = LT<T1..., T2...>;
};
} // namespace detail
/// Append items T to list L
template<class L, class... T>
using append = typename detail::append_impl<L, T...>::type;
} // namespace Dynarmic::Common::mp

View file

@ -1,18 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
namespace Dynarmic::Common::mp {
/// Binds the first sizeof...(A) arguments of metafunction F with arguments A
template<template<class...> class F, class... A>
struct bind {
template<class... T>
using type = F<A..., T...>;
};
} // namespace Dynarmic::Common::mp

View file

@ -1,51 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
#include "common/mp/append.h"
#include "common/mp/bind.h"
#include "common/mp/concat.h"
#include "common/mp/fmap.h"
#include "common/mp/list.h"
namespace Dynarmic::Common::mp {
namespace detail {
template<class... Ls>
struct cartesian_product_impl{};
template<class RL>
struct cartesian_product_impl<RL> {
using type = RL;
};
template<template<class...> class LT, class... RT, class... T1>
struct cartesian_product_impl<LT<RT...>, LT<T1...>> {
using type = concat<
fmap<bind<append, RT>::template type, list<T1...>>...
>;
};
template<class RL, class L1, class L2, class... Ls>
struct cartesian_product_impl<RL, L1, L2, Ls...> {
using type = typename cartesian_product_impl<
typename cartesian_product_impl<RL, L1>::type,
L2,
Ls...
>::type;
};
} // namespace detail
/// Produces the cartesian product of a set of lists
/// For example:
/// cartesian_product<list<A, B>, list<D, E>> == list<list<A, D>, list<A, E>, list<B, D>, list<B, E>
template<typename L1, typename... Ls>
using cartesian_product = typename detail::cartesian_product_impl<fmap<list, L1>, Ls...>::type;
} // namespace Dynarmic::Common::mp

View file

@ -1,57 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
#include "common/mp/list.h"
namespace Dynarmic::Common::mp {
namespace detail {
template<class... L>
struct concat_impl;
template<>
struct concat_impl<> {
using type = list<>;
};
template<class L>
struct concat_impl<L> {
using type = L;
};
template<template<class...> class LT, class... T1, class... T2, class... Ls>
struct concat_impl<LT<T1...>, LT<T2...>, Ls...> {
using type = typename concat_impl<LT<T1..., T2...>, Ls...>::type;
};
template<template<class...> class LT,
class... T1, class... T2, class... T3, class... T4, class... T5, class... T6, class... T7, class... T8,
class... T9, class... T10, class... T11, class... T12, class... T13, class... T14, class... T15, class... T16,
class... Ls>
struct concat_impl<
LT<T1...>, LT<T2...>, LT<T3...>, LT<T4...>, LT<T5...>, LT<T6...>, LT<T7...>, LT<T8...>,
LT<T9...>, LT<T10...>, LT<T11...>, LT<T12...>, LT<T13...>, LT<T14...>, LT<T15...>, LT<T16...>,
Ls...>
{
using type = typename concat_impl<
LT<
T1..., T2..., T3..., T4..., T5..., T6..., T7..., T8...,
T9..., T10..., T11..., T12..., T13..., T14..., T15..., T16...
>,
Ls...
>::type;
};
} // namespace detail
/// Concatenate lists together
template<class... L>
using concat = typename detail::concat_impl<L...>::type;
} // namespace Dynarmic::Common::mp

View file

@ -1,27 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
namespace Dynarmic::Common::mp {
namespace detail {
template<template<class...> class F, class L>
struct fapply_impl;
template<template<class...> class F, template<class...> class LT, class... T>
struct fapply_impl<F, LT<T...>> {
using type = F<T...>;
};
} // namespace detail
/// Invokes metafunction F where the arguments are all the members of list L
template<template<class...> class F, class L>
using fapply = typename detail::fapply_impl<F, L>::type;
} // namespace Dynarmic::Common::mp

View file

@ -1,27 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
namespace Dynarmic::Common::mp {
namespace detail {
template<template<class...> class F, class L>
struct fmap_impl;
template<template<class...> class F, template<class...> class LT, class... T>
struct fmap_impl<F, LT<T...>> {
using type = LT<F<T>...>;
};
} // namespace detail
/// Metafunction that applies each element of list L to metafunction F
template<template<class...> class F, class L>
using fmap = typename detail::fmap_impl<F, L>::type;
} // namespace Dynarmic::Common::mp

View file

@ -1,102 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2016 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
#include <cstddef>
#include <tuple>
namespace Dynarmic::Common::mp {
/// Used to provide information about an arbitrary function.
template <typename Function>
struct FunctionInfo : public FunctionInfo<decltype(&Function::operator())>
{
};
/**
* Partial specialization for function types.
*
* This is used as the supporting base for all other specializations.
*/
template <typename R, typename... Args>
struct FunctionInfo<R(Args...)>
{
using return_type = R;
static constexpr size_t args_count = sizeof...(Args);
template <size_t ParameterIndex>
struct Parameter
{
static_assert(args_count != 0 && ParameterIndex < args_count, "Non-existent function parameter index");
using type = std::tuple_element_t<ParameterIndex, std::tuple<Args...>>;
};
using equivalent_function_type = R(Args...);
};
/// Partial specialization for function pointers
template <typename R, typename... Args>
struct FunctionInfo<R(*)(Args...)> : public FunctionInfo<R(Args...)>
{
};
/// Partial specialization for member function pointers.
template <typename C, typename R, typename... Args>
struct FunctionInfo<R(C::*)(Args...)> : public FunctionInfo<R(Args...)>
{
using class_type = C;
};
/// Partial specialization for const member function pointers.
template <typename C, typename R, typename... Args>
struct FunctionInfo<R(C::*)(Args...) const> : public FunctionInfo<R(Args...)>
{
using class_type = C;
};
/**
* Helper template for retrieving the number of function parameters.
*
* @tparam Function An arbitrary function type.
*/
template <typename Function>
constexpr size_t parameter_count_v = FunctionInfo<Function>::args_count;
/**
* Helper template for retrieving the type of a function parameter.
*
* @tparam Function An arbitrary function type.
* @tparam ParameterIndex Zero-based index indicating which parameter to get the type of.
*/
template <typename Function, size_t ParameterIndex>
using parameter_type_t = typename FunctionInfo<Function>::template Parameter<ParameterIndex>::type;
/**
* Helper template for retrieving the return type of a function.
*
* @tparam Function The function type to get the return type of.
*/
template <typename Function>
using return_type_t = typename FunctionInfo<Function>::return_type;
/**
* Helper template for retrieving the class type of a member function.
*
* @tparam Function The function type to get the return type of.
*/
template <typename Function>
using class_type_t = typename FunctionInfo<Function>::class_type;
/**
* Helper template for retrieving the equivalent function type of a member function or functor.
*
* @tparam Function The function type to get the return type of.
*/
template <typename Function>
using equivalent_function_type_t = typename FunctionInfo<Function>::equivalent_function_type;
} // namespace Dynarmic::Common::mp

View file

@ -1,51 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
#include <cstddef>
#include <cstdint>
namespace Dynarmic::Common::mp {
namespace detail {
template<std::size_t size>
struct integer_of_size_impl{};
template<>
struct integer_of_size_impl<8> {
using unsigned_type = std::uint8_t;
using signed_type = std::int8_t;
};
template<>
struct integer_of_size_impl<16> {
using unsigned_type = std::uint16_t;
using signed_type = std::int16_t;
};
template<>
struct integer_of_size_impl<32> {
using unsigned_type = std::uint32_t;
using signed_type = std::int32_t;
};
template<>
struct integer_of_size_impl<64> {
using unsigned_type = std::uint64_t;
using signed_type = std::int64_t;
};
} // namespace detail
template<std::size_t size>
using unsigned_integer_of_size = typename detail::integer_of_size_impl<size>::unsigned_type;
template<std::size_t size>
using signed_integer_of_size = typename detail::integer_of_size_impl<size>::signed_type;
} // namespace Dynarmic::Common::mp

View file

@ -1,15 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
namespace Dynarmic::Common::mp {
/// Contains a list of types
template<class... T>
struct list {};
} // namespace Dynarmic::Common::mp

View file

@ -1,29 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
#include <tuple>
namespace Dynarmic::Common::mp {
namespace detail {
template<class L>
struct to_tuple_impl;
template<template<class...> class LT, class... T>
struct to_tuple_impl<LT<T...>> {
static constexpr auto value = std::make_tuple(static_cast<typename T::value_type>(T::value)...);
};
} // namespace detail
/// Metafunction that converts a list of metavalues to a tuple value.
template<class L>
constexpr auto to_tuple = detail::to_tuple_impl<L>::value;
} // namespace Dynarmic::Common::mp

View file

@ -1,17 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
#include <type_traits>
namespace Dynarmic::Common::mp {
/// Lifts a value into a type
template<auto V>
using vlift = std::integral_constant<decltype(V), V>;
} // namespace Dynarmic::Common::mp

View file

@ -1,31 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#pragma once
#include <type_traits>
#include "common/mp/list.h"
namespace Dynarmic::Common::mp {
namespace detail {
template<class VL>
struct vllift_impl{};
template<class T, T... values>
struct vllift_impl<std::integer_sequence<T, values...>> {
using type = list<std::integral_constant<T, values>...>;
};
} // namespace detail
/// Lifts values in value list VL to create a type list.
template<class VL>
using vllift = typename detail::vllift_impl<VL>::type;
} // namespace Dynarmic::Common::mp

View file

@ -10,9 +10,10 @@
#include <array> #include <array>
#include <tuple> #include <tuple>
#include <mp/traits/function_info.h>
#include "common/assert.h" #include "common/assert.h"
#include "common/bit_util.h" #include "common/bit_util.h"
#include "common/mp/function_info.h"
namespace Dynarmic::Decoder { namespace Dynarmic::Decoder {
namespace detail { namespace detail {
@ -152,7 +153,7 @@ public:
*/ */
template<typename FnT> template<typename FnT>
static auto GetMatcher(FnT fn, const char* const name, const char* const bitstring) { static auto GetMatcher(FnT fn, const char* const name, const char* const bitstring) {
constexpr size_t args_count = Common::mp::FunctionInfo<FnT>::args_count; constexpr size_t args_count = mp::parameter_count_v<FnT>;
using Iota = std::make_index_sequence<args_count>; using Iota = std::make_index_sequence<args_count>;
const auto [mask, expect] = GetMaskAndExpect(bitstring); const auto [mask, expect] = GetMaskAndExpect(bitstring);

View file

@ -11,7 +11,6 @@ add_executable(dynarmic_tests
fp/mantissa_util_tests.cpp fp/mantissa_util_tests.cpp
fp/unpacked_tests.cpp fp/unpacked_tests.cpp
main.cpp main.cpp
mp.cpp
rand_int.h rand_int.h
) )
@ -40,12 +39,12 @@ include(CreateDirectoryGroups)
create_target_directory_groups(dynarmic_tests) create_target_directory_groups(dynarmic_tests)
create_target_directory_groups(dynarmic_print_info) create_target_directory_groups(dynarmic_print_info)
target_link_libraries(dynarmic_tests PRIVATE dynarmic boost catch fmt xbyak) target_link_libraries(dynarmic_tests PRIVATE dynarmic boost catch fmt mp xbyak)
target_include_directories(dynarmic_tests PRIVATE . ../src) target_include_directories(dynarmic_tests PRIVATE . ../src)
target_compile_options(dynarmic_tests PRIVATE ${DYNARMIC_CXX_FLAGS}) target_compile_options(dynarmic_tests PRIVATE ${DYNARMIC_CXX_FLAGS})
target_compile_definitions(dynarmic_tests PRIVATE FMT_USE_USER_DEFINED_LITERALS=0) target_compile_definitions(dynarmic_tests PRIVATE FMT_USE_USER_DEFINED_LITERALS=0)
target_link_libraries(dynarmic_print_info PRIVATE dynarmic boost catch fmt) target_link_libraries(dynarmic_print_info PRIVATE dynarmic boost catch fmt mp)
target_include_directories(dynarmic_print_info PRIVATE . ../src) target_include_directories(dynarmic_print_info PRIVATE . ../src)
target_compile_options(dynarmic_print_info PRIVATE ${DYNARMIC_CXX_FLAGS}) target_compile_options(dynarmic_print_info PRIVATE ${DYNARMIC_CXX_FLAGS})
target_compile_definitions(dynarmic_print_info PRIVATE FMT_USE_USER_DEFINED_LITERALS=0) target_compile_definitions(dynarmic_print_info PRIVATE FMT_USE_USER_DEFINED_LITERALS=0)

View file

@ -1,27 +0,0 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#include <type_traits>
#include "common/mp/cartesian_product.h"
using namespace Dynarmic::Common::mp;
static_assert(
std::is_same_v<
cartesian_product<list<int, bool>, list<double, float>, list<char, unsigned>>,
list<
list<int, double, char>,
list<int, double, unsigned>,
list<int, float, char>,
list<int, float, unsigned>,
list<bool, double, char>,
list<bool, double, unsigned>,
list<bool, float, char>,
list<bool, float, unsigned>
>
>
);