Skip to main content

Fpr

Struct Fpr 

Source
pub struct Fpr { /* private fields */ }
Expand description

The 32 physical floating-point general registers.

Implementations§

Source§

impl Fpr

Source

pub const fn new() -> Self

Power-on state.

The manual does not define one; ADR 0004 requires reproducibility, so it is a documented zero.

Source

pub const fn read_s(&self, n: u8, fr: bool) -> u32

Read a 32-bit value from FPR n under the current FR view.

FRRegister n maps to
1the low half of FGR n
0FGR n & !1 — its low half for even n, its HIGH half for odd n

The FR = 0 row is the whole subtlety, and it is not what “the pair FGR[n+1]:FGR[n]” suggests: an odd register in half mode is the upper 32 bits of its even partner, and odd FGRs are not addressable at all. n64-systemtest pins it directly — after MTC1 $1 in half mode, DMFC1(0) shows the written value in its high half while DMFC1(1) is unchanged.

Source

pub const fn write_s(&mut self, n: u8, fr: bool, v: u32)

Write a 32-bit value to FPR n under the current FR view.

The other half of the 64-bit register is preserved — this models MTC1/LWC1, which deposit 32 bits and leave the rest alone. An arithmetic .S result does not behave this way; see Fpr::write_s_arith.

See Fpr::read_s for the FR = 0 mapping.

Source

pub const fn write_s_arith(&mut self, n: u8, _fr: bool, v: u32)

Write a single-precision arithmetic result, which clears the other half of the destination rather than preserving it.

This is what separates an arithmetic write-back from MTC1. n64-systemtest’s “Upper bits of 32 bit operation” reads the destination back with DMFC1 after an ADD.S and expects the upper 32 bits to be zero, not the register’s previous contents.

The destination index is used as-is in both FR modes — unlike Fpr::write_s, which under FR = 0 reaches an even partner. ADD.S $1 in half mode leaves its result in FGR1, upper half cleared, which is what the suite reads back.

Source

pub const fn read_s_fs(&self, n: u8, fr: bool) -> u32

Read the fs operand of a floating-point arithmetic instruction.

Under FR = 0 an odd index reads its even partner’s value — the low bit of the field is simply dropped. This is not the same mapping as Fpr::read_s, which models MTC1/LWC1 and reaches the partner’s high half. Two different mappings for two different instruction classes is surprising, and it is what the hardware does.

§Why this is measured rather than looked up

The manual declines to specify it: “If the FR bit is 0, an odd-numbered register cannot be specified”, and for the arithmetic instructions “If an odd number is specified, the operation is undefined” (UM §7.5.3, §16). Undefined in the manual is still deterministic in silicon, and n64-systemtest measures it — so the ROM’s table is the oracle here, and the accuracy ledger records it as such rather than as documentation.

Source

pub const fn read_s_ft(&self, n: u8, _fr: bool) -> u32

Read the ft operand of a floating-point arithmetic instruction.

Unlike Fpr::read_s_fs, the index is used as-is in both FR modes: an odd ft reads the odd FGR’s own low half.

The asymmetry is the whole point of having two accessors. It is pinned by a pair of rows that disagree under any single rule: with FR = 0, SQRT.S $13, $31 yields sqrt(16) — so fs = 31 read FGR30 — while ADD.S $2, $28, $31 yields -10 + -16 — so ft = 31 read FGR31. One shared mapping cannot satisfy both.

Source

pub const fn read_d_fs(&self, n: u8, fr: bool) -> u64

Read the fs operand of a double-precision arithmetic instruction.

Source

pub const fn read_d_ft(&self, n: u8, _fr: bool) -> u64

Read the ft operand of a double-precision arithmetic instruction.

Source

pub const fn write_d_arith(&mut self, n: u8, _fr: bool, v: u64)

Write a double-precision arithmetic result.

Like Fpr::write_s_arith, the destination index is used as-is in both modes. ADD.D $1 under FR = 0 leaves the result in FGR1, which n64-systemtest checks by observing that FGR1 does not keep its preloaded value.

Source

pub const fn read_d(&self, n: u8, fr: bool) -> u64

Read a 64-bit value from FPR n under the current FR view.

With FR = 0 the register number is forced even and the whole 64-bit FGR is the value — not an assembly of two FGRs’ low halves, which is the shape this originally had and which disagreed with hardware on every odd index.

Source

pub const fn write_d(&mut self, n: u8, fr: bool, v: u64)

Write a 64-bit value to FPR n under the current FR view.

Source

pub const fn read_raw(&self, n: u8) -> u64

Read a raw FGR, ignoring FR.

Not for any instruction. DMFC1 looked like a user of this and is not: it is a formatted 64-bit access and goes through Fpr::read_d (accuracy ledger U-7). This exists for tests and for save-state serialization, which want the physical file.

Source

pub const fn write_raw(&mut self, n: u8, v: u64)

Write a raw FGR, ignoring FR. See Fpr::read_raw.

Trait Implementations§

Source§

impl Clone for Fpr

Source§

fn clone(&self) -> Fpr

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Fpr

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Fpr

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Fpr

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for Fpr

Source§

fn eq(&self, other: &Fpr) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for Fpr

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Copy for Fpr

Source§

impl Eq for Fpr

Source§

impl StructuralPartialEq for Fpr

Auto Trait Implementations§

§

impl Freeze for Fpr

§

impl RefUnwindSafe for Fpr

§

impl Send for Fpr

§

impl Sync for Fpr

§

impl Unpin for Fpr

§

impl UnsafeUnpin for Fpr

§

impl UnwindSafe for Fpr

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,