From 6b01c13975439784cd40cf1810b67350111a41d3 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 28 Oct 2025 14:14:42 +0100 Subject: [PATCH] Revert "[dynarmic] replace mcl::bit_cast with std::bit_cast; fix IR_emit codepath warnings for UNREACHABLE(); remove type trait mcl::integer_of_size dependency (#2775)" (#2863) This reverts commit 61ab1be0e70b6e86a15f4938666d3968e20f59f3. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2863 Co-authored-by: unknown Co-committed-by: unknown --- src/dynarmic/src/dynarmic/CMakeLists.txt | 3 +- .../backend/arm64/a32_address_space.cpp | 22 +-- .../backend/arm64/a64_address_space.cpp | 30 ++-- src/dynarmic/src/dynarmic/backend/arm64/abi.h | 7 +- .../dynarmic/backend/arm64/address_space.cpp | 13 +- .../src/dynarmic/backend/arm64/devirtualize.h | 13 +- .../dynarmic/backend/arm64/emit_arm64_a64.cpp | 12 +- .../backend/arm64/emit_arm64_memory.cpp | 11 +- .../backend/arm64/emit_arm64_vector.cpp | 26 ++- .../emit_arm64_vector_floating_point.cpp | 21 +-- .../arm64/emit_arm64_vector_saturation.cpp | 6 +- .../src/dynarmic/backend/arm64/reg_alloc.cpp | 15 +- .../src/dynarmic/backend/exception_handler.h | 20 ++- .../backend/exception_handler_macos.cpp | 9 +- .../backend/exception_handler_macos_mig.c | 2 + .../backend/exception_handler_posix.cpp | 16 +- .../backend/exception_handler_windows.cpp | 2 + .../dynarmic/backend/riscv64/reg_alloc.cpp | 7 +- .../backend/x64/a32_emit_x64_memory.cpp | 4 +- .../dynarmic/backend/x64/a32_interface.cpp | 5 +- .../src/dynarmic/backend/x64/a64_emit_x64.cpp | 1 + .../backend/x64/a64_emit_x64_memory.cpp | 4 +- .../dynarmic/backend/x64/a64_interface.cpp | 5 +- .../src/dynarmic/backend/x64/block_of_code.h | 2 +- .../src/dynarmic/backend/x64/devirtualize.h | 12 +- .../backend/x64/emit_x64_floating_point.cpp | 162 ++++++++++-------- .../backend/x64/emit_x64_memory.cpp.inc | 87 ++++++---- .../dynarmic/backend/x64/emit_x64_memory.h | 12 +- .../backend/x64/emit_x64_saturation.cpp | 7 +- .../x64/emit_x64_vector_floating_point.cpp | 58 ++++--- .../x64/emit_x64_vector_saturation.cpp | 19 +- .../backend/x64/exception_handler_windows.cpp | 8 +- .../src/dynarmic/backend/x64/perf_map.h | 9 +- .../src/dynarmic/backend/x64/reg_alloc.cpp | 2 +- .../src/dynarmic/common/always_false.h | 13 ++ src/dynarmic/src/dynarmic/common/assert.h | 45 ++--- src/dynarmic/src/dynarmic/common/cast_util.h | 18 ++ src/dynarmic/src/dynarmic/common/fp/util.h | 4 - .../src/dynarmic/common/llvm_disassemble.cpp | 5 +- src/dynarmic/src/dynarmic/common/type_util.h | 31 ---- src/dynarmic/src/dynarmic/ir/ir_emitter.cpp | 2 +- src/dynarmic/src/dynarmic/ir/ir_emitter.h | 10 +- src/dynarmic/tests/test_generator.cpp | 1 + 43 files changed, 410 insertions(+), 351 deletions(-) create mode 100644 src/dynarmic/src/dynarmic/common/always_false.h create mode 100644 src/dynarmic/src/dynarmic/common/cast_util.h delete mode 100644 src/dynarmic/src/dynarmic/common/type_util.h diff --git a/src/dynarmic/src/dynarmic/CMakeLists.txt b/src/dynarmic/src/dynarmic/CMakeLists.txt index cb10b6b168..4e00e8fe0d 100644 --- a/src/dynarmic/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/src/dynarmic/CMakeLists.txt @@ -6,9 +6,10 @@ add_library(dynarmic STATIC backend/block_range_information.cpp backend/block_range_information.h backend/exception_handler.h + common/always_false.h common/assert.cpp common/assert.h - common/type_util.h + common/cast_util.h common/common_types.h common/crypto/aes.cpp common/crypto/aes.h diff --git a/src/dynarmic/src/dynarmic/backend/arm64/a32_address_space.cpp b/src/dynarmic/src/dynarmic/backend/arm64/a32_address_space.cpp index 681efce984..01af361b27 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/a32_address_space.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/a32_address_space.cpp @@ -13,7 +13,7 @@ #include "dynarmic/backend/arm64/devirtualize.h" #include "dynarmic/backend/arm64/emit_arm64.h" #include "dynarmic/backend/arm64/stack_layout.h" -#include "dynarmic/common/type_util.h" +#include "dynarmic/common/cast_util.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/frontend/A32/translate/a32_translate.h" @@ -93,9 +93,9 @@ static void* EmitExclusiveReadCallTrampoline(oaknut::CodeGenerator& code, const code.align(8); code.l(l_this); - code.dx(std::bit_cast(&conf)); + code.dx(mcl::bit_cast(&conf)); code.l(l_addr); - code.dx(std::bit_cast(Common::FptrCast(fn))); + code.dx(mcl::bit_cast(Common::FptrCast(fn))); return target; } @@ -151,9 +151,9 @@ static void* EmitExclusiveWriteCallTrampoline(oaknut::CodeGenerator& code, const code.align(8); code.l(l_this); - code.dx(std::bit_cast(&conf)); + code.dx(mcl::bit_cast(&conf)); code.l(l_addr); - code.dx(std::bit_cast(Common::FptrCast(fn))); + code.dx(mcl::bit_cast(Common::FptrCast(fn))); return target; } @@ -219,7 +219,7 @@ void A32AddressSpace::EmitPrelude() { code.MOV(Xstate, X1); code.MOV(Xhalt, X2); if (conf.page_table) { - code.MOV(Xpagetable, std::bit_cast(conf.page_table)); + code.MOV(Xpagetable, mcl::bit_cast(conf.page_table)); } if (conf.fastmem_pointer) { code.MOV(Xfastmem, *conf.fastmem_pointer); @@ -258,7 +258,7 @@ void A32AddressSpace::EmitPrelude() { code.MOV(Xstate, X1); code.MOV(Xhalt, X2); if (conf.page_table) { - code.MOV(Xpagetable, std::bit_cast(conf.page_table)); + code.MOV(Xpagetable, mcl::bit_cast(conf.page_table)); } if (conf.fastmem_pointer) { code.MOV(Xfastmem, *conf.fastmem_pointer); @@ -317,9 +317,9 @@ void A32AddressSpace::EmitPrelude() { code.align(8); code.l(l_this); - code.dx(std::bit_cast(this)); + code.dx(mcl::bit_cast(this)); code.l(l_addr); - code.dx(std::bit_cast(Common::FptrCast(fn))); + code.dx(mcl::bit_cast(Common::FptrCast(fn))); } prelude_info.return_from_run_code = code.xptr(); @@ -347,7 +347,7 @@ void A32AddressSpace::EmitPrelude() { code.align(8); code.l(l_return_to_dispatcher); - code.dx(std::bit_cast(prelude_info.return_to_dispatcher)); + code.dx(mcl::bit_cast(prelude_info.return_to_dispatcher)); prelude_info.end_of_prelude = code.offset(); @@ -369,7 +369,7 @@ EmitConfig A32AddressSpace::GetEmitConfig() { .check_halt_on_memory_access = conf.check_halt_on_memory_access, - .page_table_pointer = std::bit_cast(conf.page_table), + .page_table_pointer = mcl::bit_cast(conf.page_table), .page_table_address_space_bits = 32, .page_table_pointer_mask_bits = conf.page_table_pointer_mask_bits, .silently_mirror_page_table = true, diff --git a/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.cpp b/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.cpp index f79f0ea374..c4c1c42792 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.cpp @@ -13,7 +13,7 @@ #include "dynarmic/backend/arm64/devirtualize.h" #include "dynarmic/backend/arm64/emit_arm64.h" #include "dynarmic/backend/arm64/stack_layout.h" -#include "dynarmic/common/type_util.h" +#include "dynarmic/common/cast_util.h" #include "dynarmic/frontend/A64/a64_location_descriptor.h" #include "dynarmic/frontend/A64/translate/a64_translate.h" #include "dynarmic/interface/A64/config.h" @@ -92,9 +92,9 @@ static void* EmitExclusiveReadCallTrampoline(oaknut::CodeGenerator& code, const code.align(8); code.l(l_this); - code.dx(std::bit_cast(&conf)); + code.dx(mcl::bit_cast(&conf)); code.l(l_addr); - code.dx(std::bit_cast(Common::FptrCast(fn))); + code.dx(mcl::bit_cast(Common::FptrCast(fn))); return target; } @@ -150,9 +150,9 @@ static void* EmitExclusiveWriteCallTrampoline(oaknut::CodeGenerator& code, const code.align(8); code.l(l_this); - code.dx(std::bit_cast(&conf)); + code.dx(mcl::bit_cast(&conf)); code.l(l_addr); - code.dx(std::bit_cast(Common::FptrCast(fn))); + code.dx(mcl::bit_cast(Common::FptrCast(fn))); return target; } @@ -235,9 +235,9 @@ static void* EmitExclusiveRead128CallTrampoline(oaknut::CodeGenerator& code, con code.align(8); code.l(l_this); - code.dx(std::bit_cast(&conf)); + code.dx(mcl::bit_cast(&conf)); code.l(l_addr); - code.dx(std::bit_cast(Common::FptrCast(fn))); + code.dx(mcl::bit_cast(Common::FptrCast(fn))); return target; } @@ -317,9 +317,9 @@ static void* EmitExclusiveWrite128CallTrampoline(oaknut::CodeGenerator& code, co code.align(8); code.l(l_this); - code.dx(std::bit_cast(&conf)); + code.dx(mcl::bit_cast(&conf)); code.l(l_addr); - code.dx(std::bit_cast(Common::FptrCast(fn))); + code.dx(mcl::bit_cast(Common::FptrCast(fn))); return target; } @@ -396,7 +396,7 @@ void A64AddressSpace::EmitPrelude() { code.MOV(Xstate, X1); code.MOV(Xhalt, X2); if (conf.page_table) { - code.MOV(Xpagetable, std::bit_cast(conf.page_table)); + code.MOV(Xpagetable, mcl::bit_cast(conf.page_table)); } if (conf.fastmem_pointer) { code.MOV(Xfastmem, *conf.fastmem_pointer); @@ -434,7 +434,7 @@ void A64AddressSpace::EmitPrelude() { code.MOV(Xstate, X1); code.MOV(Xhalt, X2); if (conf.page_table) { - code.MOV(Xpagetable, std::bit_cast(conf.page_table)); + code.MOV(Xpagetable, mcl::bit_cast(conf.page_table)); } if (conf.fastmem_pointer) { code.MOV(Xfastmem, *conf.fastmem_pointer); @@ -492,9 +492,9 @@ void A64AddressSpace::EmitPrelude() { code.align(8); code.l(l_this); - code.dx(std::bit_cast(this)); + code.dx(mcl::bit_cast(this)); code.l(l_addr); - code.dx(std::bit_cast(Common::FptrCast(fn))); + code.dx(mcl::bit_cast(Common::FptrCast(fn))); } prelude_info.return_from_run_code = code.xptr(); @@ -522,7 +522,7 @@ void A64AddressSpace::EmitPrelude() { code.align(8); code.l(l_return_to_dispatcher); - code.dx(std::bit_cast(prelude_info.return_to_dispatcher)); + code.dx(mcl::bit_cast(prelude_info.return_to_dispatcher)); prelude_info.end_of_prelude = code.offset(); @@ -544,7 +544,7 @@ EmitConfig A64AddressSpace::GetEmitConfig() { .check_halt_on_memory_access = conf.check_halt_on_memory_access, - .page_table_pointer = std::bit_cast(conf.page_table), + .page_table_pointer = mcl::bit_cast(conf.page_table), .page_table_address_space_bits = conf.page_table_address_space_bits, .page_table_pointer_mask_bits = conf.page_table_pointer_mask_bits, .silently_mirror_page_table = conf.silently_mirror_page_table, diff --git a/src/dynarmic/src/dynarmic/backend/arm64/abi.h b/src/dynarmic/src/dynarmic/backend/arm64/abi.h index d0258ef5c4..635d64f062 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/abi.h @@ -17,6 +17,7 @@ #include "dynarmic/common/assert.h" #include +#include "dynarmic/common/always_false.h" namespace Dynarmic::Backend::Arm64 { @@ -36,8 +37,7 @@ constexpr auto Rscratch0() { } else if constexpr (bitsize == 64) { return Xscratch0; } else { - // TODO: This codepath is regarded as "takeable" on gcc12 - return Xscratch0; //static_assert(false); + static_assert(Common::always_false_v>); } } @@ -48,8 +48,7 @@ constexpr auto Rscratch1() { } else if constexpr (bitsize == 64) { return Xscratch1; } else { - // TODO: This codepath is regarded as "takeable" on gcc12 - return Xscratch1; //static_assert(false); + static_assert(Common::always_false_v>); } } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/address_space.cpp b/src/dynarmic/src/dynarmic/backend/arm64/address_space.cpp index 0b82f4de43..614ca03364 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/address_space.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/address_space.cpp @@ -1,14 +1,11 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD */ #include -#include -#include + +#include #include "dynarmic/backend/arm64/a64_address_space.h" #include "dynarmic/backend/arm64/a64_jitstate.h" @@ -16,7 +13,7 @@ #include "dynarmic/backend/arm64/devirtualize.h" #include "dynarmic/backend/arm64/emit_arm64.h" #include "dynarmic/backend/arm64/stack_layout.h" -#include "dynarmic/common/type_util.h" +#include "dynarmic/common/cast_util.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/llvm_disassemble.h" #include "dynarmic/interface/exclusive_monitor.h" @@ -102,7 +99,7 @@ void AddressSpace::ClearCache() { void AddressSpace::DumpDisassembly() const { for (u32* ptr = mem.ptr(); ptr < code.xptr(); ptr++) { - std::printf("%s", Common::DisassembleAArch64(*ptr, std::bit_cast(ptr)).c_str()); + std::printf("%s", Common::DisassembleAArch64(*ptr, mcl::bit_cast(ptr)).c_str()); } } @@ -319,7 +316,7 @@ void AddressSpace::RelinkForDescriptor(IR::LocationDescriptor target_descriptor, FakeCall AddressSpace::FastmemCallback(u64 host_pc) { { - const auto host_ptr = std::bit_cast(host_pc); + const auto host_ptr = mcl::bit_cast(host_pc); const auto entry_point = ReverseGetEntryPoint(host_ptr); if (!entry_point) { diff --git a/src/dynarmic/src/dynarmic/backend/arm64/devirtualize.h b/src/dynarmic/src/dynarmic/backend/arm64/devirtualize.h index 820fa1dc47..14dc3809a5 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/devirtualize.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/devirtualize.h @@ -8,8 +8,7 @@ #pragma once -#include -#include +#include #include "dynarmic/common/common_types.h" #include @@ -24,7 +23,7 @@ struct DevirtualizedCall { template DevirtualizedCall DevirtualizeWindows(mcl::class_type* this_) { static_assert(sizeof(mfp) == 8); - return DevirtualizedCall{std::bit_cast(mfp), reinterpret_cast(this_)}; + return DevirtualizedCall{mcl::bit_cast(mfp), reinterpret_cast(this_)}; } // https://github.com/ARM-software/abi-aa/blob/main/cppabi64/cppabi64.rst#representation-of-pointer-to-member-function @@ -35,16 +34,16 @@ DevirtualizedCall DevirtualizeDefault(mcl::class_type* this_) { u64 ptr; // LSB is discriminator for if function is virtual. Other bits are this adjustment. u64 adj; - } mfp_struct = std::bit_cast(mfp); + } mfp_struct = mcl::bit_cast(mfp); static_assert(sizeof(MemberFunctionPointer) == 16); static_assert(sizeof(MemberFunctionPointer) == sizeof(mfp)); u64 fn_ptr = mfp_struct.ptr; - u64 this_ptr = std::bit_cast(this_) + (mfp_struct.adj >> 1); + u64 this_ptr = mcl::bit_cast(this_) + (mfp_struct.adj >> 1); if (mfp_struct.adj & 1) { - u64 vtable = std::bit_cast(this_ptr); - fn_ptr = std::bit_cast(vtable + fn_ptr); + u64 vtable = mcl::bit_cast_pointee(this_ptr); + fn_ptr = mcl::bit_cast_pointee(vtable + fn_ptr); } return DevirtualizedCall{fn_ptr, this_ptr}; } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_a64.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_a64.cpp index 2650f1e5fc..5152a54ba2 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_a64.cpp @@ -1,13 +1,9 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD */ -#include -#include +#include #include #include "dynarmic/backend/arm64/a64_jitstate.h" @@ -499,7 +495,7 @@ template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { auto Xvalue = ctx.reg_alloc.WriteX(inst); RegAlloc::Realize(Xvalue); - code.MOV(Xscratch0, std::bit_cast(ctx.conf.tpidr_el0)); + code.MOV(Xscratch0, mcl::bit_cast(ctx.conf.tpidr_el0)); code.LDR(Xvalue, Xscratch0); } @@ -507,7 +503,7 @@ template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { auto Xvalue = ctx.reg_alloc.WriteX(inst); RegAlloc::Realize(Xvalue); - code.MOV(Xscratch0, std::bit_cast(ctx.conf.tpidrro_el0)); + code.MOV(Xscratch0, mcl::bit_cast(ctx.conf.tpidrro_el0)); code.LDR(Xvalue, Xscratch0); } @@ -516,7 +512,7 @@ void EmitIR(oaknut::CodeGenerator& code, EmitContext& c auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto Xvalue = ctx.reg_alloc.ReadX(args[0]); RegAlloc::Realize(Xvalue); - code.MOV(Xscratch0, std::bit_cast(ctx.conf.tpidr_el0)); + code.MOV(Xscratch0, mcl::bit_cast(ctx.conf.tpidr_el0)); code.STR(Xvalue, Xscratch0); } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_memory.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_memory.cpp index 58d7885d12..339e2c59a0 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_memory.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_memory.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD @@ -10,8 +7,8 @@ #include #include -#include -#include + +#include #include #include "dynarmic/backend/arm64/abi.h" @@ -551,7 +548,7 @@ void FastmemEmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::In FastmemPatchInfo{ .marker = marker, .fc = FakeCall{ - .call_pc = std::bit_cast(code.xptr()), + .call_pc = mcl::bit_cast(code.xptr()), }, .recompile = ctx.conf.recompile_on_fastmem_failure, }); @@ -601,7 +598,7 @@ void FastmemEmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::I FastmemPatchInfo{ .marker = marker, .fc = FakeCall{ - .call_pc = std::bit_cast(code.xptr()), + .call_pc = mcl::bit_cast(code.xptr()), }, .recompile = ctx.conf.recompile_on_fastmem_failure, }); diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector.cpp index faa6810ac0..e14effca3b 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD @@ -15,6 +12,7 @@ #include "dynarmic/backend/arm64/emit_context.h" #include "dynarmic/backend/arm64/fpsr_manager.h" #include "dynarmic/backend/arm64/reg_alloc.h" +#include "dynarmic/common/always_false.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/opcodes.h" @@ -45,7 +43,7 @@ static void EmitTwoOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, IR: } else if constexpr (size == 64) { emit(Qresult->D2(), Qoperand->D2()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } }); } @@ -68,7 +66,7 @@ static void EmitTwoOpArrangedWiden(oaknut::CodeGenerator& code, EmitContext& ctx } else if constexpr (size == 32) { emit(Qresult->D2(), Qoperand->toD().S2()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } }); } @@ -83,7 +81,7 @@ static void EmitTwoOpArrangedNarrow(oaknut::CodeGenerator& code, EmitContext& ct } else if constexpr (size == 64) { emit(Qresult->toD().S2(), Qoperand->D2()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } }); } @@ -106,7 +104,7 @@ static void EmitTwoOpArrangedPairWiden(oaknut::CodeGenerator& code, EmitContext& } else if constexpr (size == 32) { emit(Qresult->D2(), Qoperand->S4()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } }); } @@ -121,7 +119,7 @@ static void EmitTwoOpArrangedLower(oaknut::CodeGenerator& code, EmitContext& ctx } else if constexpr (size == 32) { emit(Qresult->toD().S2(), Qoperand->toD().S2()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } }); } @@ -149,7 +147,7 @@ static void EmitThreeOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, I } else if constexpr (size == 64) { emit(Qresult->D2(), Qa->D2(), Qb->D2()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } }); } @@ -174,7 +172,7 @@ static void EmitThreeOpArrangedWiden(oaknut::CodeGenerator& code, EmitContext& c } else if constexpr (size == 64) { emit(Qresult->Q1(), Qa->toD().D1(), Qb->toD().D1()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } }); } @@ -197,7 +195,7 @@ static void EmitThreeOpArrangedLower(oaknut::CodeGenerator& code, EmitContext& c } else if constexpr (size == 32) { emit(Qresult->toD().S2(), Qa->toD().S2(), Qb->toD().S2()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } }); } @@ -219,7 +217,7 @@ static void EmitSaturatedAccumulate(oaknut::CodeGenerator&, EmitContext& ctx, IR } else if constexpr (size == 64) { emit(Qaccumulator->D2(), Qoperand->D2()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } } @@ -240,7 +238,7 @@ static void EmitImmShift(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* ins } else if constexpr (size == 64) { emit(Qresult->D2(), Qoperand->D2(), shift_amount); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } } @@ -268,7 +266,7 @@ static void EmitReduce(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* inst, } else if constexpr (size == 64) { emit(Vresult, Qoperand->D2()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_floating_point.cpp index 3e4d5c5912..81cfc0b2db 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_floating_point.cpp @@ -6,8 +6,7 @@ * SPDX-License-Identifier: 0BSD */ -#include -#include +#include #include #include #include @@ -15,6 +14,7 @@ #include #include #include +#include #include #include "dynarmic/backend/arm64/a32_jitstate.h" @@ -24,7 +24,8 @@ #include "dynarmic/backend/arm64/emit_context.h" #include "dynarmic/backend/arm64/fpsr_manager.h" #include "dynarmic/backend/arm64/reg_alloc.h" -#include "dynarmic/common/type_util.h" +#include "dynarmic/common/always_false.h" +#include "dynarmic/common/cast_util.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/fp/info.h" @@ -83,7 +84,7 @@ static void EmitTwoOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, IR: } else if constexpr (size == 64) { emit(Qresult->D2(), Qa->D2()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } }); } @@ -111,7 +112,7 @@ static void EmitThreeOpArranged(oaknut::CodeGenerator& code, EmitContext& ctx, I } else if constexpr (size == 64) { emit(Qresult->D2(), Qa->D2(), Qb->D2()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } }); } @@ -134,7 +135,7 @@ static void EmitFMA(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* ins } else if constexpr (size == 64) { emit(Qresult->D2(), Qm->D2(), Qn->D2()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } }); } @@ -156,7 +157,7 @@ static void EmitFromFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Ins } else if constexpr (size == 64) { emit(Qto->D2(), Qfrom->D2(), fbits); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } }); } @@ -178,7 +179,7 @@ void EmitToFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) } else if constexpr (fsize == 64) { return Qto->D2(); } else { - return Qto->D2(); //static_assert(false); + static_assert(Common::always_false_v>); } }(); auto Vfrom = [&] { @@ -187,7 +188,7 @@ void EmitToFixed(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) } else if constexpr (fsize == 64) { return Qfrom->D2(); } else { - return Qfrom->D2(); //static_assert(false); + static_assert(Common::always_false_v>); } }(); @@ -270,7 +271,7 @@ static void EmitTwoOpFallbackWithoutRegAlloc(oaknut::CodeGenerator& code, EmitCo ABI_PushRegisters(code, ABI_CALLER_SAVE & ~(1ull << Qresult.index()), stack_size); - code.MOV(Xscratch0, std::bit_cast(fn)); + code.MOV(Xscratch0, mcl::bit_cast(fn)); code.ADD(X0, SP, 0 * 16); code.ADD(X1, SP, 1 * 16); code.MOV(X2, fpcr); diff --git a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_saturation.cpp b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_saturation.cpp index 0839425bd3..722a09176b 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_saturation.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_vector_saturation.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD @@ -15,6 +12,7 @@ #include "dynarmic/backend/arm64/emit_context.h" #include "dynarmic/backend/arm64/fpsr_manager.h" #include "dynarmic/backend/arm64/reg_alloc.h" +#include "dynarmic/common/always_false.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/opcodes.h" @@ -41,7 +39,7 @@ static void Emit(oaknut::CodeGenerator&, EmitContext& ctx, IR::Inst* inst, EmitF } else if constexpr (size == 64) { emit(Qresult->D2(), Qa->D2(), Qb->D2()); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } } diff --git a/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.cpp index d1d1588062..07440bd385 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/arm64/reg_alloc.cpp @@ -11,10 +11,10 @@ #include #include #include -#include -#include + #include "dynarmic/common/assert.h" #include +#include #include #include "dynarmic/common/common_types.h" @@ -22,6 +22,7 @@ #include "dynarmic/backend/arm64/emit_context.h" #include "dynarmic/backend/arm64/fpsr_manager.h" #include "dynarmic/backend/arm64/verbose_debugging_output.h" +#include "dynarmic/common/always_false.h" namespace Dynarmic::Backend::Arm64 { @@ -245,7 +246,7 @@ void RegAlloc::AssertNoMoreUses() const { } void RegAlloc::EmitVerboseDebuggingOutput() { - code.MOV(X19, std::bit_cast(&PrintVerboseDebuggingOutputLine)); // Non-volatile register + code.MOV(X19, mcl::bit_cast(&PrintVerboseDebuggingOutputLine)); // Non-volatile register const auto do_location = [&](HostLocInfo& info, HostLocType type, size_t index) { using namespace oaknut::util; @@ -300,7 +301,7 @@ int RegAlloc::GenerateImmediate(const IR::Value& value) { return 0; } else { - return 0;//static_assert(false); + static_assert(Common::always_false_v>); } } @@ -369,7 +370,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) { } else if constexpr (required_kind == HostLoc::Kind::Flags) { ASSERT_FALSE("A simple read from flags is likely a logic error."); } else { - return 0;//static_assert(false); + static_assert(Common::always_false_v>); } } @@ -394,7 +395,7 @@ int RegAlloc::RealizeWriteImpl(const IR::Inst* value) { flags.SetupLocation(value); return 0; } else { - return 0; //static_assert(false); + static_assert(Common::always_false_v>); } } @@ -415,7 +416,7 @@ int RegAlloc::RealizeReadWriteImpl(const IR::Value& read_value, const IR::Inst* } else if constexpr (kind == HostLoc::Kind::Flags) { ASSERT_FALSE("Incorrect function for ReadWrite of flags"); } else { - return write_loc; //static_assert(false); + static_assert(Common::always_false_v>); } } diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler.h b/src/dynarmic/src/dynarmic/backend/exception_handler.h index b0e2e4e372..173949628c 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler.h +++ b/src/dynarmic/src/dynarmic/backend/exception_handler.h @@ -11,17 +11,19 @@ #include #include #include + +#include #include "dynarmic/common/common_types.h" -#if defined(ARCHITECTURE_x86_64) +#if defined(MCL_ARCHITECTURE_X86_64) namespace Dynarmic::Backend::X64 { class BlockOfCode; } // namespace Dynarmic::Backend::X64 -#elif defined(ARCHITECTURE_arm64) +#elif defined(MCL_ARCHITECTURE_ARM64) namespace oaknut { class CodeBlock; } // namespace oaknut -#elif defined(ARCHITECTURE_riscv64) +#elif defined(MCL_ARCHITECTURE_RISCV) namespace Dynarmic::Backend::RV64 { class CodeBlock; } // namespace Dynarmic::Backend::RV64 @@ -31,16 +33,16 @@ class CodeBlock; namespace Dynarmic::Backend { -#if defined(ARCHITECTURE_x86_64) +#if defined(MCL_ARCHITECTURE_X86_64) struct FakeCall { u64 call_rip; u64 ret_rip; }; -#elif defined(ARCHITECTURE_arm64) +#elif defined(MCL_ARCHITECTURE_ARM64) struct FakeCall { u64 call_pc; }; -#elif defined(ARCHITECTURE_riscv64) +#elif defined(MCL_ARCHITECTURE_RISCV) struct FakeCall { }; #else @@ -52,11 +54,11 @@ public: ExceptionHandler(); ~ExceptionHandler(); -#if defined(ARCHITECTURE_x86_64) +#if defined(MCL_ARCHITECTURE_X86_64) void Register(X64::BlockOfCode& code); -#elif defined(ARCHITECTURE_arm64) +#elif defined(MCL_ARCHITECTURE_ARM64) void Register(oaknut::CodeBlock& mem, std::size_t mem_size); -#elif defined(ARCHITECTURE_riscv64) +#elif defined(MCL_ARCHITECTURE_RISCV) void Register(RV64::CodeBlock& mem, std::size_t mem_size); #else # error "Invalid architecture" diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_macos.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_macos.cpp index e1cce19ade..76e517f05b 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_macos.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_macos.cpp @@ -19,7 +19,8 @@ #include #include "dynarmic/common/assert.h" -#include +#include +#include #include "dynarmic/common/common_types.h" #include "dynarmic/backend/exception_handler.h" @@ -145,7 +146,7 @@ kern_return_t MachHandler::HandleRequest(x86_thread_state64_t* ts) { FakeCall fc = iter->cb(ts->__rip); ts->__rsp -= sizeof(u64); - *std::bit_cast(ts->__rsp) = fc.ret_rip; + *mcl::bit_cast(ts->__rsp) = fc.ret_rip; ts->__rip = fc.call_rip; return KERN_SUCCESS; @@ -270,13 +271,13 @@ ExceptionHandler::~ExceptionHandler() = default; #if defined(ARCHITECTURE_x86_64) void ExceptionHandler::Register(X64::BlockOfCode& code) { - const u64 code_begin = std::bit_cast(code.getCode()); + const u64 code_begin = mcl::bit_cast(code.getCode()); const u64 code_end = code_begin + code.GetTotalCodeSize(); impl = std::make_unique(code_begin, code_end); } #elif defined(ARCHITECTURE_arm64) void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) { - const u64 code_begin = std::bit_cast(mem.ptr()); + const u64 code_begin = mcl::bit_cast(mem.ptr()); const u64 code_end = code_begin + size; impl = std::make_unique(code_begin, code_end); } diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_macos_mig.c b/src/dynarmic/src/dynarmic/backend/exception_handler_macos_mig.c index ebbe5a079f..25678ab115 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_macos_mig.c +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_macos_mig.c @@ -3,6 +3,8 @@ * SPDX-License-Identifier: 0BSD */ +#include + #if defined(ARCHITECTURE_x86_64) # include "dynarmic/backend/x64/mig/mach_exc_server.c" #elif defined(ARCHITECTURE_arm64) diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp index d9fa71e5f6..f1f208179f 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp @@ -27,7 +27,7 @@ #else # error "Invalid architecture" #endif -#include +#include namespace Dynarmic::Backend { @@ -122,7 +122,7 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { if (auto const iter = sig_handler->FindCodeBlockInfo(CTX_RIP); iter != sig_handler->code_block_infos.end()) { FakeCall fc = iter->second.cb(CTX_RIP); CTX_RSP -= sizeof(u64); - *std::bit_cast(CTX_RSP) = fc.ret_rip; + *mcl::bit_cast(CTX_RSP) = fc.ret_rip; CTX_RIP = fc.call_rip; return; } @@ -187,17 +187,17 @@ private: ExceptionHandler::ExceptionHandler() = default; ExceptionHandler::~ExceptionHandler() = default; -#if defined(ARCHITECTURE_x86_64) +#if defined(MCL_ARCHITECTURE_X86_64) void ExceptionHandler::Register(X64::BlockOfCode& code) { - impl = std::make_unique(std::bit_cast(code.getCode()), code.GetTotalCodeSize()); + impl = std::make_unique(mcl::bit_cast(code.getCode()), code.GetTotalCodeSize()); } -#elif defined(ARCHITECTURE_arm64) +#elif defined(MCL_ARCHITECTURE_ARM64) void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) { - impl = std::make_unique(std::bit_cast(mem.ptr()), size); + impl = std::make_unique(mcl::bit_cast(mem.ptr()), size); } -#elif defined(ARCHITECTURE_riscv64) +#elif defined(MCL_ARCHITECTURE_RISCV) void ExceptionHandler::Register(RV64::CodeBlock& mem, std::size_t size) { - impl = std::make_unique(std::bit_cast(mem.ptr()), size); + impl = std::make_unique(mcl::bit_cast(mem.ptr()), size); } #else # error "Invalid architecture" diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_windows.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_windows.cpp index 332a7cbe07..58a3325e17 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_windows.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_windows.cpp @@ -6,6 +6,8 @@ * SPDX-License-Identifier: 0BSD */ +#include + #if defined(ARCHITECTURE_x86_64) # include "dynarmic/backend/x64/exception_handler_windows.cpp" #elif defined(ARCHITECTURE_arm64) diff --git a/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.cpp index b0128d6202..e09bd696b8 100644 --- a/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/riscv64/reg_alloc.cpp @@ -15,6 +15,7 @@ #include #include "dynarmic/common/common_types.h" +#include "dynarmic/common/always_false.h" namespace Dynarmic::Backend::RV64 { @@ -163,7 +164,7 @@ u32 RegAlloc::GenerateImmediate(const IR::Value& value) { } else if constexpr (kind == HostLoc::Kind::Fpr) { UNIMPLEMENTED(); } else { - //static_assert(false); + static_assert(Common::always_false_v>); } return 0; @@ -226,7 +227,7 @@ u32 RegAlloc::RealizeReadImpl(const IR::Value& value) { fprs[new_location_index].realized = true; return new_location_index; } else { - return 0; //static_assert(false); + static_assert(Common::always_false_v>); } } @@ -253,7 +254,7 @@ u32 RegAlloc::RealizeWriteImpl(const IR::Inst* value) { setup_location(fprs[new_location_index]); return new_location_index; } else { - return 0;//static_assert(false); + static_assert(Common::always_false_v>); } } diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp index 92f5cae602..a1fca21f47 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64_memory.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD @@ -13,6 +10,7 @@ #include #include +#include #include #include "dynarmic/backend/x64/a32_emit_x64.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp index f87cfb438e..382eb70f3f 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp @@ -9,12 +9,11 @@ #include #include #include -#include #include #include #include "dynarmic/common/assert.h" -#include +#include #include #include "dynarmic/common/common_types.h" @@ -48,7 +47,7 @@ static RunCodeCallbacks GenRunCodeCallbacks(A32::UserCallbacks* cb, CodePtr (*Lo static std::function GenRCP(const A32::UserConfig& conf) { return [conf](BlockOfCode& code) { if (conf.page_table) { - code.mov(code.r14, std::bit_cast(conf.page_table)); + code.mov(code.r14, mcl::bit_cast(conf.page_table)); } if (conf.fastmem_pointer) { code.mov(code.r13, *conf.fastmem_pointer); diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp index e897cef7cb..b5da18701c 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp @@ -13,6 +13,7 @@ #include "dynarmic/common/assert.h" #include #include "dynarmic/common/common_types.h" +#include #include #include "dynarmic/backend/x64/a64_jitstate.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp index fc0cd8c1f3..8fd6777542 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64_memory.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD @@ -13,6 +10,7 @@ #include #include +#include #include #include "dynarmic/backend/x64/a64_emit_x64.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp index baa5071328..c65b582982 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp @@ -9,11 +9,10 @@ #include #include #include -#include #include #include "dynarmic/common/assert.h" -#include +#include #include #include "dynarmic/backend/x64/a64_emit_x64.h" @@ -44,7 +43,7 @@ static RunCodeCallbacks GenRunCodeCallbacks(A64::UserCallbacks* cb, CodePtr (*Lo static std::function GenRCP(const A64::UserConfig& conf) { return [conf](BlockOfCode& code) { if (conf.page_table) { - code.mov(code.r14, std::bit_cast(conf.page_table)); + code.mov(code.r14, mcl::bit_cast(conf.page_table)); } if (conf.fastmem_pointer) { code.mov(code.r13, *conf.fastmem_pointer); diff --git a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h index 42e5fb0982..095e75336b 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h +++ b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.h @@ -23,7 +23,7 @@ #include "dynarmic/backend/x64/constant_pool.h" #include "dynarmic/backend/x64/host_feature.h" #include "dynarmic/backend/x64/jitstate_info.h" -#include "dynarmic/common/type_util.h" +#include "dynarmic/common/cast_util.h" #include "dynarmic/interface/halt_reason.h" #include "dynarmic/ir/cond.h" diff --git a/src/dynarmic/src/dynarmic/backend/x64/devirtualize.h b/src/dynarmic/src/dynarmic/backend/x64/devirtualize.h index 428ea749fa..318a702194 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/devirtualize.h +++ b/src/dynarmic/src/dynarmic/backend/x64/devirtualize.h @@ -10,8 +10,8 @@ #include #include -#include -#include + +#include #include "dynarmic/common/common_types.h" #include @@ -42,7 +42,7 @@ ArgCallback DevirtualizeGeneric(mcl::class_type* this_) { template ArgCallback DevirtualizeWindows(mcl::class_type* this_) { static_assert(sizeof(mfp) == 8); - return ArgCallback{std::bit_cast(mfp), reinterpret_cast(this_)}; + return ArgCallback{mcl::bit_cast(mfp), reinterpret_cast(this_)}; } template @@ -53,7 +53,7 @@ ArgCallback DevirtualizeItanium(mcl::class_type* this_) { u64 ptr; /// The required adjustment to `this`, prior to the call. u64 adj; - } mfp_struct = std::bit_cast(mfp); + } mfp_struct = mcl::bit_cast(mfp); static_assert(sizeof(MemberFunctionPointer) == 16); static_assert(sizeof(MemberFunctionPointer) == sizeof(mfp)); @@ -61,8 +61,8 @@ ArgCallback DevirtualizeItanium(mcl::class_type* this_) { u64 fn_ptr = mfp_struct.ptr; u64 this_ptr = reinterpret_cast(this_) + mfp_struct.adj; if (mfp_struct.ptr & 1) { - u64 vtable = std::bit_cast(this_ptr); - fn_ptr = std::bit_cast(vtable + fn_ptr - 1); + u64 vtable = mcl::bit_cast_pointee(this_ptr); + fn_ptr = mcl::bit_cast_pointee(vtable + fn_ptr - 1); } return ArgCallback{fn_ptr, this_ptr}; } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp index 5d03697882..a2fe4001a9 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp @@ -18,13 +18,14 @@ #include #include #include "dynarmic/common/common_types.h" +#include #include #include "dynarmic/backend/x64/abi.h" #include "dynarmic/backend/x64/block_of_code.h" #include "dynarmic/backend/x64/constants.h" #include "dynarmic/backend/x64/emit_x64.h" -#include "dynarmic/common/type_util.h" +#include "dynarmic/common/cast_util.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/fp/info.h" @@ -35,8 +36,22 @@ #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/microinstruction.h" -#define FCODE(NAME) [&](auto... args) { if (fsize == 32) code.NAME##s(args...); else code.NAME##d(args...); } -#define ICODE(NAME) [&](auto... args) { if (fsize == 32) code.NAME##d(args...); else code.NAME##q(args...); } +#define FCODE(NAME) \ + [&code](auto... args) { \ + if constexpr (fsize == 32) { \ + code.NAME##s(args...); \ + } else { \ + code.NAME##d(args...); \ + } \ + } +#define ICODE(NAME) \ + [&code](auto... args) { \ + if constexpr (fsize == 32) { \ + code.NAME##d(args...); \ + } else { \ + code.NAME##q(args...); \ + } \ + } namespace Dynarmic::Backend::X64 { @@ -90,7 +105,7 @@ void ForceDenormalsToZero(BlockOfCode& code, std::initializer_list t for (const Xbyak::Xmm& xmm : to_daz) { code.movaps(xmm0, code.Const(xword, fsize == 32 ? f32_non_sign_mask : f64_non_sign_mask)); code.andps(xmm0, xmm); - if (fsize == 32) { + if constexpr (fsize == 32) { code.pcmpgtd(xmm0, code.Const(xword, f32_smallest_normal - 1)); } else if (code.HasHostFeature(HostFeature::SSE42)) { code.pcmpgtq(xmm0, code.Const(xword, f64_smallest_normal - 1)); @@ -105,11 +120,13 @@ void ForceDenormalsToZero(BlockOfCode& code, std::initializer_list t template void DenormalsAreZero(BlockOfCode& code, EmitContext& ctx, std::initializer_list to_daz) { - if (ctx.FPCR().FZ()) + if (ctx.FPCR().FZ()) { ForceDenormalsToZero(code, to_daz); + } } -void ZeroIfNaN(BlockOfCode& code, Xbyak::Xmm xmm_value, Xbyak::Xmm xmm_scratch, size_t fsize) { +template +void ZeroIfNaN(BlockOfCode& code, Xbyak::Xmm xmm_value, Xbyak::Xmm xmm_scratch) { if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) { constexpr u32 nan_to_zero = FixupLUT(FpFixup::PosZero, FpFixup::PosZero); @@ -124,7 +141,8 @@ void ZeroIfNaN(BlockOfCode& code, Xbyak::Xmm xmm_value, Xbyak::Xmm xmm_scratch, } } -void ForceToDefaultNaN(BlockOfCode& code, Xbyak::Xmm result, size_t fsize) { +template +void ForceToDefaultNaN(BlockOfCode& code, Xbyak::Xmm result) { if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) { const Xbyak::Opmask nan_mask = k1; FCODE(vfpclasss)(nan_mask, result, u8(FpClass::QNaN | FpClass::SNaN)); @@ -190,7 +208,7 @@ void PostProcessNaN(BlockOfCode& code, Xbyak::Xmm result, Xbyak::Xmm tmp) { // We allow for the case where op1 and result are the same register. We do not read from op1 once result is written to. template void EmitPostProcessNaNs(BlockOfCode& code, Xbyak::Xmm result, Xbyak::Xmm op1, Xbyak::Xmm op2, Xbyak::Reg64 tmp, Xbyak::Label end) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; constexpr FPT exponent_mask = FP::FPInfo::exponent_mask; constexpr FPT mantissa_msb = FP::FPInfo::mantissa_msb; constexpr u8 mantissa_msb_bit = static_cast(FP::FPInfo::explicit_mantissa_width - 1); @@ -218,7 +236,7 @@ void EmitPostProcessNaNs(BlockOfCode& code, Xbyak::Xmm result, Xbyak::Xmm op1, X } constexpr size_t shift = fsize == 32 ? 0 : 48; - if (fsize == 32) { + if constexpr (fsize == 32) { code.movd(tmp.cvt32(), xmm0); } else { // We do this to avoid requiring 64-bit immediates @@ -234,7 +252,7 @@ void EmitPostProcessNaNs(BlockOfCode& code, Xbyak::Xmm result, Xbyak::Xmm op1, X // op1 == QNaN && op2 == SNaN <<< The problematic case // op1 == QNaN && op2 == Inf - if (fsize == 32) { + if constexpr (fsize == 32) { code.movd(tmp.cvt32(), op2); code.shl(tmp.cvt32(), 32 - mantissa_msb_bit); } else { @@ -273,7 +291,7 @@ void FPTwoOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) { if (ctx.HasOptimization(OptimizationFlag::Unsafe_InaccurateNaN)) { // Do nothing } else if (ctx.FPCR().DN()) { - ForceToDefaultNaN(code, result, fsize); + ForceToDefaultNaN(code, result); } else { PostProcessNaN(code, result, xmm0); } @@ -284,7 +302,7 @@ void FPTwoOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) { template void FPThreeOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -299,7 +317,7 @@ void FPThreeOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) } if (!ctx.HasOptimization(OptimizationFlag::Unsafe_InaccurateNaN)) { - ForceToDefaultNaN(code, result, fsize); + ForceToDefaultNaN(code, result); } ctx.reg_alloc.DefineValue(inst, result); @@ -343,7 +361,7 @@ void FPThreeOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) template void FPAbs(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; constexpr FPT non_sign_mask = FP::FPInfo::sign_mask - FPT(1u); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -369,7 +387,7 @@ void EmitX64::EmitFPAbs64(EmitContext& ctx, IR::Inst* inst) { template void FPNeg(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; constexpr FPT sign_mask = FP::FPInfo::sign_mask; auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -424,7 +442,7 @@ static void EmitFPMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { FCODE(ucomis)(result, operand); code.jz(*equal, code.T_NEAR); - if (is_max) { + if constexpr (is_max) { FCODE(maxs)(result, operand); } else { FCODE(mins)(result, operand); @@ -436,7 +454,7 @@ static void EmitFPMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { code.L(*equal); code.jp(nan); - if (is_max) { + if constexpr (is_max) { code.andps(result, operand); } else { code.orps(result, operand); @@ -459,7 +477,7 @@ static void EmitFPMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { template static inline void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) noexcept { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; constexpr FPT default_nan = FP::FPInfo::DefaultNaN(); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -484,7 +502,7 @@ static inline void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR:: tmp.setBit(fsize); const auto move_to_tmp = [=, &code](const Xbyak::Xmm& xmm) { - if (fsize == 32) { + if constexpr (fsize == 32) { code.movd(tmp.cvt32(), xmm); } else { code.movq(tmp.cvt64(), xmm); @@ -495,7 +513,7 @@ static inline void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR:: FCODE(ucomis)(op1, op2); code.jz(*z, code.T_NEAR); - if (is_max) { + if constexpr (is_max) { FCODE(maxs)(op2, op1); } else { FCODE(mins)(op2, op1); @@ -509,7 +527,7 @@ static inline void EmitFPMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR:: code.L(*z); code.jp(nan); - if (is_max) { + if constexpr (is_max) { code.andps(op2, op1); } else { code.orps(op2, op1); @@ -611,12 +629,12 @@ void EmitX64::EmitFPMul64(EmitContext& ctx, IR::Inst* inst) { template static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; const auto fallback_fn = negate_product ? &FP::FPMulSub : &FP::FPMulAdd; auto args = ctx.reg_alloc.GetArgumentInfo(inst); - if (fsize != 16) { + if constexpr (fsize != 16) { const bool needs_rounding_correction = ctx.FPCR().FZ(); const bool needs_nan_correction = !ctx.FPCR().DN(); @@ -625,13 +643,13 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { const Xbyak::Xmm operand2 = ctx.reg_alloc.UseXmm(args[1]); const Xbyak::Xmm operand3 = ctx.reg_alloc.UseXmm(args[2]); - if (negate_product) { + if constexpr (negate_product) { FCODE(vfnmadd231s)(result, operand2, operand3); } else { FCODE(vfmadd231s)(result, operand2, operand3); } if (ctx.FPCR().DN()) { - ForceToDefaultNaN(code, result, fsize); + ForceToDefaultNaN(code, result); } ctx.reg_alloc.DefineValue(inst, result); @@ -647,7 +665,7 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); code.movaps(result, operand1); - if (negate_product) { + if constexpr (negate_product) { FCODE(vfnmadd231s)(result, operand2, operand3); } else { FCODE(vfmadd231s)(result, operand2, operand3); @@ -668,8 +686,9 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { } else { UNREACHABLE(); } - if (ctx.FPCR().DN()) - ForceToDefaultNaN(code, result, fsize); + if (ctx.FPCR().DN()) { + ForceToDefaultNaN(code, result); + } code.L(*end); ctx.deferred_emits.emplace_back([=, &code, &ctx] { @@ -750,7 +769,7 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { code.ptest(operand2, xmm0); code.jnz(op2_done); code.vorps(result, operand2, xmm0); - if (negate_product) { + if constexpr (negate_product) { code.xorps(result, code.Const(xword, FP::FPInfo::sign_mask)); } code.jmp(*end); @@ -766,7 +785,7 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { // at this point, all SNaNs have been handled // if op1 was not a QNaN and op2 is, negate the result - if (negate_product) { + if constexpr (negate_product) { FCODE(ucomis)(operand1, operand1); code.jp(*end); FCODE(ucomis)(operand2, operand2); @@ -787,7 +806,7 @@ static void EmitFPMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { const Xbyak::Xmm operand2 = ctx.reg_alloc.UseScratchXmm(args[1]); const Xbyak::Xmm operand3 = ctx.reg_alloc.UseXmm(args[2]); - if (negate_product) { + if constexpr (negate_product) { code.xorps(operand2, code.Const(xword, FP::FPInfo::sign_mask)); } FCODE(muls)(operand2, operand3); @@ -838,7 +857,7 @@ void EmitX64::EmitFPMulSub64(EmitContext& ctx, IR::Inst* inst) { template static void EmitFPMulX(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -898,9 +917,9 @@ void EmitX64::EmitFPMulX64(EmitContext& ctx, IR::Inst* inst) { template static void EmitFPRecipEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; - if (fsize != 16) { + if constexpr (fsize != 16) { if (ctx.HasOptimization(OptimizationFlag::Unsafe_ReducedErrorFP)) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); const Xbyak::Xmm operand = ctx.reg_alloc.UseXmm(args[0]); @@ -909,7 +928,7 @@ static void EmitFPRecipEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) { FCODE(vrcp14s)(result, operand, operand); } else { - if (fsize == 32) { + if constexpr (fsize == 32) { code.rcpss(result, operand); } else { code.cvtsd2ss(result, operand); @@ -944,7 +963,7 @@ void EmitX64::EmitFPRecipEstimate64(EmitContext& ctx, IR::Inst* inst) { template static void EmitFPRecipExponent(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.HostCall(inst, args[0]); @@ -967,11 +986,11 @@ void EmitX64::EmitFPRecipExponent64(EmitContext& ctx, IR::Inst* inst) { template static void EmitFPRecipStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; auto args = ctx.reg_alloc.GetArgumentInfo(inst); - if (fsize != 16) { + if constexpr (fsize != 16) { if (code.HasHostFeature(HostFeature::FMA) && ctx.HasOptimization(OptimizationFlag::Unsafe_InaccurateNaN)) { Xbyak::Label end, fallback; @@ -1104,9 +1123,9 @@ void EmitX64::EmitFPRoundInt64(EmitContext& ctx, IR::Inst* inst) { template static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; - if (fsize != 16) { + if constexpr (fsize != 16) { if (ctx.HasOptimization(OptimizationFlag::Unsafe_ReducedErrorFP)) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); const Xbyak::Xmm operand = ctx.reg_alloc.UseXmm(args[0]); @@ -1115,7 +1134,7 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) { FCODE(vrsqrt14s)(result, operand, operand); } else { - if (fsize == 32) { + if constexpr (fsize == 32) { code.rsqrtss(result, operand); } else { code.cvtsd2ss(result, operand); @@ -1161,7 +1180,7 @@ static void EmitFPRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* i bool needs_fallback = false; code.L(*bad_values); - if (fsize == 32) { + if constexpr (fsize == 32) { code.movd(tmp, operand); if (!ctx.FPCR().FZ()) { @@ -1283,11 +1302,11 @@ void EmitX64::EmitFPRSqrtEstimate64(EmitContext& ctx, IR::Inst* inst) { template static void EmitFPRSqrtStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; auto args = ctx.reg_alloc.GetArgumentInfo(inst); - if (fsize != 16) { + if constexpr (fsize != 16) { if (code.HasHostFeature(HostFeature::FMA | HostFeature::AVX) && ctx.HasOptimization(OptimizationFlag::Unsafe_InaccurateNaN)) { const Xbyak::Xmm operand1 = ctx.reg_alloc.UseXmm(args[0]); const Xbyak::Xmm operand2 = ctx.reg_alloc.UseXmm(args[1]); @@ -1466,8 +1485,9 @@ void EmitX64::EmitFPHalfToDouble(EmitContext& ctx, IR::Inst* inst) { // Double-conversion here is acceptable as this is expanding precision. code.vcvtph2ps(result, value); code.vcvtps2pd(result, result); - if (ctx.FPCR().DN()) - ForceToDefaultNaN(code, result, 64); + if (ctx.FPCR().DN()) { + ForceToDefaultNaN<64>(code, result); + } ctx.reg_alloc.DefineValue(inst, result); return; @@ -1489,8 +1509,9 @@ void EmitX64::EmitFPHalfToSingle(EmitContext& ctx, IR::Inst* inst) { const Xbyak::Xmm value = ctx.reg_alloc.UseXmm(args[0]); code.vcvtph2ps(result, value); - if (ctx.FPCR().DN()) - ForceToDefaultNaN(code, result, 32); + if (ctx.FPCR().DN()) { + ForceToDefaultNaN<32>(code, result); + } ctx.reg_alloc.DefineValue(inst, result); return; @@ -1498,22 +1519,23 @@ void EmitX64::EmitFPHalfToSingle(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(inst, args[0]); code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value()); - code.mov(code.ABI_PARAM3.cvt32(), u32(rounding_mode)); + code.mov(code.ABI_PARAM3.cvt32(), static_cast(rounding_mode)); code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPConvert); } void EmitX64::EmitFPSingleToDouble(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const auto rounding_mode = FP::RoundingMode(args[1].GetImmediateU8()); + const auto rounding_mode = static_cast(args[1].GetImmediateU8()); // We special-case the non-IEEE-defined ToOdd rounding mode. if (rounding_mode == ctx.FPCR().RMode() && rounding_mode != FP::RoundingMode::ToOdd) { const Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); code.cvtss2sd(result, result); - if (ctx.FPCR().DN()) - ForceToDefaultNaN(code, result, 64); + if (ctx.FPCR().DN()) { + ForceToDefaultNaN<64>(code, result); + } ctx.reg_alloc.DefineValue(inst, result); } else { ctx.reg_alloc.HostCall(inst, args[0]); @@ -1531,9 +1553,12 @@ void EmitX64::EmitFPSingleToHalf(EmitContext& ctx, IR::Inst* inst) { if (code.HasHostFeature(HostFeature::F16C) && !ctx.FPCR().AHP() && !ctx.FPCR().FZ16()) { const Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); - if (ctx.FPCR().DN()) - ForceToDefaultNaN(code, result, 32); - code.vcvtps2ph(result, result, u8(*round_imm)); + + if (ctx.FPCR().DN()) { + ForceToDefaultNaN<32>(code, result); + } + code.vcvtps2ph(result, result, static_cast(*round_imm)); + ctx.reg_alloc.DefineValue(inst, result); return; } @@ -1561,18 +1586,21 @@ void EmitX64::EmitFPDoubleToHalf(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPDoubleToSingle(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); - const auto rounding_mode = FP::RoundingMode(args[1].GetImmediateU8()); + const auto rounding_mode = static_cast(args[1].GetImmediateU8()); + // We special-case the non-IEEE-defined ToOdd rounding mode. if (rounding_mode == ctx.FPCR().RMode() && rounding_mode != FP::RoundingMode::ToOdd) { const Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); + code.cvtsd2ss(result, result); - if (ctx.FPCR().DN()) - ForceToDefaultNaN(code, result, 32); + if (ctx.FPCR().DN()) { + ForceToDefaultNaN<32>(code, result); + } ctx.reg_alloc.DefineValue(inst, result); } else { ctx.reg_alloc.HostCall(inst, args[0]); code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value()); - code.mov(code.ABI_PARAM3.cvt32(), u32(rounding_mode)); + code.mov(code.ABI_PARAM3.cvt32(), static_cast(rounding_mode)); code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]); code.CallFunction(&FP::FPConvert); } @@ -1587,7 +1615,7 @@ void EmitX64::EmitFPDoubleToSingle(EmitContext& ctx, IR::Inst* inst) { /// Better than spamming thousands of templates aye? template static u64 EmitFPToFixedThunk(u64 input, FP::FPSR& fpsr, FP::FPCR fpcr, u32 extra_args) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; auto const unsigned_ = ((extra_args >> 24) & 0xff) != 0; auto const isize = ((extra_args >> 16) & 0xff); auto const rounding = FP::RoundingMode((extra_args >> 8) & 0xff); @@ -1602,7 +1630,7 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { const size_t fbits = args[1].GetImmediateU8(); const auto rounding_mode = FP::RoundingMode(args[2].GetImmediateU8()); - if (fsize != 16) { + if constexpr (fsize != 16) { const auto round_imm = ConvertRoundingModeToX64Immediate(rounding_mode); // cvttsd2si truncates during operation so rounding (and thus SSE4.1) not required @@ -1612,7 +1640,7 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { const Xbyak::Xmm src = ctx.reg_alloc.UseScratchXmm(args[0]); const Xbyak::Reg64 result = ctx.reg_alloc.ScratchGpr().cvt64(); - if (fsize == 64) { + if constexpr (fsize == 64) { if (fbits != 0) { const u64 scale_factor = static_cast((fbits + 1023) << 52); code.mulsd(src, code.Const(xword, scale_factor)); @@ -1634,13 +1662,13 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { code.cvtss2sd(src, src); } - if (isize == 64) { + if constexpr (isize == 64) { const Xbyak::Xmm scratch = ctx.reg_alloc.ScratchXmm(); if (!unsigned_) { SharedLabel saturate_max = GenSharedLabel(), end = GenSharedLabel(); - ZeroIfNaN(code, src, scratch, 64); + ZeroIfNaN<64>(code, src, scratch); code.movsd(scratch, code.Const(xword, f64_max_s64_lim)); code.comisd(scratch, src); @@ -1678,11 +1706,11 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { code.sar(result2, 63); code.or_(result, result2); } - } else if (isize == 32) { + } else if constexpr (isize == 32) { if (!unsigned_) { const Xbyak::Xmm scratch = ctx.reg_alloc.ScratchXmm(); - ZeroIfNaN(code, src, scratch, 64); + ZeroIfNaN<64>(code, src, scratch); code.minsd(src, code.Const(xword, f64_max_s32)); // maxsd not required as cvttsd2si results in 0x8000'0000 when out of range code.cvttsd2si(result.cvt32(), src); // 32 bit gpr @@ -1695,7 +1723,7 @@ static void EmitFPToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { } else { const Xbyak::Xmm scratch = ctx.reg_alloc.ScratchXmm(); - ZeroIfNaN(code, src, scratch, 64); + ZeroIfNaN<64>(code, src, scratch); code.maxsd(src, code.Const(xword, unsigned_ ? f64_min_u16 : f64_min_s16)); code.minsd(src, code.Const(xword, unsigned_ ? f64_max_u16 : f64_max_s16)); code.cvttsd2si(result, src); // 64 bit gpr diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc index 3d6a64148a..34f77b0446 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.cpp.inc @@ -4,7 +4,6 @@ */ #include -#include "dynarmic/common/type_util.h" #define AxxEmitX64 CONCATENATE_TOKENS(Axx, EmitX64) #define AxxEmitContext CONCATENATE_TOKENS(Axx, EmitContext) @@ -16,11 +15,14 @@ using Vector = std::array; } std::optional AxxEmitX64::ShouldFastmem(AxxEmitContext& ctx, IR::Inst* inst) const { - if (!conf.fastmem_pointer || !exception_handler.SupportsFastmem()) + if (!conf.fastmem_pointer || !exception_handler.SupportsFastmem()) { return std::nullopt; + } + const auto marker = std::make_tuple(ctx.Location(), inst->GetName()); - if (do_not_fastmem.count(marker) > 0) + if (do_not_fastmem.count(marker) > 0) { return std::nullopt; + } return marker; } @@ -56,12 +58,16 @@ void AxxEmitX64::EmitMemoryRead(AxxEmitContext& ctx, IR::Inst* inst) { // Neither fastmem nor page table: Use callbacks if constexpr (bitsize == 128) { ctx.reg_alloc.HostCall(nullptr, {}, args[1]); - if (ordered) code.mfence(); + if (ordered) { + code.mfence(); + } code.CallFunction(memory_read_128); ctx.reg_alloc.DefineValue(inst, xmm1); } else { ctx.reg_alloc.HostCall(inst, {}, args[1]); - if (ordered) code.mfence(); + if (ordered) { + code.mfence(); + } Devirtualize(conf.callbacks).EmitCall(code); code.ZeroExtendFrom(bitsize, code.ABI_RETURN); } @@ -96,10 +102,10 @@ void AxxEmitX64::EmitMemoryRead(AxxEmitContext& ctx, IR::Inst* inst) { code.call(wrapped_fn); fastmem_patch_info.emplace( - std::bit_cast(location), + mcl::bit_cast(location), FastmemPatchInfo{ - std::bit_cast(code.getCurr()), - std::bit_cast(wrapped_fn), + mcl::bit_cast(code.getCurr()), + mcl::bit_cast(wrapped_fn), *fastmem_marker, conf.recompile_on_fastmem_failure, }); @@ -147,7 +153,9 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.HostCall(nullptr, {}, args[1], args[2]); Devirtualize(conf.callbacks).EmitCall(code); } - if (ordered) code.mfence(); + if (ordered) { + code.mfence(); + } EmitCheckMemoryAbort(ctx, inst); return; } @@ -181,10 +189,10 @@ void AxxEmitX64::EmitMemoryWrite(AxxEmitContext& ctx, IR::Inst* inst) { code.call(wrapped_fn); fastmem_patch_info.emplace( - std::bit_cast(location), + mcl::bit_cast(location), FastmemPatchInfo{ - std::bit_cast(code.getCurr()), - std::bit_cast(wrapped_fn), + mcl::bit_cast(code.getCurr()), + mcl::bit_cast(wrapped_fn), *fastmem_marker, conf.recompile_on_fastmem_failure, }); @@ -215,7 +223,7 @@ void AxxEmitX64::EmitExclusiveReadMemory(AxxEmitContext& ctx, IR::Inst* inst) { const bool ordered = IsOrdered(args[2].GetImmediateAccType()); if constexpr (bitsize != 128) { - using T = Common::UnsignedIntegerN; + using T = mcl::unsigned_integer_of_size; ctx.reg_alloc.HostCall(inst, {}, args[1]); @@ -282,14 +290,16 @@ void AxxEmitX64::EmitExclusiveWriteMemory(AxxEmitContext& ctx, IR::Inst* inst) { code.mov(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(0)); code.mov(code.ABI_PARAM1, reinterpret_cast(&conf)); if constexpr (bitsize != 128) { - using T = Common::UnsignedIntegerN; + using T = mcl::unsigned_integer_of_size; code.CallLambda( [](AxxUserConfig& conf, Axx::VAddr vaddr, T value) -> u32 { return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, - [&](T expected) -> bool { - return (conf.callbacks->*callback)(vaddr, value, expected); - }) ? 0 : 1; + [&](T expected) -> bool { + return (conf.callbacks->*callback)(vaddr, value, expected); + }) + ? 0 + : 1; }); if (ordered) { code.mfence(); @@ -301,9 +311,11 @@ void AxxEmitX64::EmitExclusiveWriteMemory(AxxEmitContext& ctx, IR::Inst* inst) { code.CallLambda( [](AxxUserConfig& conf, Axx::VAddr vaddr, Vector& value) -> u32 { return conf.global_monitor->DoExclusiveOperation(conf.processor_id, vaddr, - [&](Vector expected) -> bool { - return (conf.callbacks->*callback)(vaddr, value, expected); - }) ? 0 : 1; + [&](Vector expected) -> bool { + return (conf.callbacks->*callback)(vaddr, value, expected); + }) + ? 0 + : 1; }); if (ordered) { code.mfence(); @@ -344,7 +356,7 @@ void AxxEmitX64::EmitExclusiveReadMemoryInline(AxxEmitContext& ctx, IR::Inst* in EmitExclusiveLock(code, conf, tmp, tmp2.cvt32()); code.mov(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(1)); - code.mov(tmp, std::bit_cast(GetExclusiveMonitorAddressPointer(conf.global_monitor, conf.processor_id))); + code.mov(tmp, mcl::bit_cast(GetExclusiveMonitorAddressPointer(conf.global_monitor, conf.processor_id))); code.mov(qword[tmp], vaddr); const auto fastmem_marker = ShouldFastmem(ctx, inst); @@ -357,10 +369,10 @@ void AxxEmitX64::EmitExclusiveReadMemoryInline(AxxEmitContext& ctx, IR::Inst* in const auto location = EmitReadMemoryMov(code, value_idx, src_ptr, ordered); fastmem_patch_info.emplace( - std::bit_cast(location), + mcl::bit_cast(location), FastmemPatchInfo{ - std::bit_cast(code.getCurr()), - std::bit_cast(wrapped_fn), + mcl::bit_cast(code.getCurr()), + mcl::bit_cast(wrapped_fn), *fastmem_marker, conf.recompile_on_exclusive_fastmem_failure, }); @@ -378,7 +390,7 @@ void AxxEmitX64::EmitExclusiveReadMemoryInline(AxxEmitContext& ctx, IR::Inst* in code.call(wrapped_fn); } - code.mov(tmp, std::bit_cast(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id))); + code.mov(tmp, mcl::bit_cast(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id))); EmitWriteMemoryMov(code, tmp, value_idx, false); EmitExclusiveUnlock(code, conf, tmp, tmp2.cvt32()); @@ -425,7 +437,7 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i SharedLabel end = GenSharedLabel(); - code.mov(tmp, std::bit_cast(GetExclusiveMonitorAddressPointer(conf.global_monitor, conf.processor_id))); + code.mov(tmp, mcl::bit_cast(GetExclusiveMonitorAddressPointer(conf.global_monitor, conf.processor_id))); code.mov(status, u32(1)); code.cmp(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(0)); code.je(*end, code.T_NEAR); @@ -435,7 +447,7 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i EmitExclusiveTestAndClear(code, conf, vaddr, tmp, rax); code.mov(code.byte[code.ABI_JIT_PTR + offsetof(AxxJitState, exclusive_state)], u8(0)); - code.mov(tmp, std::bit_cast(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id))); + code.mov(tmp, mcl::bit_cast(GetExclusiveMonitorValuePointer(conf.global_monitor, conf.processor_id))); if constexpr (bitsize == 128) { code.mov(rax, qword[tmp + 0]); @@ -463,20 +475,25 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i const auto location = code.getCurr(); if constexpr (bitsize == 128) { - code.lock(); code.cmpxchg16b(ptr[dest_ptr]); + code.lock(); + code.cmpxchg16b(ptr[dest_ptr]); } else { switch (bitsize) { case 8: - code.lock(); code.cmpxchg(code.byte[dest_ptr], value.cvt8()); + code.lock(); + code.cmpxchg(code.byte[dest_ptr], value.cvt8()); break; case 16: - code.lock(); code.cmpxchg(word[dest_ptr], value.cvt16()); + code.lock(); + code.cmpxchg(word[dest_ptr], value.cvt16()); break; case 32: - code.lock(); code.cmpxchg(dword[dest_ptr], value.cvt32()); + code.lock(); + code.cmpxchg(dword[dest_ptr], value.cvt32()); break; case 64: - code.lock(); code.cmpxchg(qword[dest_ptr], value.cvt64()); + code.lock(); + code.cmpxchg(qword[dest_ptr], value.cvt64()); break; default: UNREACHABLE(); @@ -489,10 +506,10 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i code.call(wrapped_fn); fastmem_patch_info.emplace( - std::bit_cast(location), + mcl::bit_cast(location), FastmemPatchInfo{ - std::bit_cast(code.getCurr()), - std::bit_cast(wrapped_fn), + mcl::bit_cast(code.getCurr()), + mcl::bit_cast(wrapped_fn), *fastmem_marker, conf.recompile_on_exclusive_fastmem_failure, }); diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h index 4fc006ec4c..75a47c6a80 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_memory.h @@ -1,13 +1,9 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD */ -#include -#include +#include #include #include "dynarmic/backend/x64/a32_emit_x64.h" @@ -346,7 +342,7 @@ void EmitExclusiveLock(BlockOfCode& code, const UserConfig& conf, Xbyak::Reg64 p return; } - code.mov(pointer, std::bit_cast(GetExclusiveMonitorLockPointer(conf.global_monitor))); + code.mov(pointer, mcl::bit_cast(GetExclusiveMonitorLockPointer(conf.global_monitor))); EmitSpinLockLock(code, pointer, tmp); } @@ -356,7 +352,7 @@ void EmitExclusiveUnlock(BlockOfCode& code, const UserConfig& conf, Xbyak::Reg64 return; } - code.mov(pointer, std::bit_cast(GetExclusiveMonitorLockPointer(conf.global_monitor))); + code.mov(pointer, mcl::bit_cast(GetExclusiveMonitorLockPointer(conf.global_monitor))); EmitSpinLockUnlock(code, pointer, tmp); } @@ -373,7 +369,7 @@ void EmitExclusiveTestAndClear(BlockOfCode& code, const UserConfig& conf, Xbyak: continue; } Xbyak::Label ok; - code.mov(pointer, std::bit_cast(GetExclusiveMonitorAddressPointer(conf.global_monitor, processor_index))); + code.mov(pointer, mcl::bit_cast(GetExclusiveMonitorAddressPointer(conf.global_monitor, processor_index))); code.cmp(qword[pointer], vaddr); code.jne(ok, code.T_NEAR); code.mov(qword[pointer], tmp); diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp index 84eae8c02a..31231c02aa 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp @@ -11,14 +11,13 @@ #include "dynarmic/common/assert.h" #include #include "dynarmic/common/common_types.h" +#include #include "dynarmic/backend/x64/block_of_code.h" #include "dynarmic/backend/x64/emit_x64.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/opcodes.h" -#include "dynarmic/common/fp/util.h" -#include "dynarmic/common/type_util.h" namespace Dynarmic::Backend::X64 { @@ -39,7 +38,7 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) Xbyak::Reg addend = ctx.reg_alloc.UseGpr(args[1]).changeBit(size); Xbyak::Reg overflow = ctx.reg_alloc.ScratchGpr().changeBit(size); - constexpr u64 int_max = static_cast((std::numeric_limits>::max)()); + constexpr u64 int_max = static_cast((std::numeric_limits>::max)()); if constexpr (size < 64) { code.xor_(overflow.cvt32(), overflow.cvt32()); code.bt(result.cvt32(), size - 1); @@ -83,7 +82,7 @@ void EmitUnsignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst Xbyak::Reg op_result = ctx.reg_alloc.UseScratchGpr(args[0]).changeBit(size); Xbyak::Reg addend = ctx.reg_alloc.UseScratchGpr(args[1]).changeBit(size); - constexpr u64 boundary = op == Op::Add ? (std::numeric_limits>::max)() : 0; + constexpr u64 boundary = op == Op::Add ? (std::numeric_limits>::max)() : 0; if constexpr (op == Op::Add) { code.add(op_result, addend); diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp index bc0d86509c..66a179a481 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "dynarmic/backend/x64/abi.h" @@ -30,14 +31,27 @@ #include "dynarmic/common/fp/info.h" #include "dynarmic/common/fp/op.h" #include "dynarmic/common/fp/util.h" -#include "dynarmic/common/type_util.h" #include "dynarmic/common/lut_from_list.h" #include "dynarmic/interface/optimization_flags.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/microinstruction.h" -#define FCODE(NAME) [&](auto... args) { if (fsize == 32) code.NAME##s(args...); else code.NAME##d(args...); } -#define ICODE(NAME) [&](auto... args) { if (fsize == 32) code.NAME##d(args...); else code.NAME##q(args...); } +#define FCODE(NAME) \ + [&code](auto... args) { \ + if constexpr (fsize == 32) { \ + code.NAME##s(args...); \ + } else { \ + code.NAME##d(args...); \ + } \ + } +#define ICODE(NAME) \ + [&code](auto... args) { \ + if constexpr (fsize == 32) { \ + code.NAME##d(args...); \ + } else { \ + code.NAME##q(args...); \ + } \ + } namespace Dynarmic::Backend::X64 { @@ -62,7 +76,7 @@ void MaybeStandardFPSCRValue(BlockOfCode& code, EmitContext& ctx, bool fpcr_cont template class Indexer, size_t narg> struct NaNHandler { public: - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; using function_type = void (*)(std::array, narg>&, FP::FPCR); @@ -144,33 +158,33 @@ Xbyak::Address GetVectorOf(BlockOfCode& code) { template Xbyak::Address GetNaNVector(BlockOfCode& code) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; return GetVectorOf::DefaultNaN()>(code); } template Xbyak::Address GetNegativeZeroVector(BlockOfCode& code) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; return GetVectorOf::Zero(true)>(code); } template Xbyak::Address GetNonSignMaskVector(BlockOfCode& code) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; constexpr FPT non_sign_mask = FP::FPInfo::exponent_mask | FP::FPInfo::mantissa_mask; return GetVectorOf(code); } template Xbyak::Address GetSmallestNormalVector(BlockOfCode& code) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; constexpr FPT smallest_normal_number = FP::FPValue::exponent_min, 1>(); return GetVectorOf(code); } -template value> +template value> Xbyak::Address GetVectorOf(BlockOfCode& code) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; return GetVectorOf()>(code); } @@ -1071,7 +1085,7 @@ static void EmitFPVectorMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::I if (code.HasHostFeature(HostFeature::AVX)) { MaybeStandardFPSCRValue(code, ctx, fpcr_controlled, [&] { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; // result = xmm_a == SNaN || xmm_b == QNaN { @@ -1144,7 +1158,7 @@ static void EmitFPVectorMinMaxNumeric(BlockOfCode& code, EmitContext& ctx, IR::I } MaybeStandardFPSCRValue(code, ctx, fpcr_controlled, [&] { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; // result = xmm_a == SNaN || xmm_b == QNaN { @@ -1300,7 +1314,7 @@ static void EmitFPVectorMulAddFallback(VectorArray& result, const VectorArr template void EmitFPVectorMulAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; const auto fallback_fn = [](VectorArray& result, const VectorArray& addend, const VectorArray& op1, const VectorArray& op2, FP::FPCR fpcr, FP::FPSR& fpsr) { for (size_t i = 0; i < result.size(); i++) { @@ -1411,7 +1425,7 @@ void EmitX64::EmitFPVectorMulAdd64(EmitContext& ctx, IR::Inst* inst) { template static void EmitFPVectorMulX(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; auto args = ctx.reg_alloc.GetArgumentInfo(inst); const bool fpcr_controlled = args[2].GetImmediateU1(); @@ -1477,7 +1491,7 @@ void EmitX64::EmitFPVectorMulX64(EmitContext& ctx, IR::Inst* inst) { template void FPVectorNeg(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; constexpr FPT sign_mask = FP::FPInfo::sign_mask; auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -1530,7 +1544,7 @@ void EmitX64::EmitFPVectorPairedAddLower64(EmitContext& ctx, IR::Inst* inst) { template static void EmitRecipEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; if constexpr (fsize != 16) { if (ctx.HasOptimization(OptimizationFlag::Unsafe_ReducedErrorFP)) { @@ -1576,7 +1590,7 @@ void EmitX64::EmitFPVectorRecipEstimate64(EmitContext& ctx, IR::Inst* inst) { template static void EmitRecipStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; const auto fallback_fn = [](VectorArray& result, const VectorArray& op1, const VectorArray& op2, FP::FPCR fpcr, FP::FPSR& fpsr) { for (size_t i = 0; i < result.size(); i++) { @@ -1700,7 +1714,7 @@ void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { } // Do not make a LUT out of this, let the compiler do it's thing - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; switch (rounding) { case FP::RoundingMode::ToNearest_TieEven: exact @@ -1746,7 +1760,7 @@ void EmitX64::EmitFPVectorRoundInt64(EmitContext& ctx, IR::Inst* inst) { template static void EmitRSqrtEstimate(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; const auto fallback_fn = [](VectorArray& result, const VectorArray& operand, FP::FPCR fpcr, FP::FPSR& fpsr) { for (size_t i = 0; i < result.size(); i++) { @@ -1838,7 +1852,7 @@ void EmitX64::EmitFPVectorRSqrtEstimate64(EmitContext& ctx, IR::Inst* inst) { template static void EmitRSqrtStepFused(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { - using FPT = Common::UnsignedIntegerN; + using FPT = mcl::unsigned_integer_of_size; const auto fallback_fn = [](VectorArray& result, const VectorArray& op1, const VectorArray& op2, FP::FPCR fpcr, FP::FPSR& fpsr) { for (size_t i = 0; i < result.size(); i++) { @@ -2112,7 +2126,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { FCODE(orp)(src, exceed_unsigned); } } else { - using FPT = Common::UnsignedIntegerN; // WORKAROUND: For issue 678 on MSVC + using FPT = mcl::unsigned_integer_of_size; // WORKAROUND: For issue 678 on MSVC constexpr u64 integer_max = FPT((std::numeric_limits>>::max)()); code.movaps(xmm0, GetVectorOf(code)); @@ -2136,7 +2150,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) { mp::lift_value>; static const auto lut = Common::GenerateLookupTableFromList([](I) { - using FPT = Common::UnsignedIntegerN; // WORKAROUND: For issue 678 on MSVC + using FPT = mcl::unsigned_integer_of_size; // WORKAROUND: For issue 678 on MSVC return std::pair{ mp::lower_to_tuple_v, Common::FptrCast([](VectorArray& output, const VectorArray& input, FP::FPCR fpcr, FP::FPSR& fpsr) { diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp index 412bb2bfaa..580a32dec8 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_saturation.cpp @@ -14,8 +14,23 @@ #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/opcodes.h" -#define FCODE(NAME) [&](auto... args) { if (esize == 32) code.NAME##s(args...); else code.NAME##d(args...); } -#define ICODE(NAME) [&](auto... args) { if (esize == 32) code.NAME##d(args...); else code.NAME##q(args...); } +#define FCODE(NAME) \ + [&code](auto... args) { \ + if constexpr (esize == 32) { \ + code.NAME##s(args...); \ + } else { \ + code.NAME##d(args...); \ + } \ + } + +#define ICODE(NAME) \ + [&code](auto... args) { \ + if constexpr (esize == 32) { \ + code.NAME##d(args...); \ + } else { \ + code.NAME##q(args...); \ + } \ + } namespace Dynarmic::Backend::X64 { diff --git a/src/dynarmic/src/dynarmic/backend/x64/exception_handler_windows.cpp b/src/dynarmic/src/dynarmic/backend/x64/exception_handler_windows.cpp index 4d2ca9de9a..95eacaae9b 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/exception_handler_windows.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/exception_handler_windows.cpp @@ -13,7 +13,7 @@ #include #include "dynarmic/common/assert.h" -#include +#include #include "dynarmic/common/common_types.h" #include "dynarmic/backend/exception_handler.h" @@ -184,20 +184,20 @@ struct ExceptionHandler::Impl final { // Our 3rd argument is a PCONTEXT. // If not within our codeblock, ignore this exception. - code.mov(code.rax, Safe::Negate(std::bit_cast(code.getCode()))); + code.mov(code.rax, Safe::Negate(mcl::bit_cast(code.getCode()))); code.add(code.rax, code.qword[code.ABI_PARAM3 + Xbyak::RegExp(offsetof(CONTEXT, Rip))]); code.cmp(code.rax, static_cast(code.GetTotalCodeSize())); code.ja(exception_handler_without_cb); code.lea(code.rsp, code.ptr[code.rsp - 8]); - code.mov(code.ABI_PARAM1, std::bit_cast(&cb)); + code.mov(code.ABI_PARAM1, mcl::bit_cast(&cb)); code.mov(code.ABI_PARAM2, code.ABI_PARAM3); code.CallLambda( [](const std::function& cb_, PCONTEXT ctx) { FakeCall fc = cb_(ctx->Rip); ctx->Rsp -= sizeof(u64); - *std::bit_cast(ctx->Rsp) = fc.ret_rip; + *mcl::bit_cast(ctx->Rsp) = fc.ret_rip; ctx->Rip = fc.call_rip; }); code.add(code.rsp, 8); diff --git a/src/dynarmic/src/dynarmic/backend/x64/perf_map.h b/src/dynarmic/src/dynarmic/backend/x64/perf_map.h index 5f9eea7c17..7d739ae63e 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/perf_map.h +++ b/src/dynarmic/src/dynarmic/backend/x64/perf_map.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -9,8 +6,8 @@ #pragma once #include -#include -#include + +#include namespace Dynarmic::Backend::X64 { @@ -20,7 +17,7 @@ void PerfMapRegister(const void* start, const void* end, std::string_view friend template void PerfMapRegister(T start, const void* end, std::string_view friendly_name) { - detail::PerfMapRegister(std::bit_cast(start), end, friendly_name); + detail::PerfMapRegister(mcl::bit_cast(start), end, friendly_name); } void PerfMapClear(); diff --git a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp index fc59dbcb2d..29eab7908b 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/reg_alloc.cpp @@ -11,10 +11,10 @@ #include #include #include -#include #include #include "dynarmic/common/assert.h" +#include #include #include "dynarmic/backend/x64/abi.h" diff --git a/src/dynarmic/src/dynarmic/common/always_false.h b/src/dynarmic/src/dynarmic/common/always_false.h new file mode 100644 index 0000000000..b980fea00c --- /dev/null +++ b/src/dynarmic/src/dynarmic/common/always_false.h @@ -0,0 +1,13 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2023 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +namespace Dynarmic::Common { + +template +inline constexpr bool always_false_v = false; + +} // namespace Dynarmic::Common diff --git a/src/dynarmic/src/dynarmic/common/assert.h b/src/dynarmic/src/dynarmic/common/assert.h index ce5e66edf9..0a3cb5331d 100644 --- a/src/dynarmic/src/dynarmic/common/assert.h +++ b/src/dynarmic/src/dynarmic/common/assert.h @@ -16,33 +16,38 @@ template // Temporary until MCL is fully removed #ifndef ASSERT_MSG -# define ASSERT_MSG(_a_, ...) do if (!(_a_)) [[unlikely]] assert_terminate(#_a_, __VA_ARGS__); while(0) +#define ASSERT_MSG(_a_, ...) \ + ([&]() { \ + if (!(_a_)) [[unlikely]] { \ + assert_terminate(#_a_, __VA_ARGS__); \ + } \ + }()) #endif #ifndef ASSERT_FALSE -# define ASSERT_FALSE(...) assert_terminate("false", __VA_ARGS__) +#define ASSERT_FALSE(...) \ + ([&]() { \ + assert_terminate("false", __VA_ARGS__); \ + }()) #endif + #ifndef ASSERT -# define ASSERT(_a_) ASSERT_MSG(_a_, "") +#define ASSERT(_a_) ASSERT_MSG(_a_, "") #endif #ifndef UNREACHABLE -# ifdef _MSC_VER -# define UNREACHABLE() ASSERT_FALSE("unreachable") -# else -# define UNREACHABLE() __builtin_unreachable(); -# endif +#define UNREACHABLE() ASSERT_MSG(false, "unreachable") #endif #ifdef _DEBUG -# ifndef DEBUG_ASSERT -# define DEBUG_ASSERT(_a_) ASSERT(_a_) -# endif -# ifndef DEBUG_ASSERT_MSG -# define DEBUG_ASSERT_MSG(_a_, ...) ASSERT_MSG(_a_, __VA_ARGS__) -# endif +#ifndef DEBUG_ASSERT +#define DEBUG_ASSERT(_a_) ASSERT(_a_) +#endif +#ifndef DEBUG_ASSERT_MSG +#define DEBUG_ASSERT_MSG(_a_, ...) ASSERT_MSG(_a_, __VA_ARGS__) +#endif #else // not debug -# ifndef DEBUG_ASSERT -# define DEBUG_ASSERT(_a_) -# endif -# ifndef DEBUG_ASSERT_MSG -# define DEBUG_ASSERT_MSG(_a_, _desc_, ...) -# endif +#ifndef DEBUG_ASSERT +#define DEBUG_ASSERT(_a_) +#endif +#ifndef DEBUG_ASSERT_MSG +#define DEBUG_ASSERT_MSG(_a_, _desc_, ...) +#endif #endif diff --git a/src/dynarmic/src/dynarmic/common/cast_util.h b/src/dynarmic/src/dynarmic/common/cast_util.h new file mode 100644 index 0000000000..92c9a259b3 --- /dev/null +++ b/src/dynarmic/src/dynarmic/common/cast_util.h @@ -0,0 +1,18 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2018 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include + +namespace Dynarmic::Common { + +/// Cast a lambda into an equivalent function pointer. +template +inline auto FptrCast(Function f) noexcept { + return static_cast*>(f); +} + +} // namespace Dynarmic::Common diff --git a/src/dynarmic/src/dynarmic/common/fp/util.h b/src/dynarmic/src/dynarmic/common/fp/util.h index 903c144ea6..fda34e3ee5 100644 --- a/src/dynarmic/src/dynarmic/common/fp/util.h +++ b/src/dynarmic/src/dynarmic/common/fp/util.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -9,7 +6,6 @@ #pragma once #include -#include #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/info.h" diff --git a/src/dynarmic/src/dynarmic/common/llvm_disassemble.cpp b/src/dynarmic/src/dynarmic/common/llvm_disassemble.cpp index 3830e1885e..31d55c134c 100644 --- a/src/dynarmic/src/dynarmic/common/llvm_disassemble.cpp +++ b/src/dynarmic/src/dynarmic/common/llvm_disassemble.cpp @@ -7,7 +7,7 @@ */ #include -#include + #include #ifdef DYNARMIC_USE_LLVM @@ -16,6 +16,7 @@ #endif #include "dynarmic/common/assert.h" +#include #include "dynarmic/common/common_types.h" #include "dynarmic/common/llvm_disassemble.h" @@ -52,7 +53,7 @@ std::string DisassembleX64(const void* begin, const void* end) { LLVMDisasmDispose(llvm_ctx); #else result += fmt::format("(recompile with DYNARMIC_USE_LLVM=ON to disassemble the generated x86_64 code)\n"); - result += fmt::format("start: {:016x}, end: {:016x}\n", std::bit_cast(begin), std::bit_cast(end)); + result += fmt::format("start: {:016x}, end: {:016x}\n", mcl::bit_cast(begin), mcl::bit_cast(end)); #endif return result; diff --git a/src/dynarmic/src/dynarmic/common/type_util.h b/src/dynarmic/src/dynarmic/common/type_util.h deleted file mode 100644 index 8c9e0101d0..0000000000 --- a/src/dynarmic/src/dynarmic/common/type_util.h +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -/* This file is part of the dynarmic project. - * Copyright (c) 2018 MerryMage - * SPDX-License-Identifier: 0BSD - */ - -#pragma once - -#include - -namespace Dynarmic::Common { - -/// Cast a lambda into an equivalent function pointer. -template -inline auto FptrCast(Function f) noexcept { - return static_cast*>(f); -} - -namespace Detail { -template struct IntegerOfSize {}; -template<> struct IntegerOfSize<8> { using U = std::uint8_t; using S = std::int8_t; }; -template<> struct IntegerOfSize<16> { using U = std::uint16_t; using S = std::int16_t; }; -template<> struct IntegerOfSize<32> { using U = std::uint32_t; using S = std::int32_t; }; -template<> struct IntegerOfSize<64> { using U = std::uint64_t; using S = std::int64_t; }; -} -template using UnsignedIntegerN = typename Detail::IntegerOfSize::U; -template using SignedIntegerN = typename Detail::IntegerOfSize::S; - -} // namespace Dynarmic::Common diff --git a/src/dynarmic/src/dynarmic/ir/ir_emitter.cpp b/src/dynarmic/src/dynarmic/ir/ir_emitter.cpp index 08758f0e6d..a8ef7e2989 100644 --- a/src/dynarmic/src/dynarmic/ir/ir_emitter.cpp +++ b/src/dynarmic/src/dynarmic/ir/ir_emitter.cpp @@ -11,7 +11,7 @@ #include #include "dynarmic/common/assert.h" -#include +#include #include "dynarmic/ir/opcodes.h" diff --git a/src/dynarmic/src/dynarmic/ir/ir_emitter.h b/src/dynarmic/src/dynarmic/ir/ir_emitter.h index d041337ae1..dba34bcc56 100644 --- a/src/dynarmic/src/dynarmic/ir/ir_emitter.h +++ b/src/dynarmic/src/dynarmic/ir/ir_emitter.h @@ -12,7 +12,7 @@ #include "dynarmic/common/common_types.h" #include "dynarmic/common/assert.h" -#include +#include #include "dynarmic/ir/opcodes.h" #include "dynarmic/ir/acc_type.h" @@ -2931,19 +2931,19 @@ public: } void CallHostFunction(void (*fn)(void)) { - Inst(Opcode::CallHostFunction, Imm64(std::bit_cast(fn)), Value{}, Value{}, Value{}); + Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast(fn)), Value{}, Value{}, Value{}); } void CallHostFunction(void (*fn)(u64), const U64& arg1) { - Inst(Opcode::CallHostFunction, Imm64(std::bit_cast(fn)), arg1, Value{}, Value{}); + Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast(fn)), arg1, Value{}, Value{}); } void CallHostFunction(void (*fn)(u64, u64), const U64& arg1, const U64& arg2) { - Inst(Opcode::CallHostFunction, Imm64(std::bit_cast(fn)), arg1, arg2, Value{}); + Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast(fn)), arg1, arg2, Value{}); } void CallHostFunction(void (*fn)(u64, u64, u64), const U64& arg1, const U64& arg2, const U64& arg3) { - Inst(Opcode::CallHostFunction, Imm64(std::bit_cast(fn)), arg1, arg2, arg3); + Inst(Opcode::CallHostFunction, Imm64(mcl::bit_cast(fn)), arg1, arg2, arg3); } void SetTerm(const Terminal& terminal) { diff --git a/src/dynarmic/tests/test_generator.cpp b/src/dynarmic/tests/test_generator.cpp index 70ae62a1a9..c8f05d06f8 100644 --- a/src/dynarmic/tests/test_generator.cpp +++ b/src/dynarmic/tests/test_generator.cpp @@ -17,6 +17,7 @@ #include #include +#include #include "dynarmic/common/common_types.h" #include "./A32/testenv.h"