mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Add dummy interpreter implementations for the basic COP0 instructions
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 <[email protected]> Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
This commit is contained in:
1 parent
defea54cd2
commit
5dbe9bea91
4 files changed
+62
-5
No files matched your search
@@ -685,6 +685,50 @@ namespace MIPSInt {
|
||||
PC += 4;
|
||||
}
|
||||
|
||||
// Dummy COP0 register file, for kernel-mode code (e.g. flash0:/reboot.bin) that reads/
|
||||
// writes COP0 state directly - ordinary PSP user-mode code never executes these
|
||||
// instructions (kernel state is reached via HLE syscalls instead), so this doesn't need
|
||||
// to model real COP0 semantics (interrupts, exceptions, TLB, ...), just be non-fatal and
|
||||
// give writes-then-reads-back-same-value behavior. Not part of MIPSState (which is
|
||||
// layout-sensitive for JIT register allocation) and not save-stated, in keeping with
|
||||
// "dummy" - revisit if this ever needs to be more than a bail-out.
|
||||
static u32 g_cop0Regs[32];
|
||||
|
||||
void Int_Cop0(MIPSState *mips, MIPSOpcode op) {
|
||||
int rt = _RT;
|
||||
int rd = _RD;
|
||||
|
||||
switch ((op >> 21) & 0x1f) {
|
||||
case 0: //mfc0
|
||||
if (rt != 0)
|
||||
R(rt) = g_cop0Regs[rd];
|
||||
break;
|
||||
|
||||
case 4: //mtc0
|
||||
g_cop0Regs[rd] = R(rt);
|
||||
break;
|
||||
|
||||
case 10: //rdpgpr
|
||||
if (rt != 0)
|
||||
R(rt) = R(rd);
|
||||
break;
|
||||
|
||||
case 11: //mfmc0 (di/ei)
|
||||
if (rt != 0)
|
||||
R(rt) = g_cop0Regs[12]; // Status
|
||||
break;
|
||||
|
||||
case 14: //wrpgpr
|
||||
R(rd) = R(rt);
|
||||
break;
|
||||
|
||||
default:
|
||||
_dbg_assert_msg_(false, "Trying to interpret COP0 instruction that can't be interpreted");
|
||||
break;
|
||||
}
|
||||
PC += 4;
|
||||
}
|
||||
|
||||
void Int_RType2(MIPSState *mips, MIPSOpcode op) {
|
||||
int rs = _RS;
|
||||
int rd = _RD;
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace MIPSInt
|
||||
void Int_Syscall(MIPSState *mips, MIPSOpcode op);
|
||||
|
||||
void Int_mxc1(MIPSState *mips, MIPSOpcode op);
|
||||
void Int_Cop0(MIPSState *mips, MIPSOpcode op);
|
||||
void Int_RelBranch(MIPSState *mips, MIPSOpcode op);
|
||||
void Int_RelBranchRI(MIPSState *mips, MIPSOpcode op);
|
||||
void Int_IType(MIPSState *mips, MIPSOpcode op);
|
||||
|
||||
@@ -144,6 +144,14 @@ int ExecInstruction(MIPSState *mips, MIPSOpcode op) {
|
||||
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:
|
||||
|
||||
@@ -368,23 +368,27 @@ static const MIPSInstruction tableCop2BC2[4] = // 010010 01000 ...xx ...........
|
||||
|
||||
static const MIPSInstruction tableCop0[32] = // 010000 xxxxx ..... ................
|
||||
{
|
||||
INSTR("mfc0", JITFUNC(Comp_Generic), Dis_Generic, 0, OUT_RT), // unused
|
||||
// Dummy interpreter-only implementations (Int_Cop0, Interpreter.cpp) - real hardware
|
||||
// semantics aren't modeled, just enough to not fault. Ordinary user-mode PSP code never
|
||||
// executes these; kernel-mode boot code (flash0:/reboot.bin) does. See
|
||||
// docs/VSHBootInvestigation.md.
|
||||
INSTR("mfc0", JITFUNC(Comp_Generic), Dis_Generic, Int_Cop0, OUT_RT),
|
||||
INVALID,
|
||||
INVALID,
|
||||
INVALID,
|
||||
INSTR("mtc0", JITFUNC(Comp_Generic), Dis_Generic, 0, IN_RT), // unused
|
||||
INSTR("mtc0", JITFUNC(Comp_Generic), Dis_Generic, Int_Cop0, IN_RT),
|
||||
INVALID,
|
||||
INVALID,
|
||||
INVALID,
|
||||
//8
|
||||
INVALID,
|
||||
INVALID,
|
||||
INSTR("rdpgpr", JITFUNC(Comp_Generic), Dis_Generic, 0, 0),
|
||||
INSTR("mfmc0", JITFUNC(Comp_Generic), Dis_Generic, 0, 0),
|
||||
INSTR("rdpgpr", JITFUNC(Comp_Generic), Dis_Generic, Int_Cop0, OUT_RT),
|
||||
INSTR("mfmc0", JITFUNC(Comp_Generic), Dis_Generic, Int_Cop0, OUT_RT),
|
||||
|
||||
INVALID,
|
||||
INVALID,
|
||||
INSTR("wrpgpr", JITFUNC(Comp_Generic), Dis_Generic, 0, 0),
|
||||
INSTR("wrpgpr", JITFUNC(Comp_Generic), Dis_Generic, Int_Cop0, IN_RT),
|
||||
INVALID,
|
||||
//16
|
||||
ENCODING(Cop0CO), ENCODING(Cop0CO), ENCODING(Cop0CO), ENCODING(Cop0CO), ENCODING(Cop0CO), ENCODING(Cop0CO), ENCODING(Cop0CO), ENCODING(Cop0CO),
|
||||
|
||||
Reference in new issue
Block a user