JitX64: Load/Store: Add UNPREDICTABLE ASSERTs, correct LDR R15 behavior

This commit is contained in:
MerryMage 2016-04-03 09:00:56 +01:00
parent 32d81463cf
commit 20d87c315a
5 changed files with 168 additions and 31 deletions

View File

@ -92,6 +92,8 @@ void JitX64::BLX_reg(Cond cond, ArmReg Rm_index) {
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
CompileReturnToDispatch(); CompileReturnToDispatch();
stop_compilation = true;
} }
void JitX64::BX(Cond cond, ArmReg Rm_index) { void JitX64::BX(Cond cond, ArmReg Rm_index) {
@ -111,6 +113,8 @@ void JitX64::BX(Cond cond, ArmReg Rm_index) {
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
CompileReturnToDispatch(); CompileReturnToDispatch();
stop_compilation = true;
} }
void JitX64::BXJ(Cond cond, ArmReg Rm) { void JitX64::BXJ(Cond cond, ArmReg Rm) {

View File

@ -271,6 +271,10 @@ static void LoadStoreCommon_AddrMode2(JitX64* jit, RegAlloc& reg_alloc, bool P,
void JitX64::LDR_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm12 imm12) { void JitX64::LDR_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm12 imm12) {
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
// Rd == R15 is UNPREDICTABLE only if address[1:0] is not 0b00 or if value loaded into R15[1:0] is 0b10.
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode2(this, reg_alloc, P, W, LoadStoreCommon_AddrMode2(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed,
@ -290,6 +294,12 @@ void JitX64::LDR_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_RETURN); reg_alloc.UnlockX64(ABI_RETURN);
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
if (Rd_index == 15) {
code->AND(32, MJitStateArmPC(), Imm32(0xFFFFFFFE));
code->BT(32, R(ABI_RETURN), Imm8(0));
code->SETcc(CC_C, MJitStateTFlag());
CompileReturnToDispatch();
}
} }
void JitX64::LDR_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm_index) { void JitX64::LDR_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm_index) {
@ -314,11 +324,21 @@ void JitX64::LDR_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_RETURN); reg_alloc.UnlockX64(ABI_RETURN);
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
if (Rd_index == 15) {
code->AND(32, MJitStateArmPC(), Imm32(0xFFFFFFFE));
code->BT(32, R(ABI_RETURN), Imm8(0));
code->SETcc(CC_C, MJitStateTFlag());
CompileReturnToDispatch();
}
} }
void JitX64::LDRB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm12 imm12) { void JitX64::LDRB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm12 imm12) {
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode2(this, reg_alloc, P, W, LoadStoreCommon_AddrMode2(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed,
@ -343,6 +363,10 @@ void JitX64::LDRB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
void JitX64::LDRB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm_index) { void JitX64::LDRB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm_index) {
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode2(this, reg_alloc, P, W, LoadStoreCommon_AddrMode2(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed,
@ -365,8 +389,15 @@ void JitX64::LDRB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
} }
void JitX64::STR_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm12 imm12) { void JitX64::STR_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm12 imm12) {
CompileInterpretInstruction();
return;
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
// Rd_index == R15 is IMPLEMENTATION DEFINED
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode2(this, reg_alloc, P, W, LoadStoreCommon_AddrMode2(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed,
@ -383,12 +414,21 @@ void JitX64::STR_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.UnlockX64(ABI_PARAM2); reg_alloc.UnlockX64(ABI_PARAM2);
// TODO: Exclusive stuff
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
} }
void JitX64::STR_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm_index) { void JitX64::STR_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm_index) {
CompileInterpretInstruction();
return;
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
// Rd_index == R15 is IMPLEMENTATION DEFINED
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode2(this, reg_alloc, P, W, LoadStoreCommon_AddrMode2(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed,
@ -405,12 +445,21 @@ void JitX64::STR_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.UnlockX64(ABI_PARAM2); reg_alloc.UnlockX64(ABI_PARAM2);
// TODO: Exclusive stuff
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
} }
void JitX64::STRB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm12 imm12) { void JitX64::STRB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm12 imm12) {
CompileInterpretInstruction();
return;
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode2(this, reg_alloc, P, W, LoadStoreCommon_AddrMode2(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed,
@ -427,12 +476,21 @@ void JitX64::STRB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.UnlockX64(ABI_PARAM2); reg_alloc.UnlockX64(ABI_PARAM2);
//TODO: Exclusive stuff
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
} }
void JitX64::STRB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm_index) { void JitX64::STRB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm_index) {
CompileInterpretInstruction();
return;
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode2(this, reg_alloc, P, W, LoadStoreCommon_AddrMode2(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed,
@ -449,6 +507,8 @@ void JitX64::STRB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.UnlockX64(ABI_PARAM2); reg_alloc.UnlockX64(ABI_PARAM2);
//TODO: Exclusive stuff
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
} }
@ -486,6 +546,11 @@ static ArmImm8 CombineImm8ab(ArmImm4 imm8a, ArmImm4 imm8b) {
void JitX64::LDRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) { void JitX64::LDRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) {
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index < 14, "UNPREDICTABLE");
ASSERT_MSG(Rd_index % 2 == 0, "UNDEFINED");
if (W)
ASSERT_MSG(Rn_index != Rd_index && Rn_index != Rd_index + 1, "UNPREDICTABLE");
LoadStoreCommon_AddrMode3(this, reg_alloc, P, W, LoadStoreCommon_AddrMode3(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed,
@ -497,8 +562,6 @@ void JitX64::LDRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.LockX64(ABI_RETURN); reg_alloc.LockX64(ABI_RETURN);
ASSERT_MSG(Rd_index % 2 == 0 && Rd_index != 14, "UNPREDICTABLE");
X64Reg Rd0 = reg_alloc.BindArmForWrite(Rd_index + 0); X64Reg Rd0 = reg_alloc.BindArmForWrite(Rd_index + 0);
X64Reg Rd1 = reg_alloc.BindArmForWrite(Rd_index + 1); X64Reg Rd1 = reg_alloc.BindArmForWrite(Rd_index + 1);
code->MOV(64, R(Rd0), R(ABI_RETURN)); code->MOV(64, R(Rd0), R(ABI_RETURN));
@ -515,6 +578,12 @@ void JitX64::LDRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
void JitX64::LDRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) { void JitX64::LDRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index < 14, "UNPREDICTABLE");
ASSERT_MSG(Rd_index % 2 == 0, "UNDEFINED");
ASSERT_MSG(Rm_index != Rd_index && Rm_index != Rd_index + 1, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rn_index != Rd_index && Rn_index != Rd_index + 1, "UNPREDICTABLE");
LoadStoreCommon_AddrMode3(this, reg_alloc, P, W, LoadStoreCommon_AddrMode3(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed,
@ -526,8 +595,6 @@ void JitX64::LDRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.LockX64(ABI_RETURN); reg_alloc.LockX64(ABI_RETURN);
ASSERT_MSG(Rd_index % 2 == 0 && Rd_index != 14, "UNPREDICTABLE");
X64Reg Rd0 = reg_alloc.BindArmForWrite(Rd_index + 0); X64Reg Rd0 = reg_alloc.BindArmForWrite(Rd_index + 0);
X64Reg Rd1 = reg_alloc.BindArmForWrite(Rd_index + 1); X64Reg Rd1 = reg_alloc.BindArmForWrite(Rd_index + 1);
code->MOV(64, R(Rd0), R(ABI_RETURN)); code->MOV(64, R(Rd0), R(ABI_RETURN));
@ -544,6 +611,10 @@ void JitX64::LDRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
void JitX64::LDRH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) { void JitX64::LDRH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) {
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode3(this, reg_alloc, P, W, LoadStoreCommon_AddrMode3(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed,
@ -555,8 +626,6 @@ void JitX64::LDRH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.LockX64(ABI_RETURN); reg_alloc.LockX64(ABI_RETURN);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index); X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index);
code->MOVZX(32, 16, Rd, R(ABI_RETURN)); code->MOVZX(32, 16, Rd, R(ABI_RETURN));
reg_alloc.UnlockArm(Rd_index); reg_alloc.UnlockArm(Rd_index);
@ -569,6 +638,10 @@ void JitX64::LDRH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
void JitX64::LDRH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) { void JitX64::LDRH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode3(this, reg_alloc, P, W, LoadStoreCommon_AddrMode3(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed,
@ -580,8 +653,6 @@ void JitX64::LDRH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.LockX64(ABI_RETURN); reg_alloc.LockX64(ABI_RETURN);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index); X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index);
code->MOVZX(32, 16, Rd, R(ABI_RETURN)); code->MOVZX(32, 16, Rd, R(ABI_RETURN));
reg_alloc.UnlockArm(Rd_index); reg_alloc.UnlockArm(Rd_index);
@ -594,6 +665,10 @@ void JitX64::LDRH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
void JitX64::LDRSB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) { void JitX64::LDRSB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) {
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode3(this, reg_alloc, P, W, LoadStoreCommon_AddrMode3(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed,
@ -605,8 +680,6 @@ void JitX64::LDRSB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.LockX64(ABI_RETURN); reg_alloc.LockX64(ABI_RETURN);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index); X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index);
code->MOVSX(32, 8, Rd, R(ABI_RETURN)); code->MOVSX(32, 8, Rd, R(ABI_RETURN));
reg_alloc.UnlockArm(Rd_index); reg_alloc.UnlockArm(Rd_index);
@ -619,6 +692,10 @@ void JitX64::LDRSB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe
void JitX64::LDRSB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) { void JitX64::LDRSB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode3(this, reg_alloc, P, W, LoadStoreCommon_AddrMode3(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed,
@ -630,8 +707,6 @@ void JitX64::LDRSB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.LockX64(ABI_RETURN); reg_alloc.LockX64(ABI_RETURN);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index); X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index);
code->MOVSX(32, 8, Rd, R(ABI_RETURN)); code->MOVSX(32, 8, Rd, R(ABI_RETURN));
reg_alloc.UnlockArm(Rd_index); reg_alloc.UnlockArm(Rd_index);
@ -644,6 +719,10 @@ void JitX64::LDRSB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe
void JitX64::LDRSH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) { void JitX64::LDRSH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) {
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode3(this, reg_alloc, P, W, LoadStoreCommon_AddrMode3(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed,
@ -655,8 +734,6 @@ void JitX64::LDRSH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.LockX64(ABI_RETURN); reg_alloc.LockX64(ABI_RETURN);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index); X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index);
code->MOVSX(32, 16, Rd, R(ABI_RETURN)); code->MOVSX(32, 16, Rd, R(ABI_RETURN));
reg_alloc.UnlockArm(Rd_index); reg_alloc.UnlockArm(Rd_index);
@ -669,6 +746,10 @@ void JitX64::LDRSH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe
void JitX64::LDRSH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) { void JitX64::LDRSH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode3(this, reg_alloc, P, W, LoadStoreCommon_AddrMode3(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed,
@ -680,8 +761,6 @@ void JitX64::LDRSH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.LockX64(ABI_RETURN); reg_alloc.LockX64(ABI_RETURN);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index); X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index);
code->MOVSX(32, 16, Rd, R(ABI_RETURN)); code->MOVSX(32, 16, Rd, R(ABI_RETURN));
reg_alloc.UnlockArm(Rd_index); reg_alloc.UnlockArm(Rd_index);
@ -692,8 +771,14 @@ void JitX64::LDRSH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe
} }
void JitX64::STRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) { void JitX64::STRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) {
CompileInterpretInstruction();
return;
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index < 14, "UNPREDICTABLE");
ASSERT_MSG(Rd_index % 2 == 0, "UNDEFINED");
LoadStoreCommon_AddrMode3(this, reg_alloc, P, W, LoadStoreCommon_AddrMode3(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed,
@ -705,8 +790,6 @@ void JitX64::STRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.FlushX64(ABI_PARAM3); reg_alloc.FlushX64(ABI_PARAM3);
reg_alloc.LockX64(ABI_PARAM3); reg_alloc.LockX64(ABI_PARAM3);
ASSERT_MSG(Rd_index % 2 == 0 && Rd_index != 14, "");
GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM2, Rd_index + 0); GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM2, Rd_index + 0);
GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM3, Rd_index + 1); GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM3, Rd_index + 1);
@ -716,12 +799,22 @@ void JitX64::STRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_PARAM2); reg_alloc.UnlockX64(ABI_PARAM2);
reg_alloc.UnlockX64(ABI_PARAM3); reg_alloc.UnlockX64(ABI_PARAM3);
// TODO: Exclusive stuff.
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
} }
void JitX64::STRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) { void JitX64::STRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
CompileInterpretInstruction();
return;
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index < 14, "UNPREDICTABLE");
ASSERT_MSG(Rd_index % 2 == 0, "UNDEFINED");
if (W)
ASSERT_MSG(Rn_index != Rd_index && Rn_index != Rd_index + 1, "UNPREDICTABLE");
LoadStoreCommon_AddrMode3(this, reg_alloc, P, W, LoadStoreCommon_AddrMode3(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed,
@ -733,8 +826,6 @@ void JitX64::STRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.FlushX64(ABI_PARAM3); reg_alloc.FlushX64(ABI_PARAM3);
reg_alloc.LockX64(ABI_PARAM3); reg_alloc.LockX64(ABI_PARAM3);
ASSERT_MSG(Rd_index % 2 == 0 && Rd_index != 14, "");
GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM2, Rd_index + 0); GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM2, Rd_index + 0);
GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM3, Rd_index + 1); GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM3, Rd_index + 1);
@ -744,12 +835,21 @@ void JitX64::STRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_PARAM2); reg_alloc.UnlockX64(ABI_PARAM2);
reg_alloc.UnlockX64(ABI_PARAM3); reg_alloc.UnlockX64(ABI_PARAM3);
// TODO: Exclusive stuff.
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
} }
void JitX64::STRH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) { void JitX64::STRH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) {
CompileInterpretInstruction();
return;
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rd_index != Rn_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode3(this, reg_alloc, P, W, LoadStoreCommon_AddrMode3(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePreIndexed,
@ -766,12 +866,21 @@ void JitX64::STRH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.UnlockX64(ABI_PARAM2); reg_alloc.UnlockX64(ABI_PARAM2);
// TODO: Exclusive stuff.
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
} }
void JitX64::STRH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) { void JitX64::STRH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
CompileInterpretInstruction();
return;
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
if (W)
ASSERT_MSG(Rd_index != Rn_index, "UNPREDICTABLE");
LoadStoreCommon_AddrMode3(this, reg_alloc, P, W, LoadStoreCommon_AddrMode3(this, reg_alloc, P, W,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset,
&JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPreIndexed,
@ -788,6 +897,8 @@ void JitX64::STRH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM1);
reg_alloc.UnlockX64(ABI_PARAM2); reg_alloc.UnlockX64(ABI_PARAM2);
// TODO: Exclusive stuff.
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
} }
@ -1003,8 +1114,12 @@ static void ExecuteSTMBE(u32 start_address, u16 reg_list, JitState* jit_state) {
} }
void JitX64::STM(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRegList list) { void JitX64::STM(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRegList list) {
CompileInterpretInstruction();
return;
cond_manager.CompileCond((ConditionCode)cond); cond_manager.CompileCond((ConditionCode)cond);
ASSERT_MSG(Rn_index != 15, "UNPREDICTABLE");
ASSERT_MSG(list != 0, "UNPREDICTABLE"); ASSERT_MSG(list != 0, "UNPREDICTABLE");
if (W && (list & (1 << Rn_index))) if (W && (list & (1 << Rn_index)))
ASSERT_MSG((list & ((1 << Rn_index) - 1)) == 0, "UNPREDICTABLE"); ASSERT_MSG((list & ((1 << Rn_index) - 1)) == 0, "UNPREDICTABLE");
@ -1014,6 +1129,8 @@ void JitX64::STM(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRegList
LoadAndStoreMultiple_Helper(code, reg_alloc, P, U, W, Rn_index, list, LoadAndStoreMultiple_Helper(code, reg_alloc, P, U, W, Rn_index, list,
[this](){ CompileCallHost(reinterpret_cast<const void* const>(!current.EFlag ? &ExecuteSTMLE : &ExecuteSTMBE)); }); [this](){ CompileCallHost(reinterpret_cast<const void* const>(!current.EFlag ? &ExecuteSTMLE : &ExecuteSTMBE)); });
// TODO: Exclusive stuff
current.arm_pc += GetInstSize(); current.arm_pc += GetInstSize();
} }

View File

@ -51,6 +51,7 @@ CodePtr JitX64::Compile(u32 pc, bool TFlag, bool EFlag) {
} }
reg_alloc.AssertNoLocked(); reg_alloc.AssertNoLocked();
reg_alloc.FlushEverything();
} while (!stop_compilation && ((current.arm_pc & 0xFFF) != 0)); } while (!stop_compilation && ((current.arm_pc & 0xFFF) != 0));
if (!stop_compilation) { if (!stop_compilation) {
@ -163,7 +164,6 @@ void JitX64::CompileCallHost(const void* const fn) {
// There is no need to setup the stack as the stored RSP has already been properly aligned. // There is no need to setup the stack as the stored RSP has already been properly aligned.
reg_alloc.FlushABICallerSaved(); reg_alloc.FlushABICallerSaved();
reg_alloc.FlushX64(RSP);
ASSERT(reg_alloc.JitStateReg() != RSP); ASSERT(reg_alloc.JitStateReg() != RSP);
code->MOV(64, R(RSP), MJitStateHostReturnRSP()); code->MOV(64, R(RSP), MJitStateHostReturnRSP());

View File

@ -270,7 +270,7 @@ void RegAlloc::MarkDirty(ArmReg arm_reg) {
void RegAlloc::FlushEverything() { void RegAlloc::FlushEverything() {
for (auto i : x64_reg_to_index) { for (auto i : x64_reg_to_index) {
X64State& x64_state = x64_gpr[i.second]; X64State& x64_state = x64_gpr[i.second];
ASSERT(!x64_state.locked); ASSERT(!x64_state.locked || x64_state.state == X64State::State::UserManuallyLocked);
FlushX64(i.first); FlushX64(i.first);
ASSERT(x64_state.state == X64State::State::Free); ASSERT(x64_state.state == X64State::State::Free);
} }
@ -278,15 +278,13 @@ void RegAlloc::FlushEverything() {
void RegAlloc::FlushABICallerSaved() { void RegAlloc::FlushABICallerSaved() {
for (auto i : x64_reg_to_index) { for (auto i : x64_reg_to_index) {
if (ABI_ALL_CALLER_SAVED.m_val & (1 << i.first)) { X64State& x64_state = x64_gpr[i.second];
X64State& x64_state = x64_gpr[i.second]; if (x64_state.state != X64State::State::UserManuallyLocked) {
if (x64_state.state != X64State::State::UserManuallyLocked) { ASSERT(!x64_state.locked);
ASSERT(!x64_state.locked); FlushX64(i.first);
FlushX64(i.first); ASSERT(x64_state.state == X64State::State::Free);
ASSERT(x64_state.state == X64State::State::Free); } else {
} else { ASSERT(x64_state.locked);
ASSERT(x64_state.locked);
}
} }
} }

View File

@ -50,6 +50,13 @@ TEST_CASE("Fuzz ARM load/store instructions (byte, half-word, word)", "[JitX64]"
u32 rand = RandInt<u32>(0, 0xFF); u32 rand = RandInt<u32>(0, 0xFF);
u32 Rm = RandInt<u32>(0, 14); u32 Rm = RandInt<u32>(0, 14);
if (W) {
while (Rn == Rd) {
Rn = RandInt<u32>(0, 14);
Rd = RandInt<u32>(0, 14);
}
}
u32 assemble_randoms = (Rm << 0) | (rand << 4) | (Rd << 12) | (Rn << 16) | (W << 21) | (U << 23) | (P << 24) | (cond << 28); u32 assemble_randoms = (Rm << 0) | (rand << 4) | (Rd << 12) | (Rn << 16) | (W << 21) | (U << 23) | (P << 24) | (cond << 28);
return instructions[inst_index].first | (assemble_randoms & (~instructions[inst_index].second)); return instructions[inst_index].first | (assemble_randoms & (~instructions[inst_index].second));
@ -86,6 +93,17 @@ TEST_CASE("Fuzz ARM load/store instructions (double-word)", "[JitX64]") {
u32 rand = RandInt<u32>(0, 0xF); u32 rand = RandInt<u32>(0, 0xF);
u32 Rm = RandInt<u32>(0, 14); u32 Rm = RandInt<u32>(0, 14);
if (W) {
while (Rn == Rd) {
Rn = RandInt<u32>(0, 6) * 2;
Rd = RandInt<u32>(0, 6) * 2;
}
}
while (Rm == Rd || Rm == Rd + 1) {
Rm = RandInt<u32>(0, 14);
}
u32 assemble_randoms = (Rm << 0) | (rand << 4) | (Rd << 12) | (Rn << 16) | (W << 21) | (U << 23) | (P << 24) | (cond << 28); u32 assemble_randoms = (Rm << 0) | (rand << 4) | (Rd << 12) | (Rn << 16) | (W << 21) | (U << 23) | (P << 24) | (cond << 28);
return instructions[inst_index].first | (assemble_randoms & (~instructions[inst_index].second)); return instructions[inst_index].first | (assemble_randoms & (~instructions[inst_index].second));