diff --git a/Core/MIPS/ARM64/Arm64CompALU.cpp b/Core/MIPS/ARM64/Arm64CompALU.cpp index 46a3ff09b6..9c502da2f9 100644 --- a/Core/MIPS/ARM64/Arm64CompALU.cpp +++ b/Core/MIPS/ARM64/Arm64CompALU.cpp @@ -66,7 +66,7 @@ void Arm64Jit::CompImmLogic(MIPSGPReg rs, MIPSGPReg rt, u32 uimm, void (ARM64XEm } else { gpr.MapDirtyIn(rt, rs); if (!(this->*tryArithI2R)(gpr.R(rt), gpr.R(rs), uimm)) { - gpr.SetRegImm(SCRATCH1, uimm); + MOVI2R(SCRATCH1, uimm); (this->*arith)(gpr.R(rt), gpr.R(rs), SCRATCH1); } } @@ -119,7 +119,7 @@ void Arm64Jit::Comp_IType(MIPSOpcode op) { } gpr.MapDirtyIn(rt, rs); if (!TryCMPI2R(gpr.R(rs), (u32)simm)) { - gpr.SetRegImm(SCRATCH1, simm); + MOVI2R(SCRATCH1, simm); CMP(gpr.R(rs), SCRATCH1); } CSET(gpr.R(rt), CC_LT); @@ -132,7 +132,7 @@ void Arm64Jit::Comp_IType(MIPSOpcode op) { } gpr.MapDirtyIn(rt, rs); if (!TryCMPI2R(gpr.R(rs), suimm)) { - gpr.SetRegImm(SCRATCH1, suimm); + MOVI2R(SCRATCH1, suimm); CMP(gpr.R(rs), SCRATCH1); } CSET(gpr.R(rt), CC_LO); diff --git a/Core/MIPS/ARM64/Arm64CompBranch.cpp b/Core/MIPS/ARM64/Arm64CompBranch.cpp index 4f41362428..efc556f629 100644 --- a/Core/MIPS/ARM64/Arm64CompBranch.cpp +++ b/Core/MIPS/ARM64/Arm64CompBranch.cpp @@ -534,7 +534,7 @@ void Arm64Jit::Comp_Jump(MIPSOpcode op) { // TODO: Mark this block dirty or something? May be indication it will be changed by imports. CompileDelaySlot(DELAYSLOT_NICE); FlushAll(); - gpr.SetRegImm(SCRATCH1, GetCompilerPC() + 8); + MOVI2R(SCRATCH1, GetCompilerPC() + 8); MovToPC(SCRATCH1); MOVI2R(W0, targetAddr); QuickCallFunction(SCRATCH1, (const void *)&HitInvalidJump); @@ -692,7 +692,7 @@ void Arm64Jit::Comp_Syscall(MIPSOpcode op) js.downcountAmount = -offset; if (!js.inDelaySlot) { - gpr.SetRegImm(SCRATCH1, GetCompilerPC() + 4); + MOVI2R(SCRATCH1, GetCompilerPC() + 4); MovToPC(SCRATCH1); } diff --git a/Core/MIPS/ARM64/Arm64CompFPU.cpp b/Core/MIPS/ARM64/Arm64CompFPU.cpp index 2756f5e8ed..c279d5f862 100644 --- a/Core/MIPS/ARM64/Arm64CompFPU.cpp +++ b/Core/MIPS/ARM64/Arm64CompFPU.cpp @@ -105,7 +105,7 @@ void Arm64Jit::Comp_FPULS(MIPSOpcode op) #else u32 addr = offset + gpr.GetImm(rs); #endif - gpr.SetRegImm(SCRATCH1, addr); + MOVI2R(SCRATCH1, addr); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { @@ -136,7 +136,7 @@ void Arm64Jit::Comp_FPULS(MIPSOpcode op) #else u32 addr = offset + gpr.GetImm(rs); #endif - gpr.SetRegImm(SCRATCH1, addr); + MOVI2R(SCRATCH1, addr); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { diff --git a/Core/MIPS/ARM64/Arm64CompLoadStore.cpp b/Core/MIPS/ARM64/Arm64CompLoadStore.cpp index 9824f07001..bbb7eb7409 100644 --- a/Core/MIPS/ARM64/Arm64CompLoadStore.cpp +++ b/Core/MIPS/ARM64/Arm64CompLoadStore.cpp @@ -146,7 +146,7 @@ namespace MIPSComp { // Need to initialize since this only loads part of the register. // But rs no longer matters (even if rs == rt) since we have the address. gpr.MapReg(rt, load ? MAP_DIRTY : 0); - gpr.SetRegImm(SCRATCH1, addr & ~3); + MOVI2R(SCRATCH1, addr & ~3); u8 shift = (addr & 3) * 8; @@ -376,7 +376,7 @@ namespace MIPSComp { gpr.MapReg(rt, load ? MAP_NOINIT : 0); targetReg = gpr.R(rt); } - gpr.SetRegImm(SCRATCH1, addr); + MOVI2R(SCRATCH1, addr); addrReg = SCRATCH1; } } else { diff --git a/Core/MIPS/ARM64/Arm64CompVFPU.cpp b/Core/MIPS/ARM64/Arm64CompVFPU.cpp index d722deb0f6..9fbd2dc43d 100644 --- a/Core/MIPS/ARM64/Arm64CompVFPU.cpp +++ b/Core/MIPS/ARM64/Arm64CompVFPU.cpp @@ -229,7 +229,7 @@ namespace MIPSComp { #else u32 addr = offset + gpr.GetImm(rs); #endif - gpr.SetRegImm(SCRATCH1, addr); + MOVI2R(SCRATCH1, addr); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { @@ -262,7 +262,7 @@ namespace MIPSComp { #else u32 addr = offset + gpr.GetImm(rs); #endif - gpr.SetRegImm(SCRATCH1, addr); + MOVI2R(SCRATCH1, addr); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { @@ -308,7 +308,7 @@ namespace MIPSComp { #else u32 addr = imm + gpr.GetImm(rs); #endif - gpr.SetRegImm(SCRATCH1_64, addr + (uintptr_t)Memory::base); + MOVI2R(SCRATCH1_64, addr + (uintptr_t)Memory::base); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { @@ -345,7 +345,7 @@ namespace MIPSComp { #else u32 addr = imm + gpr.GetImm(rs); #endif - gpr.SetRegImm(SCRATCH1_64, addr + (uintptr_t)Memory::base); + MOVI2R(SCRATCH1_64, addr + (uintptr_t)Memory::base); } else { gpr.MapReg(rs); if (g_Config.bFastMemory) { diff --git a/Core/MIPS/ARM64/Arm64Jit.cpp b/Core/MIPS/ARM64/Arm64Jit.cpp index 9a104db10a..b24527a2e5 100644 --- a/Core/MIPS/ARM64/Arm64Jit.cpp +++ b/Core/MIPS/ARM64/Arm64Jit.cpp @@ -170,19 +170,19 @@ void Arm64Jit::FlushPrefixV() { } if ((js.prefixSFlag & JitState::PREFIX_DIRTY) != 0) { - gpr.SetRegImm(SCRATCH1, js.prefixS); + MOVI2R(SCRATCH1, js.prefixS); STR(INDEX_UNSIGNED, SCRATCH1, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_SPREFIX])); js.prefixSFlag = (JitState::PrefixState) (js.prefixSFlag & ~JitState::PREFIX_DIRTY); } if ((js.prefixTFlag & JitState::PREFIX_DIRTY) != 0) { - gpr.SetRegImm(SCRATCH1, js.prefixT); + MOVI2R(SCRATCH1, js.prefixT); STR(INDEX_UNSIGNED, SCRATCH1, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_TPREFIX])); js.prefixTFlag = (JitState::PrefixState) (js.prefixTFlag & ~JitState::PREFIX_DIRTY); } if ((js.prefixDFlag & JitState::PREFIX_DIRTY) != 0) { - gpr.SetRegImm(SCRATCH1, js.prefixD); + MOVI2R(SCRATCH1, js.prefixD); STR(INDEX_UNSIGNED, SCRATCH1, CTXREG, offsetof(MIPSState, vfpuCtrl[VFPU_CTRL_DPREFIX])); js.prefixDFlag = (JitState::PrefixState) (js.prefixDFlag & ~JitState::PREFIX_DIRTY); } @@ -251,6 +251,10 @@ void Arm64Jit::Compile(u32 em_address) { BeginWrite(JitBlockCache::MAX_BLOCK_INSTRUCTIONS * 16); int block_num = blocks.AllocateBlock(em_address); + + // To debug really wacky JIT issues, it can be a good idea to bisect the block number, + // and disable parts of the jit using jo.disableFlags for certain ranges of blocks. + JitBlock *b = blocks.GetBlock(block_num); DoJit(em_address, b); _assert_msg_(b->originalAddress == em_address, "original %08x != em_address %08x (block %d)", b->originalAddress, em_address, b->blockNum); @@ -381,7 +385,7 @@ const u8 *Arm64Jit::DoJit(u32 em_address, JitBlock *b) { if (jo.useForwardJump) { SetJumpTarget(bail); - gpr.SetRegImm(SCRATCH1, js.blockStart); + MOVI2R(SCRATCH1, js.blockStart); B((const void *)outerLoopPCInSCRATCH1); } @@ -599,7 +603,7 @@ void Arm64Jit::Comp_ReplacementFunc(MIPSOpcode op) FlushAll(); SaveStaticRegisters(); RestoreRoundingMode(); - gpr.SetRegImm(SCRATCH1, GetCompilerPC()); + MOVI2R(SCRATCH1, GetCompilerPC()); MovToPC(SCRATCH1); // Standard function call, nothing fancy. diff --git a/Core/MIPS/ARM64/Arm64RegCache.cpp b/Core/MIPS/ARM64/Arm64RegCache.cpp index 0dc7f8c999..8f1a13ca3a 100644 --- a/Core/MIPS/ARM64/Arm64RegCache.cpp +++ b/Core/MIPS/ARM64/Arm64RegCache.cpp @@ -163,10 +163,11 @@ void Arm64RegCache::MarkDirty(ARM64Reg reg) { } void Arm64RegCache::SetRegImm(ARM64Reg reg, u64 imm) { - if (reg == INVALID_REG) { + if (reg == INVALID_REG || reg == W0 || reg == X0) { ERROR_LOG(Log::JIT, "SetRegImm to invalid register: at %08x", js_->compilerPC); return; } + _dbg_assert_(!ar[reg].tempLocked); // On ARM64, at least Cortex A57, good old MOVT/MOVW (MOVK in 64-bit) is really fast. emit_->MOVI2R(reg, imm); // ar[reg].pointerified = false; @@ -204,7 +205,7 @@ void Arm64RegCache::MapRegTo(ARM64Reg reg, MIPSGPReg mipsReg, int mapFlags) { break; } case ML_IMM: - SetRegImm(reg, mr[mipsReg].imm); + emit_->MOVI2R(reg, mr[mipsReg].imm); ar[reg].isDirty = true; // IMM is always dirty. // If we are mapping dirty, it means we're gonna overwrite. @@ -637,13 +638,13 @@ void Arm64RegCache::FlushR(MIPSGPReg r) { case ML_IMM: // IMM is always "dirty". if (r == MIPS_REG_LO) { - SetRegImm(SCRATCH1_64, mr[r].imm); + emit_->MOVI2R(SCRATCH1_64, mr[r].imm); emit_->STR(INDEX_UNSIGNED, SCRATCH1_64, CTXREG, GetMipsRegOffset(r)); } else if (r != MIPS_REG_ZERO) { // Try to optimize using a different reg. ARM64Reg storeReg = ARM64RegForFlush(r); if (storeReg == INVALID_REG) { - SetRegImm(SCRATCH1, mr[r].imm); + emit_->MOVI2R(SCRATCH1, mr[r].imm); storeReg = SCRATCH1; } emit_->STR(INDEX_UNSIGNED, storeReg, CTXREG, GetMipsRegOffset(r)); @@ -747,7 +748,7 @@ void Arm64RegCache::FlushAll() { // Cannot leave any IMMs in registers, not even ML_ARMREG_IMM, can confuse the regalloc later if this flush is mid-block // due to an interpreter fallback that changes the register. if (mr[i].loc == ML_IMM) { - SetRegImm(mr[i].reg, mr[i].imm); + emit_->MOVI2R(mr[i].reg, mr[i].imm); mr[i].loc = ML_ARMREG; ar[armReg].pointerified = false; } else if (mr[i].loc == ML_ARMREG_IMM) { diff --git a/Core/MIPS/ARM64/Arm64RegCache.h b/Core/MIPS/ARM64/Arm64RegCache.h index 5528120098..9eb4d15356 100644 --- a/Core/MIPS/ARM64/Arm64RegCache.h +++ b/Core/MIPS/ARM64/Arm64RegCache.h @@ -101,7 +101,6 @@ public: bool IsImm(MIPSGPReg reg) const; bool IsPureImm(MIPSGPReg reg) const; u64 GetImm(MIPSGPReg reg) const; - // Optimally set a register to an imm value (possibly using another register.) void SetRegImm(Arm64Gen::ARM64Reg reg, u64 imm); // May fail and return INVALID_REG if it needs flushing. diff --git a/Core/MIPS/JitCommon/JitState.cpp b/Core/MIPS/JitCommon/JitState.cpp index 801359c2e5..a36321b328 100644 --- a/Core/MIPS/JitCommon/JitState.cpp +++ b/Core/MIPS/JitCommon/JitState.cpp @@ -23,7 +23,7 @@ namespace MIPSComp { JitOptions::JitOptions() { - disableFlags = g_Config.uJitDisableFlags; + disableFlags = (JitDisable)g_Config.uJitDisableFlags; // x86 enableVFPUSIMD = !Disabled(JitDisable::SIMD); @@ -65,6 +65,6 @@ namespace MIPSComp { } bool JitOptions::Disabled(JitDisable bit) { - return (disableFlags & (uint32_t)bit) != 0; + return (disableFlags & bit) != 0; } } diff --git a/Core/MIPS/JitCommon/JitState.h b/Core/MIPS/JitCommon/JitState.h index 4dd2e226c1..50ac0cf6a9 100644 --- a/Core/MIPS/JitCommon/JitState.h +++ b/Core/MIPS/JitCommon/JitState.h @@ -18,6 +18,7 @@ #pragma once +#include "Common/Common.h" #include "Common/CommonTypes.h" #include "Common/Log.h" #include "Core/MIPS/MIPS.h" @@ -179,7 +180,9 @@ namespace MIPSComp { } }; - enum class JitDisable { + enum class JitDisable : u32 { + DEFAULT = 0, + ALU = 0x0001, ALU_IMM = 0x0002, ALU_BIT = 0x0004, @@ -212,13 +215,14 @@ namespace MIPSComp { ALL_FLAGS = 0x3FFFFFFF, }; + ENUM_CLASS_BITOPS(JitDisable); struct JitOptions { JitOptions(); bool Disabled(JitDisable bit); - uint32_t disableFlags; + JitDisable disableFlags; // x86 bool enableVFPUSIMD;