mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-07 06:18:23 +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 exclusive_state = 0;
|
||||||
u32 cpsr_nzcv = 0;
|
u32 cpsr_nzcv = 0;
|
||||||
u32 fpscr = 0;
|
u32 fpscr = 0;
|
||||||
u8 check_bit = 0;
|
u32 check_bit = 0;
|
||||||
|
|
||||||
IR::LocationDescriptor GetLocationDescriptor() const {
|
IR::LocationDescriptor GetLocationDescriptor() const {
|
||||||
return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)};
|
return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)};
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ struct A64JitState {
|
|||||||
u32 fpcr = 0;
|
u32 fpcr = 0;
|
||||||
u32 fpsr = 0;
|
u32 fpsr = 0;
|
||||||
volatile u32 halt_reason = 0;
|
volatile u32 halt_reason = 0;
|
||||||
u8 check_bit = 0;
|
u32 check_bit = 0;
|
||||||
|
|
||||||
IR::LocationDescriptor GetLocationDescriptor() const {
|
IR::LocationDescriptor GetLocationDescriptor() const {
|
||||||
const u64 fpcr_u64 = u64(fpcr & A64::LocationDescriptor::fpcr_mask) << A64::LocationDescriptor::fpcr_shift;
|
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;
|
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 {
|
struct A64Core final {
|
||||||
|
using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void *fn);
|
||||||
static HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) {
|
static HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) {
|
||||||
const auto loc = thread_ctx.GetLocationDescriptor();
|
const auto loc = thread_ctx.GetLocationDescriptor();
|
||||||
const auto entry = process.GetOrEmit(loc);
|
const auto entry = process.GetOrEmit(loc);
|
||||||
using AbstractCodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void (*fn)());
|
return (CodeFn(entry))(&process, &thread_ctx, halt_reason, (void*)&A64Core::Run);
|
||||||
using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, AbstractCodeFn fn);
|
|
||||||
return (CodeFn(entry))(&process, &thread_ctx, halt_reason, AbstractCodeFn(test_thunk));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ constexpr powah::GPR RHALTREASON = powah::R5;
|
|||||||
constexpr powah::GPR RTOCPTR = powah::R6;
|
constexpr powah::GPR RTOCPTR = powah::R6;
|
||||||
// temporals
|
// temporals
|
||||||
constexpr powah::GPR RNZCV = powah::R7;
|
constexpr powah::GPR RNZCV = powah::R7;
|
||||||
constexpr powah::GPR RCHECKBIT = powah::R8;
|
|
||||||
|
|
||||||
constexpr powah::GPR ABI_PARAM1 = powah::R3;
|
constexpr powah::GPR ABI_PARAM1 = powah::R3;
|
||||||
constexpr powah::GPR ABI_PARAM2 = powah::R4;
|
constexpr powah::GPR ABI_PARAM2 = powah::R4;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <powah_emit.hpp>
|
||||||
#include "dynarmic/backend/ppc64/emit_ppc64.h"
|
#include "dynarmic/backend/ppc64/emit_ppc64.h"
|
||||||
#include "dynarmic/backend/ppc64/reg_alloc.h"
|
#include "dynarmic/backend/ppc64/reg_alloc.h"
|
||||||
|
|
||||||
@@ -19,6 +20,8 @@ struct EmitContext {
|
|||||||
RegAlloc& reg_alloc;
|
RegAlloc& reg_alloc;
|
||||||
const EmitConfig& emit_conf;
|
const EmitConfig& emit_conf;
|
||||||
EmittedBlockInfo& ebi;
|
EmittedBlockInfo& ebi;
|
||||||
|
// label used when returning :)
|
||||||
|
powah::Label l_return;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Dynarmic::Backend::RV64
|
} // namespace Dynarmic::Backend::RV64
|
||||||
|
|||||||
@@ -146,22 +146,24 @@ void EmitIR<IR::Opcode::NZCVFromPackedFlags>(powah::Context&, EmitContext&, IR::
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
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);
|
||||||
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) {
|
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) {
|
||||||
ASSERT(false && "unimp");
|
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) {
|
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) {
|
||||||
if (ctx.emit_conf.a64_variant) {
|
if (ctx.emit_conf.a64_variant) {
|
||||||
auto const tmp = ctx.reg_alloc.ScratchGpr();
|
auto const tmp = ctx.reg_alloc.ScratchGpr();
|
||||||
code.LI(tmp, terminal.next.Value());
|
code.LI(tmp, terminal.next.Value());
|
||||||
code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc));
|
code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc));
|
||||||
code.LD(tmp, PPC64::RTOCPTR, 0);
|
// code.MTCTR(powah::R6);
|
||||||
code.MTCTR(tmp);
|
// code.BCTR();
|
||||||
code.LD(powah::R2, PPC64::RTOCPTR, 8);
|
code.B(ctx.l_return);
|
||||||
code.LD(powah::R11, PPC64::RTOCPTR, 16);
|
|
||||||
code.BCTR();
|
|
||||||
} else {
|
} else {
|
||||||
auto const tmp = ctx.reg_alloc.ScratchGpr();
|
auto const tmp = ctx.reg_alloc.ScratchGpr();
|
||||||
code.LI(tmp, terminal.next.Value());
|
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) {
|
void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
if (ctx.emit_conf.a64_variant) {
|
EmitTerminal(code, ctx, terminal, IR::Term::LinkBlock{terminal.next}, is_single_step);
|
||||||
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::PopRSBHint, IR::LocationDescriptor, bool) {
|
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_else = code.DefineLabel();
|
||||||
powah::Label const l_end = code.DefineLabel();
|
powah::Label const l_end = code.DefineLabel();
|
||||||
auto const tmp = ctx.reg_alloc.ScratchGpr();
|
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.CMPLDI(tmp, 0);
|
||||||
code.BEQ(powah::CR0, l_else);
|
code.BEQ(powah::CR0, l_else);
|
||||||
// CheckBit == 1
|
// CheckBit == 1
|
||||||
@@ -220,7 +208,7 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckHalt te
|
|||||||
ASSERT(false && "unimp");
|
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))
|
if (auto const x = std::get_if<IR::Term::ReturnToDispatch>(&terminal))
|
||||||
return EmitTerminal(code, ctx, *x, initial_location, is_single_step);
|
return EmitTerminal(code, ctx, *x, initial_location, is_single_step);
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlock>(&terminal))
|
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();
|
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))
|
if (auto const x = std::get_if<IR::Term::LeafTerminal>(&terminal))
|
||||||
return EmitLeafTerminal(code, ctx, *x, initial_location, is_single_step);
|
return EmitLeafTerminal(code, ctx, *x, initial_location, is_single_step);
|
||||||
if (auto const x = std::get_if<IR::Term::If>(&terminal))
|
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();
|
// 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);
|
code.ADDI(powah::R1, powah::R1, stack_size);
|
||||||
for (size_t i = 0; i < gp_regs.size(); ++i)
|
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(gp_regs[i], powah::R1, -int32_t(gp_regs.size() - i) * 8);
|
||||||
code.LD(powah::R0, powah::R1, 16);
|
code.LD(powah::R0, powah::R1, 16);
|
||||||
code.MTLR(powah::R0);
|
code.MTLR(powah::R0);
|
||||||
EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false);
|
|
||||||
} else {
|
} else {
|
||||||
EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false);
|
EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false);
|
||||||
}
|
}
|
||||||
|
code.BLR();
|
||||||
code.ApplyRelocs();
|
code.ApplyRelocs();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace Dynarmic::Backend::PPC64 {
|
|||||||
template<>
|
template<>
|
||||||
void EmitIR<IR::Opcode::A64SetCheckBit>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) {
|
void EmitIR<IR::Opcode::A64SetCheckBit>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(0));
|
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<>
|
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) {
|
if (inst->GetArg(0).GetType() == IR::Type::A64Reg) {
|
||||||
auto const result = ctx.reg_alloc.ScratchGpr();
|
auto const result = ctx.reg_alloc.ScratchGpr();
|
||||||
// Need to account for endianess here...
|
// 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)
|
auto const offs = offsetof(A64JitState, regs)
|
||||||
+ A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64)
|
+ A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64);
|
||||||
+ pe_offset64;
|
|
||||||
code.LWZ(result, PPC64::RJIT, offs);
|
code.LWZ(result, PPC64::RJIT, offs);
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user