1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-23 11:13:19 +01:00

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)
{
auto ctxt = vm::_ptr<SpursKernelContext>(spu.offset + 0x100);
spu.pc = ctxt->exitToKernelAddr - 4;
spu.pc = ctxt->exitToKernelAddr;
throw SpursModuleExit();
}
@ -659,7 +659,7 @@ void spursKernelDispatchWorkload(SPUThread& spu, u64 widAndPollStatus)
spu.gpr[3]._u32[3] = 0x100;
spu.gpr[4]._u64[1] = wklInfo->arg;
spu.gpr[5]._u32[3] = pollStatus;
spu.pc = 0xA00 - 4;
spu.pc = 0xA00;
}
// SPURS kernel workload exit
@ -1404,7 +1404,7 @@ void spursTasksetResumeTask(SPUThread& spu)
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
@ -1422,7 +1422,7 @@ void spursTasksetStartTask(SPUThread& spu, CellSpursTaskArgument& taskArgs)
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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -32,6 +32,7 @@ const bool s_use_ssse3 =
true;
#else
false;
#define _mm_shuffle_epi8
#endif
#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() :
(fmt::throw_exception<std::logic_error>("Invalid SPU decoder"), nullptr));
// LS base address
const auto base = vm::_ptr<const u32>(offset);
// LS pointer
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)
{
if (!test(state) || !check_state())
if (UNLIKELY(test(state)))
{
// Read opcode
const u32 op = base[pc / 4];
// Call interpreter function
table[spu_decode(op)](*this, { op });
// Next instruction
pc += 4;
if (check_state()) return;
// 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;
}
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;
}
}
}