System Control Coprocessor (COP0)
Coprocessor 0 registers for exceptions, interrupts, cache isolation and breakpoints.
This is an old revision of this page, as edited by RemmyLee at 02:44, 23 October 2026. Edit this revision | Latest revision
Summary
COP0 is the section of the R3000 that handles errors and interrupts. When an external interrupt or an error other than a debug error occurs, the content of the program counter is saved to the EPC register of COP0 and the processor jumps to 0x00000080.1
The PlayStation has no TLB, so the virtual memory registers of other MIPS processors are absent. COP0 keeps the exception registers, the status register, a revision register and a set of debug registers. They are read with MFC0 and written with MTC0, and the RFE instruction is the only COP0 command.2345
| Number | Mnemonic | Name | R/W |
|---|---|---|---|
| cop0r0 to r2 | Not present | ||
| cop0r3 | BPC | Breakpoint program counter | R/W |
| cop0r4 | Not present | ||
| cop0r5 | BDA | Breakpoint data address | R/W |
| cop0r6 | TAR | Target address | R |
| cop0r7 | DCIC | Debug and cache invalidate control | R/W |
| cop0r8 | BadA | Bad address | R |
| cop0r9 | BDAM | Breakpoint data address mask | R/W |
| cop0r10 | Not present | ||
| cop0r11 | BPCM | Breakpoint program counter mask | R/W |
| cop0r12 | SR | Status register | R/W |
| cop0r13 | CAUSE | Cause of the last exception | R |
| cop0r14 | EPC | Exception program counter | R |
| cop0r15 | PRID | Processor revision identifier | R |
| cop0r16 to r31 | Garbage | ||
| cop0r32 to r63 | Control registers, not present |
Reading cop0r0 to r2, r4, r10 or any control register causes a reserved instruction exception (excode 0Ah). The TLB commands TLBR, TLBWI, TLBWR and TLBP cause the same exception. The conditional COP0 branches and the COP0 load and store instructions instead cause a coprocessor unusable exception (excode 0Bh).5
Exceptions
An exception is raised when an error such as a bus error or a reserved instruction is detected. It triggers a jump to 0x00000080 in the same way as a device interrupt, but unlike a device interrupt it cannot be masked. Sony's manual lists the following exception categories:6
| Code | Content |
|---|---|
| AdEL | Address error (during data loading or instruction fetching) |
| AdES | Address error (during data storage) |
| IBE | Bus error (during instruction fetching) |
| DBE | Bus error (during data loading or data storing) |
| Sys | System call (during syscall instruction execution) |
| Bp | Breakpoint (during break instruction execution) |
Exception Vectors
The BEV bit of SR selects the exception vectors. The PlayStation uses only the BEV=0 vectors, and apart from the reset vector the BIOS ROM contains none of the BEV=1 vectors. Sony's manuals give the general vector as 0x00000080 and psx-spx as 80000080h. KUSEG is a mirror of KSEG0, so both addresses reach the same memory.78
| Exception | BEV=0 | BEV=1 |
|---|---|---|
| Reset | BFC00000h | BFC00000h |
| UTLB miss (not used) | 80000000h | BFC00100h |
| COP0 break (debug) | 80000040h | BFC00140h |
| General (interrupts and exceptions) | 80000080h | BFC00180h |
psx-spx reports that a change to the vectors at 800000xxh was sometimes seen by the I-cache without a flush, but not always. A change at the KUSEG mirror 000000xxh needs a flush, and flushing after any change to the vector code is the safe course.7
Exception Priority
When several exceptions occur at once the highest one is taken. psx-spx gives this order from highest to lowest:9
| Exception | Stage |
|---|---|
| Reset | Any time |
| AdEL | Data load |
| AdES | Data store |
| DBE | Data load or store |
| Ovf | ALU |
| Int | ALU |
| Sys | Instruction decode |
| Bp | Instruction decode |
| RI | Instruction decode |
| CpU | Instruction decode |
| AdEL | Instruction fetch address |
| IBE | End of instruction fetch |
cop0r13 - CAUSE - Exception Cause
CAUSE describes the most recent exception. It is read only, except that the two software interrupt bits can be written.10
| Bits | Name | Content |
|---|---|---|
| 0 to 1 | Zero | |
| 2 to 6 | ExcCode | Kind of exception |
| 7 | Zero | |
| 8 to 9 | Sw | Software interrupts (R/W) |
| 10 to 15 | IP | Interrupt pending |
| 16 to 27 | Zero | |
| 28 to 29 | CE | Coprocessor number for a coprocessor unusable exception |
| 30 | BT | Branch taken, when BD is set (TAR holds the target) |
| 31 | BD | Exception in a branch delay slot (EPC points to the branch) |
A pending interrupt bit causes an interrupt while the matching mask bit in SR is set. On the PlayStation only IP bit 10 is wired to the interrupt controller. Software sets bits 8 and 9 to request an exception and must clear them before it returns from the handler.1011
| Value | Mnemonic | Content |
|---|---|---|
| 00h | INT | External interrupt |
| 01h | MOD | TLB modification (none on the PlayStation) |
| 02h | TLBL | TLB load (none on the PlayStation) |
| 03h | TLBS | TLB store (none on the PlayStation) |
| 04h | AdEL | Address error, data load or instruction fetch |
| 05h | AdES | Address error, data store |
| 06h | IBE | Bus error on instruction fetch |
| 07h | DBE | Bus error on data load or store |
| 08h | Sys | SYSCALL instruction |
| 09h | Bp | BREAK instruction or debug break |
| 0Ah | RI | Reserved instruction |
| 0Bh | CpU | Coprocessor unusable |
| 0Ch | Ovf | Arithmetic overflow |
| 0Dh to 1Fh | Not used |
An address error is raised by a misaligned address and by an access outside KUSEG in user mode.10
cop0r12 - SR - Status Register
SR holds the interrupt enable and kernel mode bits as a three-level stack, the interrupt mask, the cache isolation bits and the coprocessor enables:12
| Bits | Name | Content |
|---|---|---|
| 0 | IEc | Current interrupt enable (0 = disable, 1 = enable) |
| 1 | KUc | Current mode (0 = kernel, 1 = user) |
| 2 | IEp | Previous interrupt enable |
| 3 | KUp | Previous mode |
| 4 | IEo | Old interrupt enable |
| 5 | KUo | Old mode |
| 6 to 7 | Zero | |
| 8 to 15 | Im | Interrupt mask |
| 16 | IsC | Isolate cache |
| 17 | SwC | Swapped cache mode (no effect on the PlayStation) |
| 18 | PZ | Write cache parity bits as 0 |
| 19 | CM | Result of the last load with the D-cache isolated |
| 20 | PE | Cache parity error (no exception) |
| 21 | TS | TLB shutdown |
| 22 | BEV | Boot exception vectors (0 = RAM, 1 = ROM) |
| 23 to 24 | Zero | |
| 25 | RE | Reverse endianness (may not exist on the PlayStation) |
| 26 to 27 | Zero | |
| 28 | CU0 | COP0 enable (0 = kernel mode only, 1 = kernel and user mode) |
| 29 | CU1 | COP1 enable (none on the PlayStation) |
| 30 | CU2 | COP2 enable (GTE) |
| 31 | CU3 | COP3 enable (none on the PlayStation) |
With IsC set, loads and stores reach the cache instead of main memory. Which part of the I-cache they reach depends on the BCC register at FFFE0130h. With TAG and IS1 set the stores write the tag memory, and with IS1 alone they write the code words. The kernel flushes the I-cache this way, as the memory control page shows.12
The COP2 enable bit takes effect after a delay of about 2 cycles. It is the only COP0 write with a known delay.13
cop0r14 - EPC - Exception Program Counter
EPC holds the address at which the exception occurred. When BD in CAUSE is set the exception occurred in a branch delay slot, and EPC then holds the address of the branch instead. That address is 4 less than the address of the faulting instruction.14
An interrupt handler should always return to EPC+0 whatever the value of BD is. If BD is set, the branch then executes again, which is needed because EPC does not store the branch destination. Other exceptions may need BD handled, and when BD is 0 the handler may return to EPC+0 to retry the instruction or EPC+4 to skip it.14
A jump to an invalid address executes without an exception. The error is raised at the target, so EPC (and BadA for an address error) points to the faulty address rather than to the jump.14
Interrupts and GTE Commands
When an interrupt occurs on a GTE command, the command is executed but EPC still points to it. A handler that returns to EPC would therefore execute the command twice, and the second run can give a wrong result if it reuses the first run's output as input. The handler must skip the command:15
if (cause AND 7Ch)=00h ;if excode=interrupt
if ([epc] AND FE000000h)=4A000000h ;and opcode=cop2cmd
epc=epc+4 ;then skip that opcode
Only newer BIOS versions do this completely, and the fix does not work in a branch delay slot. The safe course is therefore to keep GTE commands out of branch delay slots. The Crash Bandicoot games, Jinx and Spyro the Dragon draw broken geometry when the interrupt handler does not skip the command.15
RFE - Return From Exception
RFE (COP0 command 10h) pops the interrupt enable and mode stack of SR. It copies bits 2 and 3 to bits 0 and 1 and bits 4 and 5 to bits 2 and 3, and leaves bits 4 and 5 unchanged.16
RFE does not jump. The handler copies EPC to a general register, normally K0, jumps to it and executes RFE in the branch delay slot of that jump. No register can survive this, because K0 holds the return address. A handler that expects nested exceptions also saves EPC and SR in memory.16
mfc0 k0, epc ;get return address
... ;handle the exception
jr k0 ;jump to K0 after the next opcode
rfe ;restore SR bits 0 to 5
cop0r8 - BadA - Bad Address
BadA holds the address whose reference caused an address error. It is updated only by address errors (excode 04h and 05h), and every other exception, bus errors included, leaves it unchanged.17
cop0r6 - TAR - Target Address
When an exception occurs in the delay slot of a branch or jump that is taken (CAUSE bits 31 and 30 both set), TAR holds the destination of the branch.18
cop0r15 - PRID - Processor Revision
Bits 0 to 7 hold the revision and bits 8 to 15 the implementation. On a PlayStation with the CXD8606CQ CPU PRID reads 00000002h.19
cop0r16 to r31 - Garbage
These registers return garbage without raising an exception. A read shortly after reading a valid register usually returns that register's value, while later reads return values such as 00000020h, 00000040h or 00000100h. They can be read even in user mode with COP0 disabled, where every other COP0 access raises a coprocessor unusable exception.20
Debug Registers
The debug registers come from the LSI LR33300 family and are described in chapter 14 of the L64360 datasheet and chapter 4 of the LR33300/LR33310 datasheet. Ordinary R30xx CPUs such as the IDT R3041 and R3051 do not have them.21
cop0r7 - DCIC - Debug and Cache Invalidate Control
| Bit | Name | Content |
|---|---|---|
| 0 | DB | Set on any break (R/W) |
| 1 | PC | Set on a BPC program counter break (R/W) |
| 2 | DA | Set on a BDA data address break (R/W) |
| 3 | R | Set on a BDA data read break (R/W) |
| 4 | W | Set on a BDA data write break (R/W) |
| 5 | T | Set on a trace break (R/W) |
| 6 to 11 | Zero | |
| 12 to 13 | Jump redirection (0 = off, 1 to 3 = on) | |
| 14 to 15 | Unknown (R/W) | |
| 16 to 22 | Zero | |
| 23 | DE | Debug enable (enables bits 24 to 31) |
| 24 | PCE | Program counter breakpoint enable |
| 25 | DAE | Data address breakpoint enable |
| 26 | DR | Break on data read when bit 25 is set |
| 27 | DW | Break on data write when bit 25 is set |
| 28 | TE | Trace enable (break on branch, jump or call) |
| 29 | KD | Break in kernel mode |
| 30 | UD | Break in user mode |
| 31 | TR | Trap enable (0 = set status bits only, 1 = jump to the debug vector) |
On a breakpoint match the CPU jumps to 80000040h instead of 80000080h. CAUSE then holds excode 09h as for a BREAK instruction, and EPC holds the return address. The handler at 80000040h must disable the breakpoints before it jumps to the actual exception handler, and a trace break in particular must be disabled first.21
Breakpoint Address Registers
BPC (cop0r3) and BPCM (cop0r11) set the program counter breakpoint, which fires when ((PC XOR BPC) AND BPCM) is 0. BDA (cop0r5) and BDAM (cop0r9) set the data breakpoint, which fires when ((addr XOR BDA) AND BDAM) is 0.21
A BREAK instruction patched into the code gives further breakpoints. It sets the same excode 09h but goes to the normal handler at 80000080h.21
Jump Redirection
With DCIC bits 12 to 13 nonzero the CPU watches for a load of a register followed by a jump or call through that register. On that sequence it sets PC to the word at 00000000h and stores nothing useful in COP0, not even EPC. psx-spx therefore considers jump redirection close to unusable.21
Other Uses
Legacy of Kain: Soul Reaver stores LibCrypt copy protection values in the debug registers as a hidden location. Cheat devices use COP0 breaks as a hook during boot, because the expansion ROM header has only pre-boot and post-boot entry points. Older cheat firmware breaks at BFC06xxxh in the BIOS ROM and later firmware at 80030000h in RAM.21
References
-
^ Sony Computer Entertainment Inc. PlayStation Operating System. August 1998. Page 2-8.
-
^ Sony Computer Entertainment Inc. PlayStation Hardware. August 1998. Page 2-3.
-
^ psx-spx. CPU Specifications, COP0 - Register Summary. https://psx-spx.consoledev.net/cpuspecifications/
-
^ psx-spx. CPU Specifications, Coprocessor Opcode/Parameter Encoding. https://psx-spx.consoledev.net/cpuspecifications/
-
^ a b psx-spx. CPU Specifications, COP0 - Misc. https://psx-spx.consoledev.net/cpuspecifications/
-
^ Sony Computer Entertainment Inc. PlayStation Hardware. August 1998. Page 2-7, Table 2-4.
-
^ a b psx-spx. CPU Specifications, Exception Vectors. https://psx-spx.consoledev.net/cpuspecifications/
-
^ psx-spx. Memory Map, KUSEG,KSEG0,KSEG1,KSEG2 Memory Regions. https://psx-spx.consoledev.net/memorymap/
-
^ psx-spx. CPU Specifications, Exception Priority. https://psx-spx.consoledev.net/cpuspecifications/
-
^ a b c psx-spx. CPU Specifications, cop0r13 - CAUSE. https://psx-spx.consoledev.net/cpuspecifications/
-
^ psx-spx. Interrupts, PSX specific COP0 Notes. https://psx-spx.consoledev.net/interrupts/
-
^ a b psx-spx. CPU Specifications, cop0r12 - SR - System status register. https://psx-spx.consoledev.net/cpuspecifications/
-
^ psx-spx. CPU Specifications, Caution - Store Delay. https://psx-spx.consoledev.net/cpuspecifications/
-
^ a b c psx-spx. CPU Specifications, cop0r14 - EPC - Return Address from Trap. https://psx-spx.consoledev.net/cpuspecifications/
-
^ a b psx-spx. CPU Specifications, Interrupts vs GTE Commands. https://psx-spx.consoledev.net/cpuspecifications/
-
^ a b psx-spx. CPU Specifications, cop0cmd=10h - RFE opcode. https://psx-spx.consoledev.net/cpuspecifications/
-
^ psx-spx. CPU Specifications, cop0r8 - BadVaddr - Bad Virtual Address. https://psx-spx.consoledev.net/cpuspecifications/
-
^ psx-spx. CPU Specifications, cop0r6 - TAR - Target Address. https://psx-spx.consoledev.net/cpuspecifications/
-
^ psx-spx. CPU Specifications, cop0r15 - PRID. https://psx-spx.consoledev.net/cpuspecifications/
-
^ psx-spx. CPU Specifications, cop0r16-r31 - Garbage. https://psx-spx.consoledev.net/cpuspecifications/
-
^ a b c d e f psx-spx. CPU Specifications, COP0 - Debug Registers. https://psx-spx.consoledev.net/cpuspecifications/