diff --git a/src/core/arm/jit_x64/instructions/load_store.cpp b/src/core/arm/jit_x64/instructions/load_store.cpp index 8744c4ab0..7ee53001e 100644 --- a/src/core/arm/jit_x64/instructions/load_store.cpp +++ b/src/core/arm/jit_x64/instructions/load_store.cpp @@ -277,7 +277,7 @@ void JitX64::LDR_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePostIndexed, U, Rn_index, imm12); - CompileCallHost(!current.EFlag ? &Load32LE : &Load32BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Load32LE : &Load32BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.LockX64(ABI_RETURN); @@ -301,7 +301,7 @@ void JitX64::LDR_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPostIndexed, U, Rn_index, imm5, shift, Rm_index); - CompileCallHost(!current.EFlag ? &Load32LE : &Load32BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Load32LE : &Load32BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.LockX64(ABI_RETURN); @@ -325,7 +325,7 @@ void JitX64::LDRB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePostIndexed, U, Rn_index, imm12); - CompileCallHost(&Load8); + CompileCallHost(reinterpret_cast(&Load8)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.LockX64(ABI_RETURN); @@ -349,7 +349,7 @@ void JitX64::LDRB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPostIndexed, U, Rn_index, imm5, shift, Rm_index); - CompileCallHost(&Load8); + CompileCallHost(reinterpret_cast(&Load8)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.LockX64(ABI_RETURN); @@ -378,7 +378,7 @@ void JitX64::STR_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM2, Rd_index); - CompileCallHost(!current.EFlag ? &Store32LE : &Store32BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Store32LE : &Store32BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM2); @@ -400,7 +400,7 @@ void JitX64::STR_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM2, Rd_index); - CompileCallHost(!current.EFlag ? &Store32LE : &Store32BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Store32LE : &Store32BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM2); @@ -422,7 +422,7 @@ void JitX64::STRB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM2, Rd_index); - CompileCallHost(&Store8); + CompileCallHost(reinterpret_cast(&Store8)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM2); @@ -444,7 +444,7 @@ void JitX64::STRB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM2, Rd_index); - CompileCallHost(&Store8); + CompileCallHost(reinterpret_cast(&Store8)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM2); @@ -492,7 +492,7 @@ void JitX64::LDRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePostIndexed, U, Rn_index, CombineImm8ab(imm8a, imm8b)); - CompileCallHost(!current.EFlag ? &Load64LE : &Load64BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Load64LE : &Load64BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.LockX64(ABI_RETURN); @@ -521,7 +521,7 @@ void JitX64::LDRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPostIndexed, U, Rn_index, 0, 0, Rm_index); - CompileCallHost(!current.EFlag ? &Load64LE : &Load64BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Load64LE : &Load64BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.LockX64(ABI_RETURN); @@ -550,7 +550,7 @@ void JitX64::LDRH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePostIndexed, U, Rn_index, CombineImm8ab(imm8a, imm8b)); - CompileCallHost(!current.EFlag ? &Load16LE : &Load16BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Load16LE : &Load16BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.LockX64(ABI_RETURN); @@ -575,7 +575,7 @@ void JitX64::LDRH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPostIndexed, U, Rn_index, 0, 0, Rm_index); - CompileCallHost(!current.EFlag ? &Load16LE : &Load16BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Load16LE : &Load16BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.LockX64(ABI_RETURN); @@ -600,7 +600,7 @@ void JitX64::LDRSB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePostIndexed, U, Rn_index, CombineImm8ab(imm8a, imm8b)); - CompileCallHost(&Load8); + CompileCallHost(reinterpret_cast(&Load8)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.LockX64(ABI_RETURN); @@ -625,7 +625,7 @@ void JitX64::LDRSB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPostIndexed, U, Rn_index, 0, 0, Rm_index); - CompileCallHost(&Load8); + CompileCallHost(reinterpret_cast(&Load8)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.LockX64(ABI_RETURN); @@ -650,7 +650,7 @@ void JitX64::LDRSH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe &JitX64::LoadAndStoreWordOrUnsignedByte_ImmediatePostIndexed, U, Rn_index, CombineImm8ab(imm8a, imm8b)); - CompileCallHost(!current.EFlag ? &Load16LE : &Load16BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Load16LE : &Load16BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.LockX64(ABI_RETURN); @@ -675,7 +675,7 @@ void JitX64::LDRSH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe &JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPostIndexed, U, Rn_index, 0, 0, Rm_index); - CompileCallHost(!current.EFlag ? &Load16LE : &Load16BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Load16LE : &Load16BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.LockX64(ABI_RETURN); @@ -710,7 +710,7 @@ void JitX64::STRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM2, Rd_index + 0); GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM3, Rd_index + 1); - CompileCallHost(!current.EFlag ? &Store64LE : &Store64BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Store64LE : &Store64BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM2); @@ -738,7 +738,7 @@ void JitX64::STRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM2, Rd_index + 0); GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM3, Rd_index + 1); - CompileCallHost(!current.EFlag ? &Store64LE : &Store64BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Store64LE : &Store64BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM2); @@ -761,7 +761,7 @@ void JitX64::STRH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM2, Rd_index); - CompileCallHost(!current.EFlag ? &Store16LE : &Store16BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Store16LE : &Store16BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM2); @@ -783,7 +783,7 @@ void JitX64::STRH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg GetValueOfRegister(code, reg_alloc, GetReg15Value(), ABI_PARAM2, Rd_index); - CompileCallHost(!current.EFlag ? &Store16LE : &Store16BE); + CompileCallHost(reinterpret_cast(!current.EFlag ? &Store16LE : &Store16BE)); reg_alloc.UnlockX64(ABI_PARAM1); reg_alloc.UnlockX64(ABI_PARAM2); @@ -949,7 +949,7 @@ void JitX64::LDM(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRegList // TODO: Optimize LoadAndStoreMultiple_Helper(code, reg_alloc, P, U, W, Rn_index, list, - [this](){ CompileCallHost(!current.EFlag ? &ExecuteLDMLE : &ExecuteLDMBE); }); + [this](){ CompileCallHost(reinterpret_cast(!current.EFlag ? &ExecuteLDMLE : &ExecuteLDMBE)); }); current.arm_pc += GetInstSize(); if (list & (1 << 15)) { @@ -1006,7 +1006,7 @@ void JitX64::STM(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRegList // TODO: Optimize LoadAndStoreMultiple_Helper(code, reg_alloc, P, U, W, Rn_index, list, - [this](){ CompileCallHost(!current.EFlag ? &ExecuteSTMLE : &ExecuteSTMBE); }); + [this](){ CompileCallHost(reinterpret_cast(!current.EFlag ? &ExecuteSTMLE : &ExecuteSTMBE)); }); current.arm_pc += GetInstSize(); } diff --git a/src/core/arm/jit_x64/instructions/status_register.cpp b/src/core/arm/jit_x64/instructions/status_register.cpp index 82a168848..8b7b6f2e1 100644 --- a/src/core/arm/jit_x64/instructions/status_register.cpp +++ b/src/core/arm/jit_x64/instructions/status_register.cpp @@ -6,11 +6,27 @@ namespace JitX64 { +using namespace Gen; + void JitX64::CPS() { CompileInterpretInstruction(); } void JitX64::MRS() { CompileInterpretInstruction(); } void JitX64::MSR() { CompileInterpretInstruction(); } void JitX64::RFE() { CompileInterpretInstruction(); } -void JitX64::SETEND(bool E) { CompileInterpretInstruction(); } + +void JitX64::SETEND(bool E) { + cond_manager.Always(); + + if (E) { + code->OR(32, MJitStateCpsr(), Imm32(1 << 9)); + current.EFlag = true; + } else { + code->AND(32, MJitStateCpsr(), Imm32(~(1 << 9))); + current.EFlag = false; + } + + current.arm_pc += GetInstSize(); +} + void JitX64::SRS() { CompileInterpretInstruction(); } } diff --git a/src/core/arm/jit_x64/interface.cpp b/src/core/arm/jit_x64/interface.cpp index 806e23e57..8723ae3d1 100644 --- a/src/core/arm/jit_x64/interface.cpp +++ b/src/core/arm/jit_x64/interface.cpp @@ -162,6 +162,7 @@ void ARM_Jit::ExecuteInstructions(int num_instructions) { do { //state->page_table = reinterpret_cast(Memory::current_page_table->pointers.data()); + bool EFlag = (state->cpu_state.Cpsr >> 9) & 1; state->cpu_state.TFlag = (state->cpu_state.Cpsr >> 5) & 1; if (!state->cpu_state.NirqSig) { @@ -173,7 +174,7 @@ void ARM_Jit::ExecuteInstructions(int num_instructions) { else state->cpu_state.Reg[15] &= 0xfffffffc; - u8 *ptr = compiler.GetBB(state->cpu_state.Reg[15], state->cpu_state.TFlag, false); + u8 *ptr = compiler.GetBB(state->cpu_state.Reg[15], state->cpu_state.TFlag, EFlag); unsigned ticks_executed = run_jit.CallCode(state.get(), ptr, num_instructions, state->cpu_state.Reg[15]); num_instructions -= ticks_executed; diff --git a/src/core/arm/jit_x64/interpret.cpp b/src/core/arm/jit_x64/interpret.cpp index 8dd6c42fc..fda3828f7 100644 --- a/src/core/arm/jit_x64/interpret.cpp +++ b/src/core/arm/jit_x64/interpret.cpp @@ -49,8 +49,7 @@ void JitX64::CompileInterpretInstruction() { code->MOV(64, R(ABI_PARAM3), Imm64(current.TFlag)); code->MOV(64, R(ABI_PARAM4), Imm64(current.EFlag)); - const void *const fn = reinterpret_cast(&CallInterpreter); - CompileCallHost(fn); + CompileCallHost(reinterpret_cast(&CallInterpreter)); code->MOV(64, R(reg_alloc.JitStateReg()), R(ABI_RETURN)); diff --git a/src/core/arm/jit_x64/jit_x64.cpp b/src/core/arm/jit_x64/jit_x64.cpp index a3ae154ef..31eec88cd 100644 --- a/src/core/arm/jit_x64/jit_x64.cpp +++ b/src/core/arm/jit_x64/jit_x64.cpp @@ -241,6 +241,13 @@ Gen::OpArg JitX64::MJitStateVFlag() { return Gen::MDisp(reg_alloc.JitStateReg(), offsetof(JitState, cpu_state) + offsetof(ARMul_State, VFlag)); } +Gen::OpArg JitX64::MJitStateCpsr() { + static_assert(std::is_same::value, "JitState::cpu_state must be ARMul_State"); + static_assert(std::is_same::value, "Cpsr must be u32"); + + return Gen::MDisp(reg_alloc.JitStateReg(), offsetof(JitState, cpu_state) + offsetof(ARMul_State, Cpsr)); +} + Gen::OpArg JitX64::MJitStateExclusiveTag() { static_assert(std::is_same::value, "JitState::cpu_state must be ARMul_State"); static_assert(std::is_same::value, "exclusive_tag must be u32"); diff --git a/src/core/arm/jit_x64/jit_x64.h b/src/core/arm/jit_x64/jit_x64.h index 7d76d2279..3aef349e5 100644 --- a/src/core/arm/jit_x64/jit_x64.h +++ b/src/core/arm/jit_x64/jit_x64.h @@ -91,6 +91,7 @@ private: Gen::OpArg MJitStateCFlag(); Gen::OpArg MJitStateNFlag(); Gen::OpArg MJitStateVFlag(); + Gen::OpArg MJitStateCpsr(); Gen::OpArg MJitStateExclusiveTag(); Gen::OpArg MJitStateExclusiveState(); 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 e21938171..a7b84d9e0 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 @@ -12,7 +12,7 @@ #include "tests/core/arm/jit_x64/fuzz_arm_common.h" TEST_CASE("Fuzz ARM load/store instructions (byte, half-word, word)", "[JitX64]") { - const std::array, 16> instructions = {{ + const std::array, 17> instructions = {{ FromBitString32("cccc010pu0w1nnnnddddvvvvvvvvvvvv"), // LDR_imm FromBitString32("cccc011pu0w1nnnnddddvvvvvrr0mmmm"), // LDR_reg FromBitString32("cccc010pu1w1nnnnddddvvvvvvvvvvvv"), // LDRB_imm @@ -29,6 +29,7 @@ TEST_CASE("Fuzz ARM load/store instructions (byte, half-word, word)", "[JitX64]" FromBitString32("cccc000pu0w1nnnndddd00001111mmmm"), // LDRSH_reg FromBitString32("cccc000pu1w0nnnnddddvvvv1011vvvv"), // STRH_imm FromBitString32("cccc000pu0w0nnnndddd00001011mmmm"), // STRH_reg + FromBitString32("1111000100000001000000e000000000"), // SETEND }}; auto instruction_select = [&]() -> u32 { @@ -46,7 +47,7 @@ TEST_CASE("Fuzz ARM load/store instructions (byte, half-word, word)", "[JitX64]" u32 P = RandInt(0, 1); if (P) W = RandInt(0, 1); u32 U = RandInt(0, 1); - u32 rand = RandInt(0, 0xF); + u32 rand = RandInt(0, 0xFF); u32 Rm = RandInt(0, 14); u32 assemble_randoms = (Rm << 0) | (rand << 4) | (Rd << 12) | (Rn << 16) | (W << 21) | (U << 23) | (P << 24) | (cond << 28); @@ -55,7 +56,7 @@ TEST_CASE("Fuzz ARM load/store instructions (byte, half-word, word)", "[JitX64]" }; SECTION("short blocks") { - FuzzJit(1, 2, 5000, instruction_select); + FuzzJit(5, 6, 5000, instruction_select); } }