From 20d87c315ab0a9f8890a95ce232db789f2e7d034 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 3 Apr 2016 09:00:56 +0100 Subject: [PATCH] JitX64: Load/Store: Add UNPREDICTABLE ASSERTs, correct LDR R15 behavior --- src/core/arm/jit_x64/instructions/branch.cpp | 4 + .../arm/jit_x64/instructions/load_store.cpp | 157 +++++++++++++++--- src/core/arm/jit_x64/jit_x64.cpp | 2 +- src/core/arm/jit_x64/reg_alloc.cpp | 18 +- .../core/arm/jit_x64/fuzz_arm_load_store.cpp | 18 ++ 5 files changed, 168 insertions(+), 31 deletions(-) diff --git a/src/core/arm/jit_x64/instructions/branch.cpp b/src/core/arm/jit_x64/instructions/branch.cpp index 783ba796f..05afd6a2e 100644 --- a/src/core/arm/jit_x64/instructions/branch.cpp +++ b/src/core/arm/jit_x64/instructions/branch.cpp @@ -92,6 +92,8 @@ void JitX64::BLX_reg(Cond cond, ArmReg Rm_index) { current.arm_pc += GetInstSize(); CompileReturnToDispatch(); + + stop_compilation = true; } void JitX64::BX(Cond cond, ArmReg Rm_index) { @@ -111,6 +113,8 @@ void JitX64::BX(Cond cond, ArmReg Rm_index) { current.arm_pc += GetInstSize(); CompileReturnToDispatch(); + + stop_compilation = true; } void JitX64::BXJ(Cond cond, ArmReg Rm) { diff --git a/src/core/arm/jit_x64/instructions/load_store.cpp b/src/core/arm/jit_x64/instructions/load_store.cpp index f95227725..d74bd2c57 100644 --- a/src/core/arm/jit_x64/instructions/load_store.cpp +++ b/src/core/arm/jit_x64/instructions/load_store.cpp @@ -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) { 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &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); 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) { @@ -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); 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) { 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &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) { 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &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) { + CompileInterpretInstruction(); + return; + 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &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_PARAM2); + // TODO: Exclusive stuff + 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) { + CompileInterpretInstruction(); + return; + 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &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_PARAM2); + // TODO: Exclusive stuff + current.arm_pc += GetInstSize(); } 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); + ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE"); + if (W) + ASSERT_MSG(Rn_index != Rd_index, "UNPREDICTABLE"); + LoadStoreCommon_AddrMode2(this, reg_alloc, P, W, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &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_PARAM2); + //TODO: Exclusive stuff + 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) { + CompileInterpretInstruction(); + return; + 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &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_PARAM2); + //TODO: Exclusive stuff + 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) { 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &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.LockX64(ABI_RETURN); - ASSERT_MSG(Rd_index % 2 == 0 && Rd_index != 14, "UNPREDICTABLE"); - X64Reg Rd0 = reg_alloc.BindArmForWrite(Rd_index + 0); X64Reg Rd1 = reg_alloc.BindArmForWrite(Rd_index + 1); 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) { 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &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.LockX64(ABI_RETURN); - ASSERT_MSG(Rd_index % 2 == 0 && Rd_index != 14, "UNPREDICTABLE"); - X64Reg Rd0 = reg_alloc.BindArmForWrite(Rd_index + 0); X64Reg Rd1 = reg_alloc.BindArmForWrite(Rd_index + 1); 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) { 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &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.LockX64(ABI_RETURN); - ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE"); - X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index); code->MOVZX(32, 16, Rd, R(ABI_RETURN)); 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) { 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &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.LockX64(ABI_RETURN); - ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE"); - X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index); code->MOVZX(32, 16, Rd, R(ABI_RETURN)); 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) { 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &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.LockX64(ABI_RETURN); - ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE"); - X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index); code->MOVSX(32, 8, Rd, R(ABI_RETURN)); 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) { 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &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.LockX64(ABI_RETURN); - ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE"); - X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index); code->MOVSX(32, 8, Rd, R(ABI_RETURN)); 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) { 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &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.LockX64(ABI_RETURN); - ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE"); - X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index); code->MOVSX(32, 16, Rd, R(ABI_RETURN)); 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) { 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &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.LockX64(ABI_RETURN); - ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE"); - X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index); code->MOVSX(32, 16, Rd, R(ABI_RETURN)); 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) { + CompileInterpretInstruction(); + return; + 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &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.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_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_PARAM3); + // TODO: Exclusive stuff. + 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) { + CompileInterpretInstruction(); + return; + 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &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.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_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_PARAM3); + // TODO: Exclusive stuff. + 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) { + CompileInterpretInstruction(); + return; + 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediateOffset, &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_PARAM2); + // TODO: Exclusive stuff. + 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) { + CompileInterpretInstruction(); + return; + 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, &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterOffset, &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_PARAM2); + // TODO: Exclusive stuff. + 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) { + CompileInterpretInstruction(); + return; + cond_manager.CompileCond((ConditionCode)cond); + ASSERT_MSG(Rn_index != 15, "UNPREDICTABLE"); ASSERT_MSG(list != 0, "UNPREDICTABLE"); if (W && (list & (1 << Rn_index))) 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, [this](){ CompileCallHost(reinterpret_cast(!current.EFlag ? &ExecuteSTMLE : &ExecuteSTMBE)); }); + // TODO: Exclusive stuff + current.arm_pc += GetInstSize(); } diff --git a/src/core/arm/jit_x64/jit_x64.cpp b/src/core/arm/jit_x64/jit_x64.cpp index f0e560cf3..be15cfabc 100644 --- a/src/core/arm/jit_x64/jit_x64.cpp +++ b/src/core/arm/jit_x64/jit_x64.cpp @@ -51,6 +51,7 @@ CodePtr JitX64::Compile(u32 pc, bool TFlag, bool EFlag) { } reg_alloc.AssertNoLocked(); + reg_alloc.FlushEverything(); } while (!stop_compilation && ((current.arm_pc & 0xFFF) != 0)); 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. reg_alloc.FlushABICallerSaved(); - reg_alloc.FlushX64(RSP); ASSERT(reg_alloc.JitStateReg() != RSP); code->MOV(64, R(RSP), MJitStateHostReturnRSP()); diff --git a/src/core/arm/jit_x64/reg_alloc.cpp b/src/core/arm/jit_x64/reg_alloc.cpp index 77eb0d8fb..ee346b3e9 100644 --- a/src/core/arm/jit_x64/reg_alloc.cpp +++ b/src/core/arm/jit_x64/reg_alloc.cpp @@ -270,7 +270,7 @@ void RegAlloc::MarkDirty(ArmReg arm_reg) { void RegAlloc::FlushEverything() { for (auto i : x64_reg_to_index) { X64State& x64_state = x64_gpr[i.second]; - ASSERT(!x64_state.locked); + ASSERT(!x64_state.locked || x64_state.state == X64State::State::UserManuallyLocked); FlushX64(i.first); ASSERT(x64_state.state == X64State::State::Free); } @@ -278,15 +278,13 @@ void RegAlloc::FlushEverything() { void RegAlloc::FlushABICallerSaved() { for (auto i : x64_reg_to_index) { - if (ABI_ALL_CALLER_SAVED.m_val & (1 << i.first)) { - X64State& x64_state = x64_gpr[i.second]; - if (x64_state.state != X64State::State::UserManuallyLocked) { - ASSERT(!x64_state.locked); - FlushX64(i.first); - ASSERT(x64_state.state == X64State::State::Free); - } else { - ASSERT(x64_state.locked); - } + X64State& x64_state = x64_gpr[i.second]; + if (x64_state.state != X64State::State::UserManuallyLocked) { + ASSERT(!x64_state.locked); + FlushX64(i.first); + ASSERT(x64_state.state == X64State::State::Free); + } else { + ASSERT(x64_state.locked); } } diff --git a/src/tests/core/arm/jit_x64/fuzz_arm_load_store.cpp b/src/tests/core/arm/jit_x64/fuzz_arm_load_store.cpp index 4458ce44b..d3ec4c1c6 100644 --- a/src/tests/core/arm/jit_x64/fuzz_arm_load_store.cpp +++ b/src/tests/core/arm/jit_x64/fuzz_arm_load_store.cpp @@ -50,6 +50,13 @@ TEST_CASE("Fuzz ARM load/store instructions (byte, half-word, word)", "[JitX64]" u32 rand = RandInt(0, 0xFF); u32 Rm = RandInt(0, 14); + if (W) { + while (Rn == Rd) { + Rn = RandInt(0, 14); + Rd = RandInt(0, 14); + } + } + 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)); @@ -86,6 +93,17 @@ TEST_CASE("Fuzz ARM load/store instructions (double-word)", "[JitX64]") { u32 rand = RandInt(0, 0xF); u32 Rm = RandInt(0, 14); + if (W) { + while (Rn == Rd) { + Rn = RandInt(0, 6) * 2; + Rd = RandInt(0, 6) * 2; + } + } + + while (Rm == Rd || Rm == Rd + 1) { + Rm = RandInt(0, 14); + } + 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));