jit_state: Hide cpsr implementation
This commit is contained in:
parent
a4e85ad565
commit
6adc554b53
8 changed files with 87 additions and 37 deletions
|
@ -63,12 +63,12 @@ public:
|
|||
const std::array<std::uint32_t, 64>& ExtRegs() const;
|
||||
|
||||
/// View and modify CPSR.
|
||||
std::uint32_t& Cpsr();
|
||||
std::uint32_t Cpsr() const;
|
||||
void SetCpsr(std::uint32_t value);
|
||||
|
||||
/// View and modify FPSCR.
|
||||
std::uint32_t Fpscr() const;
|
||||
void SetFpscr(std::uint32_t value) const;
|
||||
void SetFpscr(std::uint32_t value);
|
||||
|
||||
/**
|
||||
* Returns true if Jit::Run was called but hasn't returned yet.
|
||||
|
|
|
@ -62,7 +62,7 @@ static Xbyak::Address MJitStateExtReg(Arm::ExtReg reg) {
|
|||
|
||||
static Xbyak::Address MJitStateCpsr() {
|
||||
using namespace Xbyak::util;
|
||||
return dword[r15 + offsetof(JitState, Cpsr)];
|
||||
return dword[r15 + offsetof(JitState, CPSR)];
|
||||
}
|
||||
|
||||
static void EraseInstruction(IR::Block& block, IR::Inst* inst) {
|
||||
|
@ -196,16 +196,25 @@ void EmitX64::EmitSetExtendedRegister64(RegAlloc& reg_alloc, IR::Block&, IR::Ins
|
|||
code->movsd(MJitStateExtReg(reg), source);
|
||||
}
|
||||
|
||||
static u32 GetCpsrImpl(JitState* jit_state) {
|
||||
return jit_state->Cpsr();
|
||||
}
|
||||
|
||||
void EmitX64::EmitGetCpsr(RegAlloc& reg_alloc, IR::Block&, IR::Inst* inst) {
|
||||
Xbyak::Reg32 result = reg_alloc.ScratchGpr().cvt32();
|
||||
code->mov(result, MJitStateCpsr());
|
||||
reg_alloc.DefineValue(inst, result);
|
||||
reg_alloc.HostCall(inst);
|
||||
code->mov(code->ABI_PARAM1, code->r15);
|
||||
code->CallFunction(&GetCpsrImpl);
|
||||
}
|
||||
|
||||
static void SetCpsrImpl(u32 value, JitState* jit_state) {
|
||||
jit_state->SetCpsr(value);
|
||||
}
|
||||
|
||||
void EmitX64::EmitSetCpsr(RegAlloc& reg_alloc, IR::Block&, IR::Inst* inst) {
|
||||
auto args = reg_alloc.GetArgumentInfo(inst);
|
||||
Xbyak::Reg32 arg = reg_alloc.UseGpr(args[0]).cvt32();
|
||||
code->mov(MJitStateCpsr(), arg);
|
||||
reg_alloc.HostCall(nullptr, args[0]);
|
||||
code->mov(code->ABI_PARAM2, code->r15);
|
||||
code->CallFunction(&SetCpsrImpl);
|
||||
}
|
||||
|
||||
void EmitX64::EmitGetNFlag(RegAlloc& reg_alloc, IR::Block&, IR::Inst* inst) {
|
||||
|
@ -404,9 +413,9 @@ void EmitX64::EmitBXWritePC(RegAlloc& reg_alloc, IR::Block&, IR::Inst* inst) {
|
|||
} else {
|
||||
using Xbyak::util::ptr;
|
||||
|
||||
Xbyak::Reg64 new_pc = reg_alloc.UseScratchGpr(arg);
|
||||
Xbyak::Reg64 tmp1 = reg_alloc.ScratchGpr();
|
||||
Xbyak::Reg64 tmp2 = reg_alloc.ScratchGpr();
|
||||
Xbyak::Reg32 new_pc = reg_alloc.UseScratchGpr(arg).cvt32();
|
||||
Xbyak::Reg32 tmp1 = reg_alloc.ScratchGpr().cvt32();
|
||||
Xbyak::Reg32 tmp2 = reg_alloc.ScratchGpr().cvt32();
|
||||
|
||||
code->mov(tmp1, MJitStateCpsr());
|
||||
code->mov(tmp2, tmp1);
|
||||
|
@ -415,7 +424,7 @@ void EmitX64::EmitBXWritePC(RegAlloc& reg_alloc, IR::Block&, IR::Inst* inst) {
|
|||
code->test(new_pc, u32(1));
|
||||
code->cmove(tmp1, tmp2); // CPSR.T = pc & 1
|
||||
code->mov(MJitStateCpsr(), tmp1);
|
||||
code->lea(tmp2, ptr[new_pc + new_pc * 1]);
|
||||
code->lea(tmp2, ptr[new_pc.cvt64() + new_pc.cvt64() * 1]);
|
||||
code->or_(tmp2, u32(0xFFFFFFFC)); // tmp2 = pc & 1 ? 0xFFFFFFFE : 0xFFFFFFFC
|
||||
code->and_(new_pc, tmp2);
|
||||
code->mov(MJitStateReg(Arm::Reg::PC), new_pc);
|
||||
|
|
|
@ -127,7 +127,7 @@ private:
|
|||
JitState& jit_state = this_.jit_state;
|
||||
|
||||
u32 pc = jit_state.Reg[15];
|
||||
Arm::PSR cpsr{jit_state.Cpsr};
|
||||
Arm::PSR cpsr{jit_state.Cpsr()};
|
||||
Arm::FPSCR fpscr{jit_state.FPSCR_mode};
|
||||
IR::LocationDescriptor descriptor{pc, cpsr, fpscr};
|
||||
|
||||
|
@ -205,19 +205,19 @@ const std::array<u32, 64>& Jit::ExtRegs() const {
|
|||
return impl->jit_state.ExtReg;
|
||||
}
|
||||
|
||||
u32& Jit::Cpsr() {
|
||||
return impl->jit_state.Cpsr;
|
||||
u32 Jit::Cpsr() const {
|
||||
return impl->jit_state.Cpsr();
|
||||
}
|
||||
|
||||
u32 Jit::Cpsr() const {
|
||||
return impl->jit_state.Cpsr;
|
||||
void Jit::SetCpsr(u32 value) {
|
||||
return impl->jit_state.SetCpsr(value);
|
||||
}
|
||||
|
||||
u32 Jit::Fpscr() const {
|
||||
return impl->jit_state.Fpscr();
|
||||
}
|
||||
|
||||
void Jit::SetFpscr(u32 value) const {
|
||||
void Jit::SetFpscr(u32 value) {
|
||||
return impl->jit_state.SetFpscr(value);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,44 @@
|
|||
namespace Dynarmic {
|
||||
namespace BackendX64 {
|
||||
|
||||
/**
|
||||
* CPSR Bits
|
||||
* =========
|
||||
*
|
||||
* ARM CPSR flags
|
||||
* --------------
|
||||
* N bit 31 Negative flag
|
||||
* Z bit 30 Zero flag
|
||||
* C bit 29 Carry flag
|
||||
* V bit 28 oVerflow flag
|
||||
* Q bit 27 Saturation flag
|
||||
* J bit 24 Jazelle instruction set flag
|
||||
* GE bits 16-19 Greater than or Equal flags
|
||||
* E bit 9 Data Endianness flag
|
||||
* A bit 8 Disable imprecise Aborts
|
||||
* I bit 7 Disable IRQ interrupts
|
||||
* F bit 6 Disable FIQ interrupts
|
||||
* T bit 5 Thumb instruction set flag
|
||||
* M bits 0-4 Processor Mode bits
|
||||
*
|
||||
* x64 LAHF+SETO flags
|
||||
* -------------------
|
||||
* SF bit 15 Sign flag
|
||||
* ZF bit 14 Zero flag
|
||||
* AF bit 12 Auxiliary flag
|
||||
* PF bit 10 Parity flag
|
||||
* CF bit 8 Carry flag
|
||||
* OF bit 0 Overflow flag
|
||||
*/
|
||||
|
||||
u32 JitState::Cpsr() const {
|
||||
return CPSR;
|
||||
}
|
||||
|
||||
void JitState::SetCpsr(u32 cpsr) {
|
||||
CPSR = cpsr;
|
||||
}
|
||||
|
||||
void JitState::ResetRSB() {
|
||||
rsb_location_descriptors.fill(0xFFFFFFFFFFFFFFFFull);
|
||||
rsb_codeptrs.fill(0);
|
||||
|
|
|
@ -25,10 +25,13 @@ constexpr size_t SpillCount = 64;
|
|||
struct JitState {
|
||||
JitState() { ResetRSB(); }
|
||||
|
||||
u32 Cpsr = 0;
|
||||
std::array<u32, 16> Reg{}; // Current register file.
|
||||
// TODO: Mode-specific register sets unimplemented.
|
||||
|
||||
u32 CPSR = 0;
|
||||
u32 Cpsr() const;
|
||||
void SetCpsr(u32 cpsr);
|
||||
|
||||
alignas(u64) std::array<u32, 64> ExtReg{}; // Extension registers.
|
||||
|
||||
std::array<u64, SpillCount> Spill{}; // Spill.
|
||||
|
|
|
@ -115,7 +115,7 @@ static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void*) {
|
|||
|
||||
jit->Regs() = interp_state.Reg;
|
||||
jit->ExtRegs() = interp_state.ExtReg;
|
||||
jit->Cpsr() = interp_state.Cpsr;
|
||||
jit->SetCpsr(interp_state.Cpsr);
|
||||
jit->SetFpscr(interp_state.VFP[VFP_FPSCR]);
|
||||
}
|
||||
|
||||
|
@ -233,7 +233,7 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe
|
|||
interp.ExtReg = initial_extregs;
|
||||
interp.VFP[VFP_FPSCR] = initial_fpscr;
|
||||
jit.Reset();
|
||||
jit.Cpsr() = initial_cpsr;
|
||||
jit.SetCpsr(initial_cpsr);
|
||||
jit.Regs() = initial_regs;
|
||||
jit.ExtRegs() = initial_extregs;
|
||||
jit.SetFpscr(initial_fpscr);
|
||||
|
@ -369,7 +369,7 @@ TEST_CASE( "arm: Optimization Failure (Randomized test case)", "[arm]" ) {
|
|||
0x6973b6bb, 0x267ea626, 0x69debf49, 0x8f976895, 0x4ecd2d0d, 0xcf89b8c7, 0xb6713f85, 0x15e2aa5,
|
||||
0xcd14336a, 0xafca0f3e, 0xace2efd9, 0x68fb82cd, 0x775447c0, 0xc9e1f8cd, 0xebe0e626, 0x0
|
||||
};
|
||||
jit.Cpsr() = 0x000001d0; // User-mode
|
||||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
jit.Run(6);
|
||||
|
||||
|
@ -407,7 +407,7 @@ TEST_CASE( "arm: shsax r11, sp, r9 (Edge-case)", "[arm]" ) {
|
|||
0x3a3b8b18, 0x96156555, 0xffef039f, 0xafb946f2, 0x2030a69a, 0xafe09b2a, 0x896823c8, 0xabde0ded,
|
||||
0x9825d6a6, 0x17498000, 0x999d2c95, 0x8b812a59, 0x209bdb58, 0x2f7fb1d4, 0x0f378107, 0x00000000
|
||||
};
|
||||
jit.Cpsr() = 0x000001d0; // User-mode
|
||||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
jit.Run(2);
|
||||
|
||||
|
@ -443,7 +443,7 @@ TEST_CASE( "arm: uasx (Edge-case)", "[arm]" ) {
|
|||
jit.Regs()[4] = 0x8ed38f4c;
|
||||
jit.Regs()[5] = 0x0000261d;
|
||||
jit.Regs()[15] = 0x00000000;
|
||||
jit.Cpsr() = 0x000001d0; // User-mode
|
||||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
jit.Run(2);
|
||||
|
||||
|
@ -472,7 +472,7 @@ static void RunVfpTests(u32 instr, std::vector<VfpTest> tests) {
|
|||
|
||||
for (const auto& test : tests) {
|
||||
jit.Regs()[15] = 0;
|
||||
jit.Cpsr() = 0x000001d0;
|
||||
jit.SetCpsr(0x000001d0);
|
||||
jit.ExtRegs()[4] = test.a;
|
||||
jit.ExtRegs()[6] = test.b;
|
||||
jit.SetFpscr(test.initial_fpscr);
|
||||
|
@ -1106,7 +1106,7 @@ TEST_CASE( "SMUAD", "[JitX64]" ) {
|
|||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
};
|
||||
jit.Cpsr() = 0x000001d0; // User-mode
|
||||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
jit.Run(6);
|
||||
|
||||
|
@ -1225,7 +1225,7 @@ TEST_CASE("arm: Test InvalidateCacheRange", "[arm]") {
|
|||
code_mem[3] = 0xeafffffe; // b +#0 (infinite loop)
|
||||
|
||||
jit.Regs() = {};
|
||||
jit.Cpsr() = 0x000001d0; // User-mode
|
||||
jit.SetCpsr(0x000001d0); // User-mode
|
||||
|
||||
jit.Run(4);
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void*) {
|
|||
interp_state.Reg[15] &= T ? 0xFFFFFFFE : 0xFFFFFFFC;
|
||||
|
||||
jit->Regs() = interp_state.Reg;
|
||||
jit->Cpsr() = interp_state.Cpsr;
|
||||
jit->SetCpsr(interp_state.Cpsr);
|
||||
}
|
||||
|
||||
static void Fail() {
|
||||
|
@ -204,7 +204,7 @@ void FuzzJitThumb(const size_t instruction_count, const size_t instructions_to_e
|
|||
|
||||
interp.Cpsr = 0x000001F0;
|
||||
interp.Reg = initial_regs;
|
||||
jit.Cpsr() = 0x000001F0;
|
||||
jit.SetCpsr(0x000001F0);
|
||||
jit.Regs() = initial_regs;
|
||||
|
||||
std::generate_n(code_mem.begin(), instruction_count, instruction_generator);
|
||||
|
|
|
@ -43,7 +43,7 @@ static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void*) {
|
|||
InterpreterMainLoop(&interp_state);
|
||||
|
||||
jit->Regs() = interp_state.Reg;
|
||||
jit->Cpsr() = interp_state.Cpsr;
|
||||
jit->SetCpsr(interp_state.Cpsr);
|
||||
}
|
||||
|
||||
static void AddTicks(u64) {}
|
||||
|
@ -66,7 +66,7 @@ TEST_CASE( "thumb: lsls r0, r1, #2", "[thumb]" ) {
|
|||
jit.Regs()[0] = 1;
|
||||
jit.Regs()[1] = 2;
|
||||
jit.Regs()[15] = 0; // PC = 0
|
||||
jit.Cpsr() = 0x00000030; // Thumb, User-mode
|
||||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
jit.Run(1);
|
||||
|
||||
|
@ -85,7 +85,7 @@ TEST_CASE( "thumb: lsls r0, r1, #31", "[thumb]" ) {
|
|||
jit.Regs()[0] = 1;
|
||||
jit.Regs()[1] = 0xFFFFFFFF;
|
||||
jit.Regs()[15] = 0; // PC = 0
|
||||
jit.Cpsr() = 0x00000030; // Thumb, User-mode
|
||||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
jit.Run(1);
|
||||
|
||||
|
@ -103,7 +103,7 @@ TEST_CASE( "thumb: revsh r4, r3", "[thumb]" ) {
|
|||
|
||||
jit.Regs()[3] = 0x12345678;
|
||||
jit.Regs()[15] = 0; // PC = 0
|
||||
jit.Cpsr() = 0x00000030; // Thumb, User-mode
|
||||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
jit.Run(1);
|
||||
|
||||
|
@ -121,7 +121,7 @@ TEST_CASE( "thumb: ldr r3, [r3, #28]", "[thumb]" ) {
|
|||
|
||||
jit.Regs()[3] = 0x12345678;
|
||||
jit.Regs()[15] = 0; // PC = 0
|
||||
jit.Cpsr() = 0x00000030; // Thumb, User-mode
|
||||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
jit.Run(1);
|
||||
|
||||
|
@ -137,7 +137,7 @@ TEST_CASE( "thumb: blx +#67712", "[thumb]" ) {
|
|||
code_mem[2] = 0xE7FE; // b +#0
|
||||
|
||||
jit.Regs()[15] = 0; // PC = 0
|
||||
jit.Cpsr() = 0x00000030; // Thumb, User-mode
|
||||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
jit.Run(1);
|
||||
|
||||
|
@ -153,7 +153,7 @@ TEST_CASE( "thumb: bl +#234584", "[thumb]" ) {
|
|||
code_mem[2] = 0xE7FE; // b +#0
|
||||
|
||||
jit.Regs()[15] = 0; // PC = 0
|
||||
jit.Cpsr() = 0x00000030; // Thumb, User-mode
|
||||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
jit.Run(1);
|
||||
|
||||
|
@ -169,7 +169,7 @@ TEST_CASE( "thumb: bl -#42", "[thumb]" ) {
|
|||
code_mem[2] = 0xE7FE; // b +#0
|
||||
|
||||
jit.Regs()[15] = 0; // PC = 0
|
||||
jit.Cpsr() = 0x00000030; // Thumb, User-mode
|
||||
jit.SetCpsr(0x00000030); // Thumb, User-mode
|
||||
|
||||
jit.Run(1);
|
||||
|
||||
|
|
Loading…
Reference in a new issue