Special Thanks
Special thanks to Wisi. This document builds upon their early DCR exploration in the dpLibMod project
===============================================================================
The APU appears to contain two separate register files.
The first file contains MIPS HI, LO, GP, CC, PC, instruction decode registers, and more.
It's accessible directly through custom instructions and indirectly through
DCRs 0x180 and 0x181.
The second file contains GTE registers, an instruction register, execution
status register, and cycle count register. It's accessible directly through
custom instructions and indirectly through DCRs 0x21 and 0x22. Indirect DCR
access requires a bit to be flipped in DCR 0x20. Writing any non-zero value
to DCR 0x20 causes it to flip between 0x49424d11 and 0x49424d10. DCR 0x20 must
be 0x49424d10 before this register file can be accessed through DCR 0x21 and 0x22.
There are 3 APU registers mapped directly to DCRs.
DCR 0x182 = r/w MIPS Instruction Register
DCR 0x183 = r/o Unknown
sw = 0xac410000 / 0xac0002 / A004 = 0x0
lw = 0x8c410000 / 0x8c0004 / A004 = 0x10000
mfc0 = 0x400d6800 / 0x2800400 / A004 = 0x10004
mtc0 = 0x40826000 / 0x2900400 / A004 = 0x10004
jal = 0x0040f809 / 0x1240801 / A004 = 0x10008
and = 0x00641824 / 0x1900008 / A004 = 0x0
DCR 0x184 = r/o Addr of operand
=============================================================================
Register File 1 - MIPS HI, LO, GP, CC, PC, and more
Range: 0x0-0x7F
Indirect DCR access:
DCR-0x180 = register number
DCR-0x181 = register value
------------APU Internal / Decode Related------------
0x0 = r/o unk, C11E44A1 no observed change.
0x1 = r/o unk, F00644A1 no observed change.
0x2 = r/o unk, 00000000 no observed change.
0x3 = r/w unk, 00010003 no observed change. Can be cleared by writing 0x0
0x4 = r/w, status register?
The act of reading A000 causes it to be set to 0x10000 depending on
what I_MASK is currently set to?
Setting I_STAT 0x1 or 0x800 causes A004 to be set to 0x10000
as well.
Bit 16 is for interrupts?
Lower 4 bits indicate instruction type?
0x4 for OTHER/CO
0x2 for store(?)
0x8 for jr, jal, beqz,
0x0 for everything else
some stores cause it to be set to 0x20?
0x000103FF, lower 10 bits and bit 16 = r/w
0x5 = r/o unk
Appears to be set to 0x1 on execution of *some* but not all load instructions
Possibly cleared on subsequent non load instruction? Unconfirmed.
0x6 = r/o word aligned opcode for use with function LUT
For instructions with non-zero primary opcode:
value = primary opcode * 4
For instructions with primary opcode zero:
value = secondary opcode * 4 + 0x100
Primary:
0x0 = special
0x4 = bcondz
0x8 = j
0xC = jal
0x10 = beq
0x14 = bne
0x18 = blez
0x1C = bgtz
0x20 = addi
0x24 = addiu
0x28 = slti
0x2C = sltiu
0x30 = andi
0x34 = ori
0x38 = xori
0x3C = lui
0x40 = COP0
0x44 = COP1
0x48 = COP2
0x4C = COP3
0x50 - 0x7C = N/A
0x80 = lb
0x84 = lh
0x88 = lwl
0x8C = lw
0x90 = lbu
0x94 = lhu
0x98 = lwr
0x9C = N/A
0xA0 = sb
0xA4 = sh
0xA8 = swl
0xAC = sw
0xB0-0xB4 = N/A
0xB8 = swr
0xBC = N/A
0xC0 = LWC0
0xC4 = LWC1
0xC8 = LWC2
0xCC = LWC3
0xD0 - 0xDC = N/A
0xE0 = SWC0
0xE4 = SWC1
0xE8 = SWC2
0xEC = SWC3
0xF0 - 0xFC = N/A
Secondary:
0x100 = sll
0x104 = N/A
0x108 = srl
0x10C = sra
0x110 = sllv
0x114 = N/A
0x118 = srlv
0x11C = srav
0x120 = jr
0x124 = jalr
0x128 = N/A
0x12C = N/A
0x130 = syscall
0x134 = break
0x138 = N/A
0x13C = N/A
0x140 = mfhi
0x144 = mthi
0x148 = mflo
0x14C = mtlo
0x150 - 0x15C = N/A
0x160 = mult
0x164 = multu
0x168 = div
0x16C = divu
0x170 - 0x17C = N/A
0x180 = add
0x184 = addu
0x188 = sub
0x18C = subu
0x190 = and
0x194 = or
0x198 = xor
0x19C = nor
0x1A0 - 0x1A4 = N/A
0x1A8 = slt
0x1AC = sltu
0x1B0 - 0x1FC = N/A
COP:
0x280 = mfc0
0x290 = mtc0
0x2C0 = rfe
value range 0x0 - 0x3FC
I FORMAT:
0x7 - N/A (instruction >> 11 & 0x1F) 0x0 - 0x1F
0x8 = opcode (not shifted) 0x0 - 0x3F
0x9 = RS (instruction >> 21 & 0x1F) 0x0 - 0x1F
0xA = RT (instruction >> 16 & 0x1F) 0x0 - 0x1F
0xB = N/A (instruction >> 11 & 0x1F) 0x0 - 0x1F
0xC = IMM (instruction & 0xFFFF) 0x0 - 0xFFFF
0xD = N/A (instruction & 0x03FFFFFF) 0x0 - 0x03FFFFFF
0xE = N/A (instruction & 0x3F) 0x0 - 0x3F
0xF = N/A (instruction >> 6 & 0x1F) 0x0 - 0x1F
R FORMAT:
0x7 - RD (instruction >> 11 & 0x1F) 0x0 - 0x1F
0x8 = opcode (not shifted) 0x0 - 0x3F
0x9 = RS (instruction >> 21 & 0x1F) 0x0 - 0x1F
0xA = RT (instruction >> 16 & 0x1F) 0x0 - 0x1F
0xB = RD (instruction >> 11 & 0x1F) 0x0 - 0x1F
0xC = N/A (instruction & 0xFFFF) 0x0 - 0xFFFF
0xD = N/A (instruction & 0x03FFFFFF) 0x0 - 0x03FFFFFF
0xE = FUNCT (instruction & 0x3F) 0x0 - 0x3F
0xF = SHIFT (instruction >> 6 & 0x1F) 0x0 - 0x1F
J FORMAT:
0x7 - RD (instruction >> 11 & 0x1F) 0x0 - 0x1F
0x8 = opcode (not shifted) 0x0 - 0x3F
0x9 = RS (instruction >> 21 & 0x1F) 0x0 - 0x1F
0xA = RT (instruction >> 16 & 0x1F) 0x0 - 0x1F
0xB = RD (instruction >> 11 & 0x1F) 0x0 - 0x1F
0xC = N/A (instruction & 0xFFFF) 0x0 - 0xFFFF
0xD = ADDR (instruction & 0x03FFFFFF) 0x0 - 0x03FFFFFF
0xE = N/A (instruction & 0x3F) 0x0 - 0x3F
0xF = N/A (instruction >> 6 & 0x1F) 0x0 - 0x1F
0x10 = r/w unk, 05010C23 no observed change. 0x0-0xFFFFFFFF
0x11 = r/o unk, 00000000 no observed change.
0x12 = r/o unk, 00000000 no observed change.
0x13 = r/w MIPS cycle counter, set by software, decrementing.
Used to control how many cycles the APU will run for.
Load instructions decrement counter by 5. When zero is
reached the next instruction given to the APU will not
be decoded and instruction type flags will not be set
causing the software to break out of the execution loop.
If in a delay slot instruction, it will proceed with correct
decode until a non delay slot instruction is reached
and then break out.
0x14 = r/w unk, 1F000000 no observed change. 0x0-1FFFFC00
0x15 = r/o unk, 00000000 no observed change.
0x16 = r/o unk, 00000000 no observed change.
0x17 = r/o unk, 00000000 no observed change.
------------MIPS Registers------------
0x18 = r/w MIPS HI, 0x0-0xFFFFFFFF
0x19 = r/w MIPS LO, 0x0-0xFFFFFFFF
0x1A = r/w MIPS PC
0x1B = r/w COP0 DCIC
0x1C = r/w COP0 BPC
0x1D = r/w COP0 BPCM
0x1E = r/w COP0 BDA
0x1F = r/w COP0 BDAM
Note: The other COP0 registers are emulated in software
0x20 - 0x3F = r/w MIPS GP Registers
------------Unknown------------
0x3F - 0x7F = r/w Unused? Hold misc values that remain mostly constant.
=============================================================================
Register File 2 - GTE Registers
Range: 0x0-0xFF
Indirect DCR access:
DCR-0x21 = register number
DCR-0x22 = register value
0x0-0x63 = Normal GTE registers
0x64-0x7F = Unknown.
0x80 = GTE instruction register
Instructions are copied to this register using custom instructions
from PPC. Once copied, execution begins immediately.
0x81 = Status register
Bits 0:29 Unknown
Bits 30:31 Busy status. These bits are polled by software after placing
an instruction in register 0x80.
0x82 = Cycle count of last GTE instruction to run
This value is read after completing a GTE instruction
and subtracted from the current MIPS cycle count. This suggests
the GTE may run at the same speed as the PPC core (440MHz).
0x83-0xFF = Unknown.