Memory map

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
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.

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

Physical Memory Map
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.