Interrupts
1F801070h I_STAT - Interrupt status register (R=Status, W=Acknowledge)
1F801074h I_MASK - Interrupt mask register (R/W)
Status: Read I_STAT (0=No IRQ, 1=IRQ)
Acknowledge: Write I_STAT (0=Clear Bit, 1=No change)
Mask: Read/Write I_MASK (0=Disabled, 1=Enabled)
0 IRQ0 VBLANK (PAL=50Hz, NTSC=60Hz)
1 IRQ1 GPU Can be requested via GP0(1Fh) command (rarely used)
2 IRQ2 CDROM
3 IRQ3 DMA
4 IRQ4 TMR0 Timer 0 aka Root Counter 0 (Sysclk or Dotclk)
5 IRQ5 TMR1 Timer 1 aka Root Counter 1 (Sysclk or H-blank)
6 IRQ6 TMR2 Timer 2 aka Root Counter 2 (Sysclk or Sysclk/8)
7 IRQ7 Controller and Memory Card - Byte Received Interrupt
8 IRQ8 SIO
9 IRQ9 SPU
10 IRQ10 Controller - Lightpen Interrupt. Also shared by PIO and DTL cards.
11-15 Not used (always zero)
16-31 Garbage
Secondary IRQ10 Controller (Port 1F802030h)
Interrupt Request / Execution
The interrupt request bits in I_STAT are edge-triggered, ie. the get set ONLY
if the corresponding interrupt source changes from "false to true".
If one or more interrupts are requested and enabled, ie. if "(I_STAT AND
I_MASK)=nonzero", then cop0r13.bit10 gets set, and when cop0r12.bit10 and
cop0r12.bit0 are set, too, then the interrupt gets executed.
Interrupt Acknowledge
To acknowledge an interrupt, write a "0" to the corresponding bit in I_STAT.
Most interrupts (except IRQ0,4,5,6) must be additionally acknowledged at the
I/O port that has caused them (eg. JOY_CTRL.bit4).
Observe that the I_STAT bits are edge-triggered (they get set only on
High-to-Low, or False-to-True edges). The correct acknowledge order is:
First, acknowledge I_STAT (eg. I_STAT.bit7=0)
Then, acknowledge corresponding I/O port (eg. JOY_CTRL.bit4=1)
COP0 Interrupt Handling
Relevant COP0 registers are cop0r13 (CAUSE, reason flags), and cop0r12 (SR,
control flags), and cop0r14 (EPC, return address), and, cop0cmd=10h (aka RFE
opcode) is used to prepare the return from interrupts. For more info, see
COP0 - Exception Handling
PSX specific COP0 Notes
COP0 has six hardware interrupt bits, of which, the PSX uses only cop0r13.bit10
(the other ones, cop0r13.bit11-15 are always zero). cop0r13.bit10 is NOT a
latch, ie. it gets automatically cleared as soon as "(I_STAT AND I_MASK)=zero",
so there's no need to do an acknowledge at the cop0 side. COP0 additionally has
two software interrupt bits, cop0r13.bit8-9, which do exist in the PSX, too,
these bits are read/write-able latches which can be set/cleared manually to
request/acknowledge exceptions by software.
PS2 IOP interrupts
The PS2's IOP has the same interrupt controller as the PS1 but with more
channels. For more details, see:
ps2tek - IOP Interrupts