Use ctr like gcc does

Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
lizzie
2025-12-10 09:13:26 +00:00
parent f3a8742535
commit 2faa4947e9
9 changed files with 24 additions and 9 deletions

View File

@@ -368,10 +368,11 @@ struct Context {
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);
void BLR() {
base[offset++] = 0x4e800020; //BCLR(R0, CR0, R0);
}
void MFCTR(GPR const rt) { MFSPR(powah::GPR{9}, rt, powah::GPR{0}); }
void MTCTR(GPR const rt) { MTSPR(powah::GPR{9}, rt, powah::GPR{0}); }
void BCTRL() { base[offset++] = 0x4e800421; } //BCCTRL(R0, CR0, R0);
// TODO: PowerPC 11 stuff
void ISEL(GPR const rd, GPR const ra, GPR const rb, uint32_t d) {

View File

@@ -4,3 +4,5 @@ The ppc64 backend currently only supports the little endian variant, with big en
- Flag handling: Flags are emulated via software, while there may be some funny tricks with the CTR, I'd rather not bother - plus it's widely known that those instructions are not nice on real metal - so I would rather take the i-cache cost.
- 128-bit atomics: No 128-bit atomic support is provided, this may cause wrong or erroneous execution in some contexts.
To handle endianess differences all 16/32/64-bit loads and stores to the "emulated memory" are byteswapped beforehand.

View File

@@ -23,6 +23,8 @@ struct A32JitState {
u32 cpsr_nzcv = 0;
u32 fpscr = 0;
u8 check_bit = 0;
void* run_fn = nullptr;
IR::LocationDescriptor GetLocationDescriptor() const {
return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)};
}

View File

@@ -74,6 +74,7 @@ struct A32Core final {
auto const loc = thread_ctx.GetLocationDescriptor();
auto const entry = process.GetOrEmit(loc);
using CodeFn = HaltReason (*)(A32AddressSpace*, A32JitState*, volatile u32*, void*);
thread_ctx.run_fn = (void*)&A32Core::Run;
return (CodeFn(entry))(&process, &thread_ctx, halt_reason, reinterpret_cast<void*>(&A32Core::Run));
}
};

View File

@@ -29,6 +29,8 @@ struct A64JitState {
u32 fpsr = 0;
volatile u32 halt_reason = 0;
u8 check_bit = 0;
void* run_fn = nullptr;
IR::LocationDescriptor GetLocationDescriptor() const {
const u64 fpcr_u64 = u64(fpcr & A64::LocationDescriptor::fpcr_mask) << A64::LocationDescriptor::fpcr_shift;
const u64 pc_u64 = pc & A64::LocationDescriptor::pc_mask;

View File

@@ -76,6 +76,7 @@ struct A64Core final {
const auto loc = thread_ctx.GetLocationDescriptor();
const auto entry = process.GetOrEmit(loc);
using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void*);
thread_ctx.run_fn = (void*)&A64Core::Run;
return (CodeFn(entry))(&process, &thread_ctx, halt_reason, reinterpret_cast<void*>(&A64Core::Run));
}
};

View File

@@ -8,11 +8,10 @@
namespace Dynarmic::Backend::PPC64 {
// Jit fn signature => (AXXAddressSpace& process, AXXJitState& thread_ctx, volatile u32* halt_reason, void* link_fn)
// 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 RLINKFN = powah::R6;
constexpr powah::GPR RNZCV = powah::R31;
constexpr powah::GPR ABI_PARAM1 = powah::R3;

View File

@@ -21,6 +21,7 @@
#include "dynarmic/ir/basic_block.h"
#include "dynarmic/ir/microinstruction.h"
#include "dynarmic/ir/opcodes.h"
#include "stack_layout.h"
namespace Dynarmic::Backend::PPC64 {
@@ -155,23 +156,28 @@ 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_lr = ctx.reg_alloc.ScratchGpr();
auto const tmp = ctx.reg_alloc.ScratchGpr();
code.LI(tmp, terminal.next.Value());
code.LD(tmp_lr, PPC64::RJIT, offsetof(StackLayout, lr));
code.MFCTR(tmp_lr);
if (ctx.emit_conf.a64_variant) {
code.LI(tmp, terminal.next.Value());
code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc));
code.MFLR(PPC64::RLINKFN);
code.LD(tmp, PPC64::RJIT, offsetof(A64JitState, run_fn));
code.MTCTR(tmp);
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.BCTRL();
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.LI(tmp, terminal.next.Value());
code.STW(tmp, PPC64::RJIT, offsetof(A32JitState, regs) + sizeof(u32) * 15);
ASSERT(false && "unimp");
}
code.MTCTR(tmp_lr);
}
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) {

View File

@@ -15,6 +15,7 @@ struct alignas(16) StackLayout {
std::array<u64, 18> regs;
std::array<u64, SpillCount> spill;
u64 check_bit;
void* lr;
};
static_assert(sizeof(StackLayout) % 16 == 0);