From 172ff8e76c7a4b1e836dd4d943962155787bfa7c Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 2 Nov 2025 20:37:30 +0000 Subject: [PATCH] spinlocks, annoyances with organistaion Signed-off-by: lizzie --- externals/powah/data2code.c | 107 ++++++++++++------ externals/powah/powah_emit.hpp | 14 ++- externals/powah/powah_gen_base.hpp | 20 ++-- src/dynarmic/src/dynarmic/CMakeLists.txt | 4 + .../src/dynarmic/backend/ppc64/a32_core.h | 4 +- .../dynarmic/backend/ppc64/a32_interface.cpp | 16 ++- .../src/dynarmic/backend/ppc64/a64_core.h | 15 +-- .../dynarmic/backend/ppc64/a64_interface.cpp | 84 +++++++------- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 8 ++ .../ppc64/emit_ppc64_data_processing.cpp | 2 +- .../backend/ppc64/exclusive_monitor.cpp | 50 ++++++++ .../src/dynarmic/backend/ppc64/hostloc.h | 26 +++++ .../src/dynarmic/backend/ppc64/reg_alloc.cpp | 43 +++---- .../src/dynarmic/backend/ppc64/reg_alloc.h | 14 +-- .../src/dynarmic/common/spin_lock_ppc64.cpp | 71 ++++++++++++ .../src/dynarmic/common/spin_lock_ppc64.h | 13 +++ 16 files changed, 356 insertions(+), 135 deletions(-) create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h create mode 100644 src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp create mode 100644 src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h diff --git a/externals/powah/data2code.c b/externals/powah/data2code.c index 2f276b29c7..3e6bad32c8 100644 --- a/externals/powah/data2code.c +++ b/externals/powah/data2code.c @@ -51,30 +51,53 @@ int main(int argc, char *argv[]) { int i_extopc = atoi(sec); //printf("// %s\n", mem); if (!strcmp(form, "XO")) { - if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0) - printf("//"); - printf( - "void %s(GPR const rt, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, rt, ra, rb, false, false); " - "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); - printf( - "void %sC(GPR const rt, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, rt, ra, rb, true, false); " - "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); - if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0) - printf("//"); - printf( - "void %s_(GPR const rt, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, rt, ra, rb, false, true); " - "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); - printf( - "void %sC_(GPR const rt, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, rt, ra, rb, true, true); " - "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + if (!strcmp(mem, "EXTSH")) { + printf( + "void %s(GPR const rt, GPR const ra) {" + " emit_%s(0x%08x, rt, ra, R0, false, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sC(GPR const rt, GPR const ra) {" + " emit_%s(0x%08x, rt, ra, R0, true, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s_(GPR const rt, GPR const ra) {" + " emit_%s(0x%08x, rt, ra, R0, false, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sC_(GPR const rt, GPR const ra) {" + " emit_%s(0x%08x, rt, ra, R0, true, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else { + if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0) + printf("//"); + printf( + "void %s(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, false, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sC(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, true, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0) + printf("//"); + printf( + "void %s_(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, false, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sC_(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, true, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } } else if (!strcmp(form, "X")) { if (!strcmp(mem, "CMPL") || !strcmp(mem, "CMP")) { @@ -83,7 +106,8 @@ int main(int argc, char *argv[]) { " emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, rb, false); " "}\n" , mem, form, i_opcode << 26); - } else if (strcmp(mem, "CNTLZD") == 0 || strcmp(mem, "CNTLZW") == 0) { + } else if (!strcmp(mem, "CNTLZD") || !strcmp(mem, "CNTLZW") + || !strcmp(mem, "EXTSB") || !strcmp(mem, "EXTSH") || !strcmp(mem, "EXTSW")) { printf( "void %s(GPR const rt, GPR const ra) {" " emit_%s(0x%08x, rt, ra, R0, false); " @@ -204,16 +228,29 @@ int main(int argc, char *argv[]) { , mem, form, (i_opcode << 26) | (i_extopc << 1)); } } else if (!strcmp(form, "M")) { - printf( - "void %s(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {" - " emit_%s(0x%08x, rs, ra, sh, mb, me, false); " - "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); - printf( - "void %s_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {" - " emit_%s(0x%08x, rs, ra, sh, mb, me, true); " - "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + if (!strcmp(mem, "RLWNM")) { + printf( + "void %s(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) {" + " emit_%s(0x%08x, rs, ra, rb.index, mb, me, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) {" + " emit_%s(0x%08x, rs, ra, rb.index, mb, me, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else { + printf( + "void %s(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {" + " emit_%s(0x%08x, rs, ra, sh, mb, me, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {" + " emit_%s(0x%08x, rs, ra, sh, mb, me, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } } else if (!strcmp(form, "MD")) { printf( "void %s(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) {" diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 3a28910a75..d10fc835ff 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -110,6 +110,7 @@ constexpr inline CPR CR6{24}; constexpr inline CPR CR7{28}; struct Context { + Context() = default; Context(void* ptr, size_t size) : base{reinterpret_cast(ptr)} , offset{0} @@ -280,6 +281,8 @@ struct Context { // Extended Memmonics, hand coded :) void MR(GPR const ra, GPR const rs) { OR(ra, rs, rs); } + void NOP() { ORI(R0, R0, 0); } + void NOT(GPR const ra, GPR const rs) { NOR(ra, rs, rs); } void ROTLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, n, 0); } void ROTRDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, 64 - n, 0); } @@ -287,6 +290,9 @@ struct Context { void ROTLWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, n, 0, 31); } void ROTRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 32 - n, 0, 31); } + void ROTLW(GPR const ra, GPR const rs, GPR const rb) { RLWNM(ra, rs, rb, 0, 31); } + void ROTLD(GPR const ra, GPR const rs, GPR const rb) { RLDCL(ra, rs, rb, 0); } + void EXTLDI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLDICR(ra, rs, b, n - 1); } void SLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICR(ra, rs, n, 63 - n); } void CLRLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, 0, n); } @@ -298,7 +304,7 @@ struct Context { void EXTLWI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLWINM(ra, rs, b, 0, n - 1); } void SRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 32 - n, n, 31); } - void CLRRWI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLWINM(ra, rs, 0, 0, 31 - n); } + void CLRRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 0, 0, 31 - n); } void CRSET(CPR const bx) { CREQV(bx, bx, bx); } void CRCLR(CPR const bx) { CRXOR(bx, bx, bx); } @@ -320,8 +326,14 @@ struct Context { void CMPDI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index / 4, 1, rx, si); } void CMPD(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index / 4, 1, rx, ry); } + void BLR() { BCLR(R0, CR0, R0); } + // TODO: PowerPC 11 stuff void ISEL(GPR const rd, GPR const ra, GPR const rb, uint32_t d) { + (void)rd; + (void)ra; + (void)rb; + (void)d; std::unreachable(); } void ISELLT(GPR const rd, GPR const ra, GPR const rb) { ISEL(rd, ra, rb, 0); } diff --git a/externals/powah/powah_gen_base.hpp b/externals/powah/powah_gen_base.hpp index cd1b7bc17b..7783bf56d6 100644 --- a/externals/powah/powah_gen_base.hpp +++ b/externals/powah/powah_gen_base.hpp @@ -124,14 +124,14 @@ void EIEIO(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, rt, ra void EIEIO_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, rt, ra, rb, true); } void EQV(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, rt, ra, rb, false); } void EQV_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, rt, ra, rb, true); } -void EXTSB(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000774, rt, ra, rb, false); } -void EXTSB_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000774, rt, ra, rb, true); } -void EXTSH(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, false, false); } -void EXTSHC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, true, false); } -void EXTSH_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, false, true); } -void EXTSHC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, true, true); } -void EXTSW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007b4, rt, ra, rb, false); } -void EXTSW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007b4, rt, ra, rb, true); } +void EXTSB(GPR const rt, GPR const ra) { emit_X(0x7c000774, rt, ra, R0, false); } +void EXTSB_(GPR const rt, GPR const ra) { emit_X(0x7c000774, rt, ra, R0, true); } +void EXTSH(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, false, false); } +void EXTSHC(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, true, false); } +void EXTSH_(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, false, true); } +void EXTSHC_(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, true, true); } +void EXTSW(GPR const rt, GPR const ra) { emit_X(0x7c0007b4, rt, ra, R0, false); } +void EXTSW_(GPR const rt, GPR const ra) { emit_X(0x7c0007b4, rt, ra, R0, true); } void FABS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, rt, ra, rb, false); } void FABS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, rt, ra, rb, true); } void FADD(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002a, frt, fra, frb, frc, false); } @@ -349,8 +349,8 @@ void RLWIMI(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = void RLWIMI_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x50000000, rs, ra, sh, mb, me, true); } void RLWINM(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, rs, ra, sh, mb, me, false); } void RLWINM_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, rs, ra, sh, mb, me, true); } -void RLWNM(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, sh, mb, me, false); } -void RLWNM_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, sh, mb, me, true); } +void RLWNM(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, rb.index, mb, me, false); } +void RLWNM_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, rb.index, mb, me, true); } void SC(uint32_t lev) { emit_SC(0x44000000, lev); } void SI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x30000000, rt, ra, d); } void SI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x34000000, rt, ra, d); } diff --git a/src/dynarmic/src/dynarmic/CMakeLists.txt b/src/dynarmic/src/dynarmic/CMakeLists.txt index 84f4be1d40..8e49140226 100644 --- a/src/dynarmic/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/src/dynarmic/CMakeLists.txt @@ -304,9 +304,13 @@ if ("ppc64" IN_LIST ARCHITECTURE) backend/ppc64/emit_ppc64_vector.cpp backend/ppc64/emit_ppc64.cpp backend/ppc64/emit_ppc64.h + backend/ppc64/exclusive_monitor.cpp backend/ppc64/reg_alloc.cpp backend/ppc64/reg_alloc.h backend/ppc64/stack_layout.h + backend/ppc64/hostloc.h + common/spin_lock_ppc64.cpp + common/spin_lock_ppc64.h # A32 backend/ppc64/a32_core.h backend/ppc64/a32_interface.cpp diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h index e90b7b203b..2d113e8c8f 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -16,12 +16,12 @@ namespace Dynarmic::Backend::PPC64 { struct A32JitState { - alignas(16) std::array vec{}; + alignas(16) std::array ext_regs{}; std::array regs{}; u32 upper_location_descriptor; u32 exclusive_state = 0; u32 cpsr_nzcv = 0; - u32 fpsr = 0; + u32 fpscr = 0; IR::LocationDescriptor GetLocationDescriptor() const { return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index 025fc0c989..178bb9775a 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -9,8 +9,12 @@ #include #include "dynarmic/common/common_types.h" +#include "dynarmic/frontend/A32/a32_location_descriptor.h" +#include "dynarmic/frontend/A32/translate/a32_translate.h" +#include "dynarmic/interface/A32/config.h" #include "dynarmic/backend/ppc64/a32_core.h" #include "dynarmic/common/atomic.h" +#include "dynarmic/ir/opt_passes.h" #include "dynarmic/interface/A32/a32.h" namespace Dynarmic::Backend::PPC64 { @@ -69,8 +73,12 @@ void A32AddressSpace::Link(EmittedBlockInfo& block_info) { UNREACHABLE(); } +} + namespace Dynarmic::A32 { +using namespace Dynarmic::Backend::PPC64; + struct Jit::Impl final { Impl(Jit* jit_interface, A32::UserConfig conf) : jit_interface(jit_interface) @@ -130,19 +138,19 @@ struct Jit::Impl final { } u32 Cpsr() const { - return current_state.Cpsr(); + return current_state.cpsr_nzcv; } void SetCpsr(u32 value) { - current_state.SetCpsr(value); + current_state.cpsr_nzcv = value; } u32 Fpscr() const { - return current_state.Fpscr(); + return current_state.fpscr; } void SetFpscr(u32 value) { - current_state.SetFpscr(value); + current_state.fpscr = value; } void ClearExclusiveState() { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index 5e3edabe48..4236e1f281 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -20,10 +20,15 @@ struct A64JitState { using ProgramCounterType = u32; alignas(16) std::array vec{}; std::array regs{}; + u64 sp = 0; + u64 pc = 0; u32 upper_location_descriptor; u32 exclusive_state = 0; u32 cpsr_nzcv = 0; + u32 pstate = 0; + u32 fpcr = 0; u32 fpsr = 0; + volatile u32 halt_reason = 0; IR::LocationDescriptor GetLocationDescriptor() const { return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; } @@ -32,15 +37,9 @@ struct A64JitState { class A64AddressSpace final { public: explicit A64AddressSpace(const A64::UserConfig& conf); - - IR::Block GenerateIR(IR::LocationDescriptor) const; - CodePtr Get(IR::LocationDescriptor descriptor); - CodePtr GetOrEmit(IR::LocationDescriptor descriptor); - void ClearCache(); - private: friend class A64Core; @@ -49,16 +48,12 @@ private: void Link(EmittedBlockInfo& block); const A64::UserConfig conf; - CodeBlock cb; powah::Context as; - ankerl::unordered_dense::map block_entries; ankerl::unordered_dense::map block_infos; - struct PreludeInfo { CodePtr end_of_prelude; - using RunCodeFuncType = HaltReason (*)(CodePtr entry_point, A64JitState* context, volatile u32* halt_reason); RunCodeFuncType run_code; CodePtr return_from_run_code; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index a0232a6ced..b324a8897f 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -8,9 +8,12 @@ #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" -#include "dynarmic/backend/ppc64/a64_core.h" +#include "dynarmic/frontend/A64/a64_location_descriptor.h" +#include "dynarmic/frontend/A64/translate/a64_translate.h" +#include "dynarmic/interface/A64/config.h" #include "dynarmic/backend/ppc64/a64_core.h" #include "dynarmic/common/atomic.h" +#include "dynarmic/ir/opt_passes.h" #include "dynarmic/interface/A64/a64.h" namespace Dynarmic::Backend::PPC64 { @@ -22,28 +25,25 @@ A64AddressSpace::A64AddressSpace(const A64::UserConfig& conf) EmitPrelude(); } -IR::Block A64AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const { - IR::Block ir_block = A64::Translate(A64::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); - Optimization::Optimize(ir_block, conf, {}); - return ir_block; -} - CodePtr A64AddressSpace::Get(IR::LocationDescriptor descriptor) { - if (const auto iter = block_entries.find(descriptor.Value()); iter != block_entries.end()) + if (auto const iter = block_entries.find(descriptor.Value()); iter != block_entries.end()) return iter->second; return nullptr; } -CodePtr A64AddressSpace::GetOrEmit(IR::LocationDescriptor descriptor) { - if (CodePtr block_entry = Get(descriptor)) { +CodePtr A64AddressSpace::GetOrEmit(IR::LocationDescriptor desc) { + if (CodePtr block_entry = Get(desc)) return block_entry; - } - IR::Block ir_block = GenerateIR(descriptor); + const auto get_code = [this](u64 vaddr) { + return conf.callbacks->MemoryReadCode(vaddr); + }; + IR::Block ir_block = A64::Translate(A64::LocationDescriptor{desc}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); + Optimization::Optimize(ir_block, conf, {}); const EmittedBlockInfo block_info = Emit(std::move(ir_block)); - block_infos.insert_or_assign(descriptor.Value(), block_info); - block_entries.insert_or_assign(descriptor.Value(), block_info.entry_point); + block_infos.insert_or_assign(desc.Value(), block_info); + block_entries.insert_or_assign(desc.Value(), block_info.entry_point); return block_info.entry_point; } @@ -59,7 +59,7 @@ void A64AddressSpace::EmitPrelude() { EmittedBlockInfo A64AddressSpace::Emit(IR::Block block) { EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), { .enable_cycle_counting = conf.enable_cycle_counting, - .always_little_endian = conf.always_little_endian, + .always_little_endian = true, }); Link(block_info); return block_info; @@ -72,18 +72,19 @@ void A64AddressSpace::Link(EmittedBlockInfo& block_info) { namespace Dynarmic::A64 { +using namespace Dynarmic::Backend::PPC64; + struct Jit::Impl final { Impl(Jit* jit_interface, A64::UserConfig conf) - : jit_interface(jit_interface) - , conf(conf) - , current_address_space(conf) - , core(conf) {} + : conf(conf) + , emitter(conf) {} HaltReason Run() { ASSERT(!is_executing); //PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason))); is_executing = true; - const HaltReason hr = block_of_code.RunCode(&jit_state, current_code_ptr); + auto const current_loc = jit_state.GetLocationDescriptor(); + const HaltReason hr = {};//block_of_code.RunCode(&jit_state, jit_state.GetOrEmit(current_loc)); //PerformRequestedCacheInvalidation(hr); is_executing = false; return hr; @@ -91,12 +92,13 @@ struct Jit::Impl final { HaltReason Step() { ASSERT(!is_executing); - //PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason))); - is_executing = true; - const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep()); - //PerformRequestedCacheInvalidation(hr); - is_executing = false; - return hr; + // //PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason))); + // is_executing = true; + // //const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep()); + // //PerformRequestedCacheInvalidation(hr); + // is_executing = false; + // return hr; + return {}; } void ClearCache() { @@ -142,23 +144,21 @@ struct Jit::Impl final { } u64 GetRegister(size_t index) const { - if (index == 31) - return GetSP(); - return jit_state.reg.at(index); + return index == 31 ? GetSP() : jit_state.regs.at(index); } void SetRegister(size_t index, u64 value) { if (index == 31) return SetSP(value); - jit_state.reg.at(index) = value; + jit_state.regs.at(index) = value; } std::array GetRegisters() const { - return jit_state.reg; + return jit_state.regs; } void SetRegisters(const std::array& value) { - jit_state.reg = value; + jit_state.regs = value; } Vector GetVector(size_t index) const { @@ -183,27 +183,27 @@ struct Jit::Impl final { } u32 GetFpcr() const { - return jit_state.GetFpcr(); + return jit_state.fpcr; } void SetFpcr(u32 value) { - jit_state.SetFpcr(value); + jit_state.fpcr = value; } u32 GetFpsr() const { - return jit_state.GetFpsr(); + return jit_state.fpsr; } void SetFpsr(u32 value) { - jit_state.SetFpsr(value); + jit_state.fpsr = value; } u32 GetPstate() const { - return jit_state.GetPstate(); + return jit_state.pstate; } void SetPstate(u32 value) { - jit_state.SetPstate(value); + jit_state.pstate = value; } void ClearExclusiveState() { @@ -214,6 +214,13 @@ struct Jit::Impl final { return is_executing; } + std::string Disassemble() const { + // const size_t size = reinterpret_cast(block_of_code.getCurr()) - reinterpret_cast(block_of_code.GetCodeBegin()); + // auto const* p = reinterpret_cast(block_of_code.GetCodeBegin()); + // return Common::DisassemblePPC64(p, p + size); + return {}; + } + private: void RequestCacheInvalidation() { // UNREACHABLE(); @@ -225,7 +232,6 @@ private: const UserConfig conf; A64JitState jit_state; A64AddressSpace emitter; - BlockOfCode block_of_code; Optimization::PolyfillOptions polyfill_options; bool invalidate_entire_cache = false; boost::icl::interval_set invalid_cache_ranges; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index e47be9fe6a..719091c872 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -3,10 +3,18 @@ #pragma once +#include +#include "dynarmic/common/common_types.h" + namespace Dynarmic::Backend::PPC64 { constexpr powah::GPR RJIT = powah::R31; +constexpr powah::GPR ABI_PARAM1 = powah::R3; +constexpr powah::GPR ABI_PARAM2 = powah::R4; +constexpr powah::GPR ABI_PARAM3 = powah::R5; +constexpr powah::GPR ABI_PARAM4 = powah::R6; + constexpr std::initializer_list GPR_ORDER{8, 9, 18, 19, 20, 21, 22, 23, 24, 25, 5, 6, 7, 28, 29, 10, 11, 12, 13, 14, 15, 16, 17}; constexpr std::initializer_list FPR_ORDER{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp index 80aa9a13d5..a376929a36 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp @@ -423,7 +423,7 @@ void EmitIR(powah::Context& code, Emit auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); - code.SRAL(result, source, source); + code.SRAD(result, source, source); ctx.reg_alloc.DefineValue(inst, result); } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp new file mode 100644 index 0000000000..9fcb0f0629 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "dynarmic/interface/exclusive_monitor.h" +#include +#include "dynarmic/common/assert.h" + +namespace Dynarmic { + +ExclusiveMonitor::ExclusiveMonitor(std::size_t processor_count) + : exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {} + +size_t ExclusiveMonitor::GetProcessorCount() const { + return exclusive_addresses.size(); +} + +void ExclusiveMonitor::Lock() { + lock.Lock(); +} + +void ExclusiveMonitor::Unlock() { + lock.Unlock(); +} + +bool ExclusiveMonitor::CheckAndClear(std::size_t processor_id, VAddr address) { + const VAddr masked_address = address & RESERVATION_GRANULE_MASK; + Lock(); + if (exclusive_addresses[processor_id] != masked_address) { + Unlock(); + return false; + } + for (VAddr& other_address : exclusive_addresses) + if (other_address == masked_address) + other_address = INVALID_EXCLUSIVE_ADDRESS; + return true; +} + +void ExclusiveMonitor::Clear() { + Lock(); + std::fill(exclusive_addresses.begin(), exclusive_addresses.end(), INVALID_EXCLUSIVE_ADDRESS); + Unlock(); +} + +void ExclusiveMonitor::ClearProcessor(size_t processor_id) { + Lock(); + exclusive_addresses[processor_id] = INVALID_EXCLUSIVE_ADDRESS; + Unlock(); +} + +} // namespace Dynarmic diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h new file mode 100644 index 0000000000..17b1f71517 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dynarmic/common/common_types.h" + +namespace Dynarmic::Backend::PPC64 { + +enum class HostLoc : uint8_t { + R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, + R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, + R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, + R30, R31, + FR0, FR1, FR2, FR3, FR4, FR5, FR6, FR7, FR8, FR9, + FR10, FR11, FR12, FR13, FR14, FR15, FR16, FR17, FR18, FR19, + FR20, FR21, FR22, FR23, FR24, FR25, FR26, FR27, FR28, FR29, + FR30, FR31, + VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9, + VR10, VR11, VR12, VR13, VR14, VR15, VR16, VR17, VR18, VR19, + VR20, VR21, VR22, VR23, VR24, VR25, VR26, VR27, VR28, VR29, + VR30, VR31, + FirstSpill, +}; + +} // namespace Dynarmic::Backend::PPC64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp index a0c752fded..4e2037790a 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "dynarmic/common/assert.h" #include @@ -175,42 +176,42 @@ u32 RegAlloc::FindFreeSpill() const { } std::optional RegAlloc::ValueLocation(const IR::Inst* value) const { - const auto contains_value = [value](const HostLocInfo& info) { + const auto fn = [value](const HostLocInfo& info) { return info.Contains(value); }; - if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) { - return HostLoc{HostLoc::Kind::Gpr, static_cast(iter - gprs.begin())}; - } else if (const auto iter = std::find_if(fprs.begin(), fprs.end(), contains_value); iter != fprs.end()) { - return HostLoc{HostLoc::Kind::Fpr, static_cast(iter - fprs.begin())}; - } else if (const auto iter = std::find_if(spills.begin(), spills.end(), contains_value); iter != spills.end()) { - return HostLoc{HostLoc::Kind::Spill, static_cast(iter - spills.begin())}; - } + if (const auto iter = std::ranges::find_if(gprs, fn); iter != gprs.end()) + return HostLoc(u32(HostLoc::R0) + u32(iter - gprs.begin())); + else if (const auto iter = std::ranges::find_if(fprs, fn); iter != fprs.end()) + return HostLoc(u32(HostLoc::FR0) + u32(iter - fprs.begin())); + else if (const auto iter = std::ranges::find_if(vprs, fn); iter != vprs.end()) + return HostLoc(u32(HostLoc::VR0) + u32(iter - vprs.begin())); + else if (const auto iter = std::ranges::find_if(spills, fn); iter != spills.end()) + return HostLoc(u32(HostLoc::FirstSpill) + u32(iter - spills.begin())); return std::nullopt; } HostLocInfo& RegAlloc::ValueInfo(HostLoc host_loc) { - switch (host_loc.kind) { - case HostLoc::Kind::Gpr: - return gprs[size_t(host_loc.index)]; - case HostLoc::Kind::Fpr: - return fprs[size_t(host_loc.index)]; - case HostLoc::Kind::Spill: - return spills[size_t(host_loc.index)]; - } + // switch (host_loc.kind) { + // case HostLoc::Kind::Gpr: + // return gprs[size_t(host_loc.index)]; + // case HostLoc::Kind::Fpr: + // return fprs[size_t(host_loc.index)]; + // case HostLoc::Kind::Spill: + // return spills[size_t(host_loc.index)]; + // } UNREACHABLE(); } HostLocInfo& RegAlloc::ValueInfo(const IR::Inst* value) { - const auto contains_value = [value](const HostLocInfo& info) { + const auto fn = [value](const HostLocInfo& info) { return info.Contains(value); }; - if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) { + if (const auto iter = std::find_if(gprs.begin(), gprs.end(), fn); iter != gprs.end()) return *iter; - } else if (const auto iter = std::find_if(fprs.begin(), fprs.end(), contains_value); iter != gprs.end()) { + else if (const auto iter = std::find_if(fprs.begin(), fprs.end(), fn); iter != fprs.end()) return *iter; - } else if (const auto iter = std::find_if(spills.begin(), spills.end(), contains_value); iter != gprs.end()) { + else if (const auto iter = std::find_if(spills.begin(), spills.end(), fn); iter != spills.end()) return *iter; - } UNREACHABLE(); } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h index 5e73513d14..034935e311 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h @@ -15,6 +15,7 @@ #include #include "dynarmic/backend/ppc64/stack_layout.h" +#include "dynarmic/backend/ppc64/hostloc.h" #include "dynarmic/ir/cond.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/value.h" @@ -23,18 +24,6 @@ namespace Dynarmic::Backend::PPC64 { class RegAlloc; -enum class HostLoc : uint8_t { - R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, - R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, - R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, - R30, R31, - VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9, - VR10, VR11, VR12, VR13, VR14, VR15, VR16, VR17, VR18, VR19, - VR20, VR21, VR22, VR23, VR24, VR25, VR26, VR27, VR28, VR29, - VR30, VR31, - FirstSpill, -}; - struct Argument { public: using copyable_reference = std::reference_wrapper; @@ -108,6 +97,7 @@ private: powah::Context& as; std::array gprs; std::array fprs; + std::array vprs; std::array spills; }; diff --git a/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp new file mode 100644 index 0000000000..8ce6d40021 --- /dev/null +++ b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include +#include "dynarmic/backend/ppc64/abi.h" +#include "dynarmic/backend/ppc64/hostloc.h" +#include "dynarmic/common/spin_lock.h" +#include "dynarmic/common/assert.h" + +namespace Dynarmic { + +/* +void acquire(atomic_flag* lock) { + while(atomic_flag_test_and_set_explicit( lock, memory_order_acquire)) + ; +} +*/ +void EmitSpinLockLock(powah::Context& code, powah::GPR const ptr, powah::GPR const tmp) { + +} + +/* +void release(atomic_flag* lock) { + atomic_flag_clear_explicit(lock, memory_order_release); +} +*/ +void EmitSpinLockUnlock(powah::Context& code, powah::GPR const ptr, powah::GPR const tmp) { + +} + +namespace { + +struct SpinLockImpl { + void Initialize(); + powah::Context code; + void* page = nullptr; + void (*lock)(volatile int*); + void (*unlock)(volatile int*); +}; + +std::once_flag flag; +SpinLockImpl impl; + +void SpinLockImpl::Initialize() { + page = mmap(nullptr, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); + ASSERT(page != nullptr); + code = powah::Context(page, 4096); + lock = reinterpret_cast(code.base); + EmitSpinLockLock(code, Backend::PPC64::ABI_PARAM1, Backend::PPC64::ABI_PARAM2); + code.BLR(); + unlock = reinterpret_cast(code.base); + EmitSpinLockUnlock(code, Backend::PPC64::ABI_PARAM1, Backend::PPC64::ABI_PARAM2); + code.BLR(); + // TODO: free the page, rework the stupid spinlock API +} + +} // namespace + +void SpinLock::Lock() noexcept { + std::call_once(flag, &SpinLockImpl::Initialize, impl); + impl.lock(&storage); +} + +void SpinLock::Unlock() noexcept { + std::call_once(flag, &SpinLockImpl::Initialize, impl); + impl.unlock(&storage); +} + +} // namespace Dynarmic diff --git a/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h new file mode 100644 index 0000000000..d2e78cc66f --- /dev/null +++ b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include + +namespace Dynarmic { + +void EmitSpinLockLock(powah::Context& code, powah::GPR const ptr, powah::GPR const tmp); +void EmitSpinLockUnlock(powah::Context& code, powah::GPR const ptr, powah::GPR const tmp); + +} // namespace Dynarmic