use common return point to not corrupt regs also use jit state for checkbit :)

This commit is contained in:
lizzie
2026-08-12 23:21:09 +00:00
parent 476a2366f2
commit c02fd907aa
7 changed files with 25 additions and 45 deletions
@@ -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)};
@@ -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;
@@ -75,18 +75,12 @@ struct A64AddressSpace final {
ankerl::unordered_dense::map<u64, EmittedBlockInfo> 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);
}
};
@@ -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;
@@ -3,6 +3,7 @@
#pragma once
#include <powah_emit.hpp>
#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
@@ -146,22 +146,24 @@ void EmitIR<IR::Opcode::NZCVFromPackedFlags>(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<IR::Term::ReturnToDispatch>(&terminal))
return EmitTerminal(code, ctx, *x, initial_location, is_single_step);
if (auto const x = std::get_if<IR::Term::LinkBlock>(&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<IR::Term::LeafTerminal>(&terminal))
return EmitLeafTerminal(code, ctx, *x, initial_location, is_single_step);
if (auto const x = std::get_if<IR::Term::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();
/*
@@ -19,7 +19,7 @@ namespace Dynarmic::Backend::PPC64 {
template<>
void EmitIR<IR::Opcode::A64SetCheckBit>(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<IR::Opcode::A64GetW>(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 {