The Memory Management Unit (MMU) in the CPU utilizes a large virtual memory space to map to various physical addresses in different ways. All memory accesses made by the CPU, whether instruction fetches or load/store instructions, use virtual addresses. The MMU uses five virtual memory segments to decide how the addresses will be mapped to the physical memory space.

Internally, all addresses are 64-bits wide. However, when in 32-bit addressing mode, the upper 32 bits are sign-extended.

Virtual Memory Map

Address Range Name Description
0x00000000 0x7FFFFFFF KUSEG User segment, TLB mapped
0x80000000 0x9FFFFFFF KSEG0 Kernel segment 0, directly mapped, cached
0xA0000000 0xBFFFFFFF KSEG1 Kernel segment 1, directly mapped, uncached
0xC0000000 0xDFFFFFFF KSSEG Kernel supervisor segment, TLB mapped
0xE0000000 0xFFFFFFFF KSEG3 Kernel segment 3, TLB mapped

For the directly mapped segments KSEG0 and KSEG1, addresses are directly translated to physical addresses by subtracting by the base address of the respective segment. Thus they can only map to the physical address range 0x00000000 - 0x1FFFFFFF.

Refer to the Translation lookaside buffer article and the TLB mapping usage guide for more information about TLB mapped segments.

Physical Memory Map

Address Range Name Description
0x00000000 0x003FFFFF RDRAM RDRAM located on motherboard
0x00400000 0x007FFFFF RDRAM RDRAM from Expansion Pak (if present)
0x00800000 0x03EFFFFF Reserved Unknown usage
0x03F00000 0x03FFFFFF RDRAM Registers RDRAM configuration registers
0x04000000 0x04000FFF RSP DMEM RSP Data Memory
0x04001000 0x04001FFF RSP IMEM RSP Instruction Memory
0x04002000 0x0403FFFF Unknown Unknown
0x04040000 0x040FFFFF RSP Registers RSP DMAs, status, semaphore, program counter, IMEM BIST status
0x04100000 0x041FFFFF RDP Command Registers RDP DMAs, clock counters for: clock, buffer busy, pipe busy, and TMEM load
0x04200000 0x042FFFFF RDP Span Registers TMEM BIST status, DP Span testing mode
0x04300000 0x043FFFFF MIPS Interface (MI) Init mode, ebus test mode, RDRAM register mode, hardware version, interrupt status, interrupt masks
0x04400000 0x044FFFFF Video Interface (VI) Video control registers
0x04500000 0x045FFFFF Audio Interface (AI) Audio DMAs, Audio DAC clock divider
0x04600000 0x046FFFFF Peripheral Interface (PI) Cartridge port DMAs, status, Domain 1 and 2 speed/latency/page-size controls
0x04700000 0x047FFFFF RDRAM Interface (RI) Operating mode, current load, refresh/select config, latency, error and bank status
0x04800000 0x048FFFFF Serial Interface (SI) SI DMAs, PIF status
0x04900000 0x04FFFFFF Unused Unused
0x05000000 0x05FFFFFF Cartridge Domain 2 Address 1 N64DD control registers (if present)
0x06000000 0x07FFFFFF Cartridge Domain 1 Address 1 N64DD IPL ROM (if present)
0x08000000 0x0FFFFFFF Cartridge Domain 2 Address 2 Cartridge SRAM (if present)
0x10000000 0x1FBFFFFF Cartridge Domain 1 Address 2 Cartridge ROM
0x1FC00000 0x1FC007BF PIF ROM (IPL1/2) Executed on boot
0x1FC007C0 0x1FC007FF PIF RAM Controller and EEPROM communication, and during IPL1/2 is used to read startup data from the PIF
0x1FC00800 0x1FCFFFFF Reserved Unknown usage
0x1FD00000 0x7FFFFFFF Cartridge Domain 1 Address 3 Mapped to same address range on physical cartridge port
0x80000000 0xFFFFFFFF External SysAD device bus Unknown usage (Unconfirmed: possibly used by processors, cache, and/or RAM for communication)

Cartridge Domains 1 and 2 are mapped one-to-one on the cartridge/bottom port. It is not known at this time what Domain 1 Address 3 was used for, if at all, but flash carts may have some use for that address range.

Memory Map accesses

The whole memory map is implemented by RCP, as the VR4300 only talks directly to RCP. The RCP behaves differently with different access sizes depending on the specific area of the map and the subcomponent in charge of implementing it.

Notice that misaligned address are forbidden by MIPS architecture and they will result in an Address Exception. So all accesses that go through the memory map are always aligned to the access size (eg: aligned to 2 bytes for 16-bit reads/writes).

Range 0x0000'0000 - 0x007F'FFFF (RDRAM)

The accesses in this area are handled by RCP via RI (Ram Interface). When the VR4300 reads or writes a location in this range, it gets stalled while the RI communicates with the RDRAM via the RAMBUS serial protocol. As soon as the read or write is finished, the VR4300 is released. Effectively, all reads and writes are synchronous (blocking) from the point of view of the VR4300, as you would expect when accessing a RAM. All access sizes work correctly: 8-bit, 16-bit, 32-bit, 64-bit.

Range 0x03F0'0000 - 0x004F'FFFF (RCP registers)

The accesses in this area are handled by RCP itself without going to an external bus, and are dispatched internally to the correct subsystem. Access to a register might optionally stall the VR4300 if the subsystem is designed to do so (eg: to perform a long blocking operation on write), but in general for standard registers, they are immediate and take only 1 PClock cycle.

Internally, all registers are 32-bits and are thus accessed as 32-bit. When the VR4300 requests a read using 8-bit or 16-bit access sizes, the data is correctly returned as expected. Notice that the register is still read in full and put it on the bus as 32-bit, but the VR4300 is able to extract the correct portion, just like reading from RAM. When the VR4300 requests a read using 64-bit, the data is also returned as expected. Two subsequence 32-bit register reads are performed, each on returning the correct value, and the VR4300 is able to recompose the final 64-bit value. So for instance, from the VR4300 side, reading 64-bit from physical address 0x0046'0010 will return a 64-bit value obtained by composing the value of the register 0x0046'0010 as MSB, and the register 0x0046'0014 as LSB.

Writes, instead, do not work correctly at all access sizes because the RCP does not implement the required circuitry to perform them. What happens is that the VR4300 puts the full register value on the bus for the write, with the correct shift (as required by the SysAD protocol), but the RCP basically ignores the access size.