Skip to main content
← PSoXide SDK guides and examples · SDK f2fec1c301f1 · All Cargo features enabled; check feature gates before use.

read_data

Macro read_data 

Source
macro_rules! read_data {
    ($reg:literal) => { ... };
}
Expand description

Read a GTE data register (MFC2). Expands to a single MFC2 instruction with the register index baked into the .word encoding, followed by a NOP that fills the one-cycle load-delay slot.

Why the NOP: MIPS R3000 MFC2/CFC2 commit their result to the CPU GPR at the END of the NEXT instruction – not at the end of MFC2 itself. Rust’s inline-asm output binding (out("$8") value) makes the compiler insert a move-from-$8 right after the .word block, and that move runs in the delay slot → sees the pre-MFC2 value of $8, not the coprocessor data. The emulator models this correctly (see cpu::committing_load), so without the NOP every read_data! call silently returns stale data.

Encoded as two .words: the MFC2 then a 32-bit zero (the MIPS canonical NOP = SLL $0, $0, 0).