mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Wire the generated ExecInstruction dispatcher into the interpreter's hot loop
Adds Core/MIPS/InterpreterDispatch.cpp, the checked-in output of GenerateInterpreterDispatch() (see the previous commit), and hooks it into RunUntilFast() in MIPSTables.cpp in place of the old MIPSGetInstruction()-based table walk + indirect call through instr->interpret. The checked-with-breakpoints/memchecks path (RunUntilWithChecks) is untouched for now, since it inspects MIPSInstruction flags directly and correctness there matters most. Also fixes a real crash in headless.cpp found while testing this: cmdLineOptions.gpuBackend.value() would throw when unset (e.g. with --graphics=software), now uses value_or(). Verified with `test.py -g --cpu=interpreter --graphics=software`: 313/314 pass; the one failure (cpu/fpu/fpu) is a pre-existing interpreter-vs-JIT denormal (flush-to-zero) difference, confirmed to fail identically with the old table-walking dispatch, so unrelated to this change. Adds Tools/update-dispatcher.py to regenerate InterpreterDispatch.cpp from a built PPSSPPHeadless binary whenever the MIPSTables.cpp tables change. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019SKhm9wKEQzRUsx9mTrrtQ
This commit is contained in:
1 parent
65495c76c0
commit
d000d5366a
10 files changed
+869
-4
No files matched your search
@@ -620,6 +620,8 @@ add_library(Core STATIC
|
||||
MIPS/MIPSDisVFPU.h
|
||||
MIPS/Interpreter.cpp
|
||||
MIPS/Interpreter.h
|
||||
MIPS/InterpreterDispatch.cpp
|
||||
MIPS/InterpreterDispatch.h
|
||||
MIPS/InterpreterVFPU.cpp
|
||||
MIPS/InterpreterVFPU.h
|
||||
MIPS/MIPSStackWalk.cpp
|
||||
|
||||
@@ -845,6 +845,7 @@
|
||||
<ClCompile Include="MIPS\MIPSDis.cpp" />
|
||||
<ClCompile Include="MIPS\MIPSDisVFPU.cpp" />
|
||||
<ClCompile Include="MIPS\Interpreter.cpp" />
|
||||
<ClCompile Include="MIPS\InterpreterDispatch.cpp" />
|
||||
<ClCompile Include="MIPS\InterpreterVFPU.cpp" />
|
||||
<ClCompile Include="MIPS\MIPSTables.cpp" />
|
||||
<ClCompile Include="MIPS\MIPSVFPUUtils.cpp" />
|
||||
@@ -1230,6 +1231,7 @@
|
||||
<ClInclude Include="MIPS\MIPSDis.h" />
|
||||
<ClInclude Include="MIPS\MIPSDisVFPU.h" />
|
||||
<ClInclude Include="MIPS\Interpreter.h" />
|
||||
<ClInclude Include="MIPS\InterpreterDispatch.h" />
|
||||
<ClInclude Include="MIPS\InterpreterVFPU.h" />
|
||||
<ClInclude Include="MIPS\MIPSTables.h" />
|
||||
<ClInclude Include="MIPS\MIPSVFPUUtils.h" />
|
||||
|
||||
@@ -114,6 +114,9 @@
|
||||
<ClCompile Include="MIPS\Interpreter.cpp">
|
||||
<Filter>MIPS</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\InterpreterDispatch.cpp">
|
||||
<Filter>MIPS</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\InterpreterVFPU.cpp">
|
||||
<Filter>MIPS</Filter>
|
||||
</ClCompile>
|
||||
@@ -1419,6 +1422,9 @@
|
||||
<ClInclude Include="MIPS\Interpreter.h">
|
||||
<Filter>MIPS</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\InterpreterDispatch.h">
|
||||
<Filter>MIPS</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\InterpreterVFPU.h">
|
||||
<Filter>MIPS</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -0,0 +1,738 @@
|
||||
// Copyright (c) 2012- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
// AUTO-GENERATED by `PPSSPPHeadless --generate-interpreter-dispatch` from the
|
||||
// tables in MIPSTables.cpp - do not hand-edit, regenerate instead.
|
||||
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/MIPS/MIPSTables.h"
|
||||
#include "Core/MIPS/Interpreter.h"
|
||||
#include "Core/MIPS/InterpreterVFPU.h"
|
||||
|
||||
int ExecInstruction(MIPSOpcode op) {
|
||||
switch ((op.encoding >> 26) & 0x3f) {
|
||||
case 0:
|
||||
{
|
||||
switch ((op.encoding >> 0) & 0x3f) {
|
||||
// sll, srl, sra, sllv, srlv, srav
|
||||
case 0:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
MIPSInt::Int_ShiftType(op);
|
||||
return 1;
|
||||
// jr, jalr
|
||||
case 8:
|
||||
case 9:
|
||||
MIPSInt::Int_JumpRegType(op);
|
||||
return 1;
|
||||
// movz, movn, add, addu, sub, subu, and, or, xor, nor, slt, sltu, max, min
|
||||
case 10:
|
||||
case 11:
|
||||
case 32:
|
||||
case 33:
|
||||
case 34:
|
||||
case 35:
|
||||
case 36:
|
||||
case 37:
|
||||
case 38:
|
||||
case 39:
|
||||
case 42:
|
||||
case 43:
|
||||
case 44:
|
||||
case 45:
|
||||
MIPSInt::Int_RType3(op);
|
||||
return 1;
|
||||
// syscall
|
||||
case 12:
|
||||
MIPSInt::Int_Syscall(op);
|
||||
return 1;
|
||||
// break
|
||||
case 13:
|
||||
MIPSInt::Int_Break(op);
|
||||
return 1;
|
||||
// sync
|
||||
case 15:
|
||||
MIPSInt::Int_Sync(op);
|
||||
return 1;
|
||||
// mfhi, mthi, mflo, mtlo, mult, multu, div, divu, madd, maddu, msub, msubu
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
case 29:
|
||||
case 46:
|
||||
case 47:
|
||||
MIPSInt::Int_MulDivType(op);
|
||||
return 1;
|
||||
// clz, clo
|
||||
case 22:
|
||||
case 23:
|
||||
MIPSInt::Int_RType2(op);
|
||||
return 1;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
switch ((op.encoding >> 16) & 0x1f) {
|
||||
// bltz, bgez, bltzl, bgezl, bltzal, bgezal, bltzall, bgezall
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
MIPSInt::Int_RelBranchRI(op);
|
||||
return 1;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
// j, jal
|
||||
case 2:
|
||||
case 3:
|
||||
MIPSInt::Int_JumpType(op);
|
||||
return 1;
|
||||
// beq, bne, blez, bgtz, beql, bnel, blezl, bgtzl
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
MIPSInt::Int_RelBranch(op);
|
||||
return 1;
|
||||
// addi, addiu, slti, sltiu, andi, ori, xori, lui
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
MIPSInt::Int_IType(op);
|
||||
return 1;
|
||||
case 16:
|
||||
{
|
||||
switch ((op.encoding >> 21) & 0x1f) {
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
case 31:
|
||||
{
|
||||
goto slow_path;
|
||||
}
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 17:
|
||||
{
|
||||
switch ((op.encoding >> 21) & 0x1f) {
|
||||
// mfc1, cfc1, mtc1, ctc1
|
||||
case 0:
|
||||
case 2:
|
||||
case 4:
|
||||
case 6:
|
||||
MIPSInt::Int_mxc1(op);
|
||||
return 1;
|
||||
case 8:
|
||||
{
|
||||
switch ((op.encoding >> 16) & 0x1f) {
|
||||
// bc1f, bc1t, bc1fl, bc1tl
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
MIPSInt::Int_FPUBranch(op);
|
||||
return 1;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
switch ((op.encoding >> 0) & 0x3f) {
|
||||
// add.s, sub.s, mul.s
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
MIPSInt::Int_FPU3op(op);
|
||||
return 1;
|
||||
// div.s
|
||||
case 3:
|
||||
MIPSInt::Int_FPU3op(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:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 36:
|
||||
MIPSInt::Int_FPU2op(op);
|
||||
return 1;
|
||||
// dis.int
|
||||
case 38:
|
||||
MIPSInt::Int_Interrupt(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:
|
||||
case 49:
|
||||
case 50:
|
||||
case 51:
|
||||
case 52:
|
||||
case 53:
|
||||
case 54:
|
||||
case 55:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 59:
|
||||
case 60:
|
||||
case 61:
|
||||
case 62:
|
||||
case 63:
|
||||
MIPSInt::Int_FPUComp(op);
|
||||
return 1;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 20:
|
||||
{
|
||||
switch ((op.encoding >> 0) & 0x3f) {
|
||||
// cvt.s.w
|
||||
case 32:
|
||||
MIPSInt::Int_FPU2op(op);
|
||||
return 1;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 18:
|
||||
{
|
||||
switch ((op.encoding >> 21) & 0x1f) {
|
||||
// mfv, mtv
|
||||
case 3:
|
||||
case 7:
|
||||
MIPSInt::Int_Mftv(op);
|
||||
return 2;
|
||||
case 8:
|
||||
{
|
||||
switch ((op.encoding >> 16) & 0x3) {
|
||||
// bvf, bvt, bvfl, bvtl
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
MIPSInt::Int_VBranch(op);
|
||||
return 2;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 24:
|
||||
{
|
||||
switch ((op.encoding >> 23) & 0x7) {
|
||||
// vadd, vsub, vdiv
|
||||
case 0:
|
||||
case 1:
|
||||
case 7:
|
||||
MIPSInt::Int_VecDo3(op);
|
||||
return 2;
|
||||
// vsbn
|
||||
case 2:
|
||||
MIPSInt::Int_Vsbn(op);
|
||||
return 2;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 25:
|
||||
{
|
||||
switch ((op.encoding >> 23) & 0x7) {
|
||||
// vmul
|
||||
case 0:
|
||||
MIPSInt::Int_VecDo3(op);
|
||||
return 2;
|
||||
// vdot
|
||||
case 1:
|
||||
MIPSInt::Int_VDot(op);
|
||||
return 2;
|
||||
// vscl
|
||||
case 2:
|
||||
MIPSInt::Int_VScl(op);
|
||||
return 2;
|
||||
// vhdp
|
||||
case 4:
|
||||
MIPSInt::Int_VHdp(op);
|
||||
return 2;
|
||||
// vcrs
|
||||
case 5:
|
||||
MIPSInt::Int_Vcrs(op);
|
||||
return 2;
|
||||
// vdet
|
||||
case 6:
|
||||
MIPSInt::Int_Vdet(op);
|
||||
return 2;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 26:
|
||||
{
|
||||
switch ((op.encoding >> 24) & 0x3) {
|
||||
// RUNBLOCK
|
||||
case 0:
|
||||
MIPSInt::Int_Emuhack(op);
|
||||
return 2;
|
||||
// RetKrnl, CallRepl
|
||||
case 1:
|
||||
case 2:
|
||||
MIPSInt::Int_Emuhack(op);
|
||||
return 1;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 27:
|
||||
{
|
||||
switch ((op.encoding >> 23) & 0x7) {
|
||||
// vcmp
|
||||
case 0:
|
||||
MIPSInt::Int_Vcmp(op);
|
||||
return 2;
|
||||
// vmin, vmax
|
||||
case 2:
|
||||
case 3:
|
||||
MIPSInt::Int_Vminmax(op);
|
||||
return 2;
|
||||
// vscmp
|
||||
case 5:
|
||||
MIPSInt::Int_Vscmp(op);
|
||||
return 2;
|
||||
// vsge
|
||||
case 6:
|
||||
MIPSInt::Int_Vsge(op);
|
||||
return 2;
|
||||
// vslt
|
||||
case 7:
|
||||
MIPSInt::Int_Vslt(op);
|
||||
return 2;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 28:
|
||||
{
|
||||
switch ((op.encoding >> 0) & 0x3f) {
|
||||
// mfic, mtic
|
||||
case 36:
|
||||
case 38:
|
||||
MIPSInt::Int_Special2(op);
|
||||
return 1;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 31:
|
||||
{
|
||||
switch ((op.encoding >> 0) & 0x3f) {
|
||||
// ext, ins
|
||||
case 0:
|
||||
case 4:
|
||||
MIPSInt::Int_Special3(op);
|
||||
return 1;
|
||||
case 24:
|
||||
case 32:
|
||||
{
|
||||
switch ((op.encoding >> 6) & 0x1f) {
|
||||
// wsbh, wsbw
|
||||
case 2:
|
||||
case 3:
|
||||
MIPSInt::Int_Allegrex2(op);
|
||||
return 1;
|
||||
// seb, bitrev, seh
|
||||
case 16:
|
||||
case 20:
|
||||
case 24:
|
||||
MIPSInt::Int_Allegrex(op);
|
||||
return 1;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
// lb, lh, lwl, lw, lbu, lhu, lwr, sb, sh, swl, sw, swr
|
||||
case 32:
|
||||
case 33:
|
||||
case 34:
|
||||
case 35:
|
||||
case 36:
|
||||
case 37:
|
||||
case 38:
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
case 43:
|
||||
case 46:
|
||||
MIPSInt::Int_ITypeMem(op);
|
||||
return 1;
|
||||
// cache
|
||||
case 47:
|
||||
MIPSInt::Int_Cache(op);
|
||||
return 1;
|
||||
// ll, sc
|
||||
case 48:
|
||||
case 56:
|
||||
MIPSInt::Int_StoreSync(op);
|
||||
return 1;
|
||||
// lwc1, swc1
|
||||
case 49:
|
||||
case 57:
|
||||
MIPSInt::Int_FPULS(op);
|
||||
return 1;
|
||||
// lv.s, sv.s
|
||||
case 50:
|
||||
case 58:
|
||||
MIPSInt::Int_SV(op);
|
||||
return 2;
|
||||
case 52:
|
||||
{
|
||||
switch ((op.encoding >> 21) & 0x1f) {
|
||||
case 0:
|
||||
{
|
||||
switch ((op.encoding >> 16) & 0x1f) {
|
||||
// vmov, vabs, vneg, vsat0, vsat1, vrcp, vrsq, vsin, vcos, vexp2, vlog2, vsqrt, vasin, vnrcp, vnsin, vrexp2
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 5:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
case 24:
|
||||
case 26:
|
||||
case 28:
|
||||
MIPSInt::Int_VV2Op(op);
|
||||
return 2;
|
||||
// vidt
|
||||
case 3:
|
||||
MIPSInt::Int_Vidt(op);
|
||||
return 2;
|
||||
// vzero, vone
|
||||
case 6:
|
||||
case 7:
|
||||
MIPSInt::Int_VVectorInit(op);
|
||||
return 2;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
switch ((op.encoding >> 16) & 0x1f) {
|
||||
// vrnds
|
||||
case 0:
|
||||
MIPSInt::Int_Vrnds(op);
|
||||
return 2;
|
||||
// vrndi, vrndf1, vrndf2
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
MIPSInt::Int_VrndX(op);
|
||||
return 2;
|
||||
// vf2h
|
||||
case 18:
|
||||
MIPSInt::Int_Vf2h(op);
|
||||
return 2;
|
||||
// vh2f
|
||||
case 19:
|
||||
MIPSInt::Int_Vh2f(op);
|
||||
return 2;
|
||||
// vsbz
|
||||
case 22:
|
||||
MIPSInt::Int_Vsbz(op);
|
||||
return 2;
|
||||
// vlgb
|
||||
case 23:
|
||||
MIPSInt::Int_Vlgb(op);
|
||||
return 2;
|
||||
// vuc2ifs, vc2i, vus2i, vs2i
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
case 27:
|
||||
MIPSInt::Int_Vx2i(op);
|
||||
return 2;
|
||||
// vi2uc, vi2c, vi2us, vi2s
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
case 31:
|
||||
MIPSInt::Int_Vi2x(op);
|
||||
return 2;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
switch ((op.encoding >> 16) & 0x1f) {
|
||||
// vsrt1
|
||||
case 0:
|
||||
MIPSInt::Int_Vsrt1(op);
|
||||
return 2;
|
||||
// vsrt2
|
||||
case 1:
|
||||
MIPSInt::Int_Vsrt2(op);
|
||||
return 2;
|
||||
// vbfy1, vbfy2
|
||||
case 2:
|
||||
case 3:
|
||||
MIPSInt::Int_Vbfy(op);
|
||||
return 2;
|
||||
// vocp
|
||||
case 4:
|
||||
MIPSInt::Int_Vocp(op);
|
||||
return 2;
|
||||
// vsocp
|
||||
case 5:
|
||||
MIPSInt::Int_Vsocp(op);
|
||||
return 2;
|
||||
// vfad
|
||||
case 6:
|
||||
MIPSInt::Int_Vfad(op);
|
||||
return 2;
|
||||
// vavg
|
||||
case 7:
|
||||
MIPSInt::Int_Vavg(op);
|
||||
return 2;
|
||||
// vsrt3
|
||||
case 8:
|
||||
MIPSInt::Int_Vsrt3(op);
|
||||
return 2;
|
||||
// vsrt4
|
||||
case 9:
|
||||
MIPSInt::Int_Vsrt4(op);
|
||||
return 2;
|
||||
// vsgn
|
||||
case 10:
|
||||
MIPSInt::Int_Vsgn(op);
|
||||
return 2;
|
||||
// vmfvc
|
||||
case 16:
|
||||
MIPSInt::Int_Vmfvc(op);
|
||||
return 2;
|
||||
// vmtvc
|
||||
case 17:
|
||||
MIPSInt::Int_Vmtvc(op);
|
||||
return 2;
|
||||
// vt4444, vt5551, vt5650
|
||||
case 25:
|
||||
case 26:
|
||||
case 27:
|
||||
MIPSInt::Int_ColorConv(op);
|
||||
return 2;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
// vcst
|
||||
case 3:
|
||||
MIPSInt::Int_Vcst(op);
|
||||
return 2;
|
||||
// vf2in, vf2iz, vf2iu, vf2id
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
MIPSInt::Int_Vf2i(op);
|
||||
return 2;
|
||||
// vi2f
|
||||
case 20:
|
||||
MIPSInt::Int_Vi2f(op);
|
||||
return 2;
|
||||
// vcmov
|
||||
case 21:
|
||||
MIPSInt::Int_Vcmov(op);
|
||||
return 2;
|
||||
// vwbn, vwbn, vwbn, vwbn, vwbn, vwbn, vwbn, vwbn
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
case 27:
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
case 31:
|
||||
MIPSInt::Int_Vwbn(op);
|
||||
return 2;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
// lv, lv.q, sv, sv.q
|
||||
case 53:
|
||||
case 54:
|
||||
case 61:
|
||||
case 62:
|
||||
MIPSInt::Int_SVQ(op);
|
||||
return 2;
|
||||
case 55:
|
||||
{
|
||||
switch ((op.encoding >> 23) & 0x7) {
|
||||
// vpfxs, vpfxs, vpfxt, vpfxt, vpfxd, vpfxd
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
MIPSInt::Int_VPFX(op);
|
||||
return 2;
|
||||
// viim.s, vfim.s
|
||||
case 6:
|
||||
case 7:
|
||||
MIPSInt::Int_Viim(op);
|
||||
return 2;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
case 60:
|
||||
{
|
||||
switch ((op.encoding >> 21) & 0x1f) {
|
||||
// vmmul, vmmul, vmmul, vmmul
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
MIPSInt::Int_Vmmul(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:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
MIPSInt::Int_Vtfm(op);
|
||||
return 2;
|
||||
// vmscl, vmscl, vmscl, vmscl
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
MIPSInt::Int_Vmscl(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);
|
||||
return 2;
|
||||
case 28:
|
||||
{
|
||||
switch ((op.encoding >> 16) & 0xf) {
|
||||
// vmmov
|
||||
case 0:
|
||||
MIPSInt::Int_Vmmov(op);
|
||||
return 2;
|
||||
// vmidt, vmzero, vmone
|
||||
case 3:
|
||||
case 6:
|
||||
case 7:
|
||||
MIPSInt::Int_VMatrixInit(op);
|
||||
return 2;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
// vrot
|
||||
case 29:
|
||||
MIPSInt::Int_Vrot(op);
|
||||
return 2;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
}
|
||||
// vflush
|
||||
case 63:
|
||||
MIPSInt::Int_Vflush(op);
|
||||
return 2;
|
||||
default:
|
||||
goto slow_path;
|
||||
}
|
||||
slow_path:
|
||||
MIPSInterpret(op);
|
||||
return MIPSGetInstructionCycleEstimate(op);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2012- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
|
||||
#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.
|
||||
int ExecInstruction(MIPSOpcode op);
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "Core/MIPS/MIPSDis.h"
|
||||
#include "Core/MIPS/MIPSDisVFPU.h"
|
||||
#include "Core/MIPS/Interpreter.h"
|
||||
#include "Core/MIPS/InterpreterDispatch.h"
|
||||
#include "Core/MIPS/InterpreterVFPU.h"
|
||||
#include "Core/MIPS/MIPSCodeUtils.h"
|
||||
#include "Core/MIPS/MIPSTables.h"
|
||||
@@ -1119,9 +1120,7 @@ static inline void RunUntilFast() {
|
||||
MIPSOpcode op = MIPSOpcode(Memory::ReadUnchecked_U32(curMips->pc));
|
||||
|
||||
bool wasInDelaySlot = curMips->inDelaySlot;
|
||||
const MIPSInstruction *instr = MIPSGetInstruction(op);
|
||||
Interpret(instr, op);
|
||||
curMips->downcount -= GetInstructionCycleEstimate(instr);
|
||||
curMips->downcount -= ExecInstruction(op);
|
||||
|
||||
// The reason we have to check this is the delay slot hack in Int_Syscall.
|
||||
if (curMips->inDelaySlot && wasInDelaySlot) {
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Regenerates Core/MIPS/InterpreterDispatch.cpp (the ExecInstruction switch-tree
|
||||
# interpreter dispatcher) from the tables in Core/MIPS/MIPSTables.cpp.
|
||||
#
|
||||
# Run this after changing anything that affects those tables - new instructions,
|
||||
# retimed cycle counts, encoding changes, etc. The generated file is checked into
|
||||
# git like any other source file, not built on the fly, so it needs to be
|
||||
# regenerated and the diff committed whenever the tables change.
|
||||
#
|
||||
# This script only needs an already-built PPSSPPHeadless binary (see
|
||||
# docs/pspautotests.md for how to build one); it doesn't build anything itself.
|
||||
# After it finishes, just build normally - Core/MIPS/InterpreterDispatch.cpp is
|
||||
# already wired into every build system, so no further steps are needed.
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# Same search list test.py uses to find a headless build.
|
||||
CANDIDATES = [
|
||||
"Windows/x64/Debug/PPSSPPHeadless.exe",
|
||||
"Windows/x64/Release/PPSSPPHeadless.exe",
|
||||
"Windows/Debug/PPSSPPHeadless.exe",
|
||||
"Windows/Release/PPSSPPHeadless.exe",
|
||||
"build/Debug/PPSSPPHeadless",
|
||||
"build/Release/PPSSPPHeadless",
|
||||
"build/RelWithDebInfo/PPSSPPHeadless",
|
||||
"build/MinSizeRel/PPSSPPHeadless",
|
||||
"build/PPSSPPHeadless",
|
||||
"./PPSSPPHeadless",
|
||||
"./PPSSPPHeadless.exe",
|
||||
]
|
||||
|
||||
OUT_PATH = os.path.join("Core", "MIPS", "InterpreterDispatch.cpp")
|
||||
|
||||
|
||||
def find_headless():
|
||||
for candidate in CANDIDATES:
|
||||
if os.path.isfile(candidate):
|
||||
return candidate
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
os.chdir(repo_root)
|
||||
|
||||
headless = find_headless()
|
||||
if headless is None:
|
||||
sys.stderr.write("error: couldn't find a built PPSSPPHeadless binary. Checked:\n")
|
||||
for candidate in CANDIDATES:
|
||||
sys.stderr.write(" %s\n" % candidate)
|
||||
sys.stderr.write("Build PPSSPPHeadless first (see docs/pspautotests.md), then re-run this script.\n")
|
||||
return 1
|
||||
|
||||
print("Using %s" % headless)
|
||||
|
||||
# subprocess/CreateProcess on Windows can fail to resolve a relative,
|
||||
# forward-slash path as the executable itself - use an absolute, normalized path.
|
||||
headless_abs = os.path.normpath(os.path.abspath(headless))
|
||||
|
||||
try:
|
||||
result = subprocess.run([headless_abs, "--generate-interpreter-dispatch"], capture_output=True)
|
||||
except OSError as e:
|
||||
sys.stderr.write("error: couldn't run %s: %s\n" % (headless, e))
|
||||
return 1
|
||||
|
||||
if result.returncode != 0:
|
||||
sys.stderr.buffer.write(result.stderr)
|
||||
sys.stderr.write("error: %s exited with code %d\n" % (headless, result.returncode))
|
||||
return 1
|
||||
|
||||
generated = result.stdout
|
||||
|
||||
# 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:
|
||||
sys.stderr.write("error: generated output doesn't look right (missing ExecInstruction) - not overwriting %s\n" % OUT_PATH)
|
||||
return 1
|
||||
|
||||
with open(OUT_PATH, "wb") as f:
|
||||
f.write(generated)
|
||||
|
||||
print("Regenerated %s" % OUT_PATH)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -515,6 +515,7 @@ EXEC_AND_LIB_FILES := \
|
||||
$(SRC)/Core/MIPS/MIPSDisVFPU.cpp \
|
||||
$(SRC)/Core/MIPS/MIPSAsm.cpp \
|
||||
$(SRC)/Core/MIPS/Interpreter.cpp.arm \
|
||||
$(SRC)/Core/MIPS/InterpreterDispatch.cpp \
|
||||
$(SRC)/Core/MIPS/InterpreterVFPU.cpp.arm \
|
||||
$(SRC)/Core/MIPS/MIPSStackWalk.cpp \
|
||||
$(SRC)/Core/MIPS/MIPSTables.cpp \
|
||||
|
||||
@@ -716,7 +716,7 @@ int main(int argc, const char* argv[]) {
|
||||
return 1;
|
||||
#else
|
||||
// TODO: Will we need a larger window for higher resolutions? Well, not if we use buffered rendering.
|
||||
window = CreateHiddenWindow(480, 272, cmdLineOptions.gpuBackend.value(), &windowDesc);
|
||||
window = CreateHiddenWindow(480, 272, cmdLineOptions.gpuBackend.value_or(GPUBackend::OPENGL), &windowDesc);
|
||||
if (!windowDesc.Valid()) {
|
||||
fprintf(stderr, "Failed to create a window for graphics context");
|
||||
return 1;
|
||||
|
||||
@@ -872,6 +872,7 @@ SOURCES_CXX += \
|
||||
$(COREDIR)/MIPS/MIPSDis.cpp \
|
||||
$(COREDIR)/MIPS/MIPSDisVFPU.cpp \
|
||||
$(COREDIR)/MIPS/Interpreter.cpp \
|
||||
$(COREDIR)/MIPS/InterpreterDispatch.cpp \
|
||||
$(COREDIR)/MIPS/InterpreterVFPU.cpp \
|
||||
$(COREDIR)/MIPS/MIPSTables.cpp \
|
||||
$(COREDIR)/MIPS/MIPSStackWalk.cpp \
|
||||
|
||||
Reference in new issue
Block a user