Implement mfic and mtic

Both were no-ops, so mfic left its destination unchanged. They read and
write the interrupt enable flag that sceKernelCpuSuspendIntr/ResumeIntr
use. Only bit 0 counts for mtic, which also goes for
sceKernelCpuResumeIntr, since on hardware it's just mtic.

Adds the intr/mfic test, recorded on hardware.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-09-25 11:08:13 -06:00
1 parent a9d63d2ee1
commit feb6caa3c4
5 files changed
+18 -18

No files matched your search

+2 -1
View File
@@ -98,7 +98,8 @@ static int sceKernelCpuSuspendIntr()
static void sceKernelCpuResumeIntr(u32 enable)
{
VERBOSE_LOG(Log::sceIntc, "sceKernelCpuResumeIntr(%i)", enable);
if (enable)
// This is mtic a0, $0, which only looks at bit 0 (tests/intr/mfic).
if (enable & 1)
{
__EnableInterrupts();
hleRunInterrupts();
+12 -14
View File
@@ -35,6 +35,7 @@
#include "Core/HLE/HLE.h"
#include "Core/HLE/HLETables.h"
#include "Core/HLE/ReplaceTables.h"
#include "Core/HLE/sceKernelInterrupt.h"
#include "Core/HW/GpioMMIO.h"
#define R(i) (mips->r[i])
@@ -1054,25 +1055,22 @@ namespace MIPSInt {
PC += 4;
}
// The interrupt enable flag, shared with the HLE sceKernelCpuSuspendIntr/ResumeIntr, which on
// hardware are just mfic v0, $0; mtic zero, $0 and mtic a0, $0. Only $0 exists.
void Int_Special2(MIPSState *mips, MIPSOpcode op) {
static int reported = 0;
int rt = _RT;
switch (op & 0x3F) {
case 36: // mfic
// move from interrupt controller, not implemented
// See related report https://report.ppsspp.org/logs/kind/316 for possible locations.
// Also see https://forums.ps2dev.org/viewtopic.php?p=32700#p32700 .
// TODO: Should we actually implement this?
if (!reported) {
WARN_LOG(Log::CPU, "MFIC Disable/Enable Interrupt CPU instruction");
reported = 1;
}
if (rt != 0)
R(rt) = __InterruptsEnabled() ? 1 : 0;
break;
case 38: // mtic
// move to interrupt controller, not implemented
if (!reported) {
WARN_LOG(Log::CPU, "MTIC Disable/Enable Interrupt CPU instruction");
reported = 1;
}
// Only bit 0 counts: mtic 2 disables. Pending interrupts run at the next scheduling point,
// not right away as with sceKernelCpuResumeIntr.
if (R(rt) & 1)
__EnableInterrupts();
else
__DisableInterrupts();
break;
}
PC += 4;
+2 -2
View File
@@ -261,9 +261,9 @@ static const MIPSInstruction tableSpecial2[64] = // 011100 ..... ..... ..... ...
INVALID_X_8,
//32
INVALID, INVALID, INVALID, INVALID,
INSTR("mfic", JITFUNC(Comp_Generic), Dis_Generic, Int_Special2, OUT_OTHER),
INSTR("mfic", JITFUNC(Comp_Generic), Dis_Generic, Int_Special2, OUT_RT | OUT_OTHER),
INVALID,
INSTR("mtic", JITFUNC(Comp_Generic), Dis_Generic, Int_Special2, OUT_OTHER),
INSTR("mtic", JITFUNC(Comp_Generic), Dis_Generic, Int_Special2, IN_RT | OUT_OTHER),
INVALID,
//40
INVALID_X_8,
+1
View File
@@ -262,6 +262,7 @@ tests_good = [
"hash/sha1ctx",
"hle/check_not_used_uids",
"intr/intr",
"intr/mfic",
"intr/enablesub",
"intr/suspended",
"intr/vblank/vblank",