7
externals/powah/powah_emit.hpp
vendored
7
externals/powah/powah_emit.hpp
vendored
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)};
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user