diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index 3663ec9c0c..35666e7f79 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -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(); } diff --git a/Core/MIPS/ARM64/Arm64IRJit.cpp b/Core/MIPS/ARM64/Arm64IRJit.cpp index f9b206fffc..2a5d38d5be 100644 --- a/Core/MIPS/ARM64/Arm64IRJit.cpp +++ b/Core/MIPS/ARM64/Arm64IRJit.cpp @@ -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(); } diff --git a/Core/MIPS/ARM64/Arm64Jit.cpp b/Core/MIPS/ARM64/Arm64Jit.cpp index 8dcdbb562d..cc1d38c90c 100644 --- a/Core/MIPS/ARM64/Arm64Jit.cpp +++ b/Core/MIPS/ARM64/Arm64Jit.cpp @@ -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(); } diff --git a/Core/MIPS/Interpreter.cpp b/Core/MIPS/Interpreter.cpp index 2ebc6cc318..b3d19e2b8d 100644 --- a/Core/MIPS/Interpreter.cpp +++ b/Core/MIPS/Interpreter.cpp @@ -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)); } } } diff --git a/Core/MIPS/Interpreter.h b/Core/MIPS/Interpreter.h index 030a0b9fd3..02dc35244c 100644 --- a/Core/MIPS/Interpreter.h +++ b/Core/MIPS/Interpreter.h @@ -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); } diff --git a/Core/MIPS/InterpreterDispatch.cpp b/Core/MIPS/InterpreterDispatch.cpp index 88790778d9..30885ec9bf 100644 --- a/Core/MIPS/InterpreterDispatch.cpp +++ b/Core/MIPS/InterpreterDispatch.cpp @@ -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; diff --git a/Core/MIPS/InterpreterDispatch.h b/Core/MIPS/InterpreterDispatch.h index 6767b8249c..e569eabe86 100644 --- a/Core/MIPS/InterpreterDispatch.h +++ b/Core/MIPS/InterpreterDispatch.h @@ -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); diff --git a/Core/MIPS/InterpreterVFPU.cpp b/Core/MIPS/InterpreterVFPU.cpp index 71c673f311..3472e4e59a 100644 --- a/Core/MIPS/InterpreterVFPU.cpp +++ b/Core/MIPS/InterpreterVFPU.cpp @@ -32,15 +32,16 @@ #include "Core/MIPS/MIPS.h" #include "Core/MIPS/Interpreter.h" +#include "Core/MIPS/InterpreterVFPU.h" #include "Core/MIPS/MIPSTables.h" #include "Core/MIPS/MIPSVFPUUtils.h" -#define R(i) (currentMIPS->r[i]) -#define V(i) (currentMIPS->v[voffset[i]]) -#define VI(i) (currentMIPS->vi[voffset[i]]) -#define FI(i) (currentMIPS->fi[i]) -#define FsI(i) (currentMIPS->fs[i]) -#define PC (currentMIPS->pc) +#define R(i) (mips->r[i]) +#define V(i) (mips->v[voffset[i]]) +#define VI(i) (mips->vi[voffset[i]]) +#define FI(i) (mips->fi[i]) +#define FsI(i) (mips->fs[i]) +#define PC (mips->pc) #define _RS ((op>>21) & 0x1F) #define _RT ((op>>16) & 0x1F) @@ -51,8 +52,8 @@ #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 #ifndef M_LOG2E #define M_E 2.71828182845904523536f @@ -101,7 +102,7 @@ inline float nanclamp(float f, float lower, float upper) return nanmin(nanmax(f, lower), upper); } -static void ApplyPrefixST(float *r, u32 data, VectorSize size, float invalid = 0.0f) { +static void ApplyPrefixST(MIPSState *mips, float *r, u32 data, VectorSize size, float invalid = 0.0f) { // Check for no prefix. if (data == 0xe4) return; @@ -123,7 +124,7 @@ static void ApplyPrefixST(float *r, u32 data, VectorSize size, float invalid = 0 if (!constants) { if (regnum >= n) { // We mostly handle this now, but still worth reporting. - ERROR_LOG_REPORT(Log::CPU, "Invalid VFPU swizzle: %08x: %i / %d at PC = %08x (%s)", data, regnum, n, currentMIPS->pc, MIPSDisasmAt(currentMIPS->pc).c_str()); + ERROR_LOG_REPORT(Log::CPU, "Invalid VFPU swizzle: %08x: %i / %d at PC = %08x (%s)", data, regnum, n, mips->pc, MIPSDisasmAt(mips->pc).c_str()); } r[i] = origV[regnum]; if (abs) @@ -137,19 +138,19 @@ static void ApplyPrefixST(float *r, u32 data, VectorSize size, float invalid = 0 } } -inline void ApplySwizzleS(float *v, VectorSize size, float invalid = 0.0f) +inline void ApplySwizzleS(MIPSState *mips, float *v, VectorSize size, float invalid = 0.0f) { - ApplyPrefixST(v, currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX], size, invalid); + ApplyPrefixST(mips, v, mips->vfpuCtrl[VFPU_CTRL_SPREFIX], size, invalid); } -inline void ApplySwizzleT(float *v, VectorSize size, float invalid = 0.0f) +inline void ApplySwizzleT(MIPSState *mips, float *v, VectorSize size, float invalid = 0.0f) { - ApplyPrefixST(v, currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX], size, invalid); + ApplyPrefixST(mips, v, mips->vfpuCtrl[VFPU_CTRL_TPREFIX], size, invalid); } -void ApplyPrefixD(float *v, VectorSize size, bool onlyWriteMask = false) +void ApplyPrefixD(MIPSState *mips, float *v, VectorSize size, bool onlyWriteMask = false) { - u32 data = currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX]; + u32 data = mips->vfpuCtrl[VFPU_CTRL_DPREFIX]; if (!data || onlyWriteMask) return; int n = GetNumVectorElements(size); @@ -163,11 +164,11 @@ void ApplyPrefixD(float *v, VectorSize size, bool onlyWriteMask = false) } } -static void RetainInvalidSwizzleST(float *d, VectorSize sz) { +static void RetainInvalidSwizzleST(MIPSState *mips, float *d, VectorSize sz) { // Somehow it's like a supernan, maybe wires through to zero? // Doesn't apply to all ops. - int sPrefix = currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX]; - int tPrefix = currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX]; + int sPrefix = mips->vfpuCtrl[VFPU_CTRL_SPREFIX]; + int tPrefix = mips->vfpuCtrl[VFPU_CTRL_TPREFIX]; int n = GetNumVectorElements(sz); // TODO: We can probably do some faster check of sPrefix and tPrefix to skip over this loop. @@ -181,26 +182,26 @@ static void RetainInvalidSwizzleST(float *d, VectorSize sz) { } } -void EatPrefixes() +void EatPrefixes(MIPSState *mips) { - currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX] = 0xe4; // passthru - currentMIPS->vfpuCtrl[VFPU_CTRL_TPREFIX] = 0xe4; // passthru - currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] = 0; + mips->vfpuCtrl[VFPU_CTRL_SPREFIX] = 0xe4; // passthru + mips->vfpuCtrl[VFPU_CTRL_TPREFIX] = 0xe4; // passthru + mips->vfpuCtrl[VFPU_CTRL_DPREFIX] = 0; } namespace MIPSInt { - void Int_VPFX(MIPSOpcode op) + void Int_VPFX(MIPSState *mips, MIPSOpcode op) { int data = op & 0x000FFFFF; int regnum = (op >> 24) & 3; if (regnum == VFPU_CTRL_DPREFIX) data &= 0x00000FFF; - currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX + regnum] = data; + mips->vfpuCtrl[VFPU_CTRL_SPREFIX + regnum] = data; PC += 4; } - void Int_SVQ(MIPSOpcode op) { + void Int_SVQ(MIPSState *mips, MIPSOpcode op) { int imm = SignExtend16ToS32(op & 0xFFFC); int rs = _RS; int vt = (((op >> 16) & 0x1f)) | ((op&1) << 5); @@ -314,7 +315,7 @@ namespace MIPSInt PC += 4; } - void Int_VMatrixInit(MIPSOpcode op) { + void Int_VMatrixInit(MIPSState *mips, MIPSOpcode op) { static const float idt[16] = { 1,0,0,0, 0,1,0,0, @@ -344,12 +345,12 @@ namespace MIPSInt default: _dbg_assert_msg_(false,"Trying to interpret instruction that can't be interpreted"); PC += 4; - EatPrefixes(); + EatPrefixes(mips); return; } // The S prefix generates constants, but only for the final (possibly transposed) row. - if (currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX] & 0xF0F00) { + if (mips->vfpuCtrl[VFPU_CTRL_SPREFIX] & 0xF0F00) { float prefixed[16]; memcpy(prefixed, m, sizeof(prefixed)); @@ -376,17 +377,17 @@ namespace MIPSInt _dbg_assert_msg_( 0, "Unknown matrix init op"); break; } - ApplyPrefixST(&prefixed[off * 4], VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Quad); + ApplyPrefixST(mips, &prefixed[off * 4], VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Quad); WriteMatrix(prefixed, sz, vd); } else { // Write mask applies to the final (maybe transposed) row. Sat causes hang. WriteMatrix(m, sz, vd); } PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_VVectorInit(MIPSOpcode op) + void Int_VVectorInit(MIPSState *mips, MIPSOpcode op) { int vd = _VD; VectorSize sz = GetVecSize(op); @@ -399,23 +400,23 @@ namespace MIPSInt default: _dbg_assert_msg_( 0, "Trying to interpret instruction that can't be interpreted"); PC += 4; - EatPrefixes(); + EatPrefixes(mips); return; } // The S prefix generates constants, but negate is still respected. u32 sprefixRemove = VFPU_ANY_SWIZZLE(); u32 sprefixAdd = VFPU_MAKE_CONSTANTS(constant, constant, constant, constant); - ApplyPrefixST(d, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), sz); + ApplyPrefixST(mips, d, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), sz); - ApplyPrefixD(d, sz); + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); - EatPrefixes(); + EatPrefixes(mips); PC += 4; } - void Int_Viim(MIPSOpcode op) { + void Int_Viim(MIPSState *mips, MIPSOpcode op) { int vt = _VT; s32 imm = SignExtend16ToS32(op & 0xFFFF); u16 uimm16 = (op&0xFFFF); @@ -430,13 +431,13 @@ namespace MIPSInt f[0] = 0; } - ApplyPrefixD(f, V_Single); + ApplyPrefixD(mips, f, V_Single); WriteVector(f, V_Single, vt); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vidt(MIPSOpcode op) { + void Int_Vidt(MIPSState *mips, MIPSOpcode op) { int vd = _VD; VectorSize sz = GetVecSize(op); float f[4]; @@ -452,16 +453,16 @@ namespace MIPSInt u32 sprefixRemove = VFPU_ANY_SWIZZLE(); u32 sprefixAdd = VFPU_MAKE_CONSTANTS(constX, constY, constZ, constW); - ApplyPrefixST(f, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), sz); + ApplyPrefixST(mips, f, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), sz); - ApplyPrefixD(f, sz); + ApplyPrefixD(mips, f, sz); WriteVector(f, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } // The test really needs some work. - void Int_Vmmul(MIPSOpcode op) { + void Int_Vmmul(MIPSState *mips, MIPSOpcode op) { float s[16]{}, t[16]{}, d[16]; int vd = _VD; @@ -480,8 +481,8 @@ namespace MIPSInt union { float f; uint32_t u; } sum = { 0.0f }; if (a == n - 1 && b == n - 1) { // S and T prefixes work on the final (or maybe first, in reverse?) dot. - ApplySwizzleS(&s[b * 4], V_Quad); - ApplySwizzleT(&t[a * 4], V_Quad); + ApplySwizzleS(mips, &s[b * 4], V_Quad); + ApplySwizzleT(mips, &t[a * 4], V_Quad); } if (useAccurateDot) { @@ -508,16 +509,16 @@ namespace MIPSInt } // The D prefix applies ONLY to the final element, but sat does work. - u32 lastmask = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & (1 << 8)) << (n - 1); - u32 lastsat = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (n + n - 2); - currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] = lastmask | lastsat; - ApplyPrefixD(&d[4 * (n - 1)], V_Quad, false); + u32 lastmask = (mips->vfpuCtrl[VFPU_CTRL_DPREFIX] & (1 << 8)) << (n - 1); + u32 lastsat = (mips->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (n + n - 2); + mips->vfpuCtrl[VFPU_CTRL_DPREFIX] = lastmask | lastsat; + ApplyPrefixD(mips, &d[4 * (n - 1)], V_Quad, false); WriteMatrix(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vmscl(MIPSOpcode op) { + void Int_Vmscl(MIPSState *mips, MIPSOpcode op) { float s[16]{}, t[4]{}, d[16]; int vd = _VD; @@ -536,27 +537,27 @@ namespace MIPSInt } // S prefix applies to the last row. - ApplySwizzleS(&s[(n - 1) * 4], V_Quad); + ApplySwizzleS(mips, &s[(n - 1) * 4], V_Quad); // T prefix applies only for the last row, and is used per element. // This is like vscl, but instead of zzzz it uses xxxx. int tlane = (vt >> 5) & 3; t[tlane] = t[0]; u32 tprefixRemove = VFPU_ANY_SWIZZLE(); u32 tprefixAdd = VFPU_SWIZZLE(tlane, tlane, tlane, tlane); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); for (int b = 0; b < n; b++) { d[(n - 1) * 4 + b] = s[(n - 1) * 4 + b] * t[b]; } // The D prefix is applied to the last row. - ApplyPrefixD(&d[(n - 1) * 4], V_Quad); + ApplyPrefixD(mips, &d[(n - 1) * 4], V_Quad); WriteMatrix(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vmmov(MIPSOpcode op) { + void Int_Vmmov(MIPSState *mips, MIPSOpcode op) { float s[16]{}; int vd = _VD; int vs = _VS; @@ -564,23 +565,23 @@ namespace MIPSInt ReadMatrix(s, sz, vs); // S and D prefixes are applied to the last row. int off = GetMatrixSide(sz) - 1; - ApplySwizzleS(&s[off * 4], V_Quad); - ApplyPrefixD(&s[off * 4], V_Quad); + ApplySwizzleS(mips, &s[off * 4], V_Quad); + ApplyPrefixD(mips, &s[off * 4], V_Quad); WriteMatrix(s, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vflush(MIPSOpcode op) + void Int_Vflush(MIPSState *mips, MIPSOpcode op) { VERBOSE_LOG(Log::CPU, "vflush"); PC += 4; // Anything with 0xFC000000 is a nop, but only 0xFFFF0000 retains prefixes. if ((op & 0xFFFF0000) != 0xFFFF0000) - EatPrefixes(); + EatPrefixes(mips); } - void Int_VV2Op(MIPSOpcode op) { + void Int_VV2Op(MIPSState *mips, MIPSOpcode op) { float s[4], d[4]; int vd = _VD; int vs = _VS; @@ -591,10 +592,10 @@ namespace MIPSInt // Some of these are prefix hacks (affects constants, etc.) switch (optype) { case 1: - ApplyPrefixST(s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, 0, VFPU_ABS(1, 1, 1, 1)), sz); + ApplyPrefixST(mips, s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, 0, VFPU_ABS(1, 1, 1, 1)), sz); break; case 2: - ApplyPrefixST(s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, 0, VFPU_NEGATE(1, 1, 1, 1)), sz); + ApplyPrefixST(mips, s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, 0, VFPU_NEGATE(1, 1, 1, 1)), sz); break; case 16: case 17: @@ -605,19 +606,19 @@ namespace MIPSInt case 22: case 23: // Similar to vdiv. Some of the behavior using the invalid constant is iffy. - ApplySwizzleS(&s[n - 1], V_Single, INFINITY); + ApplySwizzleS(mips, &s[n - 1], V_Single, INFINITY); break; case 24: case 26: // Similar to above, but also ignores negate. - ApplyPrefixST(&s[n - 1], VFPURewritePrefix(VFPU_CTRL_SPREFIX, VFPU_NEGATE(1, 0, 0, 0), 0), V_Single, -INFINITY); + ApplyPrefixST(mips, &s[n - 1], VFPURewritePrefix(VFPU_CTRL_SPREFIX, VFPU_NEGATE(1, 0, 0, 0), 0), V_Single, -INFINITY); break; case 28: // Similar to above, but also ignores negate. - ApplyPrefixST(&s[n - 1], VFPURewritePrefix(VFPU_CTRL_SPREFIX, VFPU_NEGATE(1, 0, 0, 0), 0), V_Single, INFINITY); + ApplyPrefixST(mips, &s[n - 1], VFPURewritePrefix(VFPU_CTRL_SPREFIX, VFPU_NEGATE(1, 0, 0, 0), 0), V_Single, INFINITY); break; default: - ApplySwizzleS(s, sz); + ApplySwizzleS(mips, s, sz); break; } for (int i = 0; i < (int)n; i++) { @@ -648,7 +649,7 @@ namespace MIPSInt // vsat1 is a prefix hack, so 0:1 doesn't apply. Others don't process sat at all. switch (optype) { case 5: - ApplyPrefixD(d, sz, true); + ApplyPrefixD(mips, d, sz, true); break; case 16: case 17: @@ -663,21 +664,21 @@ namespace MIPSInt case 28: { // Only the last element gets the mask applied. - u32 lastmask = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & (1 << 8)) << (n - 1); - u32 lastsat = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (n + n - 2); - currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] = lastmask | lastsat; - ApplyPrefixD(d, sz); + u32 lastmask = (mips->vfpuCtrl[VFPU_CTRL_DPREFIX] & (1 << 8)) << (n - 1); + u32 lastsat = (mips->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (n + n - 2); + mips->vfpuCtrl[VFPU_CTRL_DPREFIX] = lastmask | lastsat; + ApplyPrefixD(mips, d, sz); break; } default: - ApplyPrefixD(d, sz); + ApplyPrefixD(mips, d, sz); } WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vocp(MIPSOpcode op) { + void Int_Vocp(MIPSState *mips, MIPSOpcode op) { float s[4], t[4], d[4]; int vd = _VD; int vs = _VS; @@ -686,26 +687,26 @@ namespace MIPSInt // S prefix forces the negate flags. u32 sprefixAdd = VFPU_NEGATE(1, 1, 1, 1); - ApplyPrefixST(s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, 0, sprefixAdd), sz); + ApplyPrefixST(mips, s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, 0, sprefixAdd), sz); // T prefix forces constants on and regnum to 1. // That means negate still works, and abs activates a different constant. u32 tprefixRemove = VFPU_ANY_SWIZZLE(); u32 tprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::ONE, VFPUConst::ONE, VFPUConst::ONE, VFPUConst::ONE); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); for (int i = 0; i < GetNumVectorElements(sz); i++) { // Always positive NaN. Note that s is always negated from the registers. d[i] = my_isnan(s[i]) ? fabsf(s[i]) : t[i] + s[i]; } - RetainInvalidSwizzleST(d, sz); - ApplyPrefixD(d, sz); + RetainInvalidSwizzleST(mips, d, sz); + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vsocp(MIPSOpcode op) { + void Int_Vsocp(MIPSState *mips, MIPSOpcode op) { float s[4], t[4], d[4]; int vd = _VD; int vs = _VS; @@ -719,13 +720,13 @@ namespace MIPSInt // abs works, and applies to final position (not source.) u32 sprefixRemove = VFPU_ANY_SWIZZLE() | VFPU_NEGATE(1, 1, 1, 1); u32 sprefixAdd = VFPU_SWIZZLE(0, 0, 1, 1) | VFPU_NEGATE(1, 0, 1, 0); - ApplyPrefixST(s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), outSize); + ApplyPrefixST(mips, s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), outSize); // T prefix forces constants on and regnum to 1, 0, 1, 0. // That means negate still works, and abs activates a different constant. u32 tprefixRemove = VFPU_ANY_SWIZZLE(); u32 tprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::ONE, VFPUConst::ZERO, VFPUConst::ONE, VFPUConst::ZERO); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), outSize); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), outSize); // Essentially D prefix saturation is forced. d[0] = nanclamp(t[0] + s[0], 0.0f, 1.0f); @@ -734,13 +735,13 @@ namespace MIPSInt d[2] = nanclamp(t[2] + s[2], 0.0f, 1.0f); d[3] = nanclamp(t[3] + s[3], 0.0f, 1.0f); } - ApplyPrefixD(d, sz, true); + ApplyPrefixD(mips, d, sz, true); WriteVector(d, outSize, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vsgn(MIPSOpcode op) { + void Int_Vsgn(MIPSState *mips, MIPSOpcode op) { float s[4], t[4], d[4]; int vd = _VD; int vs = _VS; @@ -750,14 +751,14 @@ namespace MIPSInt // Not sure who would do this, but using abs/neg allows a compare against 3 or -3. u32 tprefixRemove = VFPU_ANY_SWIZZLE(); u32 tprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::ZERO, VFPUConst::ZERO, VFPUConst::ZERO, VFPUConst::ZERO); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); int n = GetNumVectorElements(sz); if (n < 4) { // Compare with a swizzled value out of bounds always produces 0. memcpy(&s[n], &t[n], sizeof(float) * (4 - n)); } - ApplySwizzleS(s, V_Quad); + ApplySwizzleS(mips, s, V_Quad); for (int i = 0; i < n; i++) { float diff = s[i] - t[i]; @@ -771,10 +772,10 @@ namespace MIPSInt else d[i] = -1.0f; } - ApplyPrefixD(d, sz); + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } inline int round_vfpu_n(double param) { @@ -782,7 +783,7 @@ namespace MIPSInt return (int)round_ieee_754(param); } - void Int_Vf2i(MIPSOpcode op) { + void Int_Vf2i(MIPSState *mips, MIPSOpcode op) { float s[4]; int d[4]; int vd = _VD; @@ -792,7 +793,7 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); // Negate, abs, and constants apply as you'd expect to the bits. - ApplySwizzleS(s, sz); + ApplySwizzleS(mips, s, sz); for (int i = 0; i < GetNumVectorElements(sz); i++) { if (my_isnan(s[i])) { d[i] = 0x7FFFFFFF; @@ -816,13 +817,13 @@ namespace MIPSInt } } // Does not apply sat, but does apply mask. - ApplyPrefixD(reinterpret_cast(d), sz, true); + ApplyPrefixD(mips, reinterpret_cast(d), sz, true); WriteVector(reinterpret_cast(d), sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vi2f(MIPSOpcode op) { + void Int_Vi2f(MIPSState *mips, MIPSOpcode op) { int s[4]; float d[4]; int vd = _VD; @@ -832,25 +833,25 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); ReadVector(reinterpret_cast(s), sz, vs); // Negate, abs, and constants apply as you'd expect to the bits. - ApplySwizzleS(reinterpret_cast(s), sz); + ApplySwizzleS(mips, reinterpret_cast(s), sz); for (int i = 0; i < GetNumVectorElements(sz); i++) { d[i] = (float)s[i] * mult; } // Sat and mask apply normally. - ApplyPrefixD(d, sz); + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vh2f(MIPSOpcode op) { + void Int_Vh2f(MIPSState *mips, MIPSOpcode op) { u32 s[4]; float d[4]; int vd = _VD; int vs = _VS; VectorSize sz = GetVecSize(op); ReadVector(reinterpret_cast(s), sz, vs); - ApplySwizzleS(reinterpret_cast(s), sz); + ApplySwizzleS(mips, reinterpret_cast(s), sz); VectorSize outsize = V_Pair; switch (sz) { @@ -869,13 +870,13 @@ namespace MIPSInt d[3] = ExpandHalf(s[1] >> 16); break; } - ApplyPrefixD(d, outsize); + ApplyPrefixD(mips, d, outsize); WriteVector(d, outsize, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vf2h(MIPSOpcode op) { + void Int_Vf2h(MIPSState *mips, MIPSOpcode op) { float s[4]{}; u32 d[4]; int vd = _VD; @@ -883,9 +884,9 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); // Swizzle can cause V_Single to properly write both components. - ApplySwizzleS(s, V_Quad); + ApplySwizzleS(mips, s, V_Quad); // Negate should not actually apply to invalid swizzle. - RetainInvalidSwizzleST(s, V_Quad); + RetainInvalidSwizzleST(mips, s, V_Quad); VectorSize outsize = V_Single; switch (sz) { @@ -905,20 +906,20 @@ namespace MIPSInt ERROR_LOG_REPORT(Log::CPU, "vf2h with invalid elements"); break; } - ApplyPrefixD(reinterpret_cast(d), outsize); + ApplyPrefixD(mips, reinterpret_cast(d), outsize); WriteVector(reinterpret_cast(d), outsize, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vx2i(MIPSOpcode op) { + void Int_Vx2i(MIPSState *mips, MIPSOpcode op) { u32 s[4], d[4]{}; int vd = _VD; int vs = _VS; VectorSize sz = GetVecSize(op); VectorSize oz = sz; ReadVector(reinterpret_cast(s), sz, vs); - ApplySwizzleS(reinterpret_cast(s), sz); + ApplySwizzleS(mips, reinterpret_cast(s), sz); // TODO: Similar to colorconv, invalid swizzle seems to reuse last output. switch ((op >> 16) & 3) { @@ -1009,13 +1010,13 @@ namespace MIPSInt } // Saturation does in fact apply. - ApplyPrefixD(reinterpret_cast(d),oz); + ApplyPrefixD(mips, reinterpret_cast(d),oz); WriteVector(reinterpret_cast(d), oz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vi2x(MIPSOpcode op) { + void Int_Vi2x(MIPSState *mips, MIPSOpcode op) { int s[4]{}; u32 d[2]{}; const int vd = _VD; @@ -1024,7 +1025,7 @@ namespace MIPSInt VectorSize oz; ReadVector(reinterpret_cast(s), sz, vs); // Negate, const, etc. apply as expected. - ApplySwizzleS(reinterpret_cast(s), V_Quad); + ApplySwizzleS(mips, reinterpret_cast(s), V_Quad); // TODO: Similar to colorconv, invalid swizzle seems to reuse last output. switch ((op >> 16) & 3) { @@ -1098,13 +1099,13 @@ namespace MIPSInt break; } // D prefix applies as expected. - ApplyPrefixD(reinterpret_cast(d), oz); + ApplyPrefixD(mips, reinterpret_cast(d), oz); WriteVector(reinterpret_cast(d), oz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_ColorConv(MIPSOpcode op) + void Int_ColorConv(MIPSState *mips, MIPSOpcode op) { int vd = _VD; int vs = _VS; @@ -1112,7 +1113,7 @@ namespace MIPSInt VectorSize isz = GetVecSize(op); VectorSize sz = V_Quad; ReadVector(reinterpret_cast(s), sz, vs); - ApplySwizzleS(reinterpret_cast(s), sz); + ApplySwizzleS(mips, reinterpret_cast(s), sz); u16 colors[4]; // TODO: Invalid swizzle values almost seem to use the last value converted in a // previous execution of these ops. It's a bit odd. @@ -1152,13 +1153,13 @@ namespace MIPSInt colors[i] = col; } u32 ov[2] = {(u32)colors[0] | (colors[1] << 16), (u32)colors[2] | (colors[3] << 16)}; - ApplyPrefixD(reinterpret_cast(ov), V_Pair); + ApplyPrefixD(mips, reinterpret_cast(ov), V_Pair); WriteVector((const float *)ov, isz == V_Single ? V_Single : V_Pair, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_VDot(MIPSOpcode op) { + void Int_VDot(MIPSState *mips, MIPSOpcode op) { float s[4]{}, t[4]{}; union { float f; uint32_t u; } d; int vd = _VD; @@ -1166,9 +1167,9 @@ namespace MIPSInt int vt = _VT; VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); - ApplySwizzleS(s, V_Quad); + ApplySwizzleS(mips, s, V_Quad); ReadVector(t, sz, vt); - ApplySwizzleT(t, V_Quad); + ApplySwizzleT(mips, t, V_Quad); if (USE_VFPU_DOT) { d.f = vfpu_dot(s, t); @@ -1184,13 +1185,13 @@ namespace MIPSInt } } - ApplyPrefixD(&d.f, V_Single); + ApplyPrefixD(mips, &d.f, V_Single); WriteVector(&d.f, V_Single, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_VHdp(MIPSOpcode op) { + void Int_VHdp(MIPSState *mips, MIPSOpcode op) { float s[4]{}, t[4]{}; float d; int vd = _VD; @@ -1199,7 +1200,7 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); ReadVector(t, sz, vt); - ApplySwizzleT(t, V_Quad); + ApplySwizzleT(mips, t, V_Quad); // S prefix forces constant 1 for the last element (w for quad.) // Otherwise it is the same as vdot. @@ -1218,7 +1219,7 @@ namespace MIPSInt sprefixRemove = VFPU_SWIZZLE(3, 0, 0, 0); sprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::ONE, VFPUConst::NONE, VFPUConst::NONE, VFPUConst::NONE); } - ApplyPrefixST(s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Quad); + ApplyPrefixST(mips, s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Quad); float sum = 0.0f; if (USE_VFPU_DOT) { @@ -1229,13 +1230,13 @@ namespace MIPSInt } } d = my_isnan(sum) ? fabsf(sum) : sum; - ApplyPrefixD(&d, V_Single); + ApplyPrefixD(mips, &d, V_Single); WriteVector(&d, V_Single, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vbfy(MIPSOpcode op) { + void Int_Vbfy(MIPSState *mips, MIPSOpcode op) { float s[4]{}, t[4]{}, d[4]; int vd = _VD; int vs = _VS; @@ -1247,13 +1248,13 @@ namespace MIPSInt // vbfy2 // S prefix forces the negate flags (so z and w are negative.) u32 sprefixAdd = VFPU_NEGATE(0, 0, 1, 1); - ApplyPrefixST(s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, 0, sprefixAdd), sz); + ApplyPrefixST(mips, s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, 0, sprefixAdd), sz); // T prefix forces swizzle (zwxy.) // That means negate still works, but constants are a bit weird. u32 tprefixRemove = VFPU_ANY_SWIZZLE(); u32 tprefixAdd = VFPU_SWIZZLE(2, 3, 0, 1); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); // Other sizes don't seem completely predictable. if (sz != V_Quad) { @@ -1263,13 +1264,13 @@ namespace MIPSInt // vbfy1 // S prefix forces the negate flags (so y and w are negative.) u32 sprefixAdd = VFPU_NEGATE(0, 1, 0, 1); - ApplyPrefixST(s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, 0, sprefixAdd), sz); + ApplyPrefixST(mips, s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, 0, sprefixAdd), sz); // T prefix forces swizzle (yxwz.) // That means negate still works, but constants are a bit weird. u32 tprefixRemove = VFPU_ANY_SWIZZLE(); u32 tprefixAdd = VFPU_SWIZZLE(1, 0, 3, 2); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); if (sz != V_Quad && sz != V_Pair) { ERROR_LOG_REPORT_ONCE(vbfy2, Log::CPU, "vfby1 with incorrect size"); @@ -1281,117 +1282,117 @@ namespace MIPSInt d[2] = s[2] + t[2]; d[3] = s[3] + t[3]; - ApplyPrefixD(d, sz); + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vsrt1(MIPSOpcode op) { + void Int_Vsrt1(MIPSState *mips, MIPSOpcode op) { float s[4], t[4], d[4]; int vd = _VD; int vs = _VS; VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); - ApplySwizzleS(s, sz); + ApplySwizzleS(mips, s, sz); ReadVector(t, sz, vs); // T is force swizzled to yxwz from S. u32 tprefixRemove = VFPU_SWIZZLE(3, 3, 3, 3); u32 tprefixAdd = VFPU_SWIZZLE(1, 0, 3, 2); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); // TODO: May mishandle NAN / negative zero / etc. d[0] = std::min(s[0], t[0]); d[1] = std::max(s[1], t[1]); d[2] = std::min(s[2], t[2]); d[3] = std::max(s[3], t[3]); - RetainInvalidSwizzleST(d, sz); - ApplyPrefixD(d, sz); + RetainInvalidSwizzleST(mips, d, sz); + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vsrt2(MIPSOpcode op) { + void Int_Vsrt2(MIPSState *mips, MIPSOpcode op) { float s[4], t[4], d[4]; int vd = _VD; int vs = _VS; VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); - ApplySwizzleS(s, sz); + ApplySwizzleS(mips, s, sz); ReadVector(t, sz, vs); // T is force swizzled to wzyx from S. u32 tprefixRemove = VFPU_SWIZZLE(3, 3, 3, 3); u32 tprefixAdd = VFPU_SWIZZLE(3, 2, 1, 0); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); // TODO: May mishandle NAN / negative zero / etc. d[0] = std::min(s[0], t[0]); d[1] = std::min(s[1], t[1]); d[2] = std::max(s[2], t[2]); d[3] = std::max(s[3], t[3]); - RetainInvalidSwizzleST(d, sz); - ApplyPrefixD(d, sz); + RetainInvalidSwizzleST(mips, d, sz); + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vsrt3(MIPSOpcode op) { + void Int_Vsrt3(MIPSState *mips, MIPSOpcode op) { float s[4], t[4], d[4]; int vd = _VD; int vs = _VS; VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); - ApplySwizzleS(s, sz); + ApplySwizzleS(mips, s, sz); ReadVector(t, sz, vs); // T is force swizzled to yxwz from S. u32 tprefixRemove = VFPU_SWIZZLE(3, 3, 3, 3); u32 tprefixAdd = VFPU_SWIZZLE(1, 0, 3, 2); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); // TODO: May mishandle NAN / negative zero / etc. d[0] = std::max(s[0], t[0]); d[1] = std::min(s[1], t[1]); d[2] = std::max(s[2], t[2]); d[3] = std::min(s[3], t[3]); - RetainInvalidSwizzleST(d, sz); - ApplyPrefixD(d, sz); + RetainInvalidSwizzleST(mips, d, sz); + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vsrt4(MIPSOpcode op) { + void Int_Vsrt4(MIPSState *mips, MIPSOpcode op) { float s[4], t[4], d[4]; int vd = _VD; int vs = _VS; VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); - ApplySwizzleS(s, sz); + ApplySwizzleS(mips, s, sz); ReadVector(t, sz, vs); // T is force swizzled to wzyx from S. u32 tprefixRemove = VFPU_SWIZZLE(3, 3, 3, 3); u32 tprefixAdd = VFPU_SWIZZLE(3, 2, 1, 0); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); // TODO: May mishandle NAN / negative zero / etc. d[0] = std::max(s[0], t[0]); d[1] = std::max(s[1], t[1]); d[2] = std::min(s[2], t[2]); d[3] = std::min(s[3], t[3]); - RetainInvalidSwizzleST(d, sz); - ApplyPrefixD(d, sz); + RetainInvalidSwizzleST(mips, d, sz); + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vcrs(MIPSOpcode op) { + void Int_Vcrs(MIPSState *mips, MIPSOpcode op) { //half a cross product float s[4]{}, t[4]{}, d[4]; int vd = _VD; @@ -1405,24 +1406,24 @@ namespace MIPSInt // That means negate still works, but constants are a bit weird. u32 sprefixRemove = VFPU_SWIZZLE(3, 3, 3, 0); u32 sprefixAdd = VFPU_SWIZZLE(1, 2, 0, 0); - ApplyPrefixST(s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), sz); + ApplyPrefixST(mips, s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), sz); // T prefix forces swizzle (zxy?.) u32 tprefixRemove = VFPU_SWIZZLE(3, 3, 3, 0); u32 tprefixAdd = VFPU_SWIZZLE(2, 0, 1, 0); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), sz); d[0] = s[0] * t[0]; d[1] = s[1] * t[1]; d[2] = s[2] * t[2]; d[3] = s[3] * t[3]; - ApplyPrefixD(d, sz); + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vdet(MIPSOpcode op) { + void Int_Vdet(MIPSState *mips, MIPSOpcode op) { float s[4]{}, t[4]{}, d[4]; int vd = _VD; int vs = _VS; @@ -1430,7 +1431,7 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); // This is normally V_Pair. Unfilled s/t values are treated as zero. ReadVector(s, sz, vs); - ApplySwizzleS(s, V_Quad); + ApplySwizzleS(mips, s, V_Quad); ReadVector(t, sz, vt); // T prefix forces swizzle for x and y (yx??.) @@ -1438,7 +1439,7 @@ namespace MIPSInt // Note: there is no forced negation here. u32 tprefixRemove = VFPU_SWIZZLE(3, 3, 0, 0); u32 tprefixAdd = VFPU_SWIZZLE(1, 0, 0, 0); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); if (USE_VFPU_DOT) { s[1] = -s[1]; @@ -1448,25 +1449,25 @@ namespace MIPSInt d[0] += s[2] * t[2] + s[3] * t[3]; } - ApplyPrefixD(d, V_Single); + ApplyPrefixD(mips, d, V_Single); WriteVector(d, V_Single, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vfad(MIPSOpcode op) { + void Int_Vfad(MIPSState *mips, MIPSOpcode op) { float s[4]{}, t[4]{}; float d; int vd = _VD; int vs = _VS; VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); - ApplySwizzleS(s, V_Quad); + ApplySwizzleS(mips, s, V_Quad); // T prefix generates constants, but abs can change the constant. u32 tprefixRemove = VFPU_ANY_SWIZZLE(); u32 tprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::ONE, VFPUConst::ONE, VFPUConst::ONE, VFPUConst::ONE); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); if (USE_VFPU_DOT) { d = vfpu_dot(s, t); @@ -1476,20 +1477,20 @@ namespace MIPSInt d += s[i] * t[i]; } } - ApplyPrefixD(&d, V_Single); + ApplyPrefixD(mips, &d, V_Single); WriteVector(&d, V_Single, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vavg(MIPSOpcode op) { + void Int_Vavg(MIPSState *mips, MIPSOpcode op) { float s[4]{}, t[4]{}; float d; int vd = _VD; int vs = _VS; VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); - ApplySwizzleS(s, V_Quad); + ApplySwizzleS(mips, s, V_Quad); // T prefix generates constants, but supports negate. u32 tprefixRemove = VFPU_ANY_SWIZZLE() | VFPU_ABS(1, 1, 1, 1); @@ -1504,7 +1505,7 @@ namespace MIPSInt tprefixAdd = VFPU_MAKE_CONSTANTS(VFPUConst::FOURTH, VFPUConst::FOURTH, VFPUConst::FOURTH, VFPUConst::FOURTH); else tprefixAdd = 0; - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); if (USE_VFPU_DOT) { d = vfpu_dot(s, t); @@ -1514,20 +1515,20 @@ namespace MIPSInt d += s[i] * t[i]; } } - ApplyPrefixD(&d, V_Single); + ApplyPrefixD(mips, &d, V_Single); WriteVector(&d, V_Single, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_VScl(MIPSOpcode op) { + void Int_VScl(MIPSState *mips, MIPSOpcode op) { float s[4], t[4], d[4]; int vd = _VD; int vs = _VS; int vt = _VT; VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); - ApplySwizzleS(s, sz); + ApplySwizzleS(mips, s, sz); // T prefix forces swizzle (zzzz for some reason, so we force V_Quad.) // That means negate still works, but constants are a bit weird. @@ -1535,29 +1536,29 @@ namespace MIPSInt t[tlane] = V(vt); u32 tprefixRemove = VFPU_ANY_SWIZZLE(); u32 tprefixAdd = VFPU_SWIZZLE(tlane, tlane, tlane, tlane); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); int n = GetNumVectorElements(sz); for (int i = 0; i < n; i++) { d[i] = s[i] * t[i]; } - ApplyPrefixD(d, sz); + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vrnds(MIPSOpcode op) { + void Int_Vrnds(MIPSState *mips, MIPSOpcode op) { int vd = _VD; int seed = VI(vd); // Swizzles apply a constant value, constants/abs/neg work to vary the seed. - ApplySwizzleS(reinterpret_cast(&seed), V_Single); - vrnd_init(uint32_t(seed), currentMIPS->vfpuCtrl + VFPU_CTRL_RCX0); + ApplySwizzleS(mips, reinterpret_cast(&seed), V_Single); + vrnd_init(uint32_t(seed), mips->vfpuCtrl + VFPU_CTRL_RCX0); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_VrndX(MIPSOpcode op) { + void Int_VrndX(MIPSState *mips, MIPSOpcode op) { FloatBits d; int vd = _VD; VectorSize sz = GetVecSize(op); @@ -1565,24 +1566,24 @@ namespace MIPSInt // Values are written in backwards order. for (int i = n - 1; i >= 0; i--) { switch ((op >> 16) & 0x1f) { - case 1: d.u[i] = vrnd_generate(currentMIPS->vfpuCtrl + VFPU_CTRL_RCX0); break; // vrndi - case 2: d.u[i] = 0x3F800000 | (vrnd_generate(currentMIPS->vfpuCtrl + VFPU_CTRL_RCX0) & 0x007FFFFF); break; // vrndf1 (>= 1, < 2) - case 3: d.u[i] = 0x40000000 | (vrnd_generate(currentMIPS->vfpuCtrl + VFPU_CTRL_RCX0) & 0x007FFFFF); break; // vrndf2 (>= 2, < 4) + case 1: d.u[i] = vrnd_generate(mips->vfpuCtrl + VFPU_CTRL_RCX0); break; // vrndi + case 2: d.u[i] = 0x3F800000 | (vrnd_generate(mips->vfpuCtrl + VFPU_CTRL_RCX0) & 0x007FFFFF); break; // vrndf1 (>= 1, < 2) + case 3: d.u[i] = 0x40000000 | (vrnd_generate(mips->vfpuCtrl + VFPU_CTRL_RCX0) & 0x007FFFFF); break; // vrndf2 (>= 2, < 4) default: _dbg_assert_msg_(false,"Trying to interpret instruction that can't be interpreted"); } } // D prefix is broken and applies to the last element only (mask and sat.) - u32 lastmask = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & (1 << 8)) << (n - 1); - u32 lastsat = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (n + n - 2); - currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] = lastmask | lastsat; - ApplyPrefixD(d.f, sz); + u32 lastmask = (mips->vfpuCtrl[VFPU_CTRL_DPREFIX] & (1 << 8)) << (n - 1); + u32 lastsat = (mips->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (n + n - 2); + mips->vfpuCtrl[VFPU_CTRL_DPREFIX] = lastmask | lastsat; + ApplyPrefixD(mips, d.f, sz); WriteVector(d.f, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } // Generates one line of a rotation matrix around one of the three axes - void Int_Vrot(MIPSOpcode op) { + void Int_Vrot(MIPSState *mips, MIPSOpcode op) { float d[4]{}; int vd = _VD; int vs = _VS; @@ -1593,7 +1594,7 @@ namespace MIPSInt int cosineLane = imm & 3; float sine, cosine; - if (currentMIPS->vfpuCtrl[VFPU_CTRL_SPREFIX] == 0x000E4) { + if (mips->vfpuCtrl[VFPU_CTRL_SPREFIX] == 0x000E4) { vfpu_sincos(V(vs), sine, cosine); if (negSin) sine = -sine; @@ -1604,7 +1605,7 @@ namespace MIPSInt u32 sprefixRemove = VFPU_NEGATE(1, 0, 0, 0); // We apply negSin later, not here. This handles zero a bit better. u32 sprefixAdd = VFPU_NEGATE(0, 0, 0, 0); - ApplyPrefixST(s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Single); + ApplyPrefixST(mips, s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Single); // Cosine ignores all prefixes, so take the original. cosine = vfpu_cos(V(vs)); @@ -1612,7 +1613,7 @@ namespace MIPSInt if (negSin) sine = -sine; - RetainInvalidSwizzleST(&sine, V_Single); + RetainInvalidSwizzleST(mips, &sine, V_Single); } if (sineLane == cosineLane) { @@ -1642,14 +1643,14 @@ namespace MIPSInt // D prefix works, just not for the cosine lane. uint32_t dprefixRemove = (3 << cosineLane) | (1 << (8 + cosineLane)); - currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] &= 0xFFFFF ^ dprefixRemove; - ApplyPrefixD(d, sz); + mips->vfpuCtrl[VFPU_CTRL_DPREFIX] &= 0xFFFFF ^ dprefixRemove; + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vtfm(MIPSOpcode op) { + void Int_Vtfm(MIPSState *mips, MIPSOpcode op) { float s[16]{}, t[4]{}; FloatBits d; int vd = _VD; @@ -1700,7 +1701,7 @@ namespace MIPSInt // S and T prefixes apply for the final row only. // The T prefix is used to apply zero/one constants, but abs still changes it. - ApplySwizzleS(&s[ins * 4], V_Quad); + ApplySwizzleS(mips, &s[ins * 4], V_Quad); VFPUConst constX = VFPUConst::NONE; VFPUConst constY = n < 2 ? VFPUConst::ZERO : VFPUConst::NONE; VFPUConst constZ = n < 3 ? VFPUConst::ZERO : VFPUConst::NONE; @@ -1716,7 +1717,7 @@ namespace MIPSInt } u32 tprefixRemove = VFPU_SWIZZLE(0, n < 2 ? 3 : 0, n < 3 ? 3 : 0, n < 4 ? 3 : 0); u32 tprefixAdd = VFPU_MAKE_CONSTANTS(constX, constY, constZ, constW); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); // Really this is the operation all rows probably use (with constant wiring.) if (USE_VFPU_DOT) { @@ -1735,16 +1736,16 @@ namespace MIPSInt } // D prefix applies to the last element only. - u32 lastmask = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & (1 << 8)) << ins; - u32 lastsat = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (ins + ins); - currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] = lastmask | lastsat; - ApplyPrefixD(d.f, sz); + u32 lastmask = (mips->vfpuCtrl[VFPU_CTRL_DPREFIX] & (1 << 8)) << ins; + u32 lastsat = (mips->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (ins + ins); + mips->vfpuCtrl[VFPU_CTRL_DPREFIX] = lastmask | lastsat; + ApplyPrefixD(mips, d.f, sz); WriteVector(d.f, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_SV(MIPSOpcode op) + void Int_SV(MIPSState *mips, MIPSOpcode op) { s32 imm = SignExtend16ToS32(op & 0xFFFC); int vt = ((op >> 16) & 0x1f) | ((op & 3) << 5); @@ -1775,7 +1776,7 @@ namespace MIPSInt } - void Int_Mftv(MIPSOpcode op) + void Int_Mftv(MIPSState *mips, MIPSOpcode op) { int imm = op & 0xFF; int rt = _RT; @@ -1787,7 +1788,7 @@ namespace MIPSInt if (imm < 128) { R(rt) = VI(imm); } else if (imm < 128 + VFPU_CTRL_MAX) { //mfvc - R(rt) = currentMIPS->vfpuCtrl[imm - 128]; + R(rt) = mips->vfpuCtrl[imm - 128]; } else { //ERROR - maybe need to make this value too an "interlock" value? _dbg_assert_msg_(false,"mfv - invalid register"); @@ -1801,7 +1802,7 @@ namespace MIPSInt } else if (imm < 128 + VFPU_CTRL_MAX) { //mtvc u32 mask; if (GetVFPUCtrlMask(imm - 128, &mask)) { - currentMIPS->vfpuCtrl[imm - 128] = R(rt) & mask; + mips->vfpuCtrl[imm - 128] = R(rt) & mask; } } else { //ERROR @@ -1816,30 +1817,30 @@ namespace MIPSInt PC += 4; } - void Int_Vmfvc(MIPSOpcode op) { + void Int_Vmfvc(MIPSState *mips, MIPSOpcode op) { int vd = _VD; int imm = (op >> 8) & 0x7F; if (imm < VFPU_CTRL_MAX) { - VI(vd) = currentMIPS->vfpuCtrl[imm]; + VI(vd) = mips->vfpuCtrl[imm]; } else { VI(vd) = 0; } PC += 4; } - void Int_Vmtvc(MIPSOpcode op) { + void Int_Vmtvc(MIPSState *mips, MIPSOpcode op) { int vs = _VS; int imm = op & 0x7F; if (imm < VFPU_CTRL_MAX) { u32 mask; if (GetVFPUCtrlMask(imm, &mask)) { - currentMIPS->vfpuCtrl[imm] = VI(vs) & mask; + mips->vfpuCtrl[imm] = VI(vs) & mask; } } PC += 4; } - void Int_Vcst(MIPSOpcode op) + void Int_Vcst(MIPSState *mips, MIPSOpcode op) { int conNum = (op >> 16) & 0x1f; int vd = _VD; @@ -1847,13 +1848,13 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); float c = cst_constants[conNum]; float temp[4] = {c,c,c,c}; - ApplyPrefixD(temp, sz); + ApplyPrefixD(mips, temp, sz); WriteVector(temp, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vcmp(MIPSOpcode op) + void Int_Vcmp(MIPSState *mips, MIPSOpcode op) { int vs = _VS; int vt = _VT; @@ -1863,9 +1864,9 @@ namespace MIPSInt float s[4]; float t[4]; ReadVector(s, sz, vs); - ApplySwizzleS(s, sz); + ApplySwizzleS(mips, s, sz); ReadVector(t, sz, vt); - ApplySwizzleT(t, sz); + ApplySwizzleT(mips, t, sz); int cc = 0; int or_val = 0; int and_val = 1; @@ -1899,7 +1900,7 @@ namespace MIPSInt default: _dbg_assert_msg_(false,"Unsupported vcmp condition code %d", cond); PC += 4; - EatPrefixes(); + EatPrefixes(mips); return; } cc |= (c<vfpuCtrl[VFPU_CTRL_CC] = - (currentMIPS->vfpuCtrl[VFPU_CTRL_CC] & ~affected_bits) | + mips->vfpuCtrl[VFPU_CTRL_CC] = + (mips->vfpuCtrl[VFPU_CTRL_CC] & ~affected_bits) | ((cc | (or_val << 4) | (and_val << 5)) & affected_bits); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vminmax(MIPSOpcode op) { + void Int_Vminmax(MIPSState *mips, MIPSOpcode op) { FloatBits s, t, d; int vt = _VT; int vs = _VS; @@ -1925,9 +1926,9 @@ namespace MIPSInt int numElements = GetNumVectorElements(sz); ReadVector(s.f, sz, vs); - ApplySwizzleS(s.f, sz); + ApplySwizzleS(mips, s.f, sz); ReadVector(t.f, sz, vt); - ApplySwizzleT(t.f, sz); + ApplySwizzleT(mips, t.f, sz); // If both are zero, take t's sign. // Otherwise: -NAN < -INF < real < INF < NAN (higher mantissa is farther from 0.) @@ -1966,26 +1967,26 @@ namespace MIPSInt default: _dbg_assert_msg_(false,"unknown min/max op %d", cond); PC += 4; - EatPrefixes(); + EatPrefixes(mips); return; } - RetainInvalidSwizzleST(d.f, sz); - ApplyPrefixD(d.f, sz); + RetainInvalidSwizzleST(mips, d.f, sz); + ApplyPrefixD(mips, d.f, sz); WriteVector(d.f, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vscmp(MIPSOpcode op) { + void Int_Vscmp(MIPSState *mips, MIPSOpcode op) { FloatBits s, t, d; int vt = _VT; int vs = _VS; int vd = _VD; VectorSize sz = GetVecSize(op); ReadVector(s.f, sz, vs); - ApplySwizzleS(s.f, sz); + ApplySwizzleS(mips, s.f, sz); ReadVector(t.f, sz, vt); - ApplySwizzleT(t.f, sz); + ApplySwizzleT(mips, t.f, sz); int n = GetNumVectorElements(sz); for (int i = 0; i < n ; i++) { float a = s.f[i] - t.f[i]; @@ -1999,14 +2000,14 @@ namespace MIPSInt d.f[i] = (float)((0.0f < a) - (a < 0.0f)); } } - RetainInvalidSwizzleST(d.f, sz); - ApplyPrefixD(d.f, sz); + RetainInvalidSwizzleST(mips, d.f, sz); + ApplyPrefixD(mips, d.f, sz); WriteVector(d.f, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vsge(MIPSOpcode op) { + void Int_Vsge(MIPSState *mips, MIPSOpcode op) { float s[4], t[4], d[4]; int vt = _VT; int vs = _VS; @@ -2014,24 +2015,24 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); int numElements = GetNumVectorElements(sz); ReadVector(s, sz, vs); - ApplySwizzleS(s, sz); + ApplySwizzleS(mips, s, sz); ReadVector(t, sz, vt); - ApplySwizzleT(t, sz); + ApplySwizzleT(mips, t, sz); for (int i = 0; i < numElements; i++) { if ( my_isnan(s[i]) || my_isnan(t[i]) ) d[i] = 0.0f; else d[i] = s[i] >= t[i] ? 1.0f : 0.0f; } - RetainInvalidSwizzleST(d, sz); + RetainInvalidSwizzleST(mips, d, sz); // The clamp cannot matter, so skip it. - ApplyPrefixD(d, sz, true); + ApplyPrefixD(mips, d, sz, true); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vslt(MIPSOpcode op) { + void Int_Vslt(MIPSState *mips, MIPSOpcode op) { float s[4], t[4], d[4]; int vt = _VT; int vs = _VS; @@ -2039,25 +2040,25 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); int numElements = GetNumVectorElements(sz); ReadVector(s, sz, vs); - ApplySwizzleS(s, sz); + ApplySwizzleS(mips, s, sz); ReadVector(t, sz, vt); - ApplySwizzleT(t, sz); + ApplySwizzleT(mips, t, sz); for (int i = 0; i < numElements; i++) { if ( my_isnan(s[i]) || my_isnan(t[i]) ) d[i] = 0.0f; else d[i] = s[i] < t[i] ? 1.0f : 0.0f; } - RetainInvalidSwizzleST(d, sz); + RetainInvalidSwizzleST(mips, d, sz); // The clamp cannot matter, so skip it. - ApplyPrefixD(d, sz, true); + ApplyPrefixD(mips, d, sz, true); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vcmov(MIPSOpcode op) { + void Int_Vcmov(MIPSState *mips, MIPSOpcode op) { int vs = _VS; int vd = _VD; int tf = (op >> 19) & 1; @@ -2067,12 +2068,12 @@ namespace MIPSInt float s[4]; float d[4]; ReadVector(s, sz, vs); - ApplySwizzleS(s, sz); + ApplySwizzleS(mips, s, sz); // Not only is D read (as T), but the T prefix applies to it. ReadVector(d, sz, vd); - ApplySwizzleT(d, sz); + ApplySwizzleT(mips, d, sz); - int CC = currentMIPS->vfpuCtrl[VFPU_CTRL_CC]; + int CC = mips->vfpuCtrl[VFPU_CTRL_CC]; if (imm3 < 6) { if (((CC >> imm3) & 1) == !tf) { @@ -2087,13 +2088,13 @@ namespace MIPSInt } else { ERROR_LOG_REPORT(Log::CPU, "Bad Imm3 in cmov: %d", imm3); } - ApplyPrefixD(d, sz); + ApplyPrefixD(mips, d, sz); WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_VecDo3(MIPSOpcode op) { + void Int_VecDo3(MIPSState *mips, MIPSOpcode op) { float s[4], t[4]; FloatBits d; int vd = _VD; @@ -2127,14 +2128,14 @@ namespace MIPSInt ReadVector(s, sz, vs); ReadVector(t, sz, vt); if (optype != 7) { - ApplySwizzleS(s, sz); - ApplySwizzleT(t, sz); + ApplySwizzleS(mips, s, sz); + ApplySwizzleT(mips, t, sz); } else { // The prefix handling of S/T is a bit odd, probably the HW doesn't do it in parallel. // The X prefix is applied to the last element in sz. // TODO: This doesn't match exactly for a swizzle past x in some cases... - ApplySwizzleS(&s[n - 1], V_Single, -INFINITY); - ApplySwizzleT(&t[n - 1], V_Single, -INFINITY); + ApplySwizzleS(mips, &s[n - 1], V_Single, -INFINITY); + ApplySwizzleT(mips, &t[n - 1], V_Single, -INFINITY); } for (int i = 0; i < (int)n; i++) { @@ -2156,20 +2157,20 @@ namespace MIPSInt // For vdiv only, the D prefix only applies mask (and like S/T, x applied to last.) if (optype == 7) { - u32 lastmask = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & (1 << 8)) << (n - 1); - u32 lastsat = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (n + n - 2); - currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] = lastmask | lastsat; - ApplyPrefixD(d.f, sz); + u32 lastmask = (mips->vfpuCtrl[VFPU_CTRL_DPREFIX] & (1 << 8)) << (n - 1); + u32 lastsat = (mips->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (n + n - 2); + mips->vfpuCtrl[VFPU_CTRL_DPREFIX] = lastmask | lastsat; + ApplyPrefixD(mips, d.f, sz); } else { - RetainInvalidSwizzleST(d.f, sz); - ApplyPrefixD(d.f, sz); + RetainInvalidSwizzleST(mips, d.f, sz); + ApplyPrefixD(mips, d.f, sz); } WriteVector(d.f, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_CrossQuat(MIPSOpcode op) { + void Int_CrossQuat(MIPSState *mips, MIPSOpcode op) { float s[4]{}, t[4]{}, d[4]; int vd = _VD; int vs = _VS; @@ -2197,8 +2198,8 @@ namespace MIPSInt // T prefix forces swizzle and negate, can be used to have weird constants. tprefixAdd = VFPU_SWIZZLE(1, 0, 3, 2) | VFPU_NEGATE(0, 1, 0, 0); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); - ApplySwizzleS(s, V_Quad); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); + ApplySwizzleS(mips, s, V_Quad); if (USE_VFPU_DOT) { // TODO: But flush any infs to 0? This seems sketchy. for (int i = 0; i < 4; ++i) { @@ -2231,8 +2232,8 @@ namespace MIPSInt // T prefix forces swizzle and negate, can be used to have weird constants. tprefixAdd = VFPU_SWIZZLE(0, 1, 2, 3) | VFPU_NEGATE(1, 1, 1, 0); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); - ApplySwizzleS(s, sz); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); + ApplySwizzleS(mips, s, sz); if (USE_VFPU_DOT) d[3] = vfpu_dot(s, t); else @@ -2245,8 +2246,8 @@ namespace MIPSInt d[0] = 0; tprefixAdd = VFPU_SWIZZLE(0, 0, 0, 0) | VFPU_NEGATE(0, 0, 0, 0); - ApplyPrefixST(t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); - ApplySwizzleS(s, V_Quad); + ApplyPrefixST(mips, t, VFPURewritePrefix(VFPU_CTRL_TPREFIX, tprefixRemove, tprefixAdd), V_Quad); + ApplySwizzleS(mips, s, V_Quad); // It's possible to populate a value by swizzling s[2]. d[1] = s[2] * t[2]; break; @@ -2263,20 +2264,20 @@ namespace MIPSInt // D prefix applies to the last element only (mask and sat) for pair and larger. if (sz != V_Single) { - u32 lastmask = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & (1 << 8)) << (n - 1); - u32 lastsat = (currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (n + n - 2); - currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] = lastmask | lastsat; - ApplyPrefixD(d, sz); + u32 lastmask = (mips->vfpuCtrl[VFPU_CTRL_DPREFIX] & (1 << 8)) << (n - 1); + u32 lastsat = (mips->vfpuCtrl[VFPU_CTRL_DPREFIX] & 3) << (n + n - 2); + mips->vfpuCtrl[VFPU_CTRL_DPREFIX] = lastmask | lastsat; + ApplyPrefixD(mips, d, sz); } else { // Single always seems to write out zero. - currentMIPS->vfpuCtrl[VFPU_CTRL_DPREFIX] = 0; + mips->vfpuCtrl[VFPU_CTRL_DPREFIX] = 0; } WriteVector(d, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vlgb(MIPSOpcode op) { + void Int_Vlgb(MIPSState *mips, MIPSOpcode op) { // Vector log binary (extract exponent) FloatBits d, s; int vd = _VD; @@ -2284,7 +2285,7 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); ReadVector(s.f, sz, vs); - ApplySwizzleS(s.f, sz); + ApplySwizzleS(mips, s.f, sz); int exp = (s.u[0] & 0x7F800000) >> 23; if (exp == 0xFF) { @@ -2300,14 +2301,14 @@ namespace MIPSInt d.u[i] = s.u[i]; } - RetainInvalidSwizzleST(d.f, sz); - ApplyPrefixD(d.f, sz); + RetainInvalidSwizzleST(mips, d.f, sz); + ApplyPrefixD(mips, d.f, sz); WriteVector(d.f, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vwbn(MIPSOpcode op) { + void Int_Vwbn(MIPSState *mips, MIPSOpcode op) { FloatBits d, s; int vd = _VD; int vs = _VS; @@ -2315,7 +2316,7 @@ namespace MIPSInt u8 exp = (u8)((op >> 16) & 0xFF); ReadVector(s.f, sz, vs); - ApplySwizzleS(s.f, sz); + ApplySwizzleS(mips, s.f, sz); u32 sigbit = s.u[0] & 0x80000000; u32 prevExp = (s.u[0] & 0x7F800000) >> 23; @@ -2338,14 +2339,14 @@ namespace MIPSInt d.u[i] = s.u[i]; } - RetainInvalidSwizzleST(d.f, sz); - ApplyPrefixD(d.f, sz); + RetainInvalidSwizzleST(mips, d.f, sz); + ApplyPrefixD(mips, d.f, sz); WriteVector(d.f, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vsbn(MIPSOpcode op) { + void Int_Vsbn(MIPSState *mips, MIPSOpcode op) { FloatBits d, s, t; int vd = _VD; int vs = _VS; @@ -2353,9 +2354,9 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); ReadVector(s.f, sz, vs); - ApplySwizzleS(s.f, sz); + ApplySwizzleS(mips, s.f, sz); ReadVector(t.f, sz, vt); - ApplySwizzleT(t.f, sz); + ApplySwizzleT(mips, t.f, sz); // Swizzle does apply to the value read as an integer. u8 exp = (u8)(127 + t.i[0]); @@ -2372,13 +2373,13 @@ namespace MIPSInt d.u[i] = s.u[i]; } - ApplyPrefixD(d.f, sz); + ApplyPrefixD(mips, d.f, sz); WriteVector(d.f, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } - void Int_Vsbz(MIPSOpcode op) { + void Int_Vsbz(MIPSState *mips, MIPSOpcode op) { // Vector scale by zero (set exp to 0 to extract mantissa) FloatBits d, s; int vd = _VD; @@ -2386,7 +2387,7 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); ReadVector(s.f, sz, vs); - ApplySwizzleS(s.f, sz); + ApplySwizzleS(mips, s.f, sz); // NAN and denormals pass through. if (my_isnan(s.f[0]) || (s.u[0] & 0x7F800000) == 0) { @@ -2400,9 +2401,9 @@ namespace MIPSInt d.u[i] = s.u[i]; } - ApplyPrefixD(d.f, sz); + ApplyPrefixD(mips, d.f, sz); WriteVector(d.f, sz, vd); PC += 4; - EatPrefixes(); + EatPrefixes(mips); } } diff --git a/Core/MIPS/InterpreterVFPU.h b/Core/MIPS/InterpreterVFPU.h index e703a57f7b..57c567ce65 100644 --- a/Core/MIPS/InterpreterVFPU.h +++ b/Core/MIPS/InterpreterVFPU.h @@ -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); } diff --git a/Core/MIPS/LoongArch64/LoongArch64Jit.cpp b/Core/MIPS/LoongArch64/LoongArch64Jit.cpp index cbb5869573..7d7b028645 100644 --- a/Core/MIPS/LoongArch64/LoongArch64Jit.cpp +++ b/Core/MIPS/LoongArch64/LoongArch64Jit.cpp @@ -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(); } diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 45b4e38b33..ddcc8b1192 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -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 diff --git a/Core/MIPS/MIPSTables.h b/Core/MIPS/MIPSTables.h index 33aba3fb0e..2e64ca58db 100644 --- a/Core/MIPS/MIPSTables.h +++ b/Core/MIPS/MIPSTables.h @@ -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(); diff --git a/Core/MIPS/RiscV/RiscVJit.cpp b/Core/MIPS/RiscV/RiscVJit.cpp index 2fd9a34523..87181c989f 100644 --- a/Core/MIPS/RiscV/RiscVJit.cpp +++ b/Core/MIPS/RiscV/RiscVJit.cpp @@ -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(); } diff --git a/Core/MIPS/x86/CompBranch.cpp b/Core/MIPS/x86/CompBranch.cpp index c847c342ed..8db2c28883 100644 --- a/Core/MIPS/x86/CompBranch.cpp +++ b/Core/MIPS/x86/CompBranch.cpp @@ -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) diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 68f4986340..3993b31c1e 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -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. diff --git a/Core/MIPS/x86/X64IRJit.cpp b/Core/MIPS/x86/X64IRJit.cpp index fbfcf9ff9c..c391e97985 100644 --- a/Core/MIPS/x86/X64IRJit.cpp +++ b/Core/MIPS/x86/X64IRJit.cpp @@ -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(); } diff --git a/Tools/update-dispatcher.py b/Tools/update-dispatcher.py index e04d1e6bea..a96ac09fb4 100644 --- a/Tools/update-dispatcher.py +++ b/Tools/update-dispatcher.py @@ -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