mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-08-31 17:55:23 +02:00
mfc0/mtc0/rdpgpr/mfmc0/wrpgpr had no interpreter execution function at all - ordinary PSP user-mode code never executes COP0 instructions directly so nobody needed one. Real kernel-mode boot code does the opposite: flash0:/reboot.bin's very first instruction is mfc0. Int_Cop0 (Interpreter.cpp) backs these with a small file-scope shadow register array - not real COP0 semantics (no interrupts/exceptions/ TLB), just enough to not fault and give plausible write-then-read-back-same-value behavior for boot code that pokes Status and other registers. Might later be added to MIPSState. Also regenerated Core/MIPS/InterpreterDispatch.cpp (`PPSSPPHeadless --generate-interpreter-dispatch`). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
745 lines
18 KiB
C++
745 lines
18 KiB
C++
// 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/Interpreter.h"
|
|
#include "Core/MIPS/InterpreterVFPU.h"
|
|
|
|
// Returns the cycle count consumed, or -1 if op isn't a recognized instruction -
|
|
// callers must fall back to MIPSInterpret() themselves in that case.
|
|
int ExecInstruction(MIPSState *mips, 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(mips, op);
|
|
return 1;
|
|
// jr, jalr
|
|
case 8:
|
|
case 9:
|
|
MIPSInt::Int_JumpRegType(mips, 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(mips, op);
|
|
return 1;
|
|
// syscall
|
|
case 12:
|
|
MIPSInt::Int_Syscall(mips, op);
|
|
return 1;
|
|
// break
|
|
case 13:
|
|
MIPSInt::Int_Break(mips, op);
|
|
return 1;
|
|
// sync
|
|
case 15:
|
|
MIPSInt::Int_Sync(mips, 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(mips, op);
|
|
return 1;
|
|
// clz, clo
|
|
case 22:
|
|
case 23:
|
|
MIPSInt::Int_RType2(mips, op);
|
|
return 1;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
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(mips, op);
|
|
return 1;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
// j, jal
|
|
case 2:
|
|
case 3:
|
|
MIPSInt::Int_JumpType(mips, 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(mips, 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(mips, op);
|
|
return 1;
|
|
case 16:
|
|
{
|
|
switch ((op.encoding >> 21) & 0x1f) {
|
|
// mfc0, mtc0, rdpgpr, mfmc0, wrpgpr
|
|
case 0:
|
|
case 4:
|
|
case 10:
|
|
case 11:
|
|
case 14:
|
|
MIPSInt::Int_Cop0(mips, op);
|
|
return 1;
|
|
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:
|
|
{
|
|
return -1;
|
|
}
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 17:
|
|
{
|
|
switch ((op.encoding >> 21) & 0x1f) {
|
|
// mfc1, cfc1, mtc1, ctc1
|
|
case 0:
|
|
case 2:
|
|
case 4:
|
|
case 6:
|
|
MIPSInt::Int_mxc1(mips, 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(mips, op);
|
|
return 1;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 16:
|
|
{
|
|
switch ((op.encoding >> 0) & 0x3f) {
|
|
// add.s, sub.s, mul.s
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
MIPSInt::Int_FPU3op(mips, op);
|
|
return 1;
|
|
// div.s
|
|
case 3:
|
|
MIPSInt::Int_FPU3op(mips, op);
|
|
return 29;
|
|
// sqrt.s, abs.s, mov.s, neg.s, round.w.s, trunc.w.s, ceil.w.s, floor.w.s, cvt.w.s
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 12:
|
|
case 13:
|
|
case 14:
|
|
case 15:
|
|
case 36:
|
|
MIPSInt::Int_FPU2op(mips, op);
|
|
return 1;
|
|
// dis.int
|
|
case 38:
|
|
MIPSInt::Int_Interrupt(mips, op);
|
|
return 1;
|
|
// c.f.s, c.un.s, c.eq.s, c.ueq.s, c.olt.s, c.ult.s, c.ole.s, c.ule.s, c.sf.s, c.ngle.s, c.seq.s, c.ngl.s, c.lt.s, c.nge.s, c.le.s, c.ngt.s
|
|
case 48:
|
|
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(mips, op);
|
|
return 1;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 20:
|
|
{
|
|
switch ((op.encoding >> 0) & 0x3f) {
|
|
// cvt.s.w
|
|
case 32:
|
|
MIPSInt::Int_FPU2op(mips, op);
|
|
return 1;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 18:
|
|
{
|
|
switch ((op.encoding >> 21) & 0x1f) {
|
|
// mfv, mtv
|
|
case 3:
|
|
case 7:
|
|
MIPSInt::Int_Mftv(mips, 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(mips, op);
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 24:
|
|
{
|
|
switch ((op.encoding >> 23) & 0x7) {
|
|
// vadd, vsub, vdiv
|
|
case 0:
|
|
case 1:
|
|
case 7:
|
|
MIPSInt::Int_VecDo3(mips, op);
|
|
return 2;
|
|
// vsbn
|
|
case 2:
|
|
MIPSInt::Int_Vsbn(mips, op);
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 25:
|
|
{
|
|
switch ((op.encoding >> 23) & 0x7) {
|
|
// vmul
|
|
case 0:
|
|
MIPSInt::Int_VecDo3(mips, op);
|
|
return 2;
|
|
// vdot
|
|
case 1:
|
|
MIPSInt::Int_VDot(mips, op);
|
|
return 2;
|
|
// vscl
|
|
case 2:
|
|
MIPSInt::Int_VScl(mips, op);
|
|
return 2;
|
|
// vhdp
|
|
case 4:
|
|
MIPSInt::Int_VHdp(mips, op);
|
|
return 2;
|
|
// vcrs
|
|
case 5:
|
|
MIPSInt::Int_Vcrs(mips, op);
|
|
return 2;
|
|
// vdet
|
|
case 6:
|
|
MIPSInt::Int_Vdet(mips, op);
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 26:
|
|
{
|
|
switch ((op.encoding >> 24) & 0x3) {
|
|
// RUNBLOCK
|
|
case 0:
|
|
MIPSInt::Int_Emuhack(mips, op);
|
|
return 2;
|
|
// RetKrnl, CallRepl
|
|
case 1:
|
|
case 2:
|
|
MIPSInt::Int_Emuhack(mips, op);
|
|
return 1;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 27:
|
|
{
|
|
switch ((op.encoding >> 23) & 0x7) {
|
|
// vcmp
|
|
case 0:
|
|
MIPSInt::Int_Vcmp(mips, op);
|
|
return 2;
|
|
// vmin, vmax
|
|
case 2:
|
|
case 3:
|
|
MIPSInt::Int_Vminmax(mips, op);
|
|
return 2;
|
|
// vscmp
|
|
case 5:
|
|
MIPSInt::Int_Vscmp(mips, op);
|
|
return 2;
|
|
// vsge
|
|
case 6:
|
|
MIPSInt::Int_Vsge(mips, op);
|
|
return 2;
|
|
// vslt
|
|
case 7:
|
|
MIPSInt::Int_Vslt(mips, op);
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 28:
|
|
{
|
|
switch ((op.encoding >> 0) & 0x3f) {
|
|
// mfic, mtic
|
|
case 36:
|
|
case 38:
|
|
MIPSInt::Int_Special2(mips, op);
|
|
return 1;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 31:
|
|
{
|
|
switch ((op.encoding >> 0) & 0x3f) {
|
|
// ext, ins
|
|
case 0:
|
|
case 4:
|
|
MIPSInt::Int_Special3(mips, op);
|
|
return 1;
|
|
case 24:
|
|
case 32:
|
|
{
|
|
switch ((op.encoding >> 6) & 0x1f) {
|
|
// wsbh, wsbw
|
|
case 2:
|
|
case 3:
|
|
MIPSInt::Int_Allegrex2(mips, op);
|
|
return 1;
|
|
// seb, bitrev, seh
|
|
case 16:
|
|
case 20:
|
|
case 24:
|
|
MIPSInt::Int_Allegrex(mips, op);
|
|
return 1;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
// 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(mips, op);
|
|
return 1;
|
|
// cache
|
|
case 47:
|
|
MIPSInt::Int_Cache(mips, op);
|
|
return 1;
|
|
// ll, sc
|
|
case 48:
|
|
case 56:
|
|
MIPSInt::Int_StoreSync(mips, op);
|
|
return 1;
|
|
// lwc1, swc1
|
|
case 49:
|
|
case 57:
|
|
MIPSInt::Int_FPULS(mips, op);
|
|
return 1;
|
|
// lv.s, sv.s
|
|
case 50:
|
|
case 58:
|
|
MIPSInt::Int_SV(mips, 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(mips, op);
|
|
return 2;
|
|
// vidt
|
|
case 3:
|
|
MIPSInt::Int_Vidt(mips, op);
|
|
return 2;
|
|
// vzero, vone
|
|
case 6:
|
|
case 7:
|
|
MIPSInt::Int_VVectorInit(mips, op);
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 1:
|
|
{
|
|
switch ((op.encoding >> 16) & 0x1f) {
|
|
// vrnds
|
|
case 0:
|
|
MIPSInt::Int_Vrnds(mips, op);
|
|
return 2;
|
|
// vrndi, vrndf1, vrndf2
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
MIPSInt::Int_VrndX(mips, op);
|
|
return 2;
|
|
// vf2h
|
|
case 18:
|
|
MIPSInt::Int_Vf2h(mips, op);
|
|
return 2;
|
|
// vh2f
|
|
case 19:
|
|
MIPSInt::Int_Vh2f(mips, op);
|
|
return 2;
|
|
// vsbz
|
|
case 22:
|
|
MIPSInt::Int_Vsbz(mips, op);
|
|
return 2;
|
|
// vlgb
|
|
case 23:
|
|
MIPSInt::Int_Vlgb(mips, op);
|
|
return 2;
|
|
// vuc2ifs, vc2i, vus2i, vs2i
|
|
case 24:
|
|
case 25:
|
|
case 26:
|
|
case 27:
|
|
MIPSInt::Int_Vx2i(mips, op);
|
|
return 2;
|
|
// vi2uc, vi2c, vi2us, vi2s
|
|
case 28:
|
|
case 29:
|
|
case 30:
|
|
case 31:
|
|
MIPSInt::Int_Vi2x(mips, op);
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 2:
|
|
{
|
|
switch ((op.encoding >> 16) & 0x1f) {
|
|
// vsrt1
|
|
case 0:
|
|
MIPSInt::Int_Vsrt1(mips, op);
|
|
return 2;
|
|
// vsrt2
|
|
case 1:
|
|
MIPSInt::Int_Vsrt2(mips, op);
|
|
return 2;
|
|
// vbfy1, vbfy2
|
|
case 2:
|
|
case 3:
|
|
MIPSInt::Int_Vbfy(mips, op);
|
|
return 2;
|
|
// vocp
|
|
case 4:
|
|
MIPSInt::Int_Vocp(mips, op);
|
|
return 2;
|
|
// vsocp
|
|
case 5:
|
|
MIPSInt::Int_Vsocp(mips, op);
|
|
return 2;
|
|
// vfad
|
|
case 6:
|
|
MIPSInt::Int_Vfad(mips, op);
|
|
return 2;
|
|
// vavg
|
|
case 7:
|
|
MIPSInt::Int_Vavg(mips, op);
|
|
return 2;
|
|
// vsrt3
|
|
case 8:
|
|
MIPSInt::Int_Vsrt3(mips, op);
|
|
return 2;
|
|
// vsrt4
|
|
case 9:
|
|
MIPSInt::Int_Vsrt4(mips, op);
|
|
return 2;
|
|
// vsgn
|
|
case 10:
|
|
MIPSInt::Int_Vsgn(mips, op);
|
|
return 2;
|
|
// vmfvc
|
|
case 16:
|
|
MIPSInt::Int_Vmfvc(mips, op);
|
|
return 2;
|
|
// vmtvc
|
|
case 17:
|
|
MIPSInt::Int_Vmtvc(mips, op);
|
|
return 2;
|
|
// vt4444, vt5551, vt5650
|
|
case 25:
|
|
case 26:
|
|
case 27:
|
|
MIPSInt::Int_ColorConv(mips, op);
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
// vcst
|
|
case 3:
|
|
MIPSInt::Int_Vcst(mips, op);
|
|
return 2;
|
|
// vf2in, vf2iz, vf2iu, vf2id
|
|
case 16:
|
|
case 17:
|
|
case 18:
|
|
case 19:
|
|
MIPSInt::Int_Vf2i(mips, op);
|
|
return 2;
|
|
// vi2f
|
|
case 20:
|
|
MIPSInt::Int_Vi2f(mips, op);
|
|
return 2;
|
|
// vcmov
|
|
case 21:
|
|
MIPSInt::Int_Vcmov(mips, 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(mips, op);
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
// lv, lv.q, sv, sv.q
|
|
case 53:
|
|
case 54:
|
|
case 61:
|
|
case 62:
|
|
MIPSInt::Int_SVQ(mips, 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(mips, op);
|
|
return 2;
|
|
// viim.s, vfim.s
|
|
case 6:
|
|
case 7:
|
|
MIPSInt::Int_Viim(mips, op);
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
case 60:
|
|
{
|
|
switch ((op.encoding >> 21) & 0x1f) {
|
|
// vmmul, vmmul, vmmul, vmmul
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
MIPSInt::Int_Vmmul(mips, op);
|
|
return 2;
|
|
// v(h)tfm2, v(h)tfm2, v(h)tfm2, v(h)tfm2, v(h)tfm3, v(h)tfm3, v(h)tfm3, v(h)tfm3, v(h)tfm4, v(h)tfm4, v(h)tfm4, v(h)tfm4
|
|
case 4:
|
|
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(mips, op);
|
|
return 2;
|
|
// vmscl, vmscl, vmscl, vmscl
|
|
case 16:
|
|
case 17:
|
|
case 18:
|
|
case 19:
|
|
MIPSInt::Int_Vmscl(mips, op);
|
|
return 2;
|
|
// vcrsp.t/vqmul.q, vcrsp.t/vqmul.q, vcrsp.t/vqmul.q, vcrsp.t/vqmul.q
|
|
case 20:
|
|
case 21:
|
|
case 22:
|
|
case 23:
|
|
MIPSInt::Int_CrossQuat(mips, op);
|
|
return 2;
|
|
case 28:
|
|
{
|
|
switch ((op.encoding >> 16) & 0xf) {
|
|
// vmmov
|
|
case 0:
|
|
MIPSInt::Int_Vmmov(mips, op);
|
|
return 2;
|
|
// vmidt, vmzero, vmone
|
|
case 3:
|
|
case 6:
|
|
case 7:
|
|
MIPSInt::Int_VMatrixInit(mips, op);
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
// vrot
|
|
case 29:
|
|
MIPSInt::Int_Vrot(mips, op);
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
// vflush
|
|
case 63:
|
|
MIPSInt::Int_Vflush(mips, op);
|
|
return 2;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|