diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 167a2c6945..0f10199a77 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -366,6 +366,9 @@ struct Context { void LI(GPR const rx, uint32_t value) { ADDI(rx, R0, value); } void LIS(GPR const rx, uint32_t value) { ADDIS(rx, R0, value); } + void MFLR(GPR const rt) { MFSPR(powah::GPR{8}, rt, powah::GPR{0}); } + void MTLR(GPR const rt) { MTSPR(powah::GPR{8}, rt, powah::GPR{0}); } + void BLR() { base[offset++] = 0x4e800020; //BCLR(R0, CR0, R0); } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index b67fa50c10..5568ff1fab 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -72,8 +72,8 @@ struct A32Core final { static HaltReason Run(A32AddressSpace& process, A32JitState& thread_ctx, volatile u32* halt_reason) { auto const loc = thread_ctx.GetLocationDescriptor(); auto const entry = process.GetOrEmit(loc); - using CodeFn = HaltReason (*)(A32JitState*, volatile u32*); - return (CodeFn(entry))(&thread_ctx, halt_reason); + using CodeFn = HaltReason (*)(A32AddressSpace*, A32JitState*, volatile u32*); + return (CodeFn(entry))(&process, &thread_ctx, halt_reason); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index 94ddd84dad..5cd10c726f 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -22,7 +22,7 @@ struct A64JitState { u64 pc = 0; alignas(16) std::array vec{}; u64 sp = 0; - u32 upper_location_descriptor; + u32 upper_location_descriptor = 0; u32 exclusive_state = 0; u32 pstate = 0; u32 fpcr = 0; @@ -30,7 +30,9 @@ struct A64JitState { volatile u32 halt_reason = 0; u8 check_bit = 0; IR::LocationDescriptor GetLocationDescriptor() const { - return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; + const u64 fpcr_u64 = u64(fpcr & A64::LocationDescriptor::fpcr_mask) << A64::LocationDescriptor::fpcr_shift; + const u64 pc_u64 = pc & A64::LocationDescriptor::pc_mask; + return IR::LocationDescriptor{pc_u64 | fpcr_u64}; } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index accbceaaaf..75ea6afc95 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -31,8 +31,7 @@ struct A64AddressSpace final { CodePtr GetOrEmit(IR::LocationDescriptor desc) { if (auto const it = block_entries.find(desc.Value()); it != block_entries.end()) return it->second; - - const auto get_code = [this](u64 vaddr) { + auto const 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}); @@ -75,8 +74,8 @@ struct A64Core final { 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 CodeFn = HaltReason (*)(A64JitState*, volatile u32*); - return (CodeFn(entry))(&thread_ctx, halt_reason); + using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*); + return (CodeFn(entry))(&process, &thread_ctx, halt_reason); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index 3e8bbbacf2..0f7e059110 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -8,7 +8,10 @@ namespace Dynarmic::Backend::PPC64 { -constexpr powah::GPR RJIT = powah::R3; //yeah it's param, so what? +// Jit fn signature => (AXXAddressSpace& process, AXXJitState& thread_ctx, volatile u32* halt_reason) +constexpr powah::GPR RPROCESS = powah::R3; +constexpr powah::GPR RJIT = powah::R4; +constexpr powah::GPR RHALTREASON = powah::R5; constexpr powah::GPR RNZCV = powah::R31; constexpr powah::GPR ABI_PARAM1 = powah::R3; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index d463c7c069..09d9e15d82 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -4,6 +4,7 @@ #include "dynarmic/backend/ppc64/emit_ppc64.h" #include +#include #include #include @@ -156,10 +157,21 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDisp void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LI(tmp, terminal.next.Value()); - if (ctx.emit_conf.a64_variant) + if (ctx.emit_conf.a64_variant) { code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); - else + code.MFLR(PPC64::RLINKFN); + for (u32 i = 0; i < 4; ++i) + code.STD(powah::GPR{3 + i}, powah::R1, -((GPR_ORDER.size() + i) * 8)); + code.ADDIS(powah::R1, powah::R1, -sizeof(StackLayout)); + code.BLR(); + code.ADDI(powah::R1, powah::R1, sizeof(StackLayout)); + for (u32 i = 0; i < 4; ++i) + code.LD(powah::GPR{3 + i}, powah::R1, -((GPR_ORDER.size() + i) * 8)); + code.MTLR(PPC64::RLINKFN); + } else { 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) { @@ -211,7 +223,7 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf EmitContext ctx{block, reg_alloc, emit_conf, ebi}; auto const start_offset = code.offset; - ebi.entry_point = CodePtr(code.base + start_offset); + ebi.entry_point = &code.base[start_offset]; // Non-volatile saves std::vector gpr_order{GPR_ORDER}; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h index ac209d8099..b7e68b71ed 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h @@ -21,21 +21,9 @@ enum class Opcode; namespace Dynarmic::Backend::PPC64 { -using CodePtr = std::byte*; - -enum class LinkTarget { - ReturnFromRunCode, -}; - -struct Relocation { - std::ptrdiff_t code_offset; - LinkTarget target; -}; - struct EmittedBlockInfo { - CodePtr entry_point; + std::uint32_t* entry_point; size_t size; - std::vector relocations; }; struct EmitConfig {