mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 10:20:14 +00:00
JitX64: Implement immediate data processing instructions
This commit is contained in:
parent
a80f9d8a66
commit
52558ae8be
@ -24,6 +24,7 @@ void JitX64::CondManager::CompileCond(const ConditionCode new_cond) {
|
|||||||
|
|
||||||
if (current_cond != ConditionCode::AL && current_cond != ConditionCode::NV) {
|
if (current_cond != ConditionCode::AL && current_cond != ConditionCode::NV) {
|
||||||
jit->reg_alloc.FlushEverything();
|
jit->reg_alloc.FlushEverything();
|
||||||
|
jit->reg_alloc.AssertNoLocked();
|
||||||
ASSERT(current_cond_fixup.ptr);
|
ASSERT(current_cond_fixup.ptr);
|
||||||
jit->code->SetJumpTarget(current_cond_fixup);
|
jit->code->SetJumpTarget(current_cond_fixup);
|
||||||
current_cond_fixup.ptr = nullptr;
|
current_cond_fixup.ptr = nullptr;
|
||||||
@ -123,6 +124,7 @@ void JitX64::CondManager::CompileCond(const ConditionCode new_cond) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
jit->reg_alloc.FlushEverything();
|
jit->reg_alloc.FlushEverything();
|
||||||
|
jit->reg_alloc.AssertNoLocked();
|
||||||
this->current_cond_fixup = jit->code->J_CC(cc, true);
|
this->current_cond_fixup = jit->code->J_CC(cc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,48 +10,41 @@ namespace JitX64 {
|
|||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
||||||
void JitX64::ADC_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
void JitX64::CompileDataProcessingHelper(ArmReg Rn_index, ArmReg Rd_index, std::function<void(X64Reg)> body) {
|
||||||
cond_manager.CompileCond((ConditionCode)cond);
|
// The major consideration is if Rn and/or Rd == R15.
|
||||||
|
|
||||||
u32 immediate = _rotr(imm8, rotate * 2);
|
|
||||||
|
|
||||||
if (Rd_index == 15) {
|
if (Rd_index == 15) {
|
||||||
X64Reg Rd = reg_alloc.AllocAndLockTemp();
|
X64Reg Rd = reg_alloc.AllocAndLockTemp();
|
||||||
reg_alloc.LockArm(Rn_index);
|
reg_alloc.LockArm(Rn_index);
|
||||||
|
|
||||||
if (Rn_index == 15) {
|
if (Rn_index == 15) {
|
||||||
|
// TODO: In this case we can actually calculat the final result.
|
||||||
|
// We can also use CompileJumpToBB instead of having to use CompileReturnToDispatch.
|
||||||
code->MOV(32, R(Rd), Imm32(GetReg15Value()));
|
code->MOV(32, R(Rd), Imm32(GetReg15Value()));
|
||||||
} else {
|
} else {
|
||||||
code->MOV(32, R(Rd), reg_alloc.ArmR(Rd_index));
|
code->MOV(32, R(Rd), reg_alloc.ArmR(Rn_index));
|
||||||
}
|
}
|
||||||
code->BT(32, MJitStateCFlag(), Imm8(0));
|
|
||||||
code->ADC(32, R(Rd), Imm32(immediate));
|
body(Rd);
|
||||||
|
|
||||||
reg_alloc.UnlockArm(Rn_index);
|
reg_alloc.UnlockArm(Rn_index);
|
||||||
|
|
||||||
if (S)
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
|
|
||||||
code->MOV(32, MJitStateArmPC(), R(Rd));
|
code->MOV(32, MJitStateArmPC(), R(Rd));
|
||||||
reg_alloc.UnlockTemp(Rd);
|
reg_alloc.UnlockTemp(Rd);
|
||||||
current.arm_pc += GetInstSize();
|
|
||||||
CompileReturnToDispatch();
|
|
||||||
return;
|
|
||||||
} else if (Rn_index == 15) {
|
} else if (Rn_index == 15) {
|
||||||
X64Reg Rd = reg_alloc.BindNoLoadAndLockArm(Rd_index);
|
X64Reg Rd = reg_alloc.BindNoLoadAndLockArm(Rd_index);
|
||||||
reg_alloc.MarkDirty(Rd_index);
|
reg_alloc.MarkDirty(Rd_index);
|
||||||
|
|
||||||
code->MOV(32, R(Rd), Imm32(GetReg15Value()));
|
code->MOV(32, R(Rd), Imm32(GetReg15Value()));
|
||||||
code->BT(32, MJitStateCFlag(), Imm8(0));
|
|
||||||
code->ADC(32, R(Rd), Imm32(immediate));
|
body(Rd);
|
||||||
|
|
||||||
reg_alloc.UnlockArm(Rd_index);
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
} else if (Rn_index == Rd_index) {
|
} else if (Rn_index == Rd_index) {
|
||||||
X64Reg Rd = reg_alloc.BindAndLockArm(Rd_index);
|
X64Reg Rd = reg_alloc.BindAndLockArm(Rd_index);
|
||||||
reg_alloc.MarkDirty(Rd_index);
|
reg_alloc.MarkDirty(Rd_index);
|
||||||
|
|
||||||
code->BT(32, MJitStateCFlag(), Imm8(0));
|
body(Rd);
|
||||||
code->ADC(32, R(Rd), Imm32(immediate));
|
|
||||||
|
|
||||||
reg_alloc.UnlockArm(Rd_index);
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
} else {
|
} else {
|
||||||
@ -60,67 +53,471 @@ void JitX64::ADC_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int ro
|
|||||||
reg_alloc.LockArm(Rn_index);
|
reg_alloc.LockArm(Rn_index);
|
||||||
|
|
||||||
code->MOV(32, R(Rd), reg_alloc.ArmR(Rn_index));
|
code->MOV(32, R(Rd), reg_alloc.ArmR(Rn_index));
|
||||||
code->BT(32, MJitStateCFlag(), Imm8(0));
|
|
||||||
code->ADC(32, R(Rd), Imm32(immediate));
|
body(Rd);
|
||||||
|
|
||||||
reg_alloc.UnlockArm(Rd_index);
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
reg_alloc.UnlockArm(Rn_index);
|
reg_alloc.UnlockArm(Rn_index);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::CompileDataProcessingHelper_Reverse(ArmReg Rn_index, ArmReg Rd_index, std::function<void(X64Reg)> body) {
|
||||||
|
// The major consideration is if Rn and/or Rd == R15.
|
||||||
|
|
||||||
|
if (Rd_index != Rn_index) {
|
||||||
|
|
||||||
|
X64Reg Rd = INVALID_REG;
|
||||||
|
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
Rd = reg_alloc.AllocAndLockTemp();
|
||||||
|
} else {
|
||||||
|
Rd = reg_alloc.BindNoLoadAndLockArm(Rd_index);
|
||||||
|
reg_alloc.MarkDirty(Rd_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
body(Rd);
|
||||||
|
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
code->MOV(32, MJitStateArmPC(), R(Rd));
|
||||||
|
reg_alloc.UnlockTemp(Rd);
|
||||||
|
} else {
|
||||||
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
X64Reg tmp = reg_alloc.AllocAndLockTemp();
|
||||||
|
|
||||||
|
body(tmp);
|
||||||
|
|
||||||
|
// TODO: Efficiency: Could implement this as a register rebind instead of needing to MOV.
|
||||||
|
reg_alloc.LockArm(Rd_index);
|
||||||
|
code->MOV(32, reg_alloc.ArmR(Rd_index), R(tmp));
|
||||||
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
|
reg_alloc.UnlockTemp(tmp);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::ADC_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||||
|
code->BT(32, MJitStateCFlag(), Imm8(0));
|
||||||
|
code->ADC(32, R(Rd), Imm32(immediate));
|
||||||
|
});
|
||||||
|
|
||||||
if (S) {
|
if (S) {
|
||||||
cond_manager.FlagsDirty();
|
cond_manager.FlagsDirty();
|
||||||
UpdateFlagsZVCN();
|
UpdateFlagsZVCN();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
CompileReturnToDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::ADD_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||||
|
code->ADD(32, R(Rd), Imm32(immediate));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (S) {
|
||||||
|
cond_manager.FlagsDirty();
|
||||||
|
UpdateFlagsZVCN();
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
CompileReturnToDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::AND_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||||
|
code->AND(32, R(Rd), Imm32(immediate));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (S) {
|
||||||
|
cond_manager.FlagsDirty();
|
||||||
|
UpdateFlagsZN();
|
||||||
|
if (rotate != 0) {
|
||||||
|
code->MOV(32, MJitStateCFlag(), Imm32(immediate & 0x80000000 ? 1 : 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
CompileReturnToDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::BIC_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||||
|
code->AND(32, R(Rd), Imm32(~immediate));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (S) {
|
||||||
|
cond_manager.FlagsDirty();
|
||||||
|
UpdateFlagsZN();
|
||||||
|
if (rotate != 0) {
|
||||||
|
code->MOV(32, MJitStateCFlag(), Imm32(immediate & 0x80000000 ? 1 : 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
CompileReturnToDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::CMN_imm(Cond cond, ArmReg Rn_index, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::CMP_imm(Cond cond, ArmReg Rn_index, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||||
|
|
||||||
|
void JitX64::EOR_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||||
|
code->XOR(32, R(Rd), Imm32(immediate));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (S) {
|
||||||
|
cond_manager.FlagsDirty();
|
||||||
|
UpdateFlagsZN();
|
||||||
|
if (rotate != 0) {
|
||||||
|
code->MOV(32, MJitStateCFlag(), Imm32(immediate & 0x80000000 ? 1 : 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
CompileReturnToDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::MOV_imm(Cond cond, bool S, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
if (Rd_index != 15) {
|
||||||
|
reg_alloc.LockArm(Rd_index);
|
||||||
|
code->MOV(32, reg_alloc.ArmR(Rd_index), Imm32(immediate));
|
||||||
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
|
} else {
|
||||||
|
code->MOV(32, MJitStateArmPC(), Imm32(immediate));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S) {
|
||||||
|
cond_manager.FlagsDirty();
|
||||||
|
reg_alloc.LockArm(Rd_index);
|
||||||
|
code->CMP(32, reg_alloc.ArmR(Rd_index), Imm32(0));
|
||||||
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
|
UpdateFlagsZN();
|
||||||
|
if (rotate != 0) {
|
||||||
|
code->MOV(32, MJitStateCFlag(), Imm32(immediate & 0x80000000 ? 1 : 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
CompileReturnToDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::MVN_imm(Cond cond, bool S, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
if (Rd_index != 15) {
|
||||||
|
reg_alloc.LockArm(Rd_index);
|
||||||
|
code->MOV(32, reg_alloc.ArmR(Rd_index), Imm32(~immediate));
|
||||||
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
|
} else {
|
||||||
|
code->MOV(32, MJitStateArmPC(), Imm32(~immediate));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S) {
|
||||||
|
cond_manager.FlagsDirty();
|
||||||
|
reg_alloc.LockArm(Rd_index);
|
||||||
|
code->CMP(32, reg_alloc.ArmR(Rd_index), Imm32(0));
|
||||||
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
|
UpdateFlagsZN();
|
||||||
|
if (rotate != 0) {
|
||||||
|
code->MOV(32, MJitStateCFlag(), Imm32(immediate & 0x80000000 ? 1 : 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
CompileReturnToDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::ORR_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||||
|
code->OR(32, R(Rd), Imm32(immediate));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (S) {
|
||||||
|
cond_manager.FlagsDirty();
|
||||||
|
UpdateFlagsZN();
|
||||||
|
if (rotate != 0) {
|
||||||
|
code->MOV(32, MJitStateCFlag(), Imm32(immediate & 0x80000000 ? 1 : 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
CompileReturnToDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::RSB_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
CompileDataProcessingHelper_Reverse(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||||
|
code->MOV(32, R(Rd), Imm32(immediate));
|
||||||
|
|
||||||
|
if (Rn_index == 15) {
|
||||||
|
code->SUB(32, R(Rd), Imm32(GetReg15Value()));
|
||||||
|
} else {
|
||||||
|
reg_alloc.LockArm(Rn_index);
|
||||||
|
code->SUB(32, R(Rd), reg_alloc.ArmR(Rn_index));
|
||||||
|
reg_alloc.UnlockArm(Rn_index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (S) {
|
||||||
|
cond_manager.FlagsDirty();
|
||||||
|
UpdateFlagsZVN();
|
||||||
|
UpdateFlagsC_complement();
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
CompileReturnToDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::RSC_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
CompileDataProcessingHelper_Reverse(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||||
|
code->MOV(32, R(Rd), Imm32(immediate));
|
||||||
|
|
||||||
|
code->BT(32, MJitStateCFlag(), Imm8(0));
|
||||||
|
code->CMC();
|
||||||
|
|
||||||
|
if (Rn_index == 15) {
|
||||||
|
code->SBB(32, R(Rd), Imm32(GetReg15Value()));
|
||||||
|
} else {
|
||||||
|
reg_alloc.LockArm(Rn_index);
|
||||||
|
code->SBB(32, R(Rd), reg_alloc.ArmR(Rn_index));
|
||||||
|
reg_alloc.UnlockArm(Rn_index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (S) {
|
||||||
|
cond_manager.FlagsDirty();
|
||||||
|
UpdateFlagsZVN();
|
||||||
|
UpdateFlagsC_complement();
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
CompileReturnToDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::SBC_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||||
|
code->BT(32, MJitStateCFlag(), Imm8(0));
|
||||||
|
code->CMC();
|
||||||
|
code->SBB(32, R(Rd), Imm32(immediate));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (S) {
|
||||||
|
cond_manager.FlagsDirty();
|
||||||
|
UpdateFlagsZVN();
|
||||||
|
UpdateFlagsC_complement();
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
CompileReturnToDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::SUB_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||||
|
code->SUB(32, R(Rd), Imm32(immediate));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (S) {
|
||||||
|
cond_manager.FlagsDirty();
|
||||||
|
UpdateFlagsZVN();
|
||||||
|
UpdateFlagsC_complement();
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
if (Rd_index == 15) {
|
||||||
|
CompileReturnToDispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::TEQ_imm(Cond cond, ArmReg Rn_index, int rotate, ArmImm8 imm8) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
|
|
||||||
|
X64Reg Rn = reg_alloc.AllocAndLockTemp();
|
||||||
|
|
||||||
|
if (Rn_index == 15) {
|
||||||
|
code->MOV(32, R(Rn), Imm32(GetReg15Value()));
|
||||||
|
} else {
|
||||||
|
reg_alloc.LockArm(Rn_index);
|
||||||
|
code->MOV(32, R(Rn), reg_alloc.ArmR(Rn_index));
|
||||||
|
reg_alloc.UnlockArm(Rn_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
code->XOR(32, R(Rn), Imm32(immediate));
|
||||||
|
|
||||||
|
reg_alloc.UnlockTemp(Rn);
|
||||||
|
|
||||||
|
cond_manager.FlagsDirty();
|
||||||
|
UpdateFlagsZN();
|
||||||
|
if (rotate != 0) {
|
||||||
|
code->MOV(32, MJitStateCFlag(), Imm32(immediate & 0x80000000 ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_alloc.AssertNoLocked();
|
||||||
|
|
||||||
current.arm_pc += GetInstSize();
|
current.arm_pc += GetInstSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitX64::ADC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
void JitX64::TST_imm(Cond cond, ArmReg Rn_index, int rotate, ArmImm8 imm8) {
|
||||||
void JitX64::ADC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
void JitX64::ADD_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
|
||||||
void JitX64::ADD_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
u32 immediate = _rotr(imm8, rotate * 2);
|
||||||
void JitX64::ADD_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
|
||||||
void JitX64::AND_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
X64Reg Rn;
|
||||||
void JitX64::AND_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
|
||||||
void JitX64::AND_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
if (Rn_index == 15) {
|
||||||
void JitX64::BIC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
Rn = reg_alloc.AllocAndLockTemp();
|
||||||
void JitX64::BIC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
code->MOV(32, R(Rn), Imm32(GetReg15Value()));
|
||||||
void JitX64::BIC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
} else {
|
||||||
void JitX64::CMN_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
Rn = reg_alloc.BindAndLockArm(Rn_index);
|
||||||
void JitX64::CMN_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
}
|
||||||
void JitX64::CMN_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
|
||||||
void JitX64::CMP_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
code->TEST(32, R(Rn), Imm32(immediate));
|
||||||
void JitX64::CMP_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
|
||||||
void JitX64::CMP_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
if (Rn_index == 15) {
|
||||||
void JitX64::EOR_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
reg_alloc.UnlockTemp(Rn);
|
||||||
void JitX64::EOR_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
} else {
|
||||||
void JitX64::EOR_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
reg_alloc.UnlockArm(Rn_index);
|
||||||
void JitX64::MOV_imm(Cond cond, bool S, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
}
|
||||||
void JitX64::MOV_reg(Cond cond, bool S, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
|
||||||
void JitX64::MOV_rsr(Cond cond, bool S, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
cond_manager.FlagsDirty();
|
||||||
void JitX64::MVN_imm(Cond cond, bool S, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
UpdateFlagsZN();
|
||||||
void JitX64::MVN_reg(Cond cond, bool S, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
if (rotate != 0) {
|
||||||
void JitX64::MVN_rsr(Cond cond, bool S, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
code->MOV(32, MJitStateCFlag(), Imm32(immediate & 0x80000000 ? 1 : 0));
|
||||||
void JitX64::ORR_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
}
|
||||||
void JitX64::ORR_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
|
||||||
void JitX64::ORR_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
reg_alloc.AssertNoLocked();
|
||||||
void JitX64::RSB_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
|
||||||
void JitX64::RSB_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
current.arm_pc += GetInstSize();
|
||||||
void JitX64::RSB_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
}
|
||||||
void JitX64::RSC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
|
||||||
void JitX64::RSC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
void JitX64::ADC_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::RSC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
void JitX64::ADC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::SBC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
void JitX64::ADD_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::SBC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
void JitX64::ADD_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::SBC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
void JitX64::AND_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::SUB_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
void JitX64::AND_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::SUB_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
void JitX64::BIC_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::SUB_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
void JitX64::BIC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::TEQ_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
void JitX64::CMN_reg(Cond cond, ArmReg Rn_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::TEQ_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
void JitX64::CMN_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::TEQ_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
void JitX64::CMP_reg(Cond cond, ArmReg Rn_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::TST_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
void JitX64::CMP_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::TST_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
void JitX64::EOR_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
void JitX64::TST_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
void JitX64::EOR_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::MOV_reg(Cond cond, bool S, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::MOV_rsr(Cond cond, bool S, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::MVN_reg(Cond cond, bool S, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::MVN_rsr(Cond cond, bool S, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::ORR_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::ORR_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::RSB_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::RSB_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::RSC_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::RSC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::SBC_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::SBC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::SUB_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::SUB_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::TEQ_reg(Cond cond, ArmReg Rn_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::TEQ_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::TST_reg(Cond cond, ArmReg Rn_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
void JitX64::TST_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ public:
|
|||||||
|
|
||||||
struct BlockOfCode : Gen::XCodeBlock {
|
struct BlockOfCode : Gen::XCodeBlock {
|
||||||
BlockOfCode() {
|
BlockOfCode() {
|
||||||
AllocCodeSpace(1024 * 1024 * 1024);
|
AllocCodeSpace(128 * 1024 * 1024);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -222,4 +222,10 @@ void ARM_Jit::ClearCache() {
|
|||||||
state->cpu_state.instruction_cache.clear();
|
state->cpu_state.instruction_cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ARM_Jit::FastClearCache() {
|
||||||
|
compiler.ClearCache();
|
||||||
|
block_of_code.ResetCodePtr();
|
||||||
|
state->cpu_state.instruction_cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ public:
|
|||||||
void ExecuteInstructions(int num_instructions) override;
|
void ExecuteInstructions(int num_instructions) override;
|
||||||
|
|
||||||
void ClearCache() override;
|
void ClearCache() override;
|
||||||
|
void FastClearCache();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool reschedule;
|
bool reschedule;
|
||||||
|
@ -106,6 +106,11 @@ private:
|
|||||||
code->SETcc(Gen::CC_S, MJitStateNFlag());
|
code->SETcc(Gen::CC_S, MJitStateNFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE void UpdateFlagsZN() {
|
||||||
|
code->SETcc(Gen::CC_Z, MJitStateZFlag());
|
||||||
|
code->SETcc(Gen::CC_S, MJitStateNFlag());
|
||||||
|
}
|
||||||
|
|
||||||
FORCE_INLINE void UpdateFlagsC_complement() {
|
FORCE_INLINE void UpdateFlagsC_complement() {
|
||||||
code->SETcc(Gen::CC_NC, MJitStateCFlag());
|
code->SETcc(Gen::CC_NC, MJitStateCFlag());
|
||||||
}
|
}
|
||||||
@ -151,6 +156,8 @@ private:
|
|||||||
virtual void STC() override;
|
virtual void STC() override;
|
||||||
|
|
||||||
// Data processing instructions
|
// Data processing instructions
|
||||||
|
void CompileDataProcessingHelper(ArmReg Rn_index, ArmReg Rd_index, std::function<void(Gen::X64Reg)> body);
|
||||||
|
void CompileDataProcessingHelper_Reverse(ArmReg Rn_index, ArmReg Rd_index, std::function<void(Gen::X64Reg)> body);
|
||||||
virtual void ADC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
virtual void ADC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||||
virtual void ADC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
virtual void ADC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||||
virtual void ADC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
virtual void ADC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||||
|
@ -71,11 +71,16 @@ void RegAlloc::FlushX64(Gen::X64Reg x64_reg) {
|
|||||||
|
|
||||||
switch (state.state) {
|
switch (state.state) {
|
||||||
case X64State::State::Free:
|
case X64State::State::Free:
|
||||||
case X64State::State::CleanArmReg:
|
|
||||||
case X64State::State::MemoryMap:
|
case X64State::State::MemoryMap:
|
||||||
case X64State::State::Temp:
|
case X64State::State::Temp:
|
||||||
state.state = X64State::State::Free;
|
state.state = X64State::State::Free;
|
||||||
break;
|
break;
|
||||||
|
case X64State::State::CleanArmReg: {
|
||||||
|
state.state = X64State::State::Free;
|
||||||
|
ArmState& arm_state = arm_gpr[state.arm_reg];
|
||||||
|
arm_state.location = MJitStateCpuReg(state.arm_reg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case X64State::State::DirtyArmReg:
|
case X64State::State::DirtyArmReg:
|
||||||
FlushArm(state.arm_reg);
|
FlushArm(state.arm_reg);
|
||||||
break;
|
break;
|
||||||
@ -92,14 +97,18 @@ void RegAlloc::LockX64(Gen::X64Reg x64_reg) {
|
|||||||
X64State& x64_state = x64_gpr[x64_reg_to_index.at(x64_reg)];
|
X64State& x64_state = x64_gpr[x64_reg_to_index.at(x64_reg)];
|
||||||
|
|
||||||
ASSERT(!x64_state.locked);
|
ASSERT(!x64_state.locked);
|
||||||
|
ASSERT(x64_state.state == X64State::State::Free);
|
||||||
x64_state.locked = true;
|
x64_state.locked = true;
|
||||||
|
x64_state.state = X64State::State::UserManuallyLocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegAlloc::UnlockX64(Gen::X64Reg x64_reg) {
|
void RegAlloc::UnlockX64(Gen::X64Reg x64_reg) {
|
||||||
X64State& x64_state = x64_gpr[x64_reg_to_index.at(x64_reg)];
|
X64State& x64_state = x64_gpr[x64_reg_to_index.at(x64_reg)];
|
||||||
|
|
||||||
ASSERT(x64_state.locked);
|
ASSERT(x64_state.locked);
|
||||||
|
ASSERT(x64_state.state == X64State::State::UserManuallyLocked);
|
||||||
x64_state.locked = false;
|
x64_state.locked = false;
|
||||||
|
x64_state.state = X64State::State::Free;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegAlloc::FlushArm(ArmReg arm_reg) {
|
void RegAlloc::FlushArm(ArmReg arm_reg) {
|
||||||
@ -300,6 +309,23 @@ void RegAlloc::UnlockMemoryMap(Gen::X64Reg x64_reg) {
|
|||||||
x64_state.locked = false;
|
x64_state.locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegAlloc::AssertNoLocked() {
|
||||||
|
for (ArmReg arm_reg = 0; arm_reg < arm_gpr.size(); arm_reg++) {
|
||||||
|
ArmState& arm_state = arm_gpr[arm_reg];
|
||||||
|
ASSERT(!arm_state.locked);
|
||||||
|
if (arm_state.location.IsSimpleReg()) {
|
||||||
|
X64State& x64_state = x64_gpr[x64_reg_to_index.at(arm_state.location.GetSimpleReg())];
|
||||||
|
ASSERT(x64_state.state == X64State::State::CleanArmReg || x64_state.state == X64State::State::DirtyArmReg);
|
||||||
|
ASSERT(x64_state.arm_reg == arm_reg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i : x64_reg_to_index) {
|
||||||
|
X64State& x64_state = x64_gpr[i.second];
|
||||||
|
ASSERT(!x64_state.locked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Gen::X64Reg RegAlloc::AllocReg() {
|
Gen::X64Reg RegAlloc::AllocReg() {
|
||||||
// TODO: This is terrible.
|
// TODO: This is terrible.
|
||||||
|
|
||||||
|
@ -32,7 +32,8 @@ private:
|
|||||||
Temp,
|
Temp,
|
||||||
DirtyArmReg,
|
DirtyArmReg,
|
||||||
CleanArmReg,
|
CleanArmReg,
|
||||||
MemoryMap
|
MemoryMap,
|
||||||
|
UserManuallyLocked
|
||||||
};
|
};
|
||||||
|
|
||||||
bool locked;
|
bool locked;
|
||||||
@ -92,6 +93,8 @@ public:
|
|||||||
/// Returns the register in which the JitState pointer is stored.
|
/// Returns the register in which the JitState pointer is stored.
|
||||||
Gen::X64Reg JitStateReg();
|
Gen::X64Reg JitStateReg();
|
||||||
|
|
||||||
|
void AssertNoLocked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// INTERNAL: Allocates a register that is free. Flushes registers that are not locked if necessary.
|
/// INTERNAL: Allocates a register that is free. Flushes registers that are not locked if necessary.
|
||||||
Gen::X64Reg AllocReg();
|
Gen::X64Reg AllocReg();
|
||||||
|
@ -39,54 +39,6 @@ std::pair<u32, u32> FromBitString(const char* str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
|
TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
|
||||||
|
|
||||||
// Init core
|
|
||||||
Core::Init();
|
|
||||||
SCOPE_EXIT({ Core::Shutdown(); });
|
|
||||||
|
|
||||||
// Prepare random numbers
|
|
||||||
std::random_device rd;
|
|
||||||
std::mt19937 mt(rd());
|
|
||||||
auto rand_int = [&mt](u32 min, u32 max) -> u32 {
|
|
||||||
std::uniform_int<u32> rand(min, max);
|
|
||||||
return rand(mt);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Prepare memory
|
|
||||||
u8* test_mem = new u8[4096 * 2];
|
|
||||||
std::memset(test_mem, 0, 4096 * 2);
|
|
||||||
Memory::MapMemoryRegion(0, 4096 * 2, test_mem);
|
|
||||||
SCOPE_EXIT({ Memory::UnmapRegion(0, 4096 * 2); });
|
|
||||||
|
|
||||||
// Prepare test subjects
|
|
||||||
JitX64::ARM_Jit jit(PrivilegeMode::USER32MODE);
|
|
||||||
ARM_DynCom interp(PrivilegeMode::USER32MODE);
|
|
||||||
SCOPE_EXIT({
|
|
||||||
jit.ClearCache();
|
|
||||||
interp.ClearCache();
|
|
||||||
});
|
|
||||||
|
|
||||||
for (int run_number = 0; run_number < 10000; run_number++) {
|
|
||||||
jit.ClearCache();
|
|
||||||
interp.ClearCache();
|
|
||||||
|
|
||||||
u32 initial_regs[15];
|
|
||||||
for (int i = 0; i < 15; i++) {
|
|
||||||
u32 val = rand_int(0, 0xFFFFFFFF);
|
|
||||||
interp.SetReg(i, val);
|
|
||||||
jit.SetReg(i, val);
|
|
||||||
initial_regs[i] = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
interp.SetCPSR(0x000001d0);
|
|
||||||
jit.SetCPSR(0x000001d0);
|
|
||||||
|
|
||||||
interp.SetPC(0);
|
|
||||||
jit.SetPC(0);
|
|
||||||
|
|
||||||
constexpr int NUM_INST = 5;
|
|
||||||
|
|
||||||
for (int i = 0; i < NUM_INST; i++) {
|
|
||||||
const std::array<std::pair<u32, u32>, 48> instructions = {{
|
const std::array<std::pair<u32, u32>, 48> instructions = {{
|
||||||
FromBitString("cccc0010101Snnnnddddrrrrvvvvvvvv"),
|
FromBitString("cccc0010101Snnnnddddrrrrvvvvvvvv"),
|
||||||
FromBitString("cccc0000101Snnnnddddvvvvvrr0mmmm"),
|
FromBitString("cccc0000101Snnnnddddvvvvvrr0mmmm"),
|
||||||
@ -138,6 +90,53 @@ TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
|
|||||||
FromBitString("cccc00010001nnnn0000ssss0rr1mmmm"),
|
FromBitString("cccc00010001nnnn0000ssss0rr1mmmm"),
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
// Init core
|
||||||
|
Core::Init();
|
||||||
|
SCOPE_EXIT({ Core::Shutdown(); });
|
||||||
|
|
||||||
|
// Prepare random numbers
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 mt(rd());
|
||||||
|
auto rand_int = [&mt](u32 min, u32 max) -> u32 {
|
||||||
|
std::uniform_int<u32> rand(min, max);
|
||||||
|
return rand(mt);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prepare memory
|
||||||
|
u8* test_mem = new u8[4096 * 2];
|
||||||
|
std::memset(test_mem, 0, 4096 * 2);
|
||||||
|
Memory::MapMemoryRegion(0, 4096 * 2, test_mem);
|
||||||
|
SCOPE_EXIT({ Memory::UnmapRegion(0, 4096 * 2); });
|
||||||
|
|
||||||
|
// Prepare test subjects
|
||||||
|
JitX64::ARM_Jit jit(PrivilegeMode::USER32MODE);
|
||||||
|
ARM_DynCom interp(PrivilegeMode::USER32MODE);
|
||||||
|
SCOPE_EXIT({
|
||||||
|
jit.FastClearCache();
|
||||||
|
interp.ClearCache();
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int run_number = 0; run_number < 10000; run_number++) {
|
||||||
|
jit.FastClearCache();
|
||||||
|
interp.ClearCache();
|
||||||
|
|
||||||
|
u32 initial_regs[15];
|
||||||
|
for (int i = 0; i < 15; i++) {
|
||||||
|
u32 val = rand_int(0, 0xFFFFFFFF);
|
||||||
|
interp.SetReg(i, val);
|
||||||
|
jit.SetReg(i, val);
|
||||||
|
initial_regs[i] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
interp.SetCPSR(0x000001d0);
|
||||||
|
jit.SetCPSR(0x000001d0);
|
||||||
|
|
||||||
|
interp.SetPC(0);
|
||||||
|
jit.SetPC(0);
|
||||||
|
|
||||||
|
constexpr int NUM_INST = 5;
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_INST; i++) {
|
||||||
size_t inst_index = rand_int(0, instructions.size() - 1);
|
size_t inst_index = rand_int(0, instructions.size() - 1);
|
||||||
u32 cond = rand_int(0x0, 0xE);
|
u32 cond = rand_int(0x0, 0xE);
|
||||||
u32 Rn = rand_int(0, 15);
|
u32 Rn = rand_int(0, 15);
|
||||||
@ -197,5 +196,7 @@ TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
|
|||||||
|
|
||||||
FAIL();
|
FAIL();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (run_number % 100 == 0) printf("%i\r", run_number);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user