ps2tek - Documentation on PS2 internals</title> </HEAD> <TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0><FONT SIZE=+2>   Contents </FONT></TABLE>
PS2 Overview
Memory Map
I/O Maps
Emotion Engine (EE)</B>
EE Timers</B>
Graphics Interface (GIF)
DMA Controller (DMAC)
Graphics Synthesizer (GS)
Vector Interface (VIF)
Vector Unit (VU)
Image Processing Unit (IPU)
EE Interrupt Controller (INTC)
IOP Hardware and Peripherals
Subsystem Interface (SIF)
BIOS


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0><FONT SIZE=+2>   PS2 Overview </FONT></TABLE>
This document, inspired by nocash's websites for various consoles, aims to be a comprehensive reference for the PlayStation 2 hardware. While it is far from complete, it is usable as a reference for what information is documented.

PS2 Hardware
</TABLE>
EE Virtual/Physical Memory Map
> Emotion Engine (EE) - Main CPU. DMAC - Intelligent DMA controller. Used for accessing most peripherals on the EE. EE Timers - Four 16-bit timers. Graphics Interface (GIF) - Transmits graphical data to the GS. Vector Interface (VIF) - Decompresses vector data, uploads microprograms to the VUs, and sends graphical data to the GIF. Vector Units (VUs) - Custom DSPs used to process vertex data, physics calculations, and other related tasks. Image Processing Unit (IPU) - MPEG1/MPEG2 video decoder. Scratchpad - 16 KB of fast memory. Graphics Synthesizer (GS) - Fixed-function GPU. Designed to draw polygons very, very fast. PCRTC - Renders GS output to a television screen. Can be programmed to work on a variety of TVs, including NTSC and PAL. Input/Output Processor (IOP) - Duplicate of the PSX's CPU. Used for slower input/output tasks and for PSX backwards compatibility. IOP DMA - Same channels as on the PSX, along with additional channels exclusive to PS2 mode. IOP Timers - Same timers as on the PSX, with three additional 32-bit counters. CDVD Drive - Reads disc media. Also responsible for MagicGate decryption. SIO2 - Serial ports used to read controllers and memory cards. SPU2 - Sound processor. Similar to the PSX SPU with added features. DEV9 - Expansion port. Used mainly for the PS2 HDD and Network Adapter. USB FireWire Subsystem Interface (SIF) - Allows the EE and IOP to communicate with each other. </TD></TR></TABLE>

<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   Memory Map </FONT>
> KUSEG: 00000000h-7FFFFFFFh User segment KSEG0: 80000000h-9FFFFFFFh Kernel segment 0 KSEG1: A0000000h-BFFFFFFFh Kernel segment 1 KSSEG: C0000000h-DFFFFFFFh Supervisor segment KSEG3: E0000000h-FFFFFFFFh Kernel segment 3 Virtual Physical 00000000h 00000000h 32 MB Main RAM (first 1 MB reserved for kernel) 20000000h 00000000h 32 MB Main RAM, uncached 30100000h 00100000h 31 MB Main RAM, uncached and accelerated 10000000h 10000000h 64 KB I/O registers 11000000h 11000000h 4 KB VU0 code memory 11004000h 11004000h 4 KB VU0 data memory 11008000h 11008000h 16 KB VU1 code memory 1100C000h 1100C000h 16 KB VU1 data memory 12000000h 12000000h 8 KB GS privileged registers 1C000000h 1C000000h 2 MB IOP RAM 1FC00000h 1FC00000h 4 MB BIOS, uncached (rom0) 9FC00000h 1FC00000h 4 MB BIOS, cached (rom09) BFC00000h 1FC00000h 4 MB BIOS, uncached (rom0b) 70000000h --------- 16 KB Scratchpad RAM (only accessible via virtual addressing) </TD></TR></TABLE> EE RAM is reportedly expandable up to 256 MB. However, the maximum seen in practice is 128 MB, for special TOOL consoles.

IOP Physical Memory Map
> KUSEG: 00000000h-7FFFFFFFh User segment KSEG0: 80000000h-9FFFFFFFh Kernel segment 0 KSEG1: A0000000h-BFFFFFFFh Kernel segment 1 Physical 00000000h 2 MB Main RAM (same as on PSX) 1D000000h SIF registers 1F800000h 64 KB Various I/O registers 1F900000h 1 KB SPU2 registers 1FC00000h 4 MB BIOS (rom0) - Same as EE BIOS FFFE0000h (KSEG2) Cache control </TD></TR></TABLE>
Additional Memory
</TABLE>
EE Map
EE Timers
> 4 MB GS VRAM (used for framebuffer, textures, zbuffer, etc) 2 MB SPU2 work RAM - quadrupled from PSX's SPU 8 MB Memory card </TD></TR></TABLE>


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   I/O Maps </FONT>
> 100000xxh Timer 0 100008xxh Timer 1 100010xxh Timer 2 100018xxh Timer 3 </TD></TR></TABLE> Image Processing Unit (IPU)
> 10002000h 8h IPU Command 10002010h 4h IPU Control 10002020h 4h IPU bit pointer control 10002030h 8h Top of bitstream 10007000h 10h Out FIFO (read) 10007010h 10h In FIFO (write) </TD></TR></TABLE> Graphics Interface (GIF)
> 10003000h 4h GIF_CTRL - Control register 10003010h 4h GIF_MODE - Mode setting 10003020h 4h GIF_STAT - Status 10003040h 4h GIF_TAG0 - Bits 0-31 of tag before 10003050h 4h GIF_TAG1 - Bits 32-63 of tag before 10003060h 4h GIF_TAG2 - Bits 64-95 of tag before 10003070h 4h GIF_TAG3 - Bits 96-127 of tag before 10003080h 4h GIF_CNT - Transfer status counter 10003090h 4h GIF_P3CNT - PATH3 transfer status counter 100030A0h 4h GIF_P3TAG - Bits 0-31 of PATH3 tag when interrupted 10006000h 10h GIF FIFO </TD></TR></TABLE> DMA Controller (DMAC)
> 100080xxh VIF0 - channel 0 100090xxh VIF1 - channel 1 1000A0xxh GIF - channel 2 1000B0xxh IPU_FROM - channel 3 1000B4xxh IPU_TO - channel 4 1000C0xxh SIF0 - channel 5 1000C4xxh SIF1 - channel 6 1000C8xxh SIF2 - channel 7 1000D0xxh SPR_FROM - channel 8 1000D4xxh SPR_TO - channel 9 1000E000h 4h D_CTRL - DMAC control 1000E010h 4h D_STAT - DMAC interrupt status 1000E020h 4h D_PCR - DMAC priority control 1000E030h 4h D_SQWC - DMAC skip quadword 1000E040h 4h D_RBSR - DMAC ringbuffer size 1000E050h 4h D_RBOR - DMAC ringbuffer offset 1000E060h 4h D_STADR - DMAC stall address 1000F520h 4h D_ENABLER - DMAC disabled status 1000F590h 4h D_ENABLEW - DMAC disable </TD></TR></TABLE> Interrupt Controller (INTC)
> 1000F000h 4h INTC_STAT - Interrupt status 1000F010h 4h INTC_MASK - Interrupt mask </TD></TR></TABLE> Subsystem Interface (SIF)
> 1000F200h 4h MSCOM - EE->IOP communication 1000F210h 4h SMCOM - IOP->EE communication 1000F220h 4h MSFLAG - EE->IOP flags 1000F230h 4h SMFLAG - IOP->EE flags 1000F240h 4h Control register </TD></TR></TABLE> Privileged GS registers
> 12000000h 8h PMODE - various PCRTC controls 12000010h 8h SMODE1 12000020h 8h SMODE2 12000030h 8h SRFSH 12000040h 8h SYNCH1 12000050h 8h SYNCH2 12000060h 8h SYNCV 12000070h 8h DISPFB1 - display buffer for output circuit 1 12000080h 8h DISPLAY1 - output circuit 1 control 12000090h 8h DISPFB2 - display buffer for output circuit 2 120000A0h 8h DISPLAY2 - output circuit 2 control 120000B0h 8h EXTBUF 120000C0h 8h EXTDATA 120000D0h 8h EXTWRITE 120000E0h 8h BGCOLOR - background color 12001000h 8h GS_CSR - control register 12001010h 8h GS_IMR - GS interrupt control 12001040h 8h BUSDIR - transfer direction 12001080h 8h SIGLBLID - signal </TD></TR></TABLE> Misc registers
> 1000F180h 1h KPUTCHAR - Console output 1000F430h 4h MCH_DRD - RDRAM initialization 1000F440h 4h MCH_RICM </TD></TR></TABLE>
IOP Map
Subsystem Interface (SIF)
> 1D000000h 4h MSCOM - EE->IOP communication 1D000010h 4h SMCOM - IOP->EE communication 1D000020h 4h MSFLAG - EE->IOP flags 1D000030h 4h SMFLAG - IOP->EE flags 1D000040h 4h Control register </TD></TR></TABLE> CDVD Drive
> 1F402004h 1h Current N command 1F402005h 1h N command status (R) 1F402005h 1h N command params (W) 1F402006h 1h Error 1F402007h 1h Send BREAK command 1F402008h 1h CDVD I_STAT - interrupt register 1F40200Ah 1h Drive status 1F40200Fh 1h Disk type 1F402016h 1h Current S command 1F402017h 1h S command status 1F402018h 1h S command params </TD></TR></TABLE> Interrupt Control
> 1F801070h 4h I_STAT - Interrupt status 1F801074h 4h I_MASK - Interrupt mask 1F801078h 1h I_CTRL - Global interrupt disable </TD></TR></TABLE> DMA registers
> 1F80108xh MDECin - channel 0 1F80109xh MDECout - channel 1 1F8010Axh SIF2 (GPU) - channel 2 1F8010Bxh CDVD - channel 3 1F8010Cxh SPU2 Core0 - channel 4 1F8010Dxh PIO - channel 5 1F8010Exh OTC - channel 6 1F80150xh SPU2 Core1 - channel 7 1F80151xh DEV9 - channel 8 1F80152xh SIF0 - channel 9 1F80153xh SIF1 - channel 10 1F80154xh SIO2in - channel 11 1F80155xh SIO2out - channel 12 1F8010F0h 4h DPCR - DMA priority control 1F8010F4h 4h DICR - DMA interrupt control 1F801570h 4h DPCR2 - DMA priority control 2 1F801574h 4h DICR2 - DMA priority control 2 1F801578h 4h DMACEN - DMA global enable 1F80157Ch 4h DMACINTEN - DMA global interrupt control </TD></TR></TABLE> IOP Timers
> 1F80110xh Timer 0 1F80111xh Timer 1 1F80112xh Timer 2 1F80148xh Timer 3 1F80149xh Timer 4 1F8014Axh Timer 5 </TD></TR></TABLE> Serial Interface (SIO2)
> 1F808200h 40h SEND3 buffer 1F808240h 20h SEND1/2 buffers 1F808260h 1h In FIFO 1F808264h 1h Out FIFO 1F808268h 4h SIO2 control 1F80826Ch 4h RECV1 1F808270h 4h RECV2 1F808274h 4h RECV3 </TD></TR></TABLE> Sound Processing Unit (SPU2)
</TABLE>
The EE is the main CPU of the PS2. Also known as the R5900, it is a custom MIPS core designed by Sony and Toshiba.

EE Reference
EE Architecture
EE Registers
EE Instruction Decoding
EE RDRAM initialization

EE COP0 Registers
EE COP0 Exception Handling
EE COP0 Memory Management
EE COP0 Caches
EE COP0 Timer

EE COP1 Registers
EE COP1 Floating Point Format


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0></TABLE>
On real hardware, the EE itself contains many different hardware units along with the main CPU, such as the DMAC and IPU. This document will consider the EE as only the MIPS CPU and its coprocessors.
> 1F900000h 180h Core0 Voice 0-23 registers 1F900190h 4h Key ON 0/1 1F900194h 4h Key OFF 0/1 1F90019Ah 2h Core attributes 1F90019Ch 4h Interrupt address H/L 1F9001A8h 4h DMA transfer address H/L 1F9001ACh 2h Internal transfer FIFO 1F9001B0h 2h AutoDMA status 1F9001C0h 120h Core0 Voice 0-23 start/loop/next addresses 1F900340h 4h ENDX 0/1 1F900344h 2h Status register ... above addresses repeat for Core1 starting at 1F900400h ... 1F900760h 2h Master Volume Left 1F900762h 2h Master Volume Right 1F900764h 2h Effect Volume Left 1F900766h 2h Effect Volume Right 1F900768h 2h Core1 External Input Volume Left 1F90076Ah 2h Core1 External Input Volume Right </TD></TR></TABLE>


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   Emotion Engine (EE) </FONT>
<FONT SIZE=+2>   EE Architecture </FONT>
</TABLE>
General-Purpose Registers (GPRs)
As per MIPS tradition, the EE has 32 GPRs. Notably, they are all 128-bit, though the full 128 bits are only used in certain instructions.
> Mix of MIPS III and MIPS IV with dozens of custom instructions Speed: 294.912 MHz Superscalar, able to issue two instructions per cycle in ideal conditions Support for custom integer SIMD instructions known as MMI (MultiMedia Instructions) 16 KB instruction cache 8 KB data cache 16 KB scratchpad. Fast memory directly accessible by program and DMAC COP0 system coprocessor. Responsible for handling memory management, exceptions, caches, and performance counters COP1 FPU. Fast single-precision unit COP2 VU0. SIMD floating-point processor that can either run as a separate CPU or be used by the EE core for COP2 instructions </TD></TR></TABLE> See Vector Unit (VU) for a general discussion on the VUs, including VU0.


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   EE Registers </FONT>
> Name Convention zero Hardwired to 0, writes are ignored at Temporary register used for pseudo-instructions v0-v1 Return register, holds values returned by functions a0-a3 Argument registers, holds first four parameters passed to a function t0-t7 Temporary registers. t0-t3 may also be used as additional argument registers s0-s7 Saved registers. Functions must save and restore these before using them t8-t9 Temporary registers k0-k1 Reserved for use by kernels gp Global pointer sp Stack pointer fp Frame pointer ra Return address. Used by JAL and (usually) JALR to store the address to return to after a function </TD></TR></TABLE> Aside from zero, all GPRs may be freely accessed if convention rules are respected.

Special Registers
</TABLE>
Normal instructions
> Name Purpose pc Program counter, address of currently-executing instruction (32-bit) hi/lo Stores multiplication and division results (64-bit) hi1/lo1 Used by MULT1/DIV1 type instructions, same as above (64-bit) sa Shift amount used by QFSRV instruction </TD></TR></TABLE>

<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   EE Instruction Decoding </FONT>
> 31---------26---------------------------------------------------0 | opcode | | ------6---------------------------------------------------------- |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 000 | *1 | *2 | J | JAL | BEQ | BNE | BLEZ | BGTZ | 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI | 010 | *3 | *4 | *5 | --- | BEQL | BNEL | BLEZL | BGTZL | 011 | DADDI |DADDIU | LDL | LDR | *6 | --- | LQ | SQ | 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU | 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE | 110 | --- | LWC1 | --- | PREF | --- | --- | LQC2 | LD | 111 | --- | SWC1 | --- | --- | --- | --- | SQC2 | SD | hi |-------|-------|-------|-------|-------|-------|-------|-------| *1 = SPECIAL, see SPECIAL list *2 = REGIMM, see REGIMM list *3 = COP0 *4 = COP1 *5 = COP2 *6 = MMI table </TD></TR></TABLE>
SPECIAL
> 31---------26------------------------------------------5--------0 | = SPECIAL | | function| ------6----------------------------------------------------6----- |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 000 | SLL | --- | SRL | SRA | SLLV | --- | SRLV | SRAV | 001 | JR | JALR | MOVZ | MOVN |SYSCALL| BREAK | --- | SYNC | 010 | MFHI | MTHI | MFLO | MTLO | DSLLV | --- | DSRLV | DSRAV | 011 | MULT | MULTU | DIV | DIVU | ---- | --- | ---- | ----- | 100 | ADD | ADDU | SUB | SUBU | AND | OR | XOR | NOR | 101 | MFSA | MTSA | SLT | SLTU | DADD | DADDU | DSUB | DSUBU | 110 | TGE | TGEU | TLT | TLTU | TEQ | --- | TNE | --- | 111 | DSLL | --- | DSRL | DSRA |DSLL32 | --- |DSRL32 |DSRA32 | hi |-------|-------|-------|-------|-------|-------|-------|-------| </TD></TR></TABLE>
REGIMM
> 31---------26----------20-------16------------------------------0 | = REGIMM | | rt | | ------6---------------------5------------------------------------ |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 00 | BLTZ | BGEZ | BLTZL | BGEZL | --- | --- | --- | --- | 01 | TGEI | TGEIU | TLTI | TLTIU | TEQI | --- | TNEI | --- | 10 | BLTZAL| BGEZAL|BLTZALL|BGEZALL| --- | --- | --- | --- | 11 | MTSAB | MTSAH | --- | --- | --- | --- | --- | --- | hi |-------|-------|-------|-------|-------|-------|-------|-------| </TD></TR></TABLE>
MMI
> 31---------26------------------------------------------5--------0 | = MMI | | function| ------6----------------------------------------------------6----- |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 000 | MADD | MADDU | --- | --- | PLZCW | --- | --- | --- | 001 | *1 | *2 | --- | --- | --- | --- | --- | --- | 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | --- | --- | --- | --- | 011 | MULT1 | MULTU1| DIV1 | DIVU1 | --- | --- | --- | --- | 100 | MADD1 | MADDU1| --- | --- | --- | --- | --- | --- | 101 | *3 | *4 | --- | --- | --- | --- | --- | --- | 110 | PMFHL | PMTHL | --- | --- | PSLLH | --- | PSRLH | PSRAH | 111 | --- | --- | --- | --- | PSLLW | --- | PSRLW | PSRAW | hi |-------|-------|-------|-------|-------|-------|-------|-------| *1 = MMI0 list *2 = MMI2 list *3 = MMI1 list *4 = MMI3 list </TD></TR></TABLE>
MMI0
> 31---------26------------------------------10--------6-5--------0 | | |function | MMI0 | ------6----------------------------------------------------6----- |---00--|---01--|---10--|---11--| lo 000 |PADDW | PSUBW | PCGTW | PMAXW | 001 |PADDH | PSUBH | PCGTH | PMAXH | 010 |PADDB | PSUBB | PCGTB | --- | 011 | --- | --- | --- | --- | 100 |PADDSW |PSUBSW |PEXTLW | PPACW | 101 |PADDSH |PSUBSH |PEXTLH | PPACH | 110 |PADDSB |PSUBSB |PEXTLB | PPACB | 111 | --- | --- | PEXT5 | PPAC5 | hi |-------|-------|-------|-------| </TD></TR></TABLE>
MMI1
> 31---------26------------------------------------------5--------0 | | |function | MMI1 | ------6----------------------------------------------------6----- |---00--|---01--|---10--|---11--| lo 000 | --- | PABSW | PCEQW | PMINW | 001 |PADSBH | PABSH | PCEQH | PMINH | 010 | --- | --- | PCEQB | --- | 011 | --- | --- | --- | --- | 100 |PADDUW |PSUBUW |PEXTUW | --- | 101 |PADDUH |PSUBUH |PEXTUH | --- | 110 |PADDUB |PSUBUB |PEXTUB | QFSRV | 111 | --- | --- | --- | --- | hi |-------|-------|-------|-------| </TD></TR></TABLE>
MMI2
> 31---------26------------------------------------------5--------0 | | |function | MMI2 | ------6----------------------------------------------------6----- |---00--|---01--|---10--|---11--| lo 000 |PMADDW | --- |PSLLVW |PSRLVW | 001 |PMSUBW | --- | --- | --- | 010 |PMFHI |PMFLO |PINTH | --- | 011 |PMULTW |PDIVW |PCPYLD | --- | 100 |PMADDH |PHMADH | PAND | PXOR | 101 |PMSUBH |PHMSBH | --- | --- | 110 | --- | --- | PEXEH | PREVH | 111 |PMULTH |PDIVBW | PEXEW |PROT3W | hi |-------|-------|-------|-------| </TD></TR></TABLE>
MMI3
> 31---------26------------------------------------------5--------0 | | |function | MMI3 | ------6----------------------------------------------------6----- |---00--|---01--|---10--|---11--| lo 000 |PMADDUW| --- | --- |PSRAVW | 001 | --- | --- | --- | --- | 010 |PMTHI | PMTLO |PINTEH | --- | 011 |PMULTUW| PDIVUW|PCPYUD | --- | 100 | --- | --- | POR | PNOR | 101 | --- | --- | --- | --- | 110 | --- | --- | PEXCH | PCPYH | 111 | --- | --- | PEXCW | --- | hi |-------|-------|-------|-------| </TD></TR></TABLE>
COP0
> 31--------26-25------21 ----------------------------------------0 | = COP0 | fmt | | ------6----------5----------------------------------------------- |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 00 | MFC0 | --- | --- | --- | MTC0 | --- | --- | --- | 01 | *1 | --- | --- | --- | --- | --- | --- | --- | 10 | *2 | --- | --- | --- | --- | --- | --- | --- | 11 | --- | --- | --- | --- | --- | --- | --- | --- | hi |-------|-------|-------|-------|-------|-------|-------|-------| *1=BC See BC0 list *2 = TLB instr, see TLB list </TD></TR></TABLE>
BC0
> 31--------26-25------21-20------16------------------------------0 | = COP0 | BC0 | fmt | | ------6----------5----------5------------------------------------ |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 00 | BC0F | BC0T | BC0FL | BC0TL | --- | --- | --- | --- | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | --- | --- | --- | --- | --- | --- | --- | --- | hi |-------|-------|-------|-------|-------|-------|-------|-------| </TD></TR></TABLE>
TLB/Exception
> 31--------26-25------21--------------------------------5--------0 | = COP0 | TLB | | fmt | ------6----------5----------------------------------------------- |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 000 | --- | TLBR | TLBWI | --- | --- | --- | TLBWR | --- | 001 | TLBP | --- | --- | --- | --- | --- | --- | --- | 010 | --- | --- | --- | --- | --- | --- | --- | --- | 011 | ERET | --- | --- | --- | --- | --- | --- | --- | 100 | --- | --- | --- | --- | --- | --- | --- | --- | 101 | --- | --- | --- | --- | --- | --- | --- | --- | 110 | --- | --- | --- | --- | --- | --- | --- | --- | 111 | EI | DI | --- | --- | --- | --- | --- | --- | hi |-------|-------|-------|-------|-------|-------|-------|-------| </TD></TR></TABLE>
COP1
> 31--------26-25------21 ----------------------------------------0 | = COP1 | fmt | | ------6----------5----------------------------------------------- |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 00 | MFC1 | --- | CFC1 | --- | MTC1 | --- | CTC1 | --- | 01 | *1 | --- | --- | --- | --- | --- | --- | --- | 10 | *2 | --- | --- | --- | *3 | --- | --- | --- | 11 | --- | --- | --- | --- | --- | --- | --- | --- | hi |-------|-------|-------|-------|-------|-------|-------|-------| *1 = BC instructions, see BC1 list *2 = S instr, see FPU list *3 = W instr, see FPU list </TD></TR></TABLE>
BC1
> 31--------26-25------21-20------16------------------------------0 | = COP1 | BC1 | fmt | | ------6----------5----------5------------------------------------ |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 00 | BC1F | BC1T | BC1FL | BC1TL | --- | --- | --- | --- | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | --- | --- | --- | --- | --- | --- | --- | --- | hi |-------|-------|-------|-------|-------|-------|-------|-------| </TD></TR></TABLE>
FPU.S
> 31--------26-25------21 -------------------------------5--------0 | = COP1 | = S | | function| ------6----------5-----------------------------------------6----- |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 000 | ADD.S | SUB.S | MUL.S | DIV.S | SQRT.S| ABS.S | MOV.S | NEG.S | 001 | --- | --- | --- | --- | --- | --- | --- | --- | 010 | --- | --- | --- | --- | --- | --- |RSQRT.S| --- | 011 | ADDA.S| SUBA.S| MULA.S| --- | MADD.S| MSUB.S|MADDA.S|MSUBA.S| 100 | --- | --- | --- | --- | CVT.W | --- | --- | --- | 101 | MAX.S | MIN.S | --- | --- | --- | --- | --- | --- | 110 | C.F | --- | C.EQ | --- | C.LT | --- | C.LE | --- | 111 | --- | --- | --- | --- | --- | --- | --- | --- | hi |-------|-------|-------|-------|-------|-------|-------|-------| </TD></TR></TABLE>
FPU.W
> 31--------26-25------21 -------------------------------5--------0 | = COP1 | = W | | function| ------6----------5-----------------------------------------6----- |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 000 | --- | --- | --- | --- | --- | --- | --- | --- | 001 | --- | --- | --- | --- | --- | --- | --- | --- | 010 | --- | --- | --- | --- | --- | --- | --- | --- | 011 | --- | --- | --- | --- | --- | --- | --- | --- | 100 | CVT.S | --- | --- | --- | --- | --- | --- | --- | 101 | --- | --- | --- | --- | --- | --- | --- | --- | 110 | --- | --- | --- | --- | --- | --- | --- | --- | 111 | --- | --- | --- | --- | --- | --- | --- | --- | hi |-------|-------|-------|-------|-------|-------|-------|-------| </TD></TR></TABLE>
COP2
> 31--------26-25------21 ----------------------------------------0 | = COP2 | fmt | | ------6----------5----------------------------------------------- |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 00 | --- | QMFC2 | CFC2 | --- | --- | QMTC2 | CTC2 | --- | 01 | *1 | --- | --- | --- | --- | --- | --- | --- | 10 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | 11 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | *2 | hi |-------|-------|-------|-------|-------|-------|-------|-------| *1 = BC instructions, see BC2 list *2 =see special1 table </TD></TR></TABLE>
BC2
> 31--------26-25------21-20------16------------------------------0 | = COP0 | BC2 | fmt | | ------6----------5----------5------------------------------------ |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 00 | BC2F | BC2T | BC2FL | BC2TL | --- | --- | --- | --- | 01 | --- | --- | --- | --- | --- | --- | --- | --- | 10 | --- | --- | --- | --- | --- | --- | --- | --- | 11 | --- | --- | --- | --- | --- | --- | --- | --- | hi |-------|-------|-------|-------|-------|-------|-------|-------| </TD></TR></TABLE>
COP2 Special1
> 31---------26-25-----21-20-----------------------------5--------0 | =COP2 | Special1 | |function| ------6----------5------------------------------------------6---- |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 000 |VADDx |VADDy |VADDz |VADDw |VSUBx |VSUBy |VSUBz |VSUBw | 001 |VMADDx |VMADDy |VMADDz |VMADDw |VMSUBx |VMSUBy |VMSUBz |VMSUBw | 010 |VMAXx |VMAXy |VMAXz |VMAXw |VMINIx |VMINIy |VMINIz |VMINIw | 011 |VMULx |VMULy |VMULz |VMULw |VMULq |VMAXi |VMULi |VMINIi | 100 |VADDq |VMADDq |VADDi |VMADDi |VSUBq |VMSUBq |VSUbi |VMSUBi | 101 |VADD |VMADD |VMUL |VMAX |VSUB |VMSUB |VOPMSUB|VMINI | 110 |VIADD |VISUB |VIADDI | --- |VIAND |VIOR | --- | --- | 111 |VCALLMS|CALLMSR| --- | --- | *1 | *1 | *1 | *1 | hi |-------|-------|-------|-------|-------|-------|-------|-------| *1=see special2 table </TD></TR></TABLE>
COP2 Special2
</TABLE>
During the early boot stages, the BIOS writes to a pair of registers; MCH_DRD and MCH_RICM used to initialize RDRAM. Not much is known about these registers. The following logic used in emulators:
Read
> 31---------26-25-----21-20------------------11-10------6-5-2-1--0 | =COP2 | Special2 | | fhi |1111|flo| ------6----------5----------------------------------------------- Note: opcode is flo | (fhi * 4). |--000--|--001--|--010--|--011--|--100--|--101--|--110--|--111--| lo 0000 |VADDAx |VADDAy |VADDAz |VADDAw |VSUBAx |VSUBAy |VSUBAz |VSUBAw | 0001 |VMADDAx|VMADDAy|VMADDAz|VMADDAw|VMSUBAx|VMSUBAy|VMSUBAz|VMSUBAw| 0010 |VITOF0 |VITOF4 |VITOF12|VITOF15|VFTOI0 |VFTOI4 |VFTOI12|VFTOI15| 0011 |VMULAx |VMULAy |VMULAz |VMULAw |VMULAq |VABS |VMULAi |VCLIPw | 0100 |VADDAq |VMADDAq|VADDAi |VMADDAi|VSUBAq |VMSUBAq|VSUBAi |VMSUBAi| 0101 |VADDA |VMADDA |VMULA | --- |VSUBA |VMSUBA |VOPMULA|VNOP | 0110 |VMOVE |VMR32 | --- | --- |VLQI |VSQI |VLQD |VSQD | 0111 |VDIV |VSQRT |VRSQRT |VWAITQ |VMTIR |VMFIR |VILWR |VISWR | 1000 |VRNEXT |VRGET |VRINIT |VRXOR | --- | --- | --- | --- | 1001 | --- | --- | --- | --- | --- | --- | --- | --- | 1010 | --- | --- | --- | --- | --- | --- | --- | --- | 1011 | --- | --- | --- | --- | --- | --- | --- | --- | 1100 | --- | --- | --- | --- | --- | --- | --- | --- | 1101 | --- | --- | --- | --- | --- | --- | --- | --- | 1110 | --- | --- | --- | --- | --- | --- | --- | --- | 1111 | --- | --- | --- | --- | --- | --- | --- | --- | hi |-------|-------|-------|-------|-------|-------|-------|-------| </TD></TR></TABLE>


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   EE RDRAM initialization </FONT>
> case 0x1000f430: { return 0; } case 0x1000f440: { uint8_t SOP = (MCH_RICM >> 6) & 0xF; uint8_t SA = (MCH_RICM >> 16) & 0xFFF; if (!SOP) { switch (SA) { case 0x21: if (rdram_sdevid < 2) { rdram_sdevid++; return 0x1F; } return 0; case 0x23: return 0x0D0D; case 0x24: return 0x0090; case 0x40: return MCH_RICM & 0x1F; } } return 0; } </TD></TR></TABLE>
Write
</TABLE>
> case 0x1000f430: { uint8_t SA = (data >> 16) & 0xFFF; uint8_t SBC = (data >> 6) & 0xF; if (SA == 0x21 && SBC == 0x1 && ((MCH_DRD >> 7) & 1) == 0) rdram_sdevid = 0; MCH_RICM = data & ~0x80000000; break; } case 0x1000f440: { MCH_DRD = data; break; } </TD></TR></TABLE>
<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   EE COP0 Registers </FONT>
</TABLE>
Exceptions
An exception is an exceptional event that stops the CPU's current task and forces it to address the event, usually with kernel privileges.
On the EE, there are exceptions for interrupts, TLB management, syscalls, and various errors. When an exception occurs, the EE jumps to one of the following vectors:
> Num Name $0 Index $1 Random $2 EntryLo0 $3 EntryLo1 $4 Context $5 PageMask $6 Wired $8 BadVAddr $9 Count $10 EntryHi $11 Compare $12 Status $13 Cause $14 EPC $15 PRid $16 Config $23 BadPAddr $24 Debug $25 Perf $28 TagLo $29 TagHi $30 ErrorEPC </TD></TR></TABLE>

<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   EE COP0 Exception Handling </FONT>
> Name Normal Bootstrap Level ------------------------------------------------ | Reset/NMI | BFC00000h | BFC00000h | 2 | ------------------------------------------------ | TLB Refill | 80000000h | BFC00200h | 1 | ------------------------------------------------ | Perf. Counter | 80000080h | BFC00280h | 2 | ------------------------------------------------ | Debug | 80000100h | BFC00300h | 2 | ------------------------------------------------ | All others | 80000180h | BFC00380h | 1 | ------------------------------------------------ | Interrupt | 80000200h | BFC00400h | 1 | ------------------------------------------------ </TD></TR></TABLE> The full exception handling works as follows.
> void handle_exception_level1(u32 vector, u8 cause) { Cause.ExcCode = cause; if (in_branch_delay) { EPC = PC - 4; Cause.BD = true; } else { EPC = PC; Cause.BD = false; } Status.EXL = true; PC = vector; } void handle_exception_level2(u32 vector, u8 cause) { Cause.ExcCode = cause; if (in_branch_delay) { ErrorEPC = PC - 4; Cause.BD2 = true; } else { ErrorEPC = PC; Cause.BD2 = false; } Status.ERL = true; PC = vector; } </TD></TR></TABLE>
$08 - COP0.BadVAddr
0-31 Virtual address that caused an exception </TD></TR></TABLE> BadVAddr is written to when a TLB Refill, TLB Modified, TLB Invalid, or Address Error exception occurs.

$12 - COP0.Status
> 0 IE - Interrupt enable 1 EXL - Exception level (set when a level 1 exception occurs) 2 ERL - Error level (set when a level 2 exception occurs) 3-4 KSU - Privilege level 0=Kernel 1=Supervisor 2=User 10 INT0 enable (INTC) 11 INT1 enable (DMAC) 12 Bus error mask - when set, bus errors are disabled 15 INT5 enable (COP0 timer) 16 EIE - Master interrupt enable 17 EDI - If not set, EI/DI only works in kernel mode 18 CH - Status of most recent Cache Hit instruction 0=miss 1=hit 22 BEV - If set, level 1 exceptions go to "bootstrap" vectors in BFC00xxx 23 DEV - If set, level 2 exceptions go to "bootstrap" vectors in BFC00xxx 28-31 Usability of coprocessors 0-3 If not set, using a coprocessor raises an exception </TD></TR></TABLE> All interrupts are disabled unless the following condition is true.
> Status.IE && Status.EIE && !Status.EXL && !Status.ERL </TD></TR></TABLE> When Status.ERL or Status.EXL is set, the EE operates in kernel mode regardless of Status.KSU.

$13 - COP0.Cause
> 2-6 Exception code 00h=Interrupt 01h=TLB Modified 02h=TLB Refill (instruction fetch or load) 03h=TLB Refill (store) 04h=Address Error (instruction fetch or load) 05h=Address Error (store) 06h=Bus Error (instruction) 07h=Bus Error (data) 08h=Syscall 09h=Breakpoint 0Ah=Reserved Instruction 0Bh=Coprocessor Unusable 0Ch=Overflow 0Dh=Trap 10 INTC interrupt pending 11 DMAC interrupt pending 15 COP0 timer interrupt pending 16-18 Error code 00h=Reset 01h=NMI 02h=Performance counter 03h=Debug 28-29 Coprocessor that triggered a CU exception 30 BD2 - Set when a level 2 exception occurs in a delay slot 31 BD - Set when a level 1 exception occurs in a delay slot </TD></TR></TABLE> Cause is used to determine what caused an exception.
The BD/BD2 bits are important as when they are set, EPC/ErrorEPC is set to the address of the branch instruction, not its delay slot. This allows the EE to re-execute the branch when it returns from an exception.

$14/$30 - COP0.EPC/COP0.ErrorEPC
> 0-31 Address to return to after an exception </TD></TR></TABLE> EPC and ErrorEPC are used by level 1 and 2 exceptions respectively. When the ERET instruction is executed, it jumps to the address in EPC or ErrorEPC, depending on if Status.EXL or Status.ERL is set.

$23 - COP0.BadPAddr
</TABLE>
Virtual Memory Basics
Virtual memory is a mechanism that allows processors to arbitrarily map a virtual address to a physical address. This is accomplished using a Memory Management Unit (MMU). For example, a program might access address 1000h. With virtual memory, this address could map to any physical address, such as 1000h, 20000h, 424000h, and so on. Virtual address 1000h might also not be mapped to anything, in which case accessing it causes an error. The PS2 and most modern OSes do not map addresses near NULL, so that if a program uses a NULL pointer, it can crash immediately rather than corrupt program data.

MIPS Memory Segments
The MIPS architecture splits the memory space in half for the user and kernel, and kernelspace is further partitioned into various segments.
> 0-31 Physical address that caused an exception </TD></TR></TABLE> BadPAddr is written to when a bus error occurs and Status.BEM is not set.


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   EE COP0 Memory Management </FONT>
> Name Range Description ------------------------------------------------------------------- | kuseg | 00000000h-7FFFFFFFh | User, TLB-mapped | ------------------------------------------------------------------- | kseg0 | 80000000h-9FFFFFFFh | Kernel, directly-mapped, cached | ------------------------------------------------------------------- | kseg1 | A0000000h-BFFFFFFFh | Kernel, directly-mapped, uncached | ------------------------------------------------------------------- | ksseg | C0000000h-DFFFFFFFh | Supervisor, TLB-mapped | ------------------------------------------------------------------- | kseg3 | E0000000h-FFFFFFFFh | Kernel, TLB-mapped | ------------------------------------------------------------------- </TD></TR></TABLE> Accessing a privileged region without the necessary privileges raises an Address Error exception.
For kseg0 and kseg1, the physical address retrieved is simply (address & 1FFFFFFFh).

Translation-Lookaside Buffer (TLB)
The EE uses a TLB, a cache of virtual->physical mappings, for memory management. The TLB contains 48 entries split into even and odd pages. A TLB entry has the following format:
> 1 V0 - Even page valid. When not set, the memory referenced in this entry is not mapped. 2 D0 - Even page dirty. When not set, writes cause an exception. 3-5 C0 - Even page cache mode. 2=Uncached 3=Cached 7=Uncached accelerated 6-25 PFN0 - Even page frame number. 33 V1 - Odd page valid. 34 D1 - Odd page dirty. 35 C1 - Odd page cache mode. 38-57 PFN1 - Odd page frame number. 63 S - Scratchpad. When set, the virtual mapping goes to scratchpad instead of main memory. 64-71 ASID - Address Space ID. 76 G - Global. When set, ASID is ignored. 77-95 VPN2 - Virtual page number / 2. Even pages have a VPN of (VPN2 * 2) and odd pages have a VPN of (VPN2 * 2) + 1 109-120 MASK - Size of an even/odd page. </TD></TR></TABLE> The units of PFN0/PFN1 and VPN2 depend on MASK. For example, if MASK indicates a size of 4 KB, then if PFN0/PFN1 are 10h/11h and VPN2 is 8h, the virtual address of the even page is (8h * 2 * 4096) or 10000h, and the virtual address of the odd page is ((8h * 2) + 1) * 4096 or 11000h.
The physical addresses of the even/odd pages are also 10000h/11000h respectively. Therefore, an access to 10500h will touch physical address 10500h.

$0 - COP0.Index
> 0-5 TLB entry to access with TLBR/TLBWI </TD></TR></TABLE>
$1 - COP0.Random
> 0-5 TLB entry to access with TLBWR </TD></TR></TABLE> Random decrements after every instruction that is executed. It has an upper bound of 47 and a lower bound of the value in Wired.

$2/$3 - COP0.EntryLo0/EntryLo1
> 0 G - Global. 1 V - Page valid. When not set, the memory referenced in this entry is not mapped. 2 D - Page dirty. When not set, writes cause an exception. 3-5 C - Page cache mode. 2=Uncached 3=Cached 7=Uncached accelerated 6-25 PFN - Page frame number. 31 S - Scratchpad. Only applicable for EntryLo0. </TD></TR></TABLE> EntryLo0/EntryLo1 modify the lower part of the TLB as given for the even page and odd page respectively.
The Global bit in the TLB entry is only set if both EntryLo0 and EntryLo1 have their G bit set.

$5 - COP0.PageMask
> 13-24 Page size 000h=4 KB 003h=16 KB 00Fh=64 KB 03Fh=256 KB 0FFh=1 MB 3FFh=4 MB FFFh=16 MB </TD></TR></TABLE>
$6 - COP0.Wired
> 0-5 Lower bound of Random </TD></TR></TABLE>
$10 - COP0.EntryHi
</TABLE>
Cache Basics
As technology has progressed, CPU speeds have far outpaced memory speeds. An access to main RAM on the PS2 takes around 40 EE cycles, and on a modern computer, it can be hundreds of cycles! CPU caches alleviate this problem. They are smaller but faster buffers of memory that the CPU attempts to access when fetching instructions or loading/storing data.
If the CPU finds what it is looking for in the cache, it is called a cache hit. If the CPU has to access main memory, it is called a cache miss.

Modern caches are very complex and have multiple levels, but the EE's caches are rather simple, having only a single level and two ways.

EE Cache Structure
The instruction cache and data cache are split into 128 and 64 cache lines respectively. Each line has two 64-byte (4-quadword) ways, which means the icache and dcache are 16 KB and 8 KB respectively.
Each way has a tag which stores metadata about the way, including, for instance, if the way has valid data in it.
The structure of the tags for the icache and dcache is as follows.
> 0-7 ASID 13-31 VPN2 </TD></TR></TABLE>


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   EE COP0 Caches </FONT>
> icache ------------------------------------------- |V|R| PFN | ------------------------------------------- dcache ------------------------------------------- |D|V|R|L| PFN | ------------------------------------------- V=Valid. If set, the way contains valid data. R=LRF bit. Used for the LRF cache replacement algorithm. D=Dirty. Set on writes. If set when the way is reloaded, the data is first stored to main memory before loading new data. L=Locked. Prevents the way from ever being reloaded. Only allowed for a single way in a line. </TD></TR></TABLE> Each cache line is indexed by virtual address. Here is how a virtual address is used:
</TABLE>
$09 - COP0.Count
> icache 31---------------------------------14-13-------------6-5---------0 | PFN | index | offset | ------------------------------------------------------------------ dcache 31------------------------------------13-12----------6-5---------0 | PFN | index | offset | ------------------------------------------------------------------ Note how the dcache index is 6-bit, whereas the icache index is 7-bit. </TD></TR></TABLE> The index is used to get the cache line to access. The offset is used to, of course, offset into the 64-byte region.

Cache Misses and Replacement Algorithm
When accessing the cache, the EE checks both ways in a line by comparing the address's PFN with the PFNs in the ways' tags. If both lookups fail, a cache miss has occurred, and new data needs to be loaded into the cache.
The EE uses a Least Recently Filled (LRF) algorithm to determine which way to load data into. If either way does not have the Valid bit set, the EE sets the Valid bit in the first way that does not have it and loads data into it. If both ways are full, the EE takes the XOR of the LRF bits in the tags. The result is the index of the way it uses. The EE then flips the LRF bit in the selected way.
If a way in the data cache has the Locked bit set, the EE will always reload the other way. This allows important data to remain in the cache indefinitely.

Four quadwords are loaded into a way at a time. Since the EE bus is 128-bit, this means a cache miss has a penalty of a minimum of four bus cycles (eight EE cycles). However, main memory is much slower - ~40 EE cycles is closer to reality, though the exact number is nondeterministic due to the nature of RDRAM.

Cache Coherency
Because the caches are separate from main memory, it is possible for the contents of the caches to be different from the contents of main memory.
This is not an issue when simply accessing memory. However, other hardware components such as the DMAC cannot read from the cache. When transferring or receiving data from hardware peripherals, the program is expected to maintain cache coherency by flushing the cache, which forces the cache to synchronize its contents with main memory.

Sony's SDK correctly maintains cache coherency in most cases, so most games are none the wiser. Certain games are so buggy, however, that they require cache emulation to work.
Some examples:
  • Dead or Alive 2: Re-uses the same buffer for sending and receiving data in a library that communicates with a custom sound module on the IOP.
    Without cache emulation, the IOP will overwrite data in the send/receive buffer, preventing the game from booting.
  • Ice Age 2: The Meltdown: Function returns a pointer to a stack array used to send data to the IOP. Astute C programmers will recognize this as undefined behavior.
    The game immediately flushes the cache after calling this function, so the ensuing corruption only occurs in the cache, and the data in main memory is protected.
  • Savage Skies: Similar to IA2. Allocates a VIF DMA buffer on the stack, then starts a transfer without waiting for it to end and returns from a function.
    Without cache emulation, the buffer is corrupted and the game is unable to go in-game.
  • WRC 4: Notably requires icache emulation. Main executable is a small decompressor that decompresses a larger executable.
    The decompressed ELF is large enough to overlap with the decompressor in memory. Without icache emulation, the decompressor is destroyed.

<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   EE COP0 Timer </FONT>
> 0-31 Timer count value </TD></TR></TABLE> Count increments automatically every EE cycle.

$11 - COP0.Compare
</TABLE>
Floating-point Registers (FPRs)
> 0-31 Timer compare value </TD></TR></TABLE> When Count==Compare, a COP0 timer interrupt is signaled. Writing to Compare acknowledges and clears the pending interrupt.


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   EE COP1 Registers </FONT>
> Name Convention f0-f3 Return values f4-f11 Temporary registers f12-f19 Argument registers f20-f31 Saved registers </TD></TR></TABLE>
Special Registers (accessed through CFC1/CTC1)
</TABLE>
COP1, along with the rest of the PS2, only supports single-precision floats. The PS2 uses IEEE 754 floats with the following format:
> Name Purpose fcr0 Reports implementation and revision of FPU fcr31 Control register, stores status flags </TD></TR></TABLE>

<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   EE COP1 Floating Point Format </FONT>
> 31-30---------23-22---------------------------------------------0 |si| exponent | mantissa | ----------------------------------------------------------------- </TD></TR></TABLE> "si" is the sign bit, and the mantissa is the fractional component. The float is calculated as follows.
</TABLE>
The EE has four hardware timers. They are all functionally equivalent, though T0 and T1 have an additional register used when an SBUS interrupt occurs.
T3 is reserved by the BIOS for alarm functions. All other timers may be used freely.

10000000h + N*800h TN_COUNT
> num = (si ? -1 : 1) * 2 ^ (exponent - 127) * (1.mantissa) </TD></TR></TABLE> 1.mantissa means the number 1 and all the fractional bits following the decimal.
For example, 3F800000h becomes 1.0f.

IEEE 754 Differences
There are major differences between the PS2 floating-point format and standard IEEE 754, used in most modern computers.
  • NaNs and Infinities do not exist on the PS2. In IEEE 754, any number with the exponent field set to 255 is a NaN/Infinity. On the PS2, it is treated as a normal value. This means the upper range of PS2 floats is greater than on IEEE 754.</LR>
  • Denormals, numbers with the exponent field set to 0, do not exist on the PS2. For every arithmetic operation, a denormal is automatically truncated to zero.
  • On the PS2, the rounding mode is always forced to round-towards-zero. The PS2 uses a quirky version where the least-significant-bit may vary after a round, and the details on this are not well understood.
  • </UL>
    <TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   EE Timers </FONT>
> 0-15 Current counter </TD></TR></TABLE> 16-bit counter incremented according to the settings in TN_MODE. Writes set the counter to the given value.

10000010h + N*800h TN_MODE
> 0-1 Clock 0=Bus clock (~147 MHz) 1=Bus clock / 16 2=Bus clock / 256 3=HBLANK 2 Gate enable 3 Gate type 0=HBLANK 1=VBLANK 4-5 Gate mode 0=Count while gate not active 1=Reset counter when gate goes from low to high 2=Reset counter when gate goes from high to low 3=Reset counter for high<->low gate transitions 6 Clear counter when it reaches compare value 7 Timer enable 8 Compare interrupt enable - trigger interrupt when COUNT==COMP 9 Overflow interrupt enable - trigger interrupt when COUNT goes from FFFFh to 0000h 10 Compare interrupt flag W: Clears flag 11 Overflow interrupt flag W: Clears flag </TD></TR></TABLE> Timer interrupts are edge-triggered: an interrupt will only be sent to the EE if either interrupt flag goes from 0 to 1.
Harry Potter and the Prisoner of Azkaban relies on this behavior, as it does not clear the interrupt flags in the timer handler but rather in a different part of the code. Not emulating this will cause the game to crash by reading from NULL.

10000020h + N*800h TN_COMP
> 0-15 Compare value </TD></TR></TABLE>
10000030h + N*800h TN_HOLD
> 0-15 Counter value when an SBUS interrupt occurs </TD></TR></TABLE> Only exists for T0 and T1.

Vertical and horizontal timings are presented below.

Vertical Timings
> PAL: 312 scanlines per frame (VBOFF: 286 | VBON: 26) NTSC: 262 scanlines per frame (VBOFF: 240 | VBON: 22) </TD></TR></TABLE>
Horizontal Timings
</TABLE>
The GIF sends textures and geometry to the GS. It takes data from three different PATHs:
- PATH1: VU1 via XGKICK instruction. Highest priority.
- PATH2: VIF1 via DIRECT/DIRECTHL. Medium priority.
- PATH3: GIF DMAC channel (channel 2). Lowest priority.
Only one PATH may run at a time. Under normal conditions, when one PATH stops, the highest priority queued PATH will begin transfer.

GIF Reference
GIF I/O
GIFtags
GIF Data Formats
GIF PATH3 Masking


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0></TABLE>
10003000h GIF_CTRL - Control register (W)
> PAL: 9436 BUSCLK cycles per scanline NTSC: 9370 BUSCLK cycles per scanline </TD></TR></TABLE>
<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   Graphics Interface (GIF) </FONT>
<FONT SIZE=+2>   GIF I/O </FONT>
> 0 Reset GIF 1-2 Unused 3 Temporary stop (1=stop transfers, 0=restart transfers) 4-31 Unused </TD></TR></TABLE>
10003010h GIF_MODE - Mode of operation (W)
> 0 Mask PATH3 (1=Mask) 1 Unused 2 Intermittent mode </TD></TR></TABLE> When PATH3 is masked by this register and GIF DMA is ongoing, the mask applies once GIF DMA ends its transfer.

10003020h GIF_STAT - Status register (R)
> 0 PATH3 masked by GIF_MODE 1 PATH3 masked by VIF1 MASKP3 register 2 Intermittent mode activated 3 Temporary stop 4 Unused 5 PATH3 interrupted (by intermittent mode?) 6 PATH3 queued 7 PATH2 queued 8 PATH1 queued 9 Output path (1=transfer ongoing) 10-11 Active path 0=Idle 1=PATH1 2=PATH2 3=PATH3 12 Transfer direction (0=EE->GS, 1=GS->EE) 13-23 Unused 24-28 Data in GIF FIFO (in quadwords, max 16) 29-31 Unused </TD></TR></TABLE>
10003040h GIF_TAG0 (R)
> 0-31 Bits 0-31 of most recently read GIFtag </TD></TR></TABLE> 10003050h GIF_TAG1 (R)
> 0-31 Bits 32-63 of most recently read GIFtag </TD></TR></TABLE> 10003060h GIF_TAG2 (R)
> 0-31 Bits 64-95 of most recently read GIFtag </TD></TR></TABLE> 10003070h GIF_TAG3 (R)
> 0-31 Bits 96-127 of most recently read GIFtag </TD></TR></TABLE> These registers are only readable when the GIF has been paused by GIF_CTRL.
For details on the GIFtag format, see
GIFtags

10003080h GIF_CNT (R)
> 0-14 Backwards loop counter from NLOOP Decrements to zero 15 Unused 16-19 Register descriptor in progress 0=highest 1=lowest 2=2nd lowest ... 15=15th lowest 20-29 VU data address being transferred 30-31 Unused </TD></TR></TABLE> Only accessible when GIF is paused by GIF_CTRL.

10003090h GIF_P3CNT (R)
> 0-14 Backwards loop counter from PATH3 NLOOP when PATH3 is interrupted 15-31 Unused </TD></TR></TABLE> Only accessible when GIF is paused by GIF_CTRL.

100030A0h GIF_P3TAG (R)
</TABLE>
The basic unit of GIF transfer data is the GIF packet. Each packet is split into one or more primitives. Every primitive must be preceded by a GIFtag.

GIFtag Format
> 0-31 Bits 0-31 of PATH3 GIFtag when PATH3 is interrupted </TD></TR></TABLE> Only accessible when GIF is paused by GIF_CTRL.


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   GIFtags </FONT>
</TABLE>
The data format after a GIFtag varies depending on the value of GIFtag.58-59. The GIF can transfer to the GS in PACKED, REGLIST, or IMAGE formats.

PACKED Format
Data is transferred in units of quadwords (16 bytes). Total amount of data in the GIF primitive = NLOOP * NREGS.
All registers not specified below output the lower 64-bits of the quadword to their GS register directly. The upper 64-bits are discarded.

Current reg=0h PRIM
> 0-14 NLOOP - Data per register to transfer 15 EOP - End of packet 16-45 Unused 46 Enable PRIM field 47-57 Data to be sent to GS PRIM register if GIFtag.46 == 1 58-59 Data format 0=PACKED 1=REGLIST 2=IMAGE 3=IMAGE 60-63 NREGS - Number of registers 0=16 registers 64-127 Register field, 4 bits each </TD></TR></TABLE>
When NLOOP == 0, all fields are ignored except EOP and no further processing is done.
When GIFtag.46 == 0, an idle cycle is inserted before processing begins.
Registers are handled in little-endian order; i.e. bits 64-67 are processed first, then 68-71, and so on.

NOTE: The GS Q register is initialized to 1.0f when reading a GIFtag.


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   GIF Data Formats </FONT>
> 0-10 Data to write to GS PRIM 11-127 Unused </TD></TR></TABLE>
Current reg=1h RGBA
> Writes to RGBAQ register (Q is unchanged) 0-7 R 8-31 Unused 32-39 G 40-63 Unused 64-71 B 72-95 Unused 96-103 A 104-127 Unused </TD></TR></TABLE> R, G, B, and A are 8-bit values. Q is set by the STQ command.

Current reg=2h STQ
> Writes to ST register and Q component of RGBAQ. 0-31 S 32-63 T 64-95 Q 96-127 Unused </TD></TR></TABLE> S, T, and Q are single-precision (32-bit) floats in IEEE 754 format.

Current reg=3h UV
> 0-13 U 14-31 Unused 32-45 V 46-127 Unused </TD></TR></TABLE> U and V are 14-bit unsigned fixed-point integers with a 4-bit fractional component.

Current reg=4h XYZ2F/XYZ3F
> 0-15 X 16-31 Unused 32-47 Y 48-67 Unused 68-91 Z 92-99 Unused 100-107 F 108-110 Unused 111 Disable drawing (1=write to XYZ3F, 0=write to XYZ2F) 112-127 Unused </TD></TR></TABLE> X and Y are signed 16-bit fixed-point integers with a 4-bit fractional component.
Z is a 24-bit integer, and F is an 8-bit integer.
The "disable drawing" bit controls whether the data is written to XYZ2F or XYZ3F.

Current reg=5h XYZ2/XYZ3
> 0-15 X 16-31 Unused 32-47 Y 48-63 Unused 64-95 Z 96-110 Unused 111 Disable drawing (1=write to XYZ3F, 0=write to XYZ2F) 112-127 Unused </TD></TR></TABLE> Similar to XYZ2F/XYZ3F above, except there is no F register and Z is 32-bit.

Current reg=Ah FOG
> 0-99 Unused 100-107 F 108-127 Unused </TD></TR></TABLE>
Current reg=Eh A+D (output data to specified address)
> 0-63 Data 64-71 Register address 72-127 Unused </TD></TR></TABLE> Outputs data to the given register address.

WARNING: Do not use this register descriptor on PATH3 when PATH1 is also running, or the GS may lock up!

Current reg=Fh NOP
</TABLE>
PATH1 and PATH2 transfer to the GS without any internal buffering. However, PATH3 has a 16-quadword GIF FIFO.
When PATH3 masking is enabled, data sent by PATH3 will reside in the FIFO until the mask is lifted. This is useful for queueing texture transfers while other paths are sending geometry. GTA: San Andreas, Lemmings, and some other games rely on this.

Furthermore, Wallace and Gromit at Project Zoo will enable the mask and start a GIF DMA transfer, expecting it to finish. Emulating PATH3 masking without emulating the GIF FIFO will cause it to hang on a black screen, as the DMA channel is unable to write any data.


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0></TABLE>
The DMAC gives an interface for the EE to access the rest of the system. It can transfer one quadword (16 bytes) at bus speed (half the rate of the EE's clock).

DMAC Reference
DMAC I/O
DMAC Chain Mode
DMAC MFIFO
DMAC Interrupts


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0></TABLE>
Channels
> Data not output to GS. </TD></TR></TABLE>
REGLIST Format
Total data in GIF primitive = NREGS * NLOOP, in units of doublewords. (64-bits)
In REGLIST, a doubleword is sent directly to the register descriptor. Every quadword contains data for two registers. When the data is prepared properly, this can multiply data density by up to a factor of 2.
When NREGS * NLOOP is odd, the last doubleword in a primitive is discarded.

IMAGE Format
Total data in GIF primitive = NLOOP only, in units of quadwords.
IMAGE is a shortcut for writing to the GS HWREG register, which transfers textures and other data to VRAM. Each quadword has enough data for two writes to HWREG.


<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=0>
<FONT SIZE=+2>   GIF PATH3 Masking </FONT>
<FONT SIZE=+2>   DMA Controller (DMAC) </FONT>
<FONT SIZE=+2>   DMAC I/O </FONT>
> 100080xxh VIF0 100090xxh VIF1 (can act as PATH2 for GIF) 1000A0xxh GIF (PATH3) 1000B0xxh IPU_FROM 1000B4xxh IPU_TO 1000C0xxh SIF0 (from IOP) 1000C4xxh SIF1 (to IOP) 1000C8xxh SIF2 (bidirectional, used for PSX mode and debugging) 1000D0xxh SPR_FROM 1000D4xxh SPR_TO </TD></TR></TABLE>
1000xx00h Dn_CHCR - Channel control (R/W)