JitX64: Implement immediate data processing instructions

This commit is contained in:
MerryMage 2016-03-20 22:05:57 +00:00
parent a80f9d8a66
commit 52558ae8be
8 changed files with 565 additions and 122 deletions

View File

@ -24,6 +24,7 @@ void JitX64::CondManager::CompileCond(const ConditionCode new_cond) {
if (current_cond != ConditionCode::AL && current_cond != ConditionCode::NV) {
jit->reg_alloc.FlushEverything();
jit->reg_alloc.AssertNoLocked();
ASSERT(current_cond_fixup.ptr);
jit->code->SetJumpTarget(current_cond_fixup);
current_cond_fixup.ptr = nullptr;
@ -123,6 +124,7 @@ void JitX64::CondManager::CompileCond(const ConditionCode new_cond) {
}
jit->reg_alloc.FlushEverything();
jit->reg_alloc.AssertNoLocked();
this->current_cond_fixup = jit->code->J_CC(cc, true);
}

View File

@ -10,48 +10,41 @@ namespace JitX64 {
using namespace Gen;
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);
void JitX64::CompileDataProcessingHelper(ArmReg Rn_index, ArmReg Rd_index, std::function<void(X64Reg)> body) {
// The major consideration is if Rn and/or Rd == R15.
if (Rd_index == 15) {
X64Reg Rd = reg_alloc.AllocAndLockTemp();
reg_alloc.LockArm(Rn_index);
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()));
} 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);
if (S)
UNIMPLEMENTED();
code->MOV(32, MJitStateArmPC(), R(Rd));
reg_alloc.UnlockTemp(Rd);
current.arm_pc += GetInstSize();
CompileReturnToDispatch();
return;
} else if (Rn_index == 15) {
X64Reg Rd = reg_alloc.BindNoLoadAndLockArm(Rd_index);
reg_alloc.MarkDirty(Rd_index);
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);
} else if (Rn_index == Rd_index) {
X64Reg Rd = reg_alloc.BindAndLockArm(Rd_index);
reg_alloc.MarkDirty(Rd_index);
code->BT(32, MJitStateCFlag(), Imm8(0));
code->ADC(32, R(Rd), Imm32(immediate));
body(Rd);
reg_alloc.UnlockArm(Rd_index);
} 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);
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(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) {
cond_manager.FlagsDirty();
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();
}
void JitX64::ADC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
void JitX64::ADC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
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(); }
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(); }
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(); }
void JitX64::BIC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
void JitX64::BIC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
void JitX64::BIC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
void JitX64::CMN_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
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(); }
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(); }
void JitX64::EOR_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
void JitX64::EOR_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
void JitX64::EOR_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
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(); }
void JitX64::MVN_imm(Cond cond, bool S, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
void JitX64::MVN_reg(Cond cond, bool S, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
void JitX64::MVN_rsr(Cond cond, bool S, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
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(); }
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(); }
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::RSC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, 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::SBC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, 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::SUB_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
void JitX64::SUB_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, 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::TEQ_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
void JitX64::TEQ_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
void JitX64::TEQ_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
void JitX64::TST_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
void JitX64::TST_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
void JitX64::TST_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
void JitX64::TST_imm(Cond cond, ArmReg Rn_index, int rotate, ArmImm8 imm8) {
cond_manager.CompileCond((ConditionCode)cond);
u32 immediate = _rotr(imm8, rotate * 2);
X64Reg Rn;
if (Rn_index == 15) {
Rn = reg_alloc.AllocAndLockTemp();
code->MOV(32, R(Rn), Imm32(GetReg15Value()));
} else {
Rn = reg_alloc.BindAndLockArm(Rn_index);
}
code->TEST(32, R(Rn), Imm32(immediate));
if (Rn_index == 15) {
reg_alloc.UnlockTemp(Rn);
} else {
reg_alloc.UnlockArm(Rn_index);
}
cond_manager.FlagsDirty();
UpdateFlagsZN();
if (rotate != 0) {
code->MOV(32, MJitStateCFlag(), Imm32(immediate & 0x80000000 ? 1 : 0));
}
reg_alloc.AssertNoLocked();
current.arm_pc += GetInstSize();
}
void JitX64::ADC_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, 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::ADD_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, 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::AND_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
void JitX64::AND_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs, 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::BIC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
void JitX64::CMN_reg(Cond cond, ArmReg Rn_index, 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::CMP_reg(Cond cond, ArmReg Rn_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
void JitX64::CMP_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs, 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::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(); }
}

View File

@ -74,7 +74,7 @@ public:
struct BlockOfCode : Gen::XCodeBlock {
BlockOfCode() {
AllocCodeSpace(1024 * 1024 * 1024);
AllocCodeSpace(128 * 1024 * 1024);
}
};
@ -222,4 +222,10 @@ void ARM_Jit::ClearCache() {
state->cpu_state.instruction_cache.clear();
}
void ARM_Jit::FastClearCache() {
compiler.ClearCache();
block_of_code.ResetCodePtr();
state->cpu_state.instruction_cache.clear();
}
}

View File

@ -41,6 +41,7 @@ public:
void ExecuteInstructions(int num_instructions) override;
void ClearCache() override;
void FastClearCache();
private:
bool reschedule;

View File

@ -106,6 +106,11 @@ private:
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() {
code->SETcc(Gen::CC_NC, MJitStateCFlag());
}
@ -151,6 +156,8 @@ private:
virtual void STC() override;
// 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_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;

View File

@ -71,11 +71,16 @@ void RegAlloc::FlushX64(Gen::X64Reg x64_reg) {
switch (state.state) {
case X64State::State::Free:
case X64State::State::CleanArmReg:
case X64State::State::MemoryMap:
case X64State::State::Temp:
state.state = X64State::State::Free;
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:
FlushArm(state.arm_reg);
break;
@ -92,14 +97,18 @@ void RegAlloc::LockX64(Gen::X64Reg x64_reg) {
X64State& x64_state = x64_gpr[x64_reg_to_index.at(x64_reg)];
ASSERT(!x64_state.locked);
ASSERT(x64_state.state == X64State::State::Free);
x64_state.locked = true;
x64_state.state = X64State::State::UserManuallyLocked;
}
void RegAlloc::UnlockX64(Gen::X64Reg x64_reg) {
X64State& x64_state = x64_gpr[x64_reg_to_index.at(x64_reg)];
ASSERT(x64_state.locked);
ASSERT(x64_state.state == X64State::State::UserManuallyLocked);
x64_state.locked = false;
x64_state.state = X64State::State::Free;
}
void RegAlloc::FlushArm(ArmReg arm_reg) {
@ -300,6 +309,23 @@ void RegAlloc::UnlockMemoryMap(Gen::X64Reg x64_reg) {
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() {
// TODO: This is terrible.

View File

@ -32,7 +32,8 @@ private:
Temp,
DirtyArmReg,
CleanArmReg,
MemoryMap
MemoryMap,
UserManuallyLocked
};
bool locked;
@ -92,6 +93,8 @@ public:
/// Returns the register in which the JitState pointer is stored.
Gen::X64Reg JitStateReg();
void AssertNoLocked();
private:
/// INTERNAL: Allocates a register that is free. Flushes registers that are not locked if necessary.
Gen::X64Reg AllocReg();

View File

@ -39,6 +39,56 @@ std::pair<u32, u32> FromBitString(const char* str) {
}
TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
const std::array<std::pair<u32, u32>, 48> instructions = {{
FromBitString("cccc0010101Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000101Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000101Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0010100Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000100Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000100Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0010000Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000000Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000000Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0011110Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0001110Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0001110Snnnnddddssss0rr1mmmm"),
FromBitString("cccc00110111nnnn0000rrrrvvvvvvvv"),
FromBitString("cccc00010111nnnn0000vvvvvrr0mmmm"),
FromBitString("cccc00010111nnnn0000ssss0rr1mmmm"),
FromBitString("cccc00110101nnnn0000rrrrvvvvvvvv"),
FromBitString("cccc00010101nnnn0000vvvvvrr0mmmm"),
FromBitString("cccc00010101nnnn0000ssss0rr1mmmm"),
FromBitString("cccc0010001Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000001Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000001Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0011101S0000ddddrrrrvvvvvvvv"),
FromBitString("cccc0001101S0000ddddvvvvvrr0mmmm"),
FromBitString("cccc0001101S0000ddddssss0rr1mmmm"),
FromBitString("cccc0011111S0000ddddrrrrvvvvvvvv"),
FromBitString("cccc0001111S0000ddddvvvvvrr0mmmm"),
FromBitString("cccc0001111S0000ddddssss0rr1mmmm"),
FromBitString("cccc0011100Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0001100Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0001100Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0010011Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000011Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000011Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0010111Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000111Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000111Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0010110Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000110Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000110Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0010010Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000010Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000010Snnnnddddssss0rr1mmmm"),
FromBitString("cccc00110011nnnn0000rrrrvvvvvvvv"),
FromBitString("cccc00010011nnnn0000vvvvvrr0mmmm"),
FromBitString("cccc00010011nnnn0000ssss0rr1mmmm"),
FromBitString("cccc00110001nnnn0000rrrrvvvvvvvv"),
FromBitString("cccc00010001nnnn0000vvvvvrr0mmmm"),
FromBitString("cccc00010001nnnn0000ssss0rr1mmmm"),
}};
// Init core
Core::Init();
@ -62,12 +112,12 @@ TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
JitX64::ARM_Jit jit(PrivilegeMode::USER32MODE);
ARM_DynCom interp(PrivilegeMode::USER32MODE);
SCOPE_EXIT({
jit.ClearCache();
jit.FastClearCache();
interp.ClearCache();
});
for (int run_number = 0; run_number < 10000; run_number++) {
jit.ClearCache();
jit.FastClearCache();
interp.ClearCache();
u32 initial_regs[15];
@ -87,57 +137,6 @@ TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
constexpr int NUM_INST = 5;
for (int i = 0; i < NUM_INST; i++) {
const std::array<std::pair<u32, u32>, 48> instructions = {{
FromBitString("cccc0010101Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000101Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000101Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0010100Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000100Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000100Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0010000Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000000Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000000Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0011110Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0001110Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0001110Snnnnddddssss0rr1mmmm"),
FromBitString("cccc00110111nnnn0000rrrrvvvvvvvv"),
FromBitString("cccc00010111nnnn0000vvvvvrr0mmmm"),
FromBitString("cccc00010111nnnn0000ssss0rr1mmmm"),
FromBitString("cccc00110101nnnn0000rrrrvvvvvvvv"),
FromBitString("cccc00010101nnnn0000vvvvvrr0mmmm"),
FromBitString("cccc00010101nnnn0000ssss0rr1mmmm"),
FromBitString("cccc0010001Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000001Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000001Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0011101S0000ddddrrrrvvvvvvvv"),
FromBitString("cccc0001101S0000ddddvvvvvrr0mmmm"),
FromBitString("cccc0001101S0000ddddssss0rr1mmmm"),
FromBitString("cccc0011111S0000ddddrrrrvvvvvvvv"),
FromBitString("cccc0001111S0000ddddvvvvvrr0mmmm"),
FromBitString("cccc0001111S0000ddddssss0rr1mmmm"),
FromBitString("cccc0011100Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0001100Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0001100Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0010011Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000011Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000011Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0010111Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000111Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000111Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0010110Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000110Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000110Snnnnddddssss0rr1mmmm"),
FromBitString("cccc0010010Snnnnddddrrrrvvvvvvvv"),
FromBitString("cccc0000010Snnnnddddvvvvvrr0mmmm"),
FromBitString("cccc0000010Snnnnddddssss0rr1mmmm"),
FromBitString("cccc00110011nnnn0000rrrrvvvvvvvv"),
FromBitString("cccc00010011nnnn0000vvvvvrr0mmmm"),
FromBitString("cccc00010011nnnn0000ssss0rr1mmmm"),
FromBitString("cccc00110001nnnn0000rrrrvvvvvvvv"),
FromBitString("cccc00010001nnnn0000vvvvvrr0mmmm"),
FromBitString("cccc00010001nnnn0000ssss0rr1mmmm"),
}};
size_t inst_index = rand_int(0, instructions.size() - 1);
u32 cond = rand_int(0x0, 0xE);
u32 Rn = rand_int(0, 15);
@ -197,5 +196,7 @@ TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
FAIL();
}
if (run_number % 100 == 0) printf("%i\r", run_number);
}
}