Optimize SPU interpreter

Made SPU decoder similar to PPU decoder
This commit is contained in:
Nekotekina 2018-02-27 19:03:00 +03:00
parent 53f8b03acc
commit 445b7c0758
5 changed files with 797 additions and 528 deletions

View file

@ -117,7 +117,7 @@ u32 cellSpursModulePollStatus(SPUThread& spu, u32* status)
void cellSpursModuleExit(SPUThread& spu) void cellSpursModuleExit(SPUThread& spu)
{ {
auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100); auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100);
spu.pc = ctxt->exitToKernelAddr - 4; spu.pc = ctxt->exitToKernelAddr;
throw SpursModuleExit(); throw SpursModuleExit();
} }
@ -659,7 +659,7 @@ void spursKernelDispatchWorkload(SPUThread& spu, u64 widAndPollStatus)
spu.gpr[3]._u32[3] = 0x100; spu.gpr[3]._u32[3] = 0x100;
spu.gpr[4]._u64[1] = wklInfo->arg; spu.gpr[4]._u64[1] = wklInfo->arg;
spu.gpr[5]._u32[3] = pollStatus; spu.gpr[5]._u32[3] = pollStatus;
spu.pc = 0xA00 - 4; spu.pc = 0xA00;
} }
// SPURS kernel workload exit // SPURS kernel workload exit
@ -1404,7 +1404,7 @@ void spursTasksetResumeTask(SPUThread& spu)
spu.gpr[80 + i] = ctxt->savedContextR80ToR127[i]; spu.gpr[80 + i] = ctxt->savedContextR80ToR127[i];
} }
spu.pc = spu.gpr[0]._u32[3] - 4; spu.pc = spu.gpr[0]._u32[3];
} }
// Start a task // Start a task
@ -1422,7 +1422,7 @@ void spursTasksetStartTask(SPUThread& spu, CellSpursTaskArgument& taskArgs)
spu.gpr[i].clear(); spu.gpr[i].clear();
} }
spu.pc = ctxt->savedContextLr.value()._u32[3] - 4; spu.pc = ctxt->savedContextLr.value()._u32[3];
} }
// Process a request and update the state of the taskset // Process a request and update the state of the taskset

View file

@ -340,18 +340,13 @@ void spu_recompiler::InterpreterCall(spu_opcode_t op)
{ {
// TODO: check correctness // TODO: check correctness
const u32 old_pc = _spu->pc;
if (test(_spu->state) && _spu->check_state()) if (test(_spu->state) && _spu->check_state())
{ {
return 0x2000000 | _spu->pc; return 0x2000000 | _spu->pc;
} }
_func(*_spu, { opcode }); if (UNLIKELY(!_func(*_spu, {opcode})))
if (old_pc != _spu->pc)
{ {
_spu->pc += 4;
return 0x2000000 | _spu->pc; return 0x2000000 | _spu->pc;
} }

File diff suppressed because it is too large Load diff

View file

@ -4,258 +4,258 @@
class SPUThread; class SPUThread;
using spu_inter_func_t = void(*)(SPUThread& spu, spu_opcode_t op); using spu_inter_func_t = bool(*)(SPUThread& spu, spu_opcode_t op);
struct spu_interpreter struct spu_interpreter
{ {
static void UNK(SPUThread&, spu_opcode_t); static bool UNK(SPUThread&, spu_opcode_t);
static void set_interrupt_status(SPUThread&, spu_opcode_t); static void set_interrupt_status(SPUThread&, spu_opcode_t);
static void STOP(SPUThread&, spu_opcode_t); static bool STOP(SPUThread&, spu_opcode_t);
static void LNOP(SPUThread&, spu_opcode_t); static bool LNOP(SPUThread&, spu_opcode_t);
static void SYNC(SPUThread&, spu_opcode_t); static bool SYNC(SPUThread&, spu_opcode_t);
static void DSYNC(SPUThread&, spu_opcode_t); static bool DSYNC(SPUThread&, spu_opcode_t);
static void MFSPR(SPUThread&, spu_opcode_t); static bool MFSPR(SPUThread&, spu_opcode_t);
static void RDCH(SPUThread&, spu_opcode_t); static bool RDCH(SPUThread&, spu_opcode_t);
static void RCHCNT(SPUThread&, spu_opcode_t); static bool RCHCNT(SPUThread&, spu_opcode_t);
static void SF(SPUThread&, spu_opcode_t); static bool SF(SPUThread&, spu_opcode_t);
static void OR(SPUThread&, spu_opcode_t); static bool OR(SPUThread&, spu_opcode_t);
static void BG(SPUThread&, spu_opcode_t); static bool BG(SPUThread&, spu_opcode_t);
static void SFH(SPUThread&, spu_opcode_t); static bool SFH(SPUThread&, spu_opcode_t);
static void NOR(SPUThread&, spu_opcode_t); static bool NOR(SPUThread&, spu_opcode_t);
static void ABSDB(SPUThread&, spu_opcode_t); static bool ABSDB(SPUThread&, spu_opcode_t);
static void ROT(SPUThread&, spu_opcode_t); static bool ROT(SPUThread&, spu_opcode_t);
static void ROTM(SPUThread&, spu_opcode_t); static bool ROTM(SPUThread&, spu_opcode_t);
static void ROTMA(SPUThread&, spu_opcode_t); static bool ROTMA(SPUThread&, spu_opcode_t);
static void SHL(SPUThread&, spu_opcode_t); static bool SHL(SPUThread&, spu_opcode_t);
static void ROTH(SPUThread&, spu_opcode_t); static bool ROTH(SPUThread&, spu_opcode_t);
static void ROTHM(SPUThread&, spu_opcode_t); static bool ROTHM(SPUThread&, spu_opcode_t);
static void ROTMAH(SPUThread&, spu_opcode_t); static bool ROTMAH(SPUThread&, spu_opcode_t);
static void SHLH(SPUThread&, spu_opcode_t); static bool SHLH(SPUThread&, spu_opcode_t);
static void ROTI(SPUThread&, spu_opcode_t); static bool ROTI(SPUThread&, spu_opcode_t);
static void ROTMI(SPUThread&, spu_opcode_t); static bool ROTMI(SPUThread&, spu_opcode_t);
static void ROTMAI(SPUThread&, spu_opcode_t); static bool ROTMAI(SPUThread&, spu_opcode_t);
static void SHLI(SPUThread&, spu_opcode_t); static bool SHLI(SPUThread&, spu_opcode_t);
static void ROTHI(SPUThread&, spu_opcode_t); static bool ROTHI(SPUThread&, spu_opcode_t);
static void ROTHMI(SPUThread&, spu_opcode_t); static bool ROTHMI(SPUThread&, spu_opcode_t);
static void ROTMAHI(SPUThread&, spu_opcode_t); static bool ROTMAHI(SPUThread&, spu_opcode_t);
static void SHLHI(SPUThread&, spu_opcode_t); static bool SHLHI(SPUThread&, spu_opcode_t);
static void A(SPUThread&, spu_opcode_t); static bool A(SPUThread&, spu_opcode_t);
static void AND(SPUThread&, spu_opcode_t); static bool AND(SPUThread&, spu_opcode_t);
static void CG(SPUThread&, spu_opcode_t); static bool CG(SPUThread&, spu_opcode_t);
static void AH(SPUThread&, spu_opcode_t); static bool AH(SPUThread&, spu_opcode_t);
static void NAND(SPUThread&, spu_opcode_t); static bool NAND(SPUThread&, spu_opcode_t);
static void AVGB(SPUThread&, spu_opcode_t); static bool AVGB(SPUThread&, spu_opcode_t);
static void MTSPR(SPUThread&, spu_opcode_t); static bool MTSPR(SPUThread&, spu_opcode_t);
static void WRCH(SPUThread&, spu_opcode_t); static bool WRCH(SPUThread&, spu_opcode_t);
static void BIZ(SPUThread&, spu_opcode_t); static bool BIZ(SPUThread&, spu_opcode_t);
static void BINZ(SPUThread&, spu_opcode_t); static bool BINZ(SPUThread&, spu_opcode_t);
static void BIHZ(SPUThread&, spu_opcode_t); static bool BIHZ(SPUThread&, spu_opcode_t);
static void BIHNZ(SPUThread&, spu_opcode_t); static bool BIHNZ(SPUThread&, spu_opcode_t);
static void STOPD(SPUThread&, spu_opcode_t); static bool STOPD(SPUThread&, spu_opcode_t);
static void STQX(SPUThread&, spu_opcode_t); static bool STQX(SPUThread&, spu_opcode_t);
static void BI(SPUThread&, spu_opcode_t); static bool BI(SPUThread&, spu_opcode_t);
static void BISL(SPUThread&, spu_opcode_t); static bool BISL(SPUThread&, spu_opcode_t);
static void IRET(SPUThread&, spu_opcode_t); static bool IRET(SPUThread&, spu_opcode_t);
static void BISLED(SPUThread&, spu_opcode_t); static bool BISLED(SPUThread&, spu_opcode_t);
static void HBR(SPUThread&, spu_opcode_t); static bool HBR(SPUThread&, spu_opcode_t);
static void GB(SPUThread&, spu_opcode_t); static bool GB(SPUThread&, spu_opcode_t);
static void GBH(SPUThread&, spu_opcode_t); static bool GBH(SPUThread&, spu_opcode_t);
static void GBB(SPUThread&, spu_opcode_t); static bool GBB(SPUThread&, spu_opcode_t);
static void FSM(SPUThread&, spu_opcode_t); static bool FSM(SPUThread&, spu_opcode_t);
static void FSMH(SPUThread&, spu_opcode_t); static bool FSMH(SPUThread&, spu_opcode_t);
static void FSMB(SPUThread&, spu_opcode_t); static bool FSMB(SPUThread&, spu_opcode_t);
static void LQX(SPUThread&, spu_opcode_t); static bool LQX(SPUThread&, spu_opcode_t);
static void CBX(SPUThread&, spu_opcode_t); static bool CBX(SPUThread&, spu_opcode_t);
static void CHX(SPUThread&, spu_opcode_t); static bool CHX(SPUThread&, spu_opcode_t);
static void CWX(SPUThread&, spu_opcode_t); static bool CWX(SPUThread&, spu_opcode_t);
static void CDX(SPUThread&, spu_opcode_t); static bool CDX(SPUThread&, spu_opcode_t);
static void ROTQBI(SPUThread&, spu_opcode_t); static bool ROTQBI(SPUThread&, spu_opcode_t);
static void ROTQMBI(SPUThread&, spu_opcode_t); static bool ROTQMBI(SPUThread&, spu_opcode_t);
static void SHLQBI(SPUThread&, spu_opcode_t); static bool SHLQBI(SPUThread&, spu_opcode_t);
static void ORX(SPUThread&, spu_opcode_t); static bool ORX(SPUThread&, spu_opcode_t);
static void CBD(SPUThread&, spu_opcode_t); static bool CBD(SPUThread&, spu_opcode_t);
static void CHD(SPUThread&, spu_opcode_t); static bool CHD(SPUThread&, spu_opcode_t);
static void CWD(SPUThread&, spu_opcode_t); static bool CWD(SPUThread&, spu_opcode_t);
static void CDD(SPUThread&, spu_opcode_t); static bool CDD(SPUThread&, spu_opcode_t);
static void ROTQBII(SPUThread&, spu_opcode_t); static bool ROTQBII(SPUThread&, spu_opcode_t);
static void ROTQMBII(SPUThread&, spu_opcode_t); static bool ROTQMBII(SPUThread&, spu_opcode_t);
static void SHLQBII(SPUThread&, spu_opcode_t); static bool SHLQBII(SPUThread&, spu_opcode_t);
static void NOP(SPUThread&, spu_opcode_t); static bool NOP(SPUThread&, spu_opcode_t);
static void CGT(SPUThread&, spu_opcode_t); static bool CGT(SPUThread&, spu_opcode_t);
static void XOR(SPUThread&, spu_opcode_t); static bool XOR(SPUThread&, spu_opcode_t);
static void CGTH(SPUThread&, spu_opcode_t); static bool CGTH(SPUThread&, spu_opcode_t);
static void EQV(SPUThread&, spu_opcode_t); static bool EQV(SPUThread&, spu_opcode_t);
static void CGTB(SPUThread&, spu_opcode_t); static bool CGTB(SPUThread&, spu_opcode_t);
static void SUMB(SPUThread&, spu_opcode_t); static bool SUMB(SPUThread&, spu_opcode_t);
static void HGT(SPUThread&, spu_opcode_t); static bool HGT(SPUThread&, spu_opcode_t);
static void CLZ(SPUThread&, spu_opcode_t); static bool CLZ(SPUThread&, spu_opcode_t);
static void XSWD(SPUThread&, spu_opcode_t); static bool XSWD(SPUThread&, spu_opcode_t);
static void XSHW(SPUThread&, spu_opcode_t); static bool XSHW(SPUThread&, spu_opcode_t);
static void CNTB(SPUThread&, spu_opcode_t); static bool CNTB(SPUThread&, spu_opcode_t);
static void XSBH(SPUThread&, spu_opcode_t); static bool XSBH(SPUThread&, spu_opcode_t);
static void CLGT(SPUThread&, spu_opcode_t); static bool CLGT(SPUThread&, spu_opcode_t);
static void ANDC(SPUThread&, spu_opcode_t); static bool ANDC(SPUThread&, spu_opcode_t);
static void CLGTH(SPUThread&, spu_opcode_t); static bool CLGTH(SPUThread&, spu_opcode_t);
static void ORC(SPUThread&, spu_opcode_t); static bool ORC(SPUThread&, spu_opcode_t);
static void CLGTB(SPUThread&, spu_opcode_t); static bool CLGTB(SPUThread&, spu_opcode_t);
static void HLGT(SPUThread&, spu_opcode_t); static bool HLGT(SPUThread&, spu_opcode_t);
static void CEQ(SPUThread&, spu_opcode_t); static bool CEQ(SPUThread&, spu_opcode_t);
static void MPYHHU(SPUThread&, spu_opcode_t); static bool MPYHHU(SPUThread&, spu_opcode_t);
static void ADDX(SPUThread&, spu_opcode_t); static bool ADDX(SPUThread&, spu_opcode_t);
static void SFX(SPUThread&, spu_opcode_t); static bool SFX(SPUThread&, spu_opcode_t);
static void CGX(SPUThread&, spu_opcode_t); static bool CGX(SPUThread&, spu_opcode_t);
static void BGX(SPUThread&, spu_opcode_t); static bool BGX(SPUThread&, spu_opcode_t);
static void MPYHHA(SPUThread&, spu_opcode_t); static bool MPYHHA(SPUThread&, spu_opcode_t);
static void MPYHHAU(SPUThread&, spu_opcode_t); static bool MPYHHAU(SPUThread&, spu_opcode_t);
static void MPY(SPUThread&, spu_opcode_t); static bool MPY(SPUThread&, spu_opcode_t);
static void MPYH(SPUThread&, spu_opcode_t); static bool MPYH(SPUThread&, spu_opcode_t);
static void MPYHH(SPUThread&, spu_opcode_t); static bool MPYHH(SPUThread&, spu_opcode_t);
static void MPYS(SPUThread&, spu_opcode_t); static bool MPYS(SPUThread&, spu_opcode_t);
static void CEQH(SPUThread&, spu_opcode_t); static bool CEQH(SPUThread&, spu_opcode_t);
static void MPYU(SPUThread&, spu_opcode_t); static bool MPYU(SPUThread&, spu_opcode_t);
static void CEQB(SPUThread&, spu_opcode_t); static bool CEQB(SPUThread&, spu_opcode_t);
static void HEQ(SPUThread&, spu_opcode_t); static bool HEQ(SPUThread&, spu_opcode_t);
static void BRZ(SPUThread&, spu_opcode_t); static bool BRZ(SPUThread&, spu_opcode_t);
static void STQA(SPUThread&, spu_opcode_t); static bool STQA(SPUThread&, spu_opcode_t);
static void BRNZ(SPUThread&, spu_opcode_t); static bool BRNZ(SPUThread&, spu_opcode_t);
static void BRHZ(SPUThread&, spu_opcode_t); static bool BRHZ(SPUThread&, spu_opcode_t);
static void BRHNZ(SPUThread&, spu_opcode_t); static bool BRHNZ(SPUThread&, spu_opcode_t);
static void STQR(SPUThread&, spu_opcode_t); static bool STQR(SPUThread&, spu_opcode_t);
static void BRA(SPUThread&, spu_opcode_t); static bool BRA(SPUThread&, spu_opcode_t);
static void LQA(SPUThread&, spu_opcode_t); static bool LQA(SPUThread&, spu_opcode_t);
static void BRASL(SPUThread&, spu_opcode_t); static bool BRASL(SPUThread&, spu_opcode_t);
static void BR(SPUThread&, spu_opcode_t); static bool BR(SPUThread&, spu_opcode_t);
static void FSMBI(SPUThread&, spu_opcode_t); static bool FSMBI(SPUThread&, spu_opcode_t);
static void BRSL(SPUThread&, spu_opcode_t); static bool BRSL(SPUThread&, spu_opcode_t);
static void LQR(SPUThread&, spu_opcode_t); static bool LQR(SPUThread&, spu_opcode_t);
static void IL(SPUThread&, spu_opcode_t); static bool IL(SPUThread&, spu_opcode_t);
static void ILHU(SPUThread&, spu_opcode_t); static bool ILHU(SPUThread&, spu_opcode_t);
static void ILH(SPUThread&, spu_opcode_t); static bool ILH(SPUThread&, spu_opcode_t);
static void IOHL(SPUThread&, spu_opcode_t); static bool IOHL(SPUThread&, spu_opcode_t);
static void ORI(SPUThread&, spu_opcode_t); static bool ORI(SPUThread&, spu_opcode_t);
static void ORHI(SPUThread&, spu_opcode_t); static bool ORHI(SPUThread&, spu_opcode_t);
static void ORBI(SPUThread&, spu_opcode_t); static bool ORBI(SPUThread&, spu_opcode_t);
static void SFI(SPUThread&, spu_opcode_t); static bool SFI(SPUThread&, spu_opcode_t);
static void SFHI(SPUThread&, spu_opcode_t); static bool SFHI(SPUThread&, spu_opcode_t);
static void ANDI(SPUThread&, spu_opcode_t); static bool ANDI(SPUThread&, spu_opcode_t);
static void ANDHI(SPUThread&, spu_opcode_t); static bool ANDHI(SPUThread&, spu_opcode_t);
static void ANDBI(SPUThread&, spu_opcode_t); static bool ANDBI(SPUThread&, spu_opcode_t);
static void AI(SPUThread&, spu_opcode_t); static bool AI(SPUThread&, spu_opcode_t);
static void AHI(SPUThread&, spu_opcode_t); static bool AHI(SPUThread&, spu_opcode_t);
static void STQD(SPUThread&, spu_opcode_t); static bool STQD(SPUThread&, spu_opcode_t);
static void LQD(SPUThread&, spu_opcode_t); static bool LQD(SPUThread&, spu_opcode_t);
static void XORI(SPUThread&, spu_opcode_t); static bool XORI(SPUThread&, spu_opcode_t);
static void XORHI(SPUThread&, spu_opcode_t); static bool XORHI(SPUThread&, spu_opcode_t);
static void XORBI(SPUThread&, spu_opcode_t); static bool XORBI(SPUThread&, spu_opcode_t);
static void CGTI(SPUThread&, spu_opcode_t); static bool CGTI(SPUThread&, spu_opcode_t);
static void CGTHI(SPUThread&, spu_opcode_t); static bool CGTHI(SPUThread&, spu_opcode_t);
static void CGTBI(SPUThread&, spu_opcode_t); static bool CGTBI(SPUThread&, spu_opcode_t);
static void HGTI(SPUThread&, spu_opcode_t); static bool HGTI(SPUThread&, spu_opcode_t);
static void CLGTI(SPUThread&, spu_opcode_t); static bool CLGTI(SPUThread&, spu_opcode_t);
static void CLGTHI(SPUThread&, spu_opcode_t); static bool CLGTHI(SPUThread&, spu_opcode_t);
static void CLGTBI(SPUThread&, spu_opcode_t); static bool CLGTBI(SPUThread&, spu_opcode_t);
static void HLGTI(SPUThread&, spu_opcode_t); static bool HLGTI(SPUThread&, spu_opcode_t);
static void MPYI(SPUThread&, spu_opcode_t); static bool MPYI(SPUThread&, spu_opcode_t);
static void MPYUI(SPUThread&, spu_opcode_t); static bool MPYUI(SPUThread&, spu_opcode_t);
static void CEQI(SPUThread&, spu_opcode_t); static bool CEQI(SPUThread&, spu_opcode_t);
static void CEQHI(SPUThread&, spu_opcode_t); static bool CEQHI(SPUThread&, spu_opcode_t);
static void CEQBI(SPUThread&, spu_opcode_t); static bool CEQBI(SPUThread&, spu_opcode_t);
static void HEQI(SPUThread&, spu_opcode_t); static bool HEQI(SPUThread&, spu_opcode_t);
static void HBRA(SPUThread&, spu_opcode_t); static bool HBRA(SPUThread&, spu_opcode_t);
static void HBRR(SPUThread&, spu_opcode_t); static bool HBRR(SPUThread&, spu_opcode_t);
static void ILA(SPUThread&, spu_opcode_t); static bool ILA(SPUThread&, spu_opcode_t);
static void SELB(SPUThread&, spu_opcode_t); static bool SELB(SPUThread&, spu_opcode_t);
static void MPYA(SPUThread&, spu_opcode_t); static bool MPYA(SPUThread&, spu_opcode_t);
static void DFCGT(SPUThread&, spu_opcode_t); static bool DFCGT(SPUThread&, spu_opcode_t);
static void DFCMGT(SPUThread&, spu_opcode_t); static bool DFCMGT(SPUThread&, spu_opcode_t);
static void DFTSV(SPUThread&, spu_opcode_t); static bool DFTSV(SPUThread&, spu_opcode_t);
static void DFCEQ(SPUThread&, spu_opcode_t); static bool DFCEQ(SPUThread&, spu_opcode_t);
static void DFCMEQ(SPUThread&, spu_opcode_t); static bool DFCMEQ(SPUThread&, spu_opcode_t);
}; };
struct spu_interpreter_fast final : spu_interpreter struct spu_interpreter_fast final : spu_interpreter
{ {
static void ROTQBYBI(SPUThread&, spu_opcode_t); static bool ROTQBYBI(SPUThread&, spu_opcode_t);
static void ROTQMBYBI(SPUThread&, spu_opcode_t); static bool ROTQMBYBI(SPUThread&, spu_opcode_t);
static void SHLQBYBI(SPUThread&, spu_opcode_t); static bool SHLQBYBI(SPUThread&, spu_opcode_t);
static void ROTQBY(SPUThread&, spu_opcode_t); static bool ROTQBY(SPUThread&, spu_opcode_t);
static void ROTQMBY(SPUThread&, spu_opcode_t); static bool ROTQMBY(SPUThread&, spu_opcode_t);
static void SHLQBY(SPUThread&, spu_opcode_t); static bool SHLQBY(SPUThread&, spu_opcode_t);
static void ROTQBYI(SPUThread&, spu_opcode_t); static bool ROTQBYI(SPUThread&, spu_opcode_t);
static void ROTQMBYI(SPUThread&, spu_opcode_t); static bool ROTQMBYI(SPUThread&, spu_opcode_t);
static void SHLQBYI(SPUThread&, spu_opcode_t); static bool SHLQBYI(SPUThread&, spu_opcode_t);
static void SHUFB(SPUThread&, spu_opcode_t); static bool SHUFB(SPUThread&, spu_opcode_t);
static void FREST(SPUThread&, spu_opcode_t); static bool FREST(SPUThread&, spu_opcode_t);
static void FRSQEST(SPUThread&, spu_opcode_t); static bool FRSQEST(SPUThread&, spu_opcode_t);
static void FCGT(SPUThread&, spu_opcode_t); static bool FCGT(SPUThread&, spu_opcode_t);
static void FA(SPUThread&, spu_opcode_t); static bool FA(SPUThread&, spu_opcode_t);
static void FS(SPUThread&, spu_opcode_t); static bool FS(SPUThread&, spu_opcode_t);
static void FM(SPUThread&, spu_opcode_t); static bool FM(SPUThread&, spu_opcode_t);
static void FCMGT(SPUThread&, spu_opcode_t); static bool FCMGT(SPUThread&, spu_opcode_t);
static void DFA(SPUThread&, spu_opcode_t); static bool DFA(SPUThread&, spu_opcode_t);
static void DFS(SPUThread&, spu_opcode_t); static bool DFS(SPUThread&, spu_opcode_t);
static void DFM(SPUThread&, spu_opcode_t); static bool DFM(SPUThread&, spu_opcode_t);
static void DFMA(SPUThread&, spu_opcode_t); static bool DFMA(SPUThread&, spu_opcode_t);
static void DFMS(SPUThread&, spu_opcode_t); static bool DFMS(SPUThread&, spu_opcode_t);
static void DFNMS(SPUThread&, spu_opcode_t); static bool DFNMS(SPUThread&, spu_opcode_t);
static void DFNMA(SPUThread&, spu_opcode_t); static bool DFNMA(SPUThread&, spu_opcode_t);
static void FSCRRD(SPUThread&, spu_opcode_t); static bool FSCRRD(SPUThread&, spu_opcode_t);
static void FESD(SPUThread&, spu_opcode_t); static bool FESD(SPUThread&, spu_opcode_t);
static void FRDS(SPUThread&, spu_opcode_t); static bool FRDS(SPUThread&, spu_opcode_t);
static void FSCRWR(SPUThread&, spu_opcode_t); static bool FSCRWR(SPUThread&, spu_opcode_t);
static void FCEQ(SPUThread&, spu_opcode_t); static bool FCEQ(SPUThread&, spu_opcode_t);
static void FCMEQ(SPUThread&, spu_opcode_t); static bool FCMEQ(SPUThread&, spu_opcode_t);
static void FI(SPUThread&, spu_opcode_t); static bool FI(SPUThread&, spu_opcode_t);
static void CFLTS(SPUThread&, spu_opcode_t); static bool CFLTS(SPUThread&, spu_opcode_t);
static void CFLTU(SPUThread&, spu_opcode_t); static bool CFLTU(SPUThread&, spu_opcode_t);
static void CSFLT(SPUThread&, spu_opcode_t); static bool CSFLT(SPUThread&, spu_opcode_t);
static void CUFLT(SPUThread&, spu_opcode_t); static bool CUFLT(SPUThread&, spu_opcode_t);
static void FNMS(SPUThread&, spu_opcode_t); static bool FNMS(SPUThread&, spu_opcode_t);
static void FMA(SPUThread&, spu_opcode_t); static bool FMA(SPUThread&, spu_opcode_t);
static void FMS(SPUThread&, spu_opcode_t); static bool FMS(SPUThread&, spu_opcode_t);
}; };
struct spu_interpreter_precise final : spu_interpreter struct spu_interpreter_precise final : spu_interpreter
{ {
static void ROTQBYBI(SPUThread&, spu_opcode_t); static bool ROTQBYBI(SPUThread&, spu_opcode_t);
static void ROTQMBYBI(SPUThread&, spu_opcode_t); static bool ROTQMBYBI(SPUThread&, spu_opcode_t);
static void SHLQBYBI(SPUThread&, spu_opcode_t); static bool SHLQBYBI(SPUThread&, spu_opcode_t);
static void ROTQBY(SPUThread&, spu_opcode_t); static bool ROTQBY(SPUThread&, spu_opcode_t);
static void ROTQMBY(SPUThread&, spu_opcode_t); static bool ROTQMBY(SPUThread&, spu_opcode_t);
static void SHLQBY(SPUThread&, spu_opcode_t); static bool SHLQBY(SPUThread&, spu_opcode_t);
static void ROTQBYI(SPUThread&, spu_opcode_t); static bool ROTQBYI(SPUThread&, spu_opcode_t);
static void ROTQMBYI(SPUThread&, spu_opcode_t); static bool ROTQMBYI(SPUThread&, spu_opcode_t);
static void SHLQBYI(SPUThread&, spu_opcode_t); static bool SHLQBYI(SPUThread&, spu_opcode_t);
static void SHUFB(SPUThread&, spu_opcode_t); static bool SHUFB(SPUThread&, spu_opcode_t);
static void FREST(SPUThread&, spu_opcode_t); static bool FREST(SPUThread&, spu_opcode_t);
static void FRSQEST(SPUThread&, spu_opcode_t); static bool FRSQEST(SPUThread&, spu_opcode_t);
static void FCGT(SPUThread&, spu_opcode_t); static bool FCGT(SPUThread&, spu_opcode_t);
static void FA(SPUThread&, spu_opcode_t); static bool FA(SPUThread&, spu_opcode_t);
static void FS(SPUThread&, spu_opcode_t); static bool FS(SPUThread&, spu_opcode_t);
static void FM(SPUThread&, spu_opcode_t); static bool FM(SPUThread&, spu_opcode_t);
static void FCMGT(SPUThread&, spu_opcode_t); static bool FCMGT(SPUThread&, spu_opcode_t);
static void DFA(SPUThread&, spu_opcode_t); static bool DFA(SPUThread&, spu_opcode_t);
static void DFS(SPUThread&, spu_opcode_t); static bool DFS(SPUThread&, spu_opcode_t);
static void DFM(SPUThread&, spu_opcode_t); static bool DFM(SPUThread&, spu_opcode_t);
static void DFMA(SPUThread&, spu_opcode_t); static bool DFMA(SPUThread&, spu_opcode_t);
static void DFMS(SPUThread&, spu_opcode_t); static bool DFMS(SPUThread&, spu_opcode_t);
static void DFNMS(SPUThread&, spu_opcode_t); static bool DFNMS(SPUThread&, spu_opcode_t);
static void DFNMA(SPUThread&, spu_opcode_t); static bool DFNMA(SPUThread&, spu_opcode_t);
static void FSCRRD(SPUThread&, spu_opcode_t); static bool FSCRRD(SPUThread&, spu_opcode_t);
static void FESD(SPUThread&, spu_opcode_t); static bool FESD(SPUThread&, spu_opcode_t);
static void FRDS(SPUThread&, spu_opcode_t); static bool FRDS(SPUThread&, spu_opcode_t);
static void FSCRWR(SPUThread&, spu_opcode_t); static bool FSCRWR(SPUThread&, spu_opcode_t);
static void FCEQ(SPUThread&, spu_opcode_t); static bool FCEQ(SPUThread&, spu_opcode_t);
static void FCMEQ(SPUThread&, spu_opcode_t); static bool FCMEQ(SPUThread&, spu_opcode_t);
static void FI(SPUThread&, spu_opcode_t); static bool FI(SPUThread&, spu_opcode_t);
static void CFLTS(SPUThread&, spu_opcode_t); static bool CFLTS(SPUThread&, spu_opcode_t);
static void CFLTU(SPUThread&, spu_opcode_t); static bool CFLTU(SPUThread&, spu_opcode_t);
static void CSFLT(SPUThread&, spu_opcode_t); static bool CSFLT(SPUThread&, spu_opcode_t);
static void CUFLT(SPUThread&, spu_opcode_t); static bool CUFLT(SPUThread&, spu_opcode_t);
static void FNMS(SPUThread&, spu_opcode_t); static bool FNMS(SPUThread&, spu_opcode_t);
static void FMA(SPUThread&, spu_opcode_t); static bool FMA(SPUThread&, spu_opcode_t);
static void FMS(SPUThread&, spu_opcode_t); static bool FMS(SPUThread&, spu_opcode_t);
}; };

View file

@ -32,6 +32,7 @@ const bool s_use_ssse3 =
true; true;
#else #else
false; false;
#define _mm_shuffle_epi8
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
@ -388,25 +389,75 @@ void SPUThread::cpu_task()
g_cfg.core.spu_decoder == spu_decoder_type::fast ? &g_spu_interpreter_fast.get_table() : g_cfg.core.spu_decoder == spu_decoder_type::fast ? &g_spu_interpreter_fast.get_table() :
(fmt::throw_exception<std::logic_error>("Invalid SPU decoder"), nullptr)); (fmt::throw_exception<std::logic_error>("Invalid SPU decoder"), nullptr));
// LS base address // LS pointer
const auto base = vm::_ptr<const u32>(offset); const auto base = vm::_ptr<const u8>(offset);
const auto bswap4 = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
v128 _op;
using func_t = decltype(&spu_interpreter::UNK);
func_t func0, func1, func2, func3, func4, func5;
while (true) while (true)
{ {
if (!test(state) || !check_state()) if (UNLIKELY(test(state)))
{ {
// Read opcode if (check_state()) return;
const u32 op = base[pc / 4];
// Call interpreter function
table[spu_decode(op)](*this, { op });
// Next instruction
pc += 4;
// Decode single instruction (may be step)
const u32 op = *reinterpret_cast<const be_t<u32>*>(base + pc);
if (table[spu_decode(op)](*this, {op})) { pc += 4; }
continue; continue;
} }
return;
if (pc % 16 || !s_use_ssse3)
{
// Unaligned
const u32 op = *reinterpret_cast<const be_t<u32>*>(base + pc);
if (table[spu_decode(op)](*this, {op})) { pc += 4; }
continue;
}
// Reinitialize
_op.vi = _mm_shuffle_epi8(_mm_load_si128(reinterpret_cast<const __m128i*>(base + pc)), bswap4);
func0 = table[spu_decode(_op._u32[0])];
func1 = table[spu_decode(_op._u32[1])];
func2 = table[spu_decode(_op._u32[2])];
func3 = table[spu_decode(_op._u32[3])];
while (LIKELY(func0(*this, {_op._u32[0]})))
{
pc += 4;
if (LIKELY(func1(*this, {_op._u32[1]})))
{
pc += 4;
u32 op2 = _op._u32[2];
u32 op3 = _op._u32[3];
_op.vi = _mm_shuffle_epi8(_mm_load_si128(reinterpret_cast<const __m128i*>(base + pc + 8)), bswap4);
func0 = table[spu_decode(_op._u32[0])];
func1 = table[spu_decode(_op._u32[1])];
func4 = table[spu_decode(_op._u32[2])];
func5 = table[spu_decode(_op._u32[3])];
if (LIKELY(func2(*this, {op2})))
{
pc += 4;
if (LIKELY(func3(*this, {op3})))
{
pc += 4;
func2 = func4;
func3 = func5;
if (UNLIKELY(test(state)))
{
break;
}
continue;
}
break;
}
break;
}
break;
}
} }
} }