From c02fd907aa7c9873a137dbed486e0c22698e22de Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 12 Aug 2026 23:21:09 +0000 Subject: [PATCH] use common return point to not corrupt regs also use jit state for checkbit :) --- .../src/dynarmic/backend/ppc64/a32_core.h | 2 +- .../src/dynarmic/backend/ppc64/a64_core.h | 2 +- .../dynarmic/backend/ppc64/a64_interface.cpp | 10 +---- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 1 - .../src/dynarmic/backend/ppc64/emit_context.h | 3 ++ .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 42 +++++++------------ .../dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 10 +---- 7 files changed, 25 insertions(+), 45 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h index d287f95671..1a3bb9296a 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -22,7 +22,7 @@ struct A32JitState { u32 exclusive_state = 0; u32 cpsr_nzcv = 0; u32 fpscr = 0; - u8 check_bit = 0; + u32 check_bit = 0; IR::LocationDescriptor GetLocationDescriptor() const { return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index d5aa0b3370..d727e0d3ed 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -28,7 +28,7 @@ struct A64JitState { u32 fpcr = 0; u32 fpsr = 0; volatile u32 halt_reason = 0; - u8 check_bit = 0; + u32 check_bit = 0; IR::LocationDescriptor GetLocationDescriptor() const { const u64 fpcr_u64 = u64(fpcr & A64::LocationDescriptor::fpcr_mask) << A64::LocationDescriptor::fpcr_shift; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index 7b3f9e88da..86e3e86c0c 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -75,18 +75,12 @@ struct A64AddressSpace final { ankerl::unordered_dense::map block_infos; }; -__attribute__((noinline)) HaltReason test_thunk(A64AddressSpace* a, A64JitState* b, volatile u32* c, void* d) { - printf("%p,%p,%p,%p\n", a, b, c, d); - return HaltReason::UserDefined2; -} - struct A64Core final { + using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void *fn); static HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) { const auto loc = thread_ctx.GetLocationDescriptor(); const auto entry = process.GetOrEmit(loc); - using AbstractCodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void (*fn)()); - using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, AbstractCodeFn fn); - return (CodeFn(entry))(&process, &thread_ctx, halt_reason, AbstractCodeFn(test_thunk)); + return (CodeFn(entry))(&process, &thread_ctx, halt_reason, (void*)&A64Core::Run); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index 2989b9ae58..937fbcd4a1 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -49,7 +49,6 @@ constexpr powah::GPR RHALTREASON = powah::R5; constexpr powah::GPR RTOCPTR = powah::R6; // temporals constexpr powah::GPR RNZCV = powah::R7; -constexpr powah::GPR RCHECKBIT = powah::R8; constexpr powah::GPR ABI_PARAM1 = powah::R3; constexpr powah::GPR ABI_PARAM2 = powah::R4; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h b/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h index d8e11e3591..147ccdf0ec 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h @@ -3,6 +3,7 @@ #pragma once +#include #include "dynarmic/backend/ppc64/emit_ppc64.h" #include "dynarmic/backend/ppc64/reg_alloc.h" @@ -19,6 +20,8 @@ struct EmitContext { RegAlloc& reg_alloc; const EmitConfig& emit_conf; EmittedBlockInfo& ebi; + // label used when returning :) + powah::Label l_return; }; } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 100558f939..d070d436c1 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -146,22 +146,24 @@ void EmitIR(powah::Context&, EmitContext&, IR:: namespace { void EmitLeafTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step); -void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal const terminal, IR::LocationDescriptor initial_location, bool is_single_step); +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step); void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) { ASSERT(false && "unimp"); } +// r3 -> process +// r4 -> thread_ctx +// r5 -> halt_reason +// r6 -> test_thunk void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { if (ctx.emit_conf.a64_variant) { auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LI(tmp, terminal.next.Value()); code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); - code.LD(tmp, PPC64::RTOCPTR, 0); - code.MTCTR(tmp); - code.LD(powah::R2, PPC64::RTOCPTR, 8); - code.LD(powah::R11, PPC64::RTOCPTR, 16); - code.BCTR(); +// code.MTCTR(powah::R6); +// code.BCTR(); + code.B(ctx.l_return); } else { auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LI(tmp, terminal.next.Value()); @@ -170,22 +172,8 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock te } } -void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { - if (ctx.emit_conf.a64_variant) { - auto const tmp = ctx.reg_alloc.ScratchGpr(); - code.LI(tmp, terminal.next.Value()); - code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); - code.LD(tmp, PPC64::RTOCPTR, 0); - code.MTCTR(tmp); - code.LD(powah::R2, PPC64::RTOCPTR, 8); - code.LD(powah::R11, PPC64::RTOCPTR, 16); - code.BCTR(); - } else { - auto const tmp = ctx.reg_alloc.ScratchGpr(); - code.LI(tmp, terminal.next.Value()); - code.STW(tmp, PPC64::RJIT, offsetof(A32JitState, regs) + sizeof(u32) * 15); - ASSERT(false && "unimp"); - } +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + EmitTerminal(code, ctx, terminal, IR::Term::LinkBlock{terminal.next}, is_single_step); } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::PopRSBHint, IR::LocationDescriptor, bool) { @@ -204,7 +192,7 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckBit ter powah::Label const l_else = code.DefineLabel(); powah::Label const l_end = code.DefineLabel(); auto const tmp = ctx.reg_alloc.ScratchGpr(); - code.MR(tmp, PPC64::RCHECKBIT); + code.LWZ(tmp, PPC64::RJIT, offsetof(A64JitState, check_bit)); code.CMPLDI(tmp, 0); code.BEQ(powah::CR0, l_else); // CheckBit == 1 @@ -220,7 +208,7 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckHalt te ASSERT(false && "unimp"); } -void EmitLeafTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LeafTerminal const terminal, IR::LocationDescriptor initial_location, bool is_single_step) { +void EmitLeafTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) { if (auto const x = std::get_if(&terminal)) return EmitTerminal(code, ctx, *x, initial_location, is_single_step); if (auto const x = std::get_if(&terminal)) @@ -234,7 +222,7 @@ void EmitLeafTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LeafTerm UNREACHABLE(); } -void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal const terminal, IR::LocationDescriptor initial_location, bool is_single_step) { +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) { if (auto const x = std::get_if(&terminal)) return EmitLeafTerminal(code, ctx, *x, initial_location, is_single_step); if (auto const x = std::get_if(&terminal)) @@ -290,15 +278,17 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf } // auto const cycles_to_add = block.CycleCount(); + EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false); + code.LABEL(ctx.l_return); code.ADDI(powah::R1, powah::R1, stack_size); for (size_t i = 0; i < gp_regs.size(); ++i) code.LD(gp_regs[i], powah::R1, -int32_t(gp_regs.size() - i) * 8); code.LD(powah::R0, powah::R1, 16); code.MTLR(powah::R0); - EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false); } else { EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false); } + code.BLR(); code.ApplyRelocs(); /* diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp index cd0b4aa1cf..7e7734009d 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -19,7 +19,7 @@ namespace Dynarmic::Backend::PPC64 { template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - code.MR(PPC64::RCHECKBIT, value); + code.STW(value, PPC64::RJIT, offsetof(A64JitState, check_bit)); } template<> @@ -48,14 +48,8 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Ins if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { auto const result = ctx.reg_alloc.ScratchGpr(); // Need to account for endianess here... -#ifdef __ORDER_BIG_ENDIAN__ - constexpr u32 pe_offset64 = 4; -#else - constexpr u32 pe_offset64 = 0; -#endif auto const offs = offsetof(A64JitState, regs) - + A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64) - + pe_offset64; + + A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64); code.LWZ(result, PPC64::RJIT, offs); ctx.reg_alloc.DefineValue(inst, result); } else {