mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-14 04:24:31 +00:00
use common return point to not corrupt regs also use jit state for checkbit :)
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user