mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 23:41:26 +12:00
Optimize SPU interpreter
Made SPU decoder similar to PPU decoder
This commit is contained in:
parent
53f8b03acc
commit
445b7c0758
5 changed files with 797 additions and 528 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue