Plumb an explicit MIPSState *mips through the interpreter's Int_* handlers

All ~82 MIPSInt::Int_* functions (Interpreter.cpp/.h,
InterpreterVFPU.cpp/.h) now take an explicit MIPSState *mips instead
of reaching for the global currentMIPS internally, along with their
file-local helpers (DelayBranchTo, SkipLikely, ApplySwizzleS/T,
ApplyPrefixD/ST, RetainInvalidSwizzleST, EatPrefixes). MIPSInterpretFunc,
Interpret(), ExecInstruction()/InterpreterDispatch.cpp (regenerated),
and RunUntilFast() all thread mips through accordingly.

Deliberately left on currentMIPS for now: MIPSVFPUUtils.cpp's
ReadVector/WriteVector/ReadMatrix/WriteMatrix/VFPURewritePrefix -
these are shared with every JIT backend's compile-time VFPU code, so
parameterizing them would balloon this into a JIT-wide refactor. This
is a partial refactor; that's the next boundary to push on.

Several JIT backends (x86 Jit.cpp, ARM/ArmJit.cpp, ARM64/Arm64Jit.cpp,
x86/X64IRJit.cpp, RiscV/RiscVJit.cpp, LoongArch64/LoongArch64Jit.cpp,
ARM64/Arm64IRJit.cpp) bake the raw interpreter function pointer
directly into JIT-generated machine code as their "fall back to the
interpreter for this one op" mechanism, with only a single argument
register set up for the call. Rather than hand-editing register
allocation across four architectures that can't be build-tested here,
added MIPSInterpretTrampoline(MIPSOpcode op) - a 1-arg wrapper around
MIPSInterpret(currentMIPS, op) - and pointed all 7 such call sites at
it instead, leaving that codegen untouched. Two other call sites
(JitLogMiss, JitBranchLog) were plain C++ calls and just got the
extra argument directly.

Verified (Windows x64): PPSSPPWindows/PPSSPPHeadless/UnitTest all
build clean, 49/49 unit tests pass. `test.py -g --graphics=software`:
interpreter 312/314 (cpu/fpu/fpu is the pre-existing, unrelated
interpreter-vs-JIT denormal difference; gpu/rendertarget/copy passes
standalone, so was cross-test state bleed in the batch run, not a
regression), default JIT 314/314, jit-ir 313/314 (gpu/vertices/morph
is an expected difference from the vertex decoder taking a different
mode with this core change, not a bug).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_019SKhm9wKEQzRUsx9mTrrtQ
This commit is contained in:
Henrik RydgårdandClaude Sonnet 5 committed 2026-08-12 14:02:19 +02:00
1 parent ba4c3d93f3
commit ffad0acea1
17 files changed
+620 -608

No files matched your search

+1 -1
View File
@@ -569,7 +569,7 @@ void ArmJit::Comp_Generic(MIPSOpcode op)
gpr.SetRegImm(SCRATCHREG1, GetCompilerPC());
MovToPC(SCRATCHREG1);
gpr.SetRegImm(R0, op.encoding);
QuickCallFunction(R1, (void *)func);
QuickCallFunction(R1, (void *)&MIPSInterpretTrampoline);
ApplyRoundingMode();
RestoreDowncount();
}
+1 -1
View File
@@ -276,7 +276,7 @@ void Arm64JitBackend::CompIR_Interpret(IRInst inst) {
QuickCallFunction(SCRATCH2_64, &NotifyMIPSInterpret);
}
MOVI2R(X0, inst.constant);
QuickCallFunction(SCRATCH2_64, MIPSGetInterpretFunc(op));
QuickCallFunction(SCRATCH2_64, &MIPSInterpretTrampoline);
WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT);
LoadStaticRegisters();
}
+1 -1
View File
@@ -581,7 +581,7 @@ void Arm64Jit::Comp_Generic(MIPSOpcode op) {
MOVI2R(SCRATCH1, GetCompilerPC());
MovToPC(SCRATCH1);
MOVI2R(W0, op.encoding);
QuickCallFunction(SCRATCH2_64, (void *)func);
QuickCallFunction(SCRATCH2_64, (void *)&MIPSInterpretTrampoline);
ApplyRoundingMode();
LoadStaticRegisters();
}
+94 -94
View File
@@ -35,11 +35,11 @@
#include "Core/HLE/HLETables.h"
#include "Core/HLE/ReplaceTables.h"
#define R(i) (currentMIPS->r[i])
#define F(i) (currentMIPS->f[i])
#define FI(i) (currentMIPS->fi[i])
#define FsI(i) (currentMIPS->fs[i])
#define PC (currentMIPS->pc)
#define R(i) (mips->r[i])
#define F(i) (mips->f[i])
#define FI(i) (mips->fi[i])
#define FsI(i) (mips->fs[i])
#define PC (mips->pc)
#define _SIMM16_SHL2 ((u32)(s32)(s16)(op & 0xFFFF) << 2)
#define _RS ((op>>21) & 0x1F)
@@ -51,27 +51,27 @@
#define _POS ((op>>6 ) & 0x1F)
#define _SIZE ((op>>11) & 0x1F)
#define HI currentMIPS->hi
#define LO currentMIPS->lo
#define HI mips->hi
#define LO mips->lo
static inline void DelayBranchTo(u32 where)
static inline void DelayBranchTo(MIPSState *mips, u32 where)
{
if (!Memory::IsValidAddress(where) || (where & 3) != 0) {
Core_ExecException(where, PC, ExecExceptionType::JUMP);
}
PC += 4;
mipsr4k.nextPC = where;
mipsr4k.inDelaySlot = true;
mips->nextPC = where;
mips->inDelaySlot = true;
}
static inline void SkipLikely() {
static inline void SkipLikely(MIPSState *mips) {
MIPSInfo delaySlot = MIPSGetInfo(Memory::Read_Instruction(PC + 4, true));
// Don't actually skip if it is a jump (seen in Brooktown High.)
if (delaySlot & IS_JUMP) {
PC += 4;
} else {
PC += 8;
--mipsr4k.downcount;
--mips->downcount;
}
}
@@ -95,7 +95,7 @@ int MIPS_SingleStep(MIPSState *mips) {
namespace MIPSInt
{
void Int_Cache(MIPSOpcode op)
void Int_Cache(MIPSState *mips, MIPSOpcode op)
{
int imm = SignExtend16ToS32(op);
int rs = _RS;
@@ -154,37 +154,37 @@ namespace MIPSInt
PC += 4;
}
void Int_Syscall(MIPSOpcode op)
void Int_Syscall(MIPSState *mips, MIPSOpcode op)
{
// Need to pre-move PC, as CallSyscall may result in a rescheduling!
// To do this neater, we'll need a little generated kernel loop that syscall can jump to and then RFI from
// but I don't see a need to bother.
if (mipsr4k.inDelaySlot)
if (mips->inDelaySlot)
{
mipsr4k.pc = mipsr4k.nextPC;
mips->pc = mips->nextPC;
}
else
{
mipsr4k.pc += 4;
mips->pc += 4;
}
mipsr4k.inDelaySlot = false;
mips->inDelaySlot = false;
CallSyscall(op);
}
void Int_Sync(MIPSOpcode op)
void Int_Sync(MIPSState *mips, MIPSOpcode op)
{
//DEBUG_LOG(Log::CPU, "sync");
PC += 4;
}
void Int_Break(MIPSOpcode op)
void Int_Break(MIPSState *mips, MIPSOpcode op)
{
Reporting::ReportMessage("BREAK instruction hit");
Core_BreakException(PC);
PC += 4;
}
void Int_RelBranch(MIPSOpcode op)
void Int_RelBranch(MIPSState *mips, MIPSOpcode op)
{
int imm = _SIMM16_SHL2;
int rs = _RS;
@@ -193,15 +193,15 @@ namespace MIPSInt
switch (op >> 26)
{
case 4: if (R(rt) == R(rs)) DelayBranchTo(addr); else PC += 4; break; //beq
case 5: if (R(rt) != R(rs)) DelayBranchTo(addr); else PC += 4; break; //bne
case 6: if ((s32)R(rs) <= 0) DelayBranchTo(addr); else PC += 4; break; //blez
case 7: if ((s32)R(rs) > 0) DelayBranchTo(addr); else PC += 4; break; //bgtz
case 4: if (R(rt) == R(rs)) DelayBranchTo(mips, addr); else PC += 4; break; //beq
case 5: if (R(rt) != R(rs)) DelayBranchTo(mips, addr); else PC += 4; break; //bne
case 6: if ((s32)R(rs) <= 0) DelayBranchTo(mips, addr); else PC += 4; break; //blez
case 7: if ((s32)R(rs) > 0) DelayBranchTo(mips, addr); else PC += 4; break; //bgtz
case 20: if (R(rt) == R(rs)) DelayBranchTo(addr); else SkipLikely(); break; //beql
case 21: if (R(rt) != R(rs)) DelayBranchTo(addr); else SkipLikely(); break; //bnel
case 22: if ((s32)R(rs) <= 0) DelayBranchTo(addr); else SkipLikely(); break; //blezl
case 23: if ((s32)R(rs) > 0) DelayBranchTo(addr); else SkipLikely(); break; //bgtzl
case 20: if (R(rt) == R(rs)) DelayBranchTo(mips, addr); else SkipLikely(mips); break; //beql
case 21: if (R(rt) != R(rs)) DelayBranchTo(mips, addr); else SkipLikely(mips); break; //bnel
case 22: if ((s32)R(rs) <= 0) DelayBranchTo(mips, addr); else SkipLikely(mips); break; //blezl
case 23: if ((s32)R(rs) > 0) DelayBranchTo(mips, addr); else SkipLikely(mips); break; //bgtzl
default:
_dbg_assert_msg_(false,"Trying to interpret instruction that can't be interpreted");
@@ -209,7 +209,7 @@ namespace MIPSInt
}
}
void Int_RelBranchRI(MIPSOpcode op)
void Int_RelBranchRI(MIPSState *mips, MIPSOpcode op)
{
int imm = _SIMM16_SHL2;
int rs = _RS;
@@ -217,14 +217,14 @@ namespace MIPSInt
switch ((op>>16) & 0x1F)
{
case 0: if ((s32)R(rs) < 0) DelayBranchTo(addr); else PC += 4; break;//bltz
case 1: if ((s32)R(rs) >= 0) DelayBranchTo(addr); else PC += 4; break;//bgez
case 2: if ((s32)R(rs) < 0) DelayBranchTo(addr); else SkipLikely(); break;//bltzl
case 3: if ((s32)R(rs) >= 0) DelayBranchTo(addr); else SkipLikely(); break;//bgezl
case 16: R(MIPS_REG_RA) = PC + 8; if ((s32)R(rs) < 0) DelayBranchTo(addr); else PC += 4; break;//bltzal
case 17: R(MIPS_REG_RA) = PC + 8; if ((s32)R(rs) >= 0) DelayBranchTo(addr); else PC += 4; break;//bgezal
case 18: R(MIPS_REG_RA) = PC + 8; if ((s32)R(rs) < 0) DelayBranchTo(addr); else SkipLikely(); break;//bltzall
case 19: R(MIPS_REG_RA) = PC + 8; if ((s32)R(rs) >= 0) DelayBranchTo(addr); else SkipLikely(); break;//bgezall
case 0: if ((s32)R(rs) < 0) DelayBranchTo(mips, addr); else PC += 4; break;//bltz
case 1: if ((s32)R(rs) >= 0) DelayBranchTo(mips, addr); else PC += 4; break;//bgez
case 2: if ((s32)R(rs) < 0) DelayBranchTo(mips, addr); else SkipLikely(mips); break;//bltzl
case 3: if ((s32)R(rs) >= 0) DelayBranchTo(mips, addr); else SkipLikely(mips); break;//bgezl
case 16: R(MIPS_REG_RA) = PC + 8; if ((s32)R(rs) < 0) DelayBranchTo(mips, addr); else PC += 4; break;//bltzal
case 17: R(MIPS_REG_RA) = PC + 8; if ((s32)R(rs) >= 0) DelayBranchTo(mips, addr); else PC += 4; break;//bgezal
case 18: R(MIPS_REG_RA) = PC + 8; if ((s32)R(rs) < 0) DelayBranchTo(mips, addr); else SkipLikely(mips); break;//bltzall
case 19: R(MIPS_REG_RA) = PC + 8; if ((s32)R(rs) >= 0) DelayBranchTo(mips, addr); else SkipLikely(mips); break;//bgezall
default:
_dbg_assert_msg_(false,"Trying to interpret instruction that can't be interpreted");
break;
@@ -232,58 +232,58 @@ namespace MIPSInt
}
void Int_VBranch(MIPSOpcode op)
void Int_VBranch(MIPSState *mips, MIPSOpcode op)
{
int imm = _SIMM16_SHL2;
u32 addr = PC + imm + 4;
// x, y, z, w, any, all, (invalid), (invalid)
int imm3 = (op>>18)&7;
int val = (currentMIPS->vfpuCtrl[VFPU_CTRL_CC] >> imm3) & 1;
int val = (mips->vfpuCtrl[VFPU_CTRL_CC] >> imm3) & 1;
switch ((op >> 16) & 3)
{
case 0: if (!val) DelayBranchTo(addr); else PC += 4; break; //bvf
case 1: if ( val) DelayBranchTo(addr); else PC += 4; break; //bvt
case 2: if (!val) DelayBranchTo(addr); else SkipLikely(); break; //bvfl
case 3: if ( val) DelayBranchTo(addr); else SkipLikely(); break; //bvtl
case 0: if (!val) DelayBranchTo(mips, addr); else PC += 4; break; //bvf
case 1: if ( val) DelayBranchTo(mips, addr); else PC += 4; break; //bvt
case 2: if (!val) DelayBranchTo(mips, addr); else SkipLikely(mips); break; //bvfl
case 3: if ( val) DelayBranchTo(mips, addr); else SkipLikely(mips); break; //bvtl
}
}
void Int_FPUBranch(MIPSOpcode op)
void Int_FPUBranch(MIPSState *mips, MIPSOpcode op)
{
int imm = _SIMM16_SHL2;
u32 addr = PC + imm + 4;
switch((op>>16)&0x1f)
{
case 0: if (!currentMIPS->fpcond) DelayBranchTo(addr); else PC += 4; break;//bc1f
case 1: if ( currentMIPS->fpcond) DelayBranchTo(addr); else PC += 4; break;//bc1t
case 2: if (!currentMIPS->fpcond) DelayBranchTo(addr); else SkipLikely(); break;//bc1fl
case 3: if ( currentMIPS->fpcond) DelayBranchTo(addr); else SkipLikely(); break;//bc1tl
case 0: if (!mips->fpcond) DelayBranchTo(mips, addr); else PC += 4; break;//bc1f
case 1: if ( mips->fpcond) DelayBranchTo(mips, addr); else PC += 4; break;//bc1t
case 2: if (!mips->fpcond) DelayBranchTo(mips, addr); else SkipLikely(mips); break;//bc1fl
case 3: if ( mips->fpcond) DelayBranchTo(mips, addr); else SkipLikely(mips); break;//bc1tl
default:
_dbg_assert_msg_(false,"Trying to interpret instruction that can't be interpreted");
break;
}
}
void Int_JumpType(MIPSOpcode op)
void Int_JumpType(MIPSState *mips, MIPSOpcode op)
{
if (mipsr4k.inDelaySlot)
if (mips->inDelaySlot)
ERROR_LOG(Log::CPU, "Jump in delay slot :(");
u32 off = ((op & 0x03FFFFFF) << 2);
u32 addr = (currentMIPS->pc & 0xF0000000) | off;
u32 addr = (mips->pc & 0xF0000000) | off;
switch (op>>26)
{
case 2: //j
if (!mipsr4k.inDelaySlot)
DelayBranchTo(addr);
if (!mips->inDelaySlot)
DelayBranchTo(mips, addr);
break;
case 3: //jal
R(MIPS_REG_RA) = PC + 8;
if (!mipsr4k.inDelaySlot)
DelayBranchTo(addr);
if (!mips->inDelaySlot)
DelayBranchTo(mips, addr);
break;
default:
_dbg_assert_msg_(false,"Trying to interpret instruction that can't be interpreted");
@@ -291,9 +291,9 @@ namespace MIPSInt
}
}
void Int_JumpRegType(MIPSOpcode op)
void Int_JumpRegType(MIPSState *mips, MIPSOpcode op)
{
if (mipsr4k.inDelaySlot) {
if (mips->inDelaySlot) {
// There's one of these in Star Soldier at 0881808c, which seems benign.
ERROR_LOG(Log::CPU, "Jump in delay slot :(");
}
@@ -304,20 +304,20 @@ namespace MIPSInt
switch (op & 0x3f)
{
case 8: //jr
if (!mipsr4k.inDelaySlot)
DelayBranchTo(addr);
if (!mips->inDelaySlot)
DelayBranchTo(mips, addr);
break;
case 9: //jalr
if (rd != 0)
R(rd) = PC + 8;
// Update rd, but otherwise do not take the branch if we're branching.
if (!mipsr4k.inDelaySlot)
DelayBranchTo(addr);
if (!mips->inDelaySlot)
DelayBranchTo(mips, addr);
break;
}
}
void Int_IType(MIPSOpcode op) {
void Int_IType(MIPSState *mips, MIPSOpcode op) {
u32 uimm = op & 0xFFFF;
u32 suimm = SignExtend16ToU32(op);
s32 simm = SignExtend16ToS32(op);
@@ -347,7 +347,7 @@ namespace MIPSInt
PC += 4;
}
void Int_StoreSync(MIPSOpcode op) {
void Int_StoreSync(MIPSState *mips, MIPSOpcode op) {
int imm = (signed short)(op & 0xFFFF);
int rt = _RT;
int rs = _RS;
@@ -363,10 +363,10 @@ namespace MIPSInt
}
R(rt) = Memory::ReadUnchecked_U32(addr);
}
currentMIPS->llBit = 1;
mips->llBit = 1;
break;
case 56: // sc
if (currentMIPS->llBit) {
if (mips->llBit) {
if (!Memory::IsValid4AlignedAddress(addr)) {
Core_MemoryException(addr, 4, PC, MemoryExceptionType::WRITE_WORD, "sc");
return;
@@ -387,7 +387,7 @@ namespace MIPSInt
}
void Int_RType3(MIPSOpcode op) {
void Int_RType3(MIPSState *mips, MIPSOpcode op) {
int rt = _RT;
int rs = _RS;
int rd = _RD;
@@ -421,7 +421,7 @@ namespace MIPSInt
}
void Int_ITypeMem(MIPSOpcode op) {
void Int_ITypeMem(MIPSState *mips, MIPSOpcode op) {
int imm = (signed short)(op&0xFFFF);
int rt = _RT;
int rs = _RS;
@@ -557,7 +557,7 @@ namespace MIPSInt
PC += 4;
}
void Int_FPULS(MIPSOpcode op) {
void Int_FPULS(MIPSState *mips, MIPSOpcode op) {
s32 offset = (s16)(op & 0xFFFF);
int ft = _FT;
int rs = _RS;
@@ -585,7 +585,7 @@ namespace MIPSInt
PC += 4;
}
void Int_mxc1(MIPSOpcode op)
void Int_mxc1(MIPSState *mips, MIPSOpcode op)
{
int fs = _FS;
int rt = _RT;
@@ -599,8 +599,8 @@ namespace MIPSInt
case 2: //cfc1
if (rt != 0) {
if (fs == 31) {
currentMIPS->fcr31 = (currentMIPS->fcr31 & ~(1<<23)) | ((currentMIPS->fpcond & 1)<<23);
R(rt) = currentMIPS->fcr31;
mips->fcr31 = (mips->fcr31 & ~(1<<23)) | ((mips->fpcond & 1)<<23);
R(rt) = mips->fcr31;
} else if (fs == 0) {
R(rt) = MIPSState::FCR0_VALUE;
} else {
@@ -619,8 +619,8 @@ namespace MIPSInt
{
u32 value = R(rt);
if (fs == 31) {
currentMIPS->fcr31 = value & 0x0181FFFF;
currentMIPS->fpcond = (value >> 23) & 1;
mips->fcr31 = value & 0x0181FFFF;
mips->fpcond = (value >> 23) & 1;
// Don't bother locking, assuming the CPU can't be reset now anyway.
if (MIPSComp::jit) {
// In case of DISABLE, we need to tell jit we updated FCR31.
@@ -640,7 +640,7 @@ namespace MIPSInt
PC += 4;
}
void Int_RType2(MIPSOpcode op)
void Int_RType2(MIPSState *mips, MIPSOpcode op)
{
int rs = _RS;
int rd = _RD;
@@ -667,7 +667,7 @@ namespace MIPSInt
PC += 4;
}
void Int_MulDivType(MIPSOpcode op)
void Int_MulDivType(MIPSState *mips, MIPSOpcode op)
{
int rt = _RT;
int rs = _RS;
@@ -772,7 +772,7 @@ namespace MIPSInt
}
void Int_ShiftType(MIPSOpcode op)
void Int_ShiftType(MIPSState *mips, MIPSOpcode op)
{
int rt = _RT;
int rs = _RS;
@@ -826,7 +826,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Allegrex(MIPSOpcode op)
void Int_Allegrex(MIPSState *mips, MIPSOpcode op)
{
int rt = _RT;
int rd = _RD;
@@ -859,7 +859,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Allegrex2(MIPSOpcode op)
void Int_Allegrex2(MIPSState *mips, MIPSOpcode op)
{
int rt = _RT;
int rd = _RD;
@@ -886,7 +886,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Special2(MIPSOpcode op)
void Int_Special2(MIPSState *mips, MIPSOpcode op)
{
static int reported = 0;
switch (op & 0x3F)
@@ -912,7 +912,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Special3(MIPSOpcode op)
void Int_Special3(MIPSState *mips, MIPSOpcode op)
{
int rs = _RS;
int rt = _RT;
@@ -945,7 +945,7 @@ namespace MIPSInt
PC += 4;
}
void Int_FPU2op(MIPSOpcode op)
void Int_FPU2op(MIPSState *mips, MIPSOpcode op)
{
int fs = _FS;
int fd = _FD;
@@ -992,7 +992,7 @@ namespace MIPSInt
FsI(fd) = my_isinf(F(fs)) && F(fs) < 0.0f ? -2147483648LL : 2147483647LL;
break;
}
switch (currentMIPS->fcr31 & 3)
switch (mips->fcr31 & 3)
{
case 0: FsI(fd) = (int)round_ieee_754(F(fs)); break; // RINT_0
case 1: FsI(fd) = (int)F(fs); break; // CAST_1
@@ -1007,7 +1007,7 @@ namespace MIPSInt
PC += 4;
}
void Int_FPUComp(MIPSOpcode op)
void Int_FPUComp(MIPSState *mips, MIPSOpcode op)
{
int fs = _FS;
int ft = _FT;
@@ -1059,11 +1059,11 @@ namespace MIPSInt
cond = false;
break;
}
currentMIPS->fpcond = cond;
mips->fpcond = cond;
PC += 4;
}
void Int_FPU3op(MIPSOpcode op)
void Int_FPU3op(MIPSState *mips, MIPSOpcode op)
{
int ft = _FT;
int fs = _FS;
@@ -1089,7 +1089,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Interrupt(MIPSOpcode op)
void Int_Interrupt(MIPSState *mips, MIPSOpcode op)
{
static int reported = 0;
switch (op & 1)
@@ -1097,7 +1097,7 @@ namespace MIPSInt
case 0:
// unlikely to be legitimately used
if (!reported) {
Reporting::ReportMessage("INTERRUPT instruction hit (%08x) at %08x", op.encoding, currentMIPS->pc);
Reporting::ReportMessage("INTERRUPT instruction hit (%08x) at %08x", op.encoding, mips->pc);
WARN_LOG(Log::CPU, "Disable/Enable Interrupt CPU instruction");
reported = 1;
}
@@ -1106,7 +1106,7 @@ namespace MIPSInt
PC += 4;
}
void Int_Emuhack(MIPSOpcode op)
void Int_Emuhack(MIPSState *mips, MIPSOpcode op)
{
if (((op >> 24) & 3) != EMUOP_CALL_REPLACEMENT) {
_dbg_assert_msg_(false, "Trying to interpret emuhack instruction that can't be interpreted");
@@ -1122,20 +1122,20 @@ namespace MIPSInt
if (entry->flags & (REPFLAG_HOOKENTER | REPFLAG_HOOKEXIT)) {
// Interpret the original instruction under the hook.
MIPSInterpret(currentMIPS, Memory::Read_Instruction(PC, true));
MIPSInterpret(mips, Memory::Read_Instruction(PC, true));
} else if (cycles < 0) {
// Leave PC unchanged, call the replacement again (assumes args are modified.)
currentMIPS->downcount += cycles;
mips->downcount += cycles;
} else {
PC = currentMIPS->r[MIPS_REG_RA];
currentMIPS->downcount -= cycles;
PC = mips->r[MIPS_REG_RA];
mips->downcount -= cycles;
}
} else {
if (!entry || !entry->replaceFunc) {
ERROR_LOG(Log::CPU, "Bad replacement function index %i", index);
}
// Interpret the original instruction under it.
MIPSInterpret(currentMIPS, Memory::Read_Instruction(PC, true));
MIPSInterpret(mips, Memory::Read_Instruction(PC, true));
}
}
}
+27 -27
View File
@@ -24,32 +24,32 @@ int MIPS_SingleStep(MIPSState *mips);
namespace MIPSInt
{
void Int_Syscall(MIPSOpcode op);
void Int_Syscall(MIPSState *mips, MIPSOpcode op);
void Int_mxc1(MIPSOpcode op);
void Int_RelBranch(MIPSOpcode op);
void Int_RelBranchRI(MIPSOpcode op);
void Int_IType(MIPSOpcode op);
void Int_ITypeMem(MIPSOpcode op);
void Int_RType2(MIPSOpcode op);
void Int_RType3(MIPSOpcode op);
void Int_ShiftType(MIPSOpcode op);
void Int_MulDivType(MIPSOpcode op);
void Int_JumpType(MIPSOpcode op);
void Int_JumpRegType(MIPSOpcode op);
void Int_Allegrex2(MIPSOpcode op);
void Int_FPULS(MIPSOpcode op);
void Int_FPU3op(MIPSOpcode op);
void Int_FPU2op(MIPSOpcode op);
void Int_Allegrex(MIPSOpcode op);
void Int_FPUComp(MIPSOpcode op);
void Int_FPUBranch(MIPSOpcode op);
void Int_Emuhack(MIPSOpcode op);
void Int_Special2(MIPSOpcode op);
void Int_Special3(MIPSOpcode op);
void Int_Interrupt(MIPSOpcode op);
void Int_Cache(MIPSOpcode op);
void Int_Sync(MIPSOpcode op);
void Int_Break(MIPSOpcode op);
void Int_StoreSync(MIPSOpcode op);
void Int_mxc1(MIPSState *mips, MIPSOpcode op);
void Int_RelBranch(MIPSState *mips, MIPSOpcode op);
void Int_RelBranchRI(MIPSState *mips, MIPSOpcode op);
void Int_IType(MIPSState *mips, MIPSOpcode op);
void Int_ITypeMem(MIPSState *mips, MIPSOpcode op);
void Int_RType2(MIPSState *mips, MIPSOpcode op);
void Int_RType3(MIPSState *mips, MIPSOpcode op);
void Int_ShiftType(MIPSState *mips, MIPSOpcode op);
void Int_MulDivType(MIPSState *mips, MIPSOpcode op);
void Int_JumpType(MIPSState *mips, MIPSOpcode op);
void Int_JumpRegType(MIPSState *mips, MIPSOpcode op);
void Int_Allegrex2(MIPSState *mips, MIPSOpcode op);
void Int_FPULS(MIPSState *mips, MIPSOpcode op);
void Int_FPU3op(MIPSState *mips, MIPSOpcode op);
void Int_FPU2op(MIPSState *mips, MIPSOpcode op);
void Int_Allegrex(MIPSState *mips, MIPSOpcode op);
void Int_FPUComp(MIPSState *mips, MIPSOpcode op);
void Int_FPUBranch(MIPSState *mips, MIPSOpcode op);
void Int_Emuhack(MIPSState *mips, MIPSOpcode op);
void Int_Special2(MIPSState *mips, MIPSOpcode op);
void Int_Special3(MIPSState *mips, MIPSOpcode op);
void Int_Interrupt(MIPSState *mips, MIPSOpcode op);
void Int_Cache(MIPSState *mips, MIPSOpcode op);
void Int_Sync(MIPSState *mips, MIPSOpcode op);
void Int_Break(MIPSState *mips, MIPSOpcode op);
void Int_StoreSync(MIPSState *mips, MIPSOpcode op);
}
+87 -87
View File
@@ -24,7 +24,7 @@
// Returns the cycle count consumed, or -1 if op isn't a recognized instruction -
// callers must fall back to MIPSInterpret() themselves in that case.
int ExecInstruction(MIPSOpcode op) {
int ExecInstruction(MIPSState *mips, MIPSOpcode op) {
switch ((op.encoding >> 26) & 0x3f) {
case 0:
{
@@ -36,12 +36,12 @@ int ExecInstruction(MIPSOpcode op) {
case 4:
case 6:
case 7:
MIPSInt::Int_ShiftType(op);
MIPSInt::Int_ShiftType(mips, op);
return 1;
// jr, jalr
case 8:
case 9:
MIPSInt::Int_JumpRegType(op);
MIPSInt::Int_JumpRegType(mips, op);
return 1;
// movz, movn, add, addu, sub, subu, and, or, xor, nor, slt, sltu, max, min
case 10:
@@ -58,19 +58,19 @@ int ExecInstruction(MIPSOpcode op) {
case 43:
case 44:
case 45:
MIPSInt::Int_RType3(op);
MIPSInt::Int_RType3(mips, op);
return 1;
// syscall
case 12:
MIPSInt::Int_Syscall(op);
MIPSInt::Int_Syscall(mips, op);
return 1;
// break
case 13:
MIPSInt::Int_Break(op);
MIPSInt::Int_Break(mips, op);
return 1;
// sync
case 15:
MIPSInt::Int_Sync(op);
MIPSInt::Int_Sync(mips, op);
return 1;
// mfhi, mthi, mflo, mtlo, mult, multu, div, divu, madd, maddu, msub, msubu
case 16:
@@ -85,12 +85,12 @@ int ExecInstruction(MIPSOpcode op) {
case 29:
case 46:
case 47:
MIPSInt::Int_MulDivType(op);
MIPSInt::Int_MulDivType(mips, op);
return 1;
// clz, clo
case 22:
case 23:
MIPSInt::Int_RType2(op);
MIPSInt::Int_RType2(mips, op);
return 1;
default:
return -1;
@@ -108,7 +108,7 @@ int ExecInstruction(MIPSOpcode op) {
case 17:
case 18:
case 19:
MIPSInt::Int_RelBranchRI(op);
MIPSInt::Int_RelBranchRI(mips, op);
return 1;
default:
return -1;
@@ -117,7 +117,7 @@ int ExecInstruction(MIPSOpcode op) {
// j, jal
case 2:
case 3:
MIPSInt::Int_JumpType(op);
MIPSInt::Int_JumpType(mips, op);
return 1;
// beq, bne, blez, bgtz, beql, bnel, blezl, bgtzl
case 4:
@@ -128,7 +128,7 @@ int ExecInstruction(MIPSOpcode op) {
case 21:
case 22:
case 23:
MIPSInt::Int_RelBranch(op);
MIPSInt::Int_RelBranch(mips, op);
return 1;
// addi, addiu, slti, sltiu, andi, ori, xori, lui
case 8:
@@ -139,7 +139,7 @@ int ExecInstruction(MIPSOpcode op) {
case 13:
case 14:
case 15:
MIPSInt::Int_IType(op);
MIPSInt::Int_IType(mips, op);
return 1;
case 16:
{
@@ -175,7 +175,7 @@ int ExecInstruction(MIPSOpcode op) {
case 2:
case 4:
case 6:
MIPSInt::Int_mxc1(op);
MIPSInt::Int_mxc1(mips, op);
return 1;
case 8:
{
@@ -185,7 +185,7 @@ int ExecInstruction(MIPSOpcode op) {
case 1:
case 2:
case 3:
MIPSInt::Int_FPUBranch(op);
MIPSInt::Int_FPUBranch(mips, op);
return 1;
default:
return -1;
@@ -198,11 +198,11 @@ int ExecInstruction(MIPSOpcode op) {
case 0:
case 1:
case 2:
MIPSInt::Int_FPU3op(op);
MIPSInt::Int_FPU3op(mips, op);
return 1;
// div.s
case 3:
MIPSInt::Int_FPU3op(op);
MIPSInt::Int_FPU3op(mips, op);
return 29;
// sqrt.s, abs.s, mov.s, neg.s, round.w.s, trunc.w.s, ceil.w.s, floor.w.s, cvt.w.s
case 4:
@@ -214,11 +214,11 @@ int ExecInstruction(MIPSOpcode op) {
case 14:
case 15:
case 36:
MIPSInt::Int_FPU2op(op);
MIPSInt::Int_FPU2op(mips, op);
return 1;
// dis.int
case 38:
MIPSInt::Int_Interrupt(op);
MIPSInt::Int_Interrupt(mips, op);
return 1;
// c.f.s, c.un.s, c.eq.s, c.ueq.s, c.olt.s, c.ult.s, c.ole.s, c.ule.s, c.sf.s, c.ngle.s, c.seq.s, c.ngl.s, c.lt.s, c.nge.s, c.le.s, c.ngt.s
case 48:
@@ -237,7 +237,7 @@ int ExecInstruction(MIPSOpcode op) {
case 61:
case 62:
case 63:
MIPSInt::Int_FPUComp(op);
MIPSInt::Int_FPUComp(mips, op);
return 1;
default:
return -1;
@@ -248,7 +248,7 @@ int ExecInstruction(MIPSOpcode op) {
switch ((op.encoding >> 0) & 0x3f) {
// cvt.s.w
case 32:
MIPSInt::Int_FPU2op(op);
MIPSInt::Int_FPU2op(mips, op);
return 1;
default:
return -1;
@@ -264,7 +264,7 @@ int ExecInstruction(MIPSOpcode op) {
// mfv, mtv
case 3:
case 7:
MIPSInt::Int_Mftv(op);
MIPSInt::Int_Mftv(mips, op);
return 2;
case 8:
{
@@ -274,7 +274,7 @@ int ExecInstruction(MIPSOpcode op) {
case 1:
case 2:
case 3:
MIPSInt::Int_VBranch(op);
MIPSInt::Int_VBranch(mips, op);
return 2;
default:
return -1;
@@ -291,11 +291,11 @@ int ExecInstruction(MIPSOpcode op) {
case 0:
case 1:
case 7:
MIPSInt::Int_VecDo3(op);
MIPSInt::Int_VecDo3(mips, op);
return 2;
// vsbn
case 2:
MIPSInt::Int_Vsbn(op);
MIPSInt::Int_Vsbn(mips, op);
return 2;
default:
return -1;
@@ -306,27 +306,27 @@ int ExecInstruction(MIPSOpcode op) {
switch ((op.encoding >> 23) & 0x7) {
// vmul
case 0:
MIPSInt::Int_VecDo3(op);
MIPSInt::Int_VecDo3(mips, op);
return 2;
// vdot
case 1:
MIPSInt::Int_VDot(op);
MIPSInt::Int_VDot(mips, op);
return 2;
// vscl
case 2:
MIPSInt::Int_VScl(op);
MIPSInt::Int_VScl(mips, op);
return 2;
// vhdp
case 4:
MIPSInt::Int_VHdp(op);
MIPSInt::Int_VHdp(mips, op);
return 2;
// vcrs
case 5:
MIPSInt::Int_Vcrs(op);
MIPSInt::Int_Vcrs(mips, op);
return 2;
// vdet
case 6:
MIPSInt::Int_Vdet(op);
MIPSInt::Int_Vdet(mips, op);
return 2;
default:
return -1;
@@ -337,12 +337,12 @@ int ExecInstruction(MIPSOpcode op) {
switch ((op.encoding >> 24) & 0x3) {
// RUNBLOCK
case 0:
MIPSInt::Int_Emuhack(op);
MIPSInt::Int_Emuhack(mips, op);
return 2;
// RetKrnl, CallRepl
case 1:
case 2:
MIPSInt::Int_Emuhack(op);
MIPSInt::Int_Emuhack(mips, op);
return 1;
default:
return -1;
@@ -353,24 +353,24 @@ int ExecInstruction(MIPSOpcode op) {
switch ((op.encoding >> 23) & 0x7) {
// vcmp
case 0:
MIPSInt::Int_Vcmp(op);
MIPSInt::Int_Vcmp(mips, op);
return 2;
// vmin, vmax
case 2:
case 3:
MIPSInt::Int_Vminmax(op);
MIPSInt::Int_Vminmax(mips, op);
return 2;
// vscmp
case 5:
MIPSInt::Int_Vscmp(op);
MIPSInt::Int_Vscmp(mips, op);
return 2;
// vsge
case 6:
MIPSInt::Int_Vsge(op);
MIPSInt::Int_Vsge(mips, op);
return 2;
// vslt
case 7:
MIPSInt::Int_Vslt(op);
MIPSInt::Int_Vslt(mips, op);
return 2;
default:
return -1;
@@ -382,7 +382,7 @@ int ExecInstruction(MIPSOpcode op) {
// mfic, mtic
case 36:
case 38:
MIPSInt::Int_Special2(op);
MIPSInt::Int_Special2(mips, op);
return 1;
default:
return -1;
@@ -394,7 +394,7 @@ int ExecInstruction(MIPSOpcode op) {
// ext, ins
case 0:
case 4:
MIPSInt::Int_Special3(op);
MIPSInt::Int_Special3(mips, op);
return 1;
case 24:
case 32:
@@ -403,13 +403,13 @@ int ExecInstruction(MIPSOpcode op) {
// wsbh, wsbw
case 2:
case 3:
MIPSInt::Int_Allegrex2(op);
MIPSInt::Int_Allegrex2(mips, op);
return 1;
// seb, bitrev, seh
case 16:
case 20:
case 24:
MIPSInt::Int_Allegrex(op);
MIPSInt::Int_Allegrex(mips, op);
return 1;
default:
return -1;
@@ -432,26 +432,26 @@ int ExecInstruction(MIPSOpcode op) {
case 42:
case 43:
case 46:
MIPSInt::Int_ITypeMem(op);
MIPSInt::Int_ITypeMem(mips, op);
return 1;
// cache
case 47:
MIPSInt::Int_Cache(op);
MIPSInt::Int_Cache(mips, op);
return 1;
// ll, sc
case 48:
case 56:
MIPSInt::Int_StoreSync(op);
MIPSInt::Int_StoreSync(mips, op);
return 1;
// lwc1, swc1
case 49:
case 57:
MIPSInt::Int_FPULS(op);
MIPSInt::Int_FPULS(mips, op);
return 1;
// lv.s, sv.s
case 50:
case 58:
MIPSInt::Int_SV(op);
MIPSInt::Int_SV(mips, op);
return 2;
case 52:
{
@@ -476,16 +476,16 @@ int ExecInstruction(MIPSOpcode op) {
case 24:
case 26:
case 28:
MIPSInt::Int_VV2Op(op);
MIPSInt::Int_VV2Op(mips, op);
return 2;
// vidt
case 3:
MIPSInt::Int_Vidt(op);
MIPSInt::Int_Vidt(mips, op);
return 2;
// vzero, vone
case 6:
case 7:
MIPSInt::Int_VVectorInit(op);
MIPSInt::Int_VVectorInit(mips, op);
return 2;
default:
return -1;
@@ -496,43 +496,43 @@ int ExecInstruction(MIPSOpcode op) {
switch ((op.encoding >> 16) & 0x1f) {
// vrnds
case 0:
MIPSInt::Int_Vrnds(op);
MIPSInt::Int_Vrnds(mips, op);
return 2;
// vrndi, vrndf1, vrndf2
case 1:
case 2:
case 3:
MIPSInt::Int_VrndX(op);
MIPSInt::Int_VrndX(mips, op);
return 2;
// vf2h
case 18:
MIPSInt::Int_Vf2h(op);
MIPSInt::Int_Vf2h(mips, op);
return 2;
// vh2f
case 19:
MIPSInt::Int_Vh2f(op);
MIPSInt::Int_Vh2f(mips, op);
return 2;
// vsbz
case 22:
MIPSInt::Int_Vsbz(op);
MIPSInt::Int_Vsbz(mips, op);
return 2;
// vlgb
case 23:
MIPSInt::Int_Vlgb(op);
MIPSInt::Int_Vlgb(mips, op);
return 2;
// vuc2ifs, vc2i, vus2i, vs2i
case 24:
case 25:
case 26:
case 27:
MIPSInt::Int_Vx2i(op);
MIPSInt::Int_Vx2i(mips, op);
return 2;
// vi2uc, vi2c, vi2us, vi2s
case 28:
case 29:
case 30:
case 31:
MIPSInt::Int_Vi2x(op);
MIPSInt::Int_Vi2x(mips, op);
return 2;
default:
return -1;
@@ -543,58 +543,58 @@ int ExecInstruction(MIPSOpcode op) {
switch ((op.encoding >> 16) & 0x1f) {
// vsrt1
case 0:
MIPSInt::Int_Vsrt1(op);
MIPSInt::Int_Vsrt1(mips, op);
return 2;
// vsrt2
case 1:
MIPSInt::Int_Vsrt2(op);
MIPSInt::Int_Vsrt2(mips, op);
return 2;
// vbfy1, vbfy2
case 2:
case 3:
MIPSInt::Int_Vbfy(op);
MIPSInt::Int_Vbfy(mips, op);
return 2;
// vocp
case 4:
MIPSInt::Int_Vocp(op);
MIPSInt::Int_Vocp(mips, op);
return 2;
// vsocp
case 5:
MIPSInt::Int_Vsocp(op);
MIPSInt::Int_Vsocp(mips, op);
return 2;
// vfad
case 6:
MIPSInt::Int_Vfad(op);
MIPSInt::Int_Vfad(mips, op);
return 2;
// vavg
case 7:
MIPSInt::Int_Vavg(op);
MIPSInt::Int_Vavg(mips, op);
return 2;
// vsrt3
case 8:
MIPSInt::Int_Vsrt3(op);
MIPSInt::Int_Vsrt3(mips, op);
return 2;
// vsrt4
case 9:
MIPSInt::Int_Vsrt4(op);
MIPSInt::Int_Vsrt4(mips, op);
return 2;
// vsgn
case 10:
MIPSInt::Int_Vsgn(op);
MIPSInt::Int_Vsgn(mips, op);
return 2;
// vmfvc
case 16:
MIPSInt::Int_Vmfvc(op);
MIPSInt::Int_Vmfvc(mips, op);
return 2;
// vmtvc
case 17:
MIPSInt::Int_Vmtvc(op);
MIPSInt::Int_Vmtvc(mips, op);
return 2;
// vt4444, vt5551, vt5650
case 25:
case 26:
case 27:
MIPSInt::Int_ColorConv(op);
MIPSInt::Int_ColorConv(mips, op);
return 2;
default:
return -1;
@@ -602,22 +602,22 @@ int ExecInstruction(MIPSOpcode op) {
}
// vcst
case 3:
MIPSInt::Int_Vcst(op);
MIPSInt::Int_Vcst(mips, op);
return 2;
// vf2in, vf2iz, vf2iu, vf2id
case 16:
case 17:
case 18:
case 19:
MIPSInt::Int_Vf2i(op);
MIPSInt::Int_Vf2i(mips, op);
return 2;
// vi2f
case 20:
MIPSInt::Int_Vi2f(op);
MIPSInt::Int_Vi2f(mips, op);
return 2;
// vcmov
case 21:
MIPSInt::Int_Vcmov(op);
MIPSInt::Int_Vcmov(mips, op);
return 2;
// vwbn, vwbn, vwbn, vwbn, vwbn, vwbn, vwbn, vwbn
case 24:
@@ -628,7 +628,7 @@ int ExecInstruction(MIPSOpcode op) {
case 29:
case 30:
case 31:
MIPSInt::Int_Vwbn(op);
MIPSInt::Int_Vwbn(mips, op);
return 2;
default:
return -1;
@@ -639,7 +639,7 @@ int ExecInstruction(MIPSOpcode op) {
case 54:
case 61:
case 62:
MIPSInt::Int_SVQ(op);
MIPSInt::Int_SVQ(mips, op);
return 2;
case 55:
{
@@ -651,12 +651,12 @@ int ExecInstruction(MIPSOpcode op) {
case 3:
case 4:
case 5:
MIPSInt::Int_VPFX(op);
MIPSInt::Int_VPFX(mips, op);
return 2;
// viim.s, vfim.s
case 6:
case 7:
MIPSInt::Int_Viim(op);
MIPSInt::Int_Viim(mips, op);
return 2;
default:
return -1;
@@ -670,7 +670,7 @@ int ExecInstruction(MIPSOpcode op) {
case 1:
case 2:
case 3:
MIPSInt::Int_Vmmul(op);
MIPSInt::Int_Vmmul(mips, op);
return 2;
// v(h)tfm2, v(h)tfm2, v(h)tfm2, v(h)tfm2, v(h)tfm3, v(h)tfm3, v(h)tfm3, v(h)tfm3, v(h)tfm4, v(h)tfm4, v(h)tfm4, v(h)tfm4
case 4:
@@ -685,34 +685,34 @@ int ExecInstruction(MIPSOpcode op) {
case 13:
case 14:
case 15:
MIPSInt::Int_Vtfm(op);
MIPSInt::Int_Vtfm(mips, op);
return 2;
// vmscl, vmscl, vmscl, vmscl
case 16:
case 17:
case 18:
case 19:
MIPSInt::Int_Vmscl(op);
MIPSInt::Int_Vmscl(mips, op);
return 2;
// vcrsp.t/vqmul.q, vcrsp.t/vqmul.q, vcrsp.t/vqmul.q, vcrsp.t/vqmul.q
case 20:
case 21:
case 22:
case 23:
MIPSInt::Int_CrossQuat(op);
MIPSInt::Int_CrossQuat(mips, op);
return 2;
case 28:
{
switch ((op.encoding >> 16) & 0xf) {
// vmmov
case 0:
MIPSInt::Int_Vmmov(op);
MIPSInt::Int_Vmmov(mips, op);
return 2;
// vmidt, vmzero, vmone
case 3:
case 6:
case 7:
MIPSInt::Int_VMatrixInit(op);
MIPSInt::Int_VMatrixInit(mips, op);
return 2;
default:
return -1;
@@ -720,7 +720,7 @@ int ExecInstruction(MIPSOpcode op) {
}
// vrot
case 29:
MIPSInt::Int_Vrot(op);
MIPSInt::Int_Vrot(mips, op);
return 2;
default:
return -1;
@@ -728,7 +728,7 @@ int ExecInstruction(MIPSOpcode op) {
}
// vflush
case 63:
MIPSInt::Int_Vflush(op);
MIPSInt::Int_Vflush(mips, op);
return 2;
default:
return -1;
+8 -8
View File
@@ -20,11 +20,11 @@
#include "Core/MIPS/MIPS.h"
// Fast switch-tree interpreter dispatcher, generated into InterpreterDispatch.cpp by
// GenerateInterpreterDispatch() in MIPSTables.cpp. Executes op on the global currentMIPS
// (same convention as the MIPSInt::Int_* handlers it calls into) and returns the number of
// cycles it consumed - or -1 if op isn't a recognized instruction (an invalid encoding, or
// one of the handful of real instructions with no interpreter implementation, e.g.
// tge/tlt/teq/...). Not total by design: the caller must fall back to MIPSInterpret() on a
// negative return, since deciding what "unhandled" means is a caller policy, not something
// a mechanically generated dispatch tree should embed.
int ExecInstruction(MIPSOpcode op);
// GenerateInterpreterDispatch() in MIPSTables.cpp. Executes op on mips (same convention as
// the MIPSInt::Int_* handlers it calls into) and returns the number of cycles it consumed -
// or -1 if op isn't a recognized instruction (an invalid encoding, or one of the handful of
// real instructions with no interpreter implementation, e.g. tge/tlt/teq/...). Not total by
// design: the caller must fall back to MIPSInterpret() on a negative return, since deciding
// what "unhandled" means is a caller policy, not something a mechanically generated dispatch
// tree should embed.
int ExecInstruction(MIPSState *mips, MIPSOpcode op);
File diff suppressed because it is too large. Load diff
+55 -57
View File
@@ -20,63 +20,61 @@
#include "Common/CommonTypes.h"
#include "Core/MIPS/MIPS.h"
int MIPS_SingleStep();
namespace MIPSInt
{
void Int_SV(MIPSOpcode op);
void Int_SVQ(MIPSOpcode op);
void Int_Mftv(MIPSOpcode op);
void Int_VecDo3(MIPSOpcode op);
void Int_Vcst(MIPSOpcode op);
void Int_VMatrixInit(MIPSOpcode op);
void Int_VVectorInit(MIPSOpcode op);
void Int_Vmmul(MIPSOpcode op);
void Int_Vmscl(MIPSOpcode op);
void Int_Vmmov(MIPSOpcode op);
void Int_VV2Op(MIPSOpcode op);
void Int_Vrot(MIPSOpcode op);
void Int_VDot(MIPSOpcode op);
void Int_VHdp(MIPSOpcode op);
void Int_Vavg(MIPSOpcode op);
void Int_Vfad(MIPSOpcode op);
void Int_Vocp(MIPSOpcode op);
void Int_Vsocp(MIPSOpcode op);
void Int_Vsgn(MIPSOpcode op);
void Int_Vtfm(MIPSOpcode op);
void Int_Viim(MIPSOpcode op);
void Int_VScl(MIPSOpcode op);
void Int_Vidt(MIPSOpcode op);
void Int_Vcmp(MIPSOpcode op);
void Int_Vminmax(MIPSOpcode op);
void Int_Vscmp(MIPSOpcode op);
void Int_Vcrs(MIPSOpcode op);
void Int_Vdet(MIPSOpcode op);
void Int_Vcmov(MIPSOpcode op);
void Int_CrossQuat(MIPSOpcode op);
void Int_VPFX(MIPSOpcode op);
void Int_Vflush(MIPSOpcode op);
void Int_Vbfy(MIPSOpcode op);
void Int_Vsrt1(MIPSOpcode op);
void Int_Vsrt2(MIPSOpcode op);
void Int_Vsrt3(MIPSOpcode op);
void Int_Vsrt4(MIPSOpcode op);
void Int_Vf2i(MIPSOpcode op);
void Int_Vi2f(MIPSOpcode op);
void Int_Vi2x(MIPSOpcode op);
void Int_Vx2i(MIPSOpcode op);
void Int_VBranch(MIPSOpcode op);
void Int_Vrnds(MIPSOpcode op);
void Int_VrndX(MIPSOpcode op);
void Int_ColorConv(MIPSOpcode op);
void Int_Vh2f(MIPSOpcode op);
void Int_Vf2h(MIPSOpcode op);
void Int_Vsge(MIPSOpcode op);
void Int_Vslt(MIPSOpcode op);
void Int_Vmfvc(MIPSOpcode op);
void Int_Vmtvc(MIPSOpcode op);
void Int_Vlgb(MIPSOpcode op);
void Int_Vwbn(MIPSOpcode op);
void Int_Vsbn(MIPSOpcode op);
void Int_Vsbz(MIPSOpcode op);
void Int_SV(MIPSState *mips, MIPSOpcode op);
void Int_SVQ(MIPSState *mips, MIPSOpcode op);
void Int_Mftv(MIPSState *mips, MIPSOpcode op);
void Int_VecDo3(MIPSState *mips, MIPSOpcode op);
void Int_Vcst(MIPSState *mips, MIPSOpcode op);
void Int_VMatrixInit(MIPSState *mips, MIPSOpcode op);
void Int_VVectorInit(MIPSState *mips, MIPSOpcode op);
void Int_Vmmul(MIPSState *mips, MIPSOpcode op);
void Int_Vmscl(MIPSState *mips, MIPSOpcode op);
void Int_Vmmov(MIPSState *mips, MIPSOpcode op);
void Int_VV2Op(MIPSState *mips, MIPSOpcode op);
void Int_Vrot(MIPSState *mips, MIPSOpcode op);
void Int_VDot(MIPSState *mips, MIPSOpcode op);
void Int_VHdp(MIPSState *mips, MIPSOpcode op);
void Int_Vavg(MIPSState *mips, MIPSOpcode op);
void Int_Vfad(MIPSState *mips, MIPSOpcode op);
void Int_Vocp(MIPSState *mips, MIPSOpcode op);
void Int_Vsocp(MIPSState *mips, MIPSOpcode op);
void Int_Vsgn(MIPSState *mips, MIPSOpcode op);
void Int_Vtfm(MIPSState *mips, MIPSOpcode op);
void Int_Viim(MIPSState *mips, MIPSOpcode op);
void Int_VScl(MIPSState *mips, MIPSOpcode op);
void Int_Vidt(MIPSState *mips, MIPSOpcode op);
void Int_Vcmp(MIPSState *mips, MIPSOpcode op);
void Int_Vminmax(MIPSState *mips, MIPSOpcode op);
void Int_Vscmp(MIPSState *mips, MIPSOpcode op);
void Int_Vcrs(MIPSState *mips, MIPSOpcode op);
void Int_Vdet(MIPSState *mips, MIPSOpcode op);
void Int_Vcmov(MIPSState *mips, MIPSOpcode op);
void Int_CrossQuat(MIPSState *mips, MIPSOpcode op);
void Int_VPFX(MIPSState *mips, MIPSOpcode op);
void Int_Vflush(MIPSState *mips, MIPSOpcode op);
void Int_Vbfy(MIPSState *mips, MIPSOpcode op);
void Int_Vsrt1(MIPSState *mips, MIPSOpcode op);
void Int_Vsrt2(MIPSState *mips, MIPSOpcode op);
void Int_Vsrt3(MIPSState *mips, MIPSOpcode op);
void Int_Vsrt4(MIPSState *mips, MIPSOpcode op);
void Int_Vf2i(MIPSState *mips, MIPSOpcode op);
void Int_Vi2f(MIPSState *mips, MIPSOpcode op);
void Int_Vi2x(MIPSState *mips, MIPSOpcode op);
void Int_Vx2i(MIPSState *mips, MIPSOpcode op);
void Int_VBranch(MIPSState *mips, MIPSOpcode op);
void Int_Vrnds(MIPSState *mips, MIPSOpcode op);
void Int_VrndX(MIPSState *mips, MIPSOpcode op);
void Int_ColorConv(MIPSState *mips, MIPSOpcode op);
void Int_Vh2f(MIPSState *mips, MIPSOpcode op);
void Int_Vf2h(MIPSState *mips, MIPSOpcode op);
void Int_Vsge(MIPSState *mips, MIPSOpcode op);
void Int_Vslt(MIPSState *mips, MIPSOpcode op);
void Int_Vmfvc(MIPSState *mips, MIPSOpcode op);
void Int_Vmtvc(MIPSState *mips, MIPSOpcode op);
void Int_Vlgb(MIPSState *mips, MIPSOpcode op);
void Int_Vwbn(MIPSState *mips, MIPSOpcode op);
void Int_Vsbn(MIPSState *mips, MIPSOpcode op);
void Int_Vsbz(MIPSState *mips, MIPSOpcode op);
}
+1 -1
View File
@@ -259,7 +259,7 @@ void LoongArch64JitBackend::CompIR_Interpret(IRInst inst) {
QuickCallFunction(&NotifyMIPSInterpret, SCRATCH2);
}
LI(R4, (int32_t)inst.constant);
QuickCallFunction((const u8 *)MIPSGetInterpretFunc(op), SCRATCH2);
QuickCallFunction((const u8 *)&MIPSInterpretTrampoline, SCRATCH2);
WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT);
LoadStaticRegisters();
}
+19 -14
View File
@@ -976,7 +976,7 @@ static void EmitDispatchLevel(std::string &out, MipsEncoding encoding, int inden
out += ind + StringFromFormat("// %s\n", names.c_str());
for (u32 idx : group)
out += ind + StringFromFormat("case %d:\n", idx);
out += ind2 + StringFromFormat("MIPSInt::%s(op);\n", instr.interpretName);
out += ind2 + StringFromFormat("MIPSInt::%s(mips, op);\n", instr.interpretName);
out += ind2 + StringFromFormat("return %d;\n", (int)instr.flags.cycles);
} else {
for (u32 idx : group)
@@ -985,7 +985,7 @@ static void EmitDispatchLevel(std::string &out, MipsEncoding encoding, int inden
EmitDispatchLevel(out, instr.altEncoding, indent + 1);
out += ind + "}\n";
// No trailing return here - the nested switch above always either returns
// a value directly from a case, or falls to its own default's "goto slow_path;".
// a value directly from a case, or falls to its own default's "return -1;".
}
}
@@ -995,15 +995,15 @@ static void EmitDispatchLevel(std::string &out, MipsEncoding encoding, int inden
}
// Generates a full, compilable Core/MIPS/InterpreterDispatch.cpp: a fast
// int ExecInstruction(MIPSOpcode op) dispatcher, built by resolving the tables above into
// a nested switch tree at generation time, so each real instruction is reached by a direct
// call instead of MIPSGetInstruction()'s per-instruction table walk plus indirect call
// through instr->interpret. Leaves call straight into the existing MIPSInt::Int_* handlers
// - the tables only record which handler an opcode maps to, not the handler's behavior, so
// that's the only thing there is to call - and return that instruction's fixed cycle count
// (baked in at generation time, same value MIPSGetInstructionCycleEstimate() would have
// returned) so the caller can still track downcount. Operates on the global currentMIPS,
// same as the Int_* handlers do.
// int ExecInstruction(MIPSState *mips, MIPSOpcode op) dispatcher, built by resolving the
// tables above into a nested switch tree at generation time, so each real instruction is
// reached by a direct call instead of MIPSGetInstruction()'s per-instruction table walk plus
// indirect call through instr->interpret. Leaves call straight into the existing
// MIPSInt::Int_* handlers - the tables only record which handler an opcode maps to, not the
// handler's behavior, so that's the only thing there is to call - and return that
// instruction's fixed cycle count (baked in at generation time, same value
// MIPSGetInstructionCycleEstimate() would have returned) so the caller can still track
// downcount.
//
// The generated function is deliberately not total: most of the 32-bit opcode space doesn't
// decode to anything (either a genuinely invalid encoding, or a real-but-uninterpreted
@@ -1036,7 +1036,7 @@ std::string GenerateInterpreterDispatch() {
out += "#include \"Core/MIPS/InterpreterVFPU.h\"\n\n";
out += "// Returns the cycle count consumed, or -1 if op isn't a recognized instruction -\n";
out += "// callers must fall back to MIPSInterpret() themselves in that case.\n";
out += "int ExecInstruction(MIPSOpcode op) {\n";
out += "int ExecInstruction(MIPSState *mips, MIPSOpcode op) {\n";
EmitDispatchLevel(out, Imme, 1);
out += "}\n";
return out;
@@ -1097,7 +1097,7 @@ static void HandleUnknownInstruction(MIPSState *mips, MIPSOpcode op) {
static inline void Interpret(MIPSState *mips, const MIPSInstruction *instr, MIPSOpcode op) {
if (instr && instr->interpret) {
instr->interpret(op);
instr->interpret(mips, op);
} else {
HandleUnknownInstruction(mips, op);
}
@@ -1114,6 +1114,11 @@ void MIPSInterpret(MIPSState *mips, MIPSOpcode op) {
Interpret(mips, instr, op);
}
// See the declaration comment in MIPSTables.h.
void CDECL MIPSInterpretTrampoline(MIPSOpcode op) {
MIPSInterpret(currentMIPS, op);
}
static inline void RunUntilFast(MIPSState *curMips) {
// NEVER stop in a delay slot!
while (curMips->downcount >= 0 && coreState == CORE_RUNNING_CPU) {
@@ -1125,7 +1130,7 @@ static inline void RunUntilFast(MIPSState *curMips) {
MIPSOpcode op = MIPSOpcode(Memory::ReadUnchecked_U32(curMips->pc));
bool wasInDelaySlot = curMips->inDelaySlot;
int cycles = ExecInstruction(op);
int cycles = ExecInstruction(curMips, op);
if (cycles < 0) {
// Not a recognized instruction (invalid encoding, or a known instruction
// with no interpreter implementation, e.g. tge/tlt/teq/...). No point
+11 -3
View File
@@ -122,7 +122,7 @@ struct MIPSInfo {
};
typedef void (CDECL *MIPSDisFunc)(MIPSOpcode opcode, uint32_t pc, char *out, size_t outSize);
typedef void (CDECL *MIPSInterpretFunc)(MIPSOpcode opcode);
typedef void (CDECL *MIPSInterpretFunc)(MIPSState *mips, MIPSOpcode opcode);
namespace MIPSComp {
class MIPSFrontendInterface;
@@ -135,12 +135,20 @@ void MIPSInterpret(MIPSState *mips, MIPSOpcode op); //only for those rare ones
int MIPSInterpret_RunUntil(MIPSState *mips, u64 globalTicks);
MIPSInterpretFunc MIPSGetInterpretFunc(MIPSOpcode op);
// 1-arg (MIPSOpcode only) trampoline around MIPSInterpret(currentMIPS, op), for JIT backends
// (x86/ARM/ARM64/RiscV/LoongArch64 Comp_Generic / CompIR_Interpret) that bake a raw function
// pointer directly into generated machine code as their interpreter fallback - that codegen
// only arranges a single MIPSOpcode argument before the call, so it can't target a real
// MIPSInterpretFunc (now 2-arg) without also being taught to pass an explicit MIPSState*.
// TODO: teach each JIT's codegen to pass mips explicitly, then delete this.
void CDECL MIPSInterpretTrampoline(MIPSOpcode op);
int MIPSGetInstructionCycleEstimate(MIPSOpcode op);
int MIPSGetMemoryAccessSize(MIPSOpcode op);
const char *MIPSGetName(MIPSOpcode op);
std::string MIPSDisasmAt(u32 compilerPC);
// Generates the full contents of Core/MIPS/InterpreterDispatch.cpp: a fast switch-tree
// int ExecInstruction(MIPSOpcode op) dispatcher, derived from the tables in MIPSTables.cpp.
// See GenerateInterpreterDispatch()'s comment (in the .cpp) for details.
// int ExecInstruction(MIPSState *mips, MIPSOpcode op) dispatcher, derived from the tables in
// MIPSTables.cpp. See GenerateInterpreterDispatch()'s comment (in the .cpp) for details.
std::string GenerateInterpreterDispatch();
+1 -1
View File
@@ -260,7 +260,7 @@ void RiscVJitBackend::CompIR_Interpret(IRInst inst) {
QuickCallFunction(&NotifyMIPSInterpret, SCRATCH2);
}
LI(X10, (int32_t)inst.constant);
QuickCallFunction((const u8 *)MIPSGetInterpretFunc(op), SCRATCH2);
QuickCallFunction((const u8 *)&MIPSInterpretTrampoline, SCRATCH2);
WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT);
LoadStaticRegisters();
}
+1 -1
View File
@@ -85,7 +85,7 @@ static void JitBranchLog(MIPSOpcode op, u32 pc) {
MIPSInterpretFunc func = MIPSGetInterpretFunc(op);
MIPSInfo info = MIPSGetInfo(op);
func(op);
func(currentMIPS, op);
// Branch taken, use nextPC.
if (currentMIPS->inDelaySlot)
+2 -2
View File
@@ -111,7 +111,7 @@ static void JitLogMiss(MIPSOpcode op)
notJitOps[MIPSGetName(op)]++;
MIPSInterpretFunc func = MIPSGetInterpretFunc(op);
func(op);
func(currentMIPS, op);
}
#ifdef _MSC_VER
@@ -626,7 +626,7 @@ void Jit::Comp_Generic(MIPSOpcode op) {
if (USE_JIT_MISSMAP)
ABI_CallFunctionC(&JitLogMiss, op.encoding);
else
ABI_CallFunctionC(func, op.encoding);
ABI_CallFunctionC(&MIPSInterpretTrampoline, op.encoding);
ApplyRoundingMode();
} else {
// These are basically always due to some kind of crash or corruption now.
+1 -1
View File
@@ -256,7 +256,7 @@ void X64JitBackend::CompIR_Interpret(IRInst inst) {
if (DebugStatsEnabled()) {
ABI_CallFunctionP((const void *)&NotifyMIPSInterpret, (void *)MIPSGetName(op));
}
ABI_CallFunctionC((const void *)MIPSGetInterpretFunc(op), inst.constant);
ABI_CallFunctionC((const void *)&MIPSInterpretTrampoline, inst.constant);
WriteDebugProfilerStatus(IRProfilerStatus::IN_JIT);
LoadStaticRegisters();
}
+1 -1
View File
@@ -75,7 +75,7 @@ def main():
# Sanity check before clobbering the tracked file - a stale/broken binary should
# fail loudly here rather than silently truncating InterpreterDispatch.cpp.
if b"int ExecInstruction(MIPSOpcode op)" not in generated:
if b"int ExecInstruction(MIPSState *mips, MIPSOpcode op)" not in generated:
sys.stderr.write("error: generated output doesn't look right (missing ExecInstruction) - not overwriting %s\n" % OUT_PATH)
return 1