mp: Migrate to shared version of mp library
This commit is contained in:
parent
66fa4a0b54
commit
81fcb4e537
23 changed files with 92 additions and 575 deletions
4
externals/CMakeLists.txt
vendored
4
externals/CMakeLists.txt
vendored
|
@ -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>)
|
||||||
|
|
|
@ -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}>
|
||||||
)
|
)
|
||||||
|
|
|
@ -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__)
|
||||||
|
|
|
@ -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>;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
27
tests/mp.cpp
27
tests/mp.cpp
|
@ -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>
|
|
||||||
>
|
|
||||||
>
|
|
||||||
);
|
|
Loading…
Reference in a new issue