From bd88286b215a7f2db0ede8c8450a8b89c80234f3 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 4 Apr 2020 10:57:41 +0100 Subject: [PATCH] cast_util: Add FptrCast Reduce unnecessary type duplication when casting a lambda to a function pointer. --- src/backend/x64/a32_emit_x64.cpp | 6 ++-- src/backend/x64/a64_emit_x64.cpp | 28 +++++++++---------- src/backend/x64/block_of_code.h | 7 +++++ src/backend/x64/emit_x64_floating_point.cpp | 5 ++-- src/backend/x64/emit_x64_vector.cpp | 4 +-- .../x64/emit_x64_vector_floating_point.cpp | 6 ++-- src/common/cast_util.h | 8 ++++++ 7 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/backend/x64/a32_emit_x64.cpp b/src/backend/x64/a32_emit_x64.cpp index 61caf942..6548fd00 100644 --- a/src/backend/x64/a32_emit_x64.cpp +++ b/src/backend/x64/a32_emit_x64.cpp @@ -647,9 +647,7 @@ void A32EmitX64::EmitA32InstructionSynchronizationBarrier(A32EmitContext& ctx, I ctx.reg_alloc.HostCall(nullptr); code.mov(code.ABI_PARAM1, reinterpret_cast(jit_interface)); - code.CallFunction(static_cast([](A32::Jit* jit) { - jit->ClearCache(); - })); + code.CallLambda([](A32::Jit* jit) { jit->ClearCache(); }); } void A32EmitX64::EmitA32BXWritePC(A32EmitContext& ctx, IR::Inst* inst) { @@ -814,7 +812,7 @@ static void ReadMemory(BlockOfCode& code, RegAlloc& reg_alloc, IR::Inst* inst, c const Xbyak::Reg64 vaddr = code.ABI_PARAM2; const Xbyak::Reg64 value = reg_alloc.ScratchGpr({ABI_RETURN}); - + const auto src_ptr = EmitVAddrLookup(code, reg_alloc, config, abort, vaddr, value); switch (bit_size) { case 8: diff --git a/src/backend/x64/a64_emit_x64.cpp b/src/backend/x64/a64_emit_x64.cpp index b5183c43..6dec97f5 100644 --- a/src/backend/x64/a64_emit_x64.cpp +++ b/src/backend/x64/a64_emit_x64.cpp @@ -619,9 +619,7 @@ void A64EmitX64::EmitA64InstructionSynchronizationBarrier(A64EmitContext& ctx, I ctx.reg_alloc.HostCall(nullptr); code.mov(code.ABI_PARAM1, reinterpret_cast(jit_interface)); - code.CallFunction(static_cast([](A64::Jit* jit) { - jit->ClearCache(); - })); + code.CallLambda([](A64::Jit* jit) { jit->ClearCache(); }); } void A64EmitX64::EmitA64GetCNTFRQ(A64EmitContext& ctx, IR::Inst* inst) { @@ -691,11 +689,11 @@ void A64EmitX64::EmitA64SetExclusive(A64EmitContext& ctx, IR::Inst* inst) { code.mov(code.byte[r15 + offsetof(A64JitState, exclusive_state)], u8(1)); code.mov(code.ABI_PARAM1, reinterpret_cast(&conf)); - code.CallFunction(static_cast( + code.CallLambda( [](A64::UserConfig& conf, u64 vaddr, u8 size) { conf.global_monitor->Mark(conf.processor_id, vaddr, size); } - )); + ); return; } @@ -1025,52 +1023,52 @@ void A64EmitX64::EmitExclusiveWrite(A64EmitContext& ctx, IR::Inst* inst, size_t code.mov(code.ABI_PARAM1, reinterpret_cast(&conf)); switch (bitsize) { case 8: - code.CallFunction(static_cast( + code.CallLambda( [](A64::UserConfig& conf, u64 vaddr, u8 value) -> u32 { return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, 1, [&]{ conf.callbacks->MemoryWrite8(vaddr, value); }) ? 0 : 1; } - )); + ); break; case 16: - code.CallFunction(static_cast( + code.CallLambda( [](A64::UserConfig& conf, u64 vaddr, u16 value) -> u32 { return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, 2, [&]{ conf.callbacks->MemoryWrite16(vaddr, value); }) ? 0 : 1; } - )); + ); break; case 32: - code.CallFunction(static_cast( + code.CallLambda( [](A64::UserConfig& conf, u64 vaddr, u32 value) -> u32 { return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, 4, [&]{ conf.callbacks->MemoryWrite32(vaddr, value); }) ? 0 : 1; } - )); + ); break; case 64: - code.CallFunction(static_cast( + code.CallLambda( [](A64::UserConfig& conf, u64 vaddr, u64 value) -> u32 { return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, 8, [&]{ conf.callbacks->MemoryWrite64(vaddr, value); }) ? 0 : 1; } - )); + ); break; case 128: code.sub(rsp, 16 + ABI_SHADOW_SPACE); code.lea(code.ABI_PARAM3, ptr[rsp + ABI_SHADOW_SPACE]); code.movaps(xword[code.ABI_PARAM3], xmm1); - code.CallFunction(static_cast( + code.CallLambda( [](A64::UserConfig& conf, u64 vaddr, A64::Vector& value) -> u32 { return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, 16, [&]{ conf.callbacks->MemoryWrite128(vaddr, value); }) ? 0 : 1; } - )); + ); code.add(rsp, 16 + ABI_SHADOW_SPACE); break; default: diff --git a/src/backend/x64/block_of_code.h b/src/backend/x64/block_of_code.h index 00ef565e..2d944946 100644 --- a/src/backend/x64/block_of_code.h +++ b/src/backend/x64/block_of_code.h @@ -16,6 +16,7 @@ #include "backend/x64/callback.h" #include "backend/x64/constant_pool.h" #include "backend/x64/jitstate_info.h" +#include "common/cast_util.h" #include "common/common_types.h" namespace Dynarmic::BackendX64 { @@ -83,6 +84,12 @@ public: } } + /// Code emitter: Calls the lambda. Lambda must not have any captures. + template + void CallLambda(Lambda l) { + CallFunction(Common::FptrCast(l)); + } + Xbyak::Address MConst(const Xbyak::AddressFrame& frame, u64 lower, u64 upper = 0); /// Far code sits far away from the near code. Execution remains primarily in near code. diff --git a/src/backend/x64/emit_x64_floating_point.cpp b/src/backend/x64/emit_x64_floating_point.cpp index fb23b752..45aee0ca 100644 --- a/src/backend/x64/emit_x64_floating_point.cpp +++ b/src/backend/x64/emit_x64_floating_point.cpp @@ -20,6 +20,7 @@ #include "backend/x64/emit_x64.h" #include "common/assert.h" #include "common/common_types.h" +#include "common/cast_util.h" #include "common/fp/fpcr.h" #include "common/fp/fpsr.h" #include "common/fp/info.h" @@ -861,7 +862,7 @@ static void EmitFPRound(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, siz [](auto args) { return std::pair{ mp::lower_to_tuple_v, - static_cast( + Common::FptrCast( [](u64 input, FP::FPSR& fpsr, FP::FPCR fpcr) { constexpr auto t = mp::lower_to_tuple_v; constexpr size_t fsize = std::get<0>(t); @@ -1289,7 +1290,7 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { [](auto args) { return std::pair{ mp::lower_to_tuple_v, - static_cast( + Common::FptrCast( [](u64 input, FP::FPSR& fpsr, FP::FPCR fpcr) { constexpr auto t = mp::lower_to_tuple_v; constexpr size_t fbits = std::get<0>(t); diff --git a/src/backend/x64/emit_x64_vector.cpp b/src/backend/x64/emit_x64_vector.cpp index f92a1597..0f50eadb 100644 --- a/src/backend/x64/emit_x64_vector.cpp +++ b/src/backend/x64/emit_x64_vector.cpp @@ -4050,7 +4050,7 @@ void EmitX64::EmitVectorTableLookup(EmitContext& ctx, IR::Inst* inst) { code.movaps(xword[code.ABI_PARAM2], defaults); code.movaps(xword[code.ABI_PARAM3], indicies); - code.CallFunction(static_cast*, VectorArray&, const VectorArray&, size_t)>( + code.CallLambda( [](const VectorArray* table, VectorArray& result, const VectorArray& indicies, size_t table_size) { for (size_t i = 0; i < result.size(); ++i) { const size_t index = indicies[i] / table[0].size(); @@ -4060,7 +4060,7 @@ void EmitX64::EmitVectorTableLookup(EmitContext& ctx, IR::Inst* inst) { } } } - )); + ); code.movaps(result, xword[rsp + ABI_SHADOW_SPACE + (table_size + 0) * 16]); code.add(rsp, stack_space + ABI_SHADOW_SPACE); diff --git a/src/backend/x64/emit_x64_vector_floating_point.cpp b/src/backend/x64/emit_x64_vector_floating_point.cpp index 810213aa..286227fb 100644 --- a/src/backend/x64/emit_x64_vector_floating_point.cpp +++ b/src/backend/x64/emit_x64_vector_floating_point.cpp @@ -1005,7 +1005,7 @@ static void EmitFPVectorMulX(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst FCODE(mulp)(result, xmm_b); FCODE(cmpunordp)(nan_mask, result); - const auto nan_handler = static_cast, 3>&, FP::FPCR)>( + const auto nan_handler = Common::FptrCast( [](std::array, 3>& values, FP::FPCR fpcr) { VectorArray& result = values[0]; for (size_t elementi = 0; elementi < result.size(); ++elementi) { @@ -1217,7 +1217,7 @@ void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { [](auto arg) { return std::pair{ mp::lower_to_tuple_v, - static_cast&, const VectorArray&, FP::FPCR, FP::FPSR&)>( + Common::FptrCast( [](VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { constexpr auto t = mp::lower_to_tuple_v; constexpr FP::RoundingMode rounding_mode = std::get<0>(t); @@ -1476,7 +1476,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { [](auto arg) { return std::pair{ mp::lower_to_tuple_v, - static_cast&, const VectorArray&, FP::FPCR, FP::FPSR&)>( + Common::FptrCast( [](VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { constexpr auto t = mp::lower_to_tuple_v; constexpr size_t fbits = std::get<0>(t); diff --git a/src/common/cast_util.h b/src/common/cast_util.h index 3033a2b0..bde4c933 100644 --- a/src/common/cast_util.h +++ b/src/common/cast_util.h @@ -9,6 +9,8 @@ #include #include +#include + namespace Dynarmic::Common { /// Reinterpret objects of one type as another by bit-casting between object representations. @@ -35,4 +37,10 @@ inline Dest BitCastPointee(const SourcePtr source) noexcept { return reinterpret_cast(dest); } +/// Cast a lambda into an equivalent function pointer. +template +inline auto FptrCast(Function f) noexcept { + return static_cast*>(f); +} + } // namespace Dynarmic::Common