diff --git a/Core/MIPS/IR/IRInst.h b/Core/MIPS/IR/IRInst.h index e727697d3f7d..cec31c7ee305 100644 --- a/Core/MIPS/IR/IRInst.h +++ b/Core/MIPS/IR/IRInst.h @@ -18,8 +18,6 @@ // MIPS->target JITs. enum class IROp : uint8_t { - Nop, - SetConst, SetConstF, @@ -230,6 +228,8 @@ enum class IROp : uint8_t { ValidateAddress16, ValidateAddress32, ValidateAddress128, + + Nop, }; enum IRComparison { @@ -358,7 +358,7 @@ struct IRInst { }; // Returns the new PC. -u32 IRInterpret(MIPSState *ms, const IRInst *inst, int count); +u32 IRInterpret(MIPSState *ms, const IRInst *inst); // Each IR block gets a constant pool. class IRWriter { diff --git a/Core/MIPS/IR/IRInterpreter.cpp b/Core/MIPS/IR/IRInterpreter.cpp index c8d98ad6fdbf..bf00db5c78b5 100644 --- a/Core/MIPS/IR/IRInterpreter.cpp +++ b/Core/MIPS/IR/IRInterpreter.cpp @@ -108,13 +108,9 @@ u32 RunValidateAddress(u32 pc, u32 addr, u32 isWrite) { } // We cannot use NEON on ARM32 here until we make it a hard dependency. We can, however, on ARM64. -u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { - const IRInst *end = inst + count; - while (inst != end) { +u32 IRInterpret(MIPSState *mips, const IRInst *inst) { + while (true) { switch (inst->op) { - case IROp::Nop: - _assert_(false); - break; case IROp::SetConst: mips->r[inst->dest] = inst->constant; break; @@ -1121,19 +1117,21 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count) { case IROp::UpdateRoundingMode: // TODO: Implement break; - + case IROp::Nop: + _assert_(false); + break; default: // Unimplemented IR op. Bad. Crash(); } - inst++; - } #ifdef _DEBUG - if (mips->r[0] != 0) - Crash(); + if (mips->r[0] != 0) + Crash(); #endif + inst++; + } - // We hit count. If this is a full block, it was badly constructed. + // We should not reach here anymore. return 0; } diff --git a/Core/MIPS/IR/IRInterpreter.h b/Core/MIPS/IR/IRInterpreter.h index 21e7f15dc73a..d381183586ef 100644 --- a/Core/MIPS/IR/IRInterpreter.h +++ b/Core/MIPS/IR/IRInterpreter.h @@ -23,4 +23,4 @@ inline static u32 ReverseBits32(u32 v) { u32 IRRunBreakpoint(u32 pc); u32 IRRunMemCheck(u32 pc, u32 addr); -u32 IRInterpret(MIPSState *ms, const IRInst *inst, int count); +u32 IRInterpret(MIPSState *ms, const IRInst *inst); diff --git a/Core/MIPS/IR/IRJit.cpp b/Core/MIPS/IR/IRJit.cpp index 3d9f9e5eaf78..c89c5fa41f85 100644 --- a/Core/MIPS/IR/IRJit.cpp +++ b/Core/MIPS/IR/IRJit.cpp @@ -246,21 +246,23 @@ void IRJit::RunLoopUntil(u64 globalticks) { if (coreState != 0) { break; } - while (mips_->downcount >= 0) { - u32 inst = Memory::ReadUnchecked_U32(mips_->pc); + + MIPSState *mips = mips_; + + while (mips->downcount >= 0) { + u32 inst = Memory::ReadUnchecked_U32(mips->pc); u32 opcode = inst & 0xFF000000; if (opcode == MIPS_EMUHACK_OPCODE) { IRBlock *block = blocks_.GetBlockUnchecked(inst & 0xFFFFFF); - u32 startPC = mips_->pc; - mips_->pc = IRInterpret(mips_, block->GetInstructions(), block->GetNumInstructions()); + mips->pc = IRInterpret(mips, block->GetInstructions()); // Note: this will "jump to zero" on a badly constructed block missing exits. - if (!Memory::IsValidAddress(mips_->pc) || (mips_->pc & 3) != 0) { - Core_ExecException(mips_->pc, startPC, ExecExceptionType::JUMP); + if (!Memory::IsValid4AlignedAddress(mips->pc)) { + Core_ExecException(mips->pc, block->GetOriginalStart(), ExecExceptionType::JUMP); break; } } else { // RestoreRoundingMode(true); - Compile(mips_->pc); + Compile(mips->pc); // ApplyRoundingMode(true); } } diff --git a/Core/MIPS/IR/IRNativeCommon.cpp b/Core/MIPS/IR/IRNativeCommon.cpp index bb1589303bec..abd76511ec4a 100644 --- a/Core/MIPS/IR/IRNativeCommon.cpp +++ b/Core/MIPS/IR/IRNativeCommon.cpp @@ -153,13 +153,14 @@ void IRNativeBackend::DoMIPSInst(uint32_t value) { } uint32_t IRNativeBackend::DoIRInst(uint64_t value) { - IRInst inst; + IRInst inst[2]; memcpy(&inst, &value, sizeof(inst)); if constexpr (enableDebugStats) - debugSeenNotCompiledIR[(uint8_t)inst.op]++; + debugSeenNotCompiledIR[(uint8_t)inst[0].op]++; - return IRInterpret(currentMIPS, &inst, 1); + inst[1].op = IROp::ExitToPC; + return IRInterpret(currentMIPS, &inst[0]); } int IRNativeBackend::ReportBadAddress(uint32_t addr, uint32_t alignment, uint32_t isWrite) { diff --git a/Core/MemMap.h b/Core/MemMap.h index e447620b7831..8c2d6f2dda8d 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -296,6 +296,21 @@ inline bool IsValidAddress(const u32 address) { } } +inline bool IsValid4AlignedAddress(const u32 address) { + if ((address & 0x3E000003) == 0x08000000) { + return true; + } else if ((address & 0x3F800003) == 0x04000000) { + return true; + } else if ((address & 0xBFFFC003) == 0x00010000) { + return true; + } else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) { + return (address & 3) == 0; + } else { + return false; + } +} + + inline u32 MaxSizeAtAddress(const u32 address){ if ((address & 0x3E000000) == 0x08000000) { return 0x08000000 + g_MemorySize - (address & 0x3FFFFFFF);