Expand description
The floating-point register file (T-13-001).
32 physical 64-bit FGRs. How software sees them depends on
Status.FR (UM §6.3.5, and the FPR/FGR figures in Ch. 7):
FR | Register n addresses |
|---|---|
| 1 | FGR n — 32 independent 64-bit registers |
| 0 | FGR n & !1 — odd FGRs are not addressable at all |
With FR = 0 there are 16 usable 64-bit registers, and a 32-bit access
picks a half of one of them: an even register number is the low half,
an odd register number is the high half of its even partner.
§This is not the “FGR pair” model, and the difference is observable
It is natural to read “FR = 0 uses register pairs” as the value is
FGR[n+1]:FGR[n], assembled from two registers’ low halves. This module
had exactly that, and it is wrong: it makes MTC1 $1 write FGR1, where
hardware writes the upper half of FGR0 and leaves FGR1 untouched.
n64-systemtest pins it directly. In half mode, after MTC1 $1:
DMFC1(0) == 0x01234567_89ABCDEF <- the write landed in FGR0's HIGH half
DMFC1(1) == 0x44445555_66667777 <- unchanged§Three write behaviors, not one
Fpr::write_s—MTC1/LWC1: deposit 32 bits, preserve the other half of the register.Fpr::write_s_arith— a single-precision arithmetic result: clear the other half. The suite’s “Upper bits of 32 bit operation” reads the destination back withDMFC1after anADD.Sand expects zero there.Fpr::write_d— a 64-bit value, whole register.
Collapsing the first two is invisible until something reads the register at a different width, which is precisely what those tests do.
Structs§
- Fpr
- The 32 physical floating-point general registers.