jit_state: Hide cpsr implementation

This commit is contained in:
MerryMage 2017-12-02 13:55:04 +00:00
parent a4e85ad565
commit 6adc554b53
8 changed files with 87 additions and 37 deletions

View file

@ -63,12 +63,12 @@ public:
const std::array<std::uint32_t, 64>& ExtRegs() const; const std::array<std::uint32_t, 64>& ExtRegs() const;
/// View and modify CPSR. /// View and modify CPSR.
std::uint32_t& Cpsr();
std::uint32_t Cpsr() const; std::uint32_t Cpsr() const;
void SetCpsr(std::uint32_t value);
/// View and modify FPSCR. /// View and modify FPSCR.
std::uint32_t Fpscr() const; 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. * Returns true if Jit::Run was called but hasn't returned yet.

View file

@ -62,7 +62,7 @@ static Xbyak::Address MJitStateExtReg(Arm::ExtReg reg) {
static Xbyak::Address MJitStateCpsr() { static Xbyak::Address MJitStateCpsr() {
using namespace Xbyak::util; 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) { 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); 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) { void EmitX64::EmitGetCpsr(RegAlloc& reg_alloc, IR::Block&, IR::Inst* inst) {
Xbyak::Reg32 result = reg_alloc.ScratchGpr().cvt32(); reg_alloc.HostCall(inst);
code->mov(result, MJitStateCpsr()); code->mov(code->ABI_PARAM1, code->r15);
reg_alloc.DefineValue(inst, result); 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) { void EmitX64::EmitSetCpsr(RegAlloc& reg_alloc, IR::Block&, IR::Inst* inst) {
auto args = reg_alloc.GetArgumentInfo(inst); auto args = reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 arg = reg_alloc.UseGpr(args[0]).cvt32(); reg_alloc.HostCall(nullptr, args[0]);
code->mov(MJitStateCpsr(), arg); code->mov(code->ABI_PARAM2, code->r15);
code->CallFunction(&SetCpsrImpl);
} }
void EmitX64::EmitGetNFlag(RegAlloc& reg_alloc, IR::Block&, IR::Inst* inst) { 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 { } else {
using Xbyak::util::ptr; using Xbyak::util::ptr;
Xbyak::Reg64 new_pc = reg_alloc.UseScratchGpr(arg); Xbyak::Reg32 new_pc = reg_alloc.UseScratchGpr(arg).cvt32();
Xbyak::Reg64 tmp1 = reg_alloc.ScratchGpr(); Xbyak::Reg32 tmp1 = reg_alloc.ScratchGpr().cvt32();
Xbyak::Reg64 tmp2 = reg_alloc.ScratchGpr(); Xbyak::Reg32 tmp2 = reg_alloc.ScratchGpr().cvt32();
code->mov(tmp1, MJitStateCpsr()); code->mov(tmp1, MJitStateCpsr());
code->mov(tmp2, tmp1); 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->test(new_pc, u32(1));
code->cmove(tmp1, tmp2); // CPSR.T = pc & 1 code->cmove(tmp1, tmp2); // CPSR.T = pc & 1
code->mov(MJitStateCpsr(), tmp1); 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->or_(tmp2, u32(0xFFFFFFFC)); // tmp2 = pc & 1 ? 0xFFFFFFFE : 0xFFFFFFFC
code->and_(new_pc, tmp2); code->and_(new_pc, tmp2);
code->mov(MJitStateReg(Arm::Reg::PC), new_pc); code->mov(MJitStateReg(Arm::Reg::PC), new_pc);

View file

@ -127,7 +127,7 @@ private:
JitState& jit_state = this_.jit_state; JitState& jit_state = this_.jit_state;
u32 pc = jit_state.Reg[15]; 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}; Arm::FPSCR fpscr{jit_state.FPSCR_mode};
IR::LocationDescriptor descriptor{pc, cpsr, fpscr}; IR::LocationDescriptor descriptor{pc, cpsr, fpscr};
@ -205,19 +205,19 @@ const std::array<u32, 64>& Jit::ExtRegs() const {
return impl->jit_state.ExtReg; return impl->jit_state.ExtReg;
} }
u32& Jit::Cpsr() { u32 Jit::Cpsr() const {
return impl->jit_state.Cpsr; return impl->jit_state.Cpsr();
} }
u32 Jit::Cpsr() const { void Jit::SetCpsr(u32 value) {
return impl->jit_state.Cpsr; return impl->jit_state.SetCpsr(value);
} }
u32 Jit::Fpscr() const { u32 Jit::Fpscr() const {
return impl->jit_state.Fpscr(); return impl->jit_state.Fpscr();
} }
void Jit::SetFpscr(u32 value) const { void Jit::SetFpscr(u32 value) {
return impl->jit_state.SetFpscr(value); return impl->jit_state.SetFpscr(value);
} }

View file

@ -14,6 +14,44 @@
namespace Dynarmic { namespace Dynarmic {
namespace BackendX64 { 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() { void JitState::ResetRSB() {
rsb_location_descriptors.fill(0xFFFFFFFFFFFFFFFFull); rsb_location_descriptors.fill(0xFFFFFFFFFFFFFFFFull);
rsb_codeptrs.fill(0); rsb_codeptrs.fill(0);

View file

@ -25,10 +25,13 @@ constexpr size_t SpillCount = 64;
struct JitState { struct JitState {
JitState() { ResetRSB(); } JitState() { ResetRSB(); }
u32 Cpsr = 0;
std::array<u32, 16> Reg{}; // Current register file. std::array<u32, 16> Reg{}; // Current register file.
// TODO: Mode-specific register sets unimplemented. // 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. alignas(u64) std::array<u32, 64> ExtReg{}; // Extension registers.
std::array<u64, SpillCount> Spill{}; // Spill. std::array<u64, SpillCount> Spill{}; // Spill.

View file

@ -115,7 +115,7 @@ static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void*) {
jit->Regs() = interp_state.Reg; jit->Regs() = interp_state.Reg;
jit->ExtRegs() = interp_state.ExtReg; jit->ExtRegs() = interp_state.ExtReg;
jit->Cpsr() = interp_state.Cpsr; jit->SetCpsr(interp_state.Cpsr);
jit->SetFpscr(interp_state.VFP[VFP_FPSCR]); 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.ExtReg = initial_extregs;
interp.VFP[VFP_FPSCR] = initial_fpscr; interp.VFP[VFP_FPSCR] = initial_fpscr;
jit.Reset(); jit.Reset();
jit.Cpsr() = initial_cpsr; jit.SetCpsr(initial_cpsr);
jit.Regs() = initial_regs; jit.Regs() = initial_regs;
jit.ExtRegs() = initial_extregs; jit.ExtRegs() = initial_extregs;
jit.SetFpscr(initial_fpscr); 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, 0x6973b6bb, 0x267ea626, 0x69debf49, 0x8f976895, 0x4ecd2d0d, 0xcf89b8c7, 0xb6713f85, 0x15e2aa5,
0xcd14336a, 0xafca0f3e, 0xace2efd9, 0x68fb82cd, 0x775447c0, 0xc9e1f8cd, 0xebe0e626, 0x0 0xcd14336a, 0xafca0f3e, 0xace2efd9, 0x68fb82cd, 0x775447c0, 0xc9e1f8cd, 0xebe0e626, 0x0
}; };
jit.Cpsr() = 0x000001d0; // User-mode jit.SetCpsr(0x000001d0); // User-mode
jit.Run(6); 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, 0x3a3b8b18, 0x96156555, 0xffef039f, 0xafb946f2, 0x2030a69a, 0xafe09b2a, 0x896823c8, 0xabde0ded,
0x9825d6a6, 0x17498000, 0x999d2c95, 0x8b812a59, 0x209bdb58, 0x2f7fb1d4, 0x0f378107, 0x00000000 0x9825d6a6, 0x17498000, 0x999d2c95, 0x8b812a59, 0x209bdb58, 0x2f7fb1d4, 0x0f378107, 0x00000000
}; };
jit.Cpsr() = 0x000001d0; // User-mode jit.SetCpsr(0x000001d0); // User-mode
jit.Run(2); jit.Run(2);
@ -443,7 +443,7 @@ TEST_CASE( "arm: uasx (Edge-case)", "[arm]" ) {
jit.Regs()[4] = 0x8ed38f4c; jit.Regs()[4] = 0x8ed38f4c;
jit.Regs()[5] = 0x0000261d; jit.Regs()[5] = 0x0000261d;
jit.Regs()[15] = 0x00000000; jit.Regs()[15] = 0x00000000;
jit.Cpsr() = 0x000001d0; // User-mode jit.SetCpsr(0x000001d0); // User-mode
jit.Run(2); jit.Run(2);
@ -472,7 +472,7 @@ static void RunVfpTests(u32 instr, std::vector<VfpTest> tests) {
for (const auto& test : tests) { for (const auto& test : tests) {
jit.Regs()[15] = 0; jit.Regs()[15] = 0;
jit.Cpsr() = 0x000001d0; jit.SetCpsr(0x000001d0);
jit.ExtRegs()[4] = test.a; jit.ExtRegs()[4] = test.a;
jit.ExtRegs()[6] = test.b; jit.ExtRegs()[6] = test.b;
jit.SetFpscr(test.initial_fpscr); jit.SetFpscr(test.initial_fpscr);
@ -1106,7 +1106,7 @@ TEST_CASE( "SMUAD", "[JitX64]" ) {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
}; };
jit.Cpsr() = 0x000001d0; // User-mode jit.SetCpsr(0x000001d0); // User-mode
jit.Run(6); jit.Run(6);
@ -1225,7 +1225,7 @@ TEST_CASE("arm: Test InvalidateCacheRange", "[arm]") {
code_mem[3] = 0xeafffffe; // b +#0 (infinite loop) code_mem[3] = 0xeafffffe; // b +#0 (infinite loop)
jit.Regs() = {}; jit.Regs() = {};
jit.Cpsr() = 0x000001d0; // User-mode jit.SetCpsr(0x000001d0); // User-mode
jit.Run(4); jit.Run(4);

View file

@ -107,7 +107,7 @@ static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void*) {
interp_state.Reg[15] &= T ? 0xFFFFFFFE : 0xFFFFFFFC; interp_state.Reg[15] &= T ? 0xFFFFFFFE : 0xFFFFFFFC;
jit->Regs() = interp_state.Reg; jit->Regs() = interp_state.Reg;
jit->Cpsr() = interp_state.Cpsr; jit->SetCpsr(interp_state.Cpsr);
} }
static void Fail() { static void Fail() {
@ -204,7 +204,7 @@ void FuzzJitThumb(const size_t instruction_count, const size_t instructions_to_e
interp.Cpsr = 0x000001F0; interp.Cpsr = 0x000001F0;
interp.Reg = initial_regs; interp.Reg = initial_regs;
jit.Cpsr() = 0x000001F0; jit.SetCpsr(0x000001F0);
jit.Regs() = initial_regs; jit.Regs() = initial_regs;
std::generate_n(code_mem.begin(), instruction_count, instruction_generator); std::generate_n(code_mem.begin(), instruction_count, instruction_generator);

View file

@ -43,7 +43,7 @@ static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit, void*) {
InterpreterMainLoop(&interp_state); InterpreterMainLoop(&interp_state);
jit->Regs() = interp_state.Reg; jit->Regs() = interp_state.Reg;
jit->Cpsr() = interp_state.Cpsr; jit->SetCpsr(interp_state.Cpsr);
} }
static void AddTicks(u64) {} static void AddTicks(u64) {}
@ -66,7 +66,7 @@ TEST_CASE( "thumb: lsls r0, r1, #2", "[thumb]" ) {
jit.Regs()[0] = 1; jit.Regs()[0] = 1;
jit.Regs()[1] = 2; jit.Regs()[1] = 2;
jit.Regs()[15] = 0; // PC = 0 jit.Regs()[15] = 0; // PC = 0
jit.Cpsr() = 0x00000030; // Thumb, User-mode jit.SetCpsr(0x00000030); // Thumb, User-mode
jit.Run(1); jit.Run(1);
@ -85,7 +85,7 @@ TEST_CASE( "thumb: lsls r0, r1, #31", "[thumb]" ) {
jit.Regs()[0] = 1; jit.Regs()[0] = 1;
jit.Regs()[1] = 0xFFFFFFFF; jit.Regs()[1] = 0xFFFFFFFF;
jit.Regs()[15] = 0; // PC = 0 jit.Regs()[15] = 0; // PC = 0
jit.Cpsr() = 0x00000030; // Thumb, User-mode jit.SetCpsr(0x00000030); // Thumb, User-mode
jit.Run(1); jit.Run(1);
@ -103,7 +103,7 @@ TEST_CASE( "thumb: revsh r4, r3", "[thumb]" ) {
jit.Regs()[3] = 0x12345678; jit.Regs()[3] = 0x12345678;
jit.Regs()[15] = 0; // PC = 0 jit.Regs()[15] = 0; // PC = 0
jit.Cpsr() = 0x00000030; // Thumb, User-mode jit.SetCpsr(0x00000030); // Thumb, User-mode
jit.Run(1); jit.Run(1);
@ -121,7 +121,7 @@ TEST_CASE( "thumb: ldr r3, [r3, #28]", "[thumb]" ) {
jit.Regs()[3] = 0x12345678; jit.Regs()[3] = 0x12345678;
jit.Regs()[15] = 0; // PC = 0 jit.Regs()[15] = 0; // PC = 0
jit.Cpsr() = 0x00000030; // Thumb, User-mode jit.SetCpsr(0x00000030); // Thumb, User-mode
jit.Run(1); jit.Run(1);
@ -137,7 +137,7 @@ TEST_CASE( "thumb: blx +#67712", "[thumb]" ) {
code_mem[2] = 0xE7FE; // b +#0 code_mem[2] = 0xE7FE; // b +#0
jit.Regs()[15] = 0; // PC = 0 jit.Regs()[15] = 0; // PC = 0
jit.Cpsr() = 0x00000030; // Thumb, User-mode jit.SetCpsr(0x00000030); // Thumb, User-mode
jit.Run(1); jit.Run(1);
@ -153,7 +153,7 @@ TEST_CASE( "thumb: bl +#234584", "[thumb]" ) {
code_mem[2] = 0xE7FE; // b +#0 code_mem[2] = 0xE7FE; // b +#0
jit.Regs()[15] = 0; // PC = 0 jit.Regs()[15] = 0; // PC = 0
jit.Cpsr() = 0x00000030; // Thumb, User-mode jit.SetCpsr(0x00000030); // Thumb, User-mode
jit.Run(1); jit.Run(1);
@ -169,7 +169,7 @@ TEST_CASE( "thumb: bl -#42", "[thumb]" ) {
code_mem[2] = 0xE7FE; // b +#0 code_mem[2] = 0xE7FE; // b +#0
jit.Regs()[15] = 0; // PC = 0 jit.Regs()[15] = 0; // PC = 0
jit.Cpsr() = 0x00000030; // Thumb, User-mode jit.SetCpsr(0x00000030); // Thumb, User-mode
jit.Run(1); jit.Run(1);