F adds IEEE 754-2008 single precision: thirty-two f-registers ( FLEN flen Width of the floating-point registers: 32 with F, 64 with D, 128 with Q. Independent of XLEN. defined in ch. I·21 — open in glossary = 32), a control/status CSR, and a design philosophy with hardware consequences — no FP traps, hardware-produced default results, canonical NaNs only, and integers never stored in f-registers. It depends on Zicsr.
21.2 fcsr: rounding and flags
fcsr
frm (bits 7–5) and fflags (bits 4–0) are also standalone CSRs, with
pseudo-instructions for each (FRCSR/FSCSR, FRRM/FSRM,
FRFLAGS/FSFLAGS). Every rounding instruction carries a 3-bit rm
field: a static mode rounding mode RNE 000 (nearest-even), RTZ 001, RDN 010, RUP 011, RMM 100 (nearest-max-magnitude), 111 DYN in an instruction's rm field = use frm. 101/110 (and DYN inside frm) reserved - reserved-rm behavior is reserved (trapping legal).
defined in ch. I·21 — open in glossary
, or 111 (DYN) to
use frm.
| rm | Meaning | |
|---|---|---|
| RNE | 000 | Round to nearest, ties to even — the default; also what software writes in rm fields that don’t matter |
| RTZ | 001 | Toward zero |
| RDN | 010 | Down (−∞) |
| RUP | 011 | Up (+∞) |
| RMM | 100 | Nearest, ties to max magnitude |
| (reserved) | 101 / 110 | Reserved — behavior reserved |
| DYN | 111 | In rm: use frm. Inside frm itself: reserved |
There are no FP traps. Flags (NV, DZ, OF, UF, NX) accrue stickily and software checks them explicitly; hardware must deliver IEEE default results (quiet NaN, ±∞, clipped integers…) with no user-level fixup — though an implementation may invisibly trap to M-mode firmware to produce them.
21.3–21.5 NaNs, subnormals, loads/stores
An arithmetic result that is NaN is the
canonical NaN canonical nan The only NaN RISC-V FP ops produce: positive sign, quiet bit set, all other significand bits clear (0x7fc00000 single). Payload propagation is not standard; FLW/FSW/FMV/FSGNJ still preserve raw bits.
defined in ch. I·21 — open in glossary
: 0x7fc00000 — positive
sign, quiet bit, empty payload. No payload propagation (allowed only as a
nonstandard mode). Subnormals are fully supported per IEEE, with
tininess detected after rounding tininess after rounding RISC-V detects underflow tininess AFTER rounding (fewer spurious underflow flags) - an IEEE-allowed choice your FPU's UF detector must match.
defined in ch. I·21 — open in glossary
.
FLW/FSW (LOAD-FP/STORE-FP opcodes, base+imm12) transfer bits
verbatim — non-canonical NaN payloads survive loads and stores —
and are atomic only when naturally aligned; misaligned behavior follows
the u02 EEI rules.
21.6 Computation
Two-operand arithmetic is R-type under OP-FP: funct5 selects the
operation, the 2-bit fmt field is 00 (S) throughout F:
FMIN.S/FMAX.S implement the 754-201x minimumNumber/maximumNumber
semantics (amended in F v2.2): −0.0 < +0.0; both NaN → canonical NaN; one
NaN → the other operand — but a signaling NaN input sets NV even
when the result is a number.
The fused multiply-adds get RISC-V’s only four-source-field format, R4-type (rs3 replaces funct5’s slot at [31:27]):
| Computes | Note | |
|---|---|---|
| FMADD.S | (rs1 × rs2) + rs3 | One rounding — the point of fusion |
| FMSUB.S | (rs1 × rs2) − rs3 | |
| FNMSUB.S | −(rs1 × rs2) + rs3 | Negates the PRODUCT |
| FNMADD.S | −(rs1 × rs2) − rs3 | See FNMSUB naming note |
One mandated flag subtlety: ∞ × 0 sets NV even when rs3 is a quiet NaN (IEEE merely permits this; RISC-V requires it).
21.7 Conversions and moves
FCVT.{W,WU,L,LU}.S / FCVT.S.{W,WU,L,LU} convert with rounding per rm
(L forms RV64-only; W results sign-extend on RV64). Out-of-range inputs
clip and set NV — memorize Table 27’s corners:
| FCVT.W.S | FCVT.WU.S | FCVT.L.S | FCVT.LU.S | |
|---|---|---|---|---|
| Out-of-range negative / −∞ | −2³¹ | 0 | −2⁶³ | 0 |
| Out-of-range positive / +∞ | 2³¹−1 | 2³²−1 | 2⁶³−1 | 2⁶⁴−1 |
| NaN | 2³¹−1 | 2³²−1 | 2⁶³−1 | 2⁶⁴−1 |
Conversions set NX when the rounded result differs from the input (and NV
isn’t set). FCVT.S.W rd, x0 materializes a clean +0.0.
The sign-injection trio fsgnj family FSGNJ/FSGNJN/FSGNJX: rs1's bits with the sign from rs2 / its inverse / the XOR of both signs. No flags, no NaN canonicalization. With rs1=rs2 they are FMV.S / FNEG.S / FABS.S.
defined in ch. I·21 — open in glossary
FSGNJ/FSGNJN/FSGNJX
builds FMV.S, FNEG.S, FABS.S (rs1 = rs2 forms) plus IEEE copySign —
no flags, no NaN canonicalization. Raw-bit moves between files:
FMV.X.W (RV64: upper 32 bits = copies of the sign bit) and FMV.W.X,
both payload-preserving.
21.8 Compares
FEQ.S/FLT.S/FLE.S write 0/1 to an integer register; any NaN
operand makes the result 0. FLT/FLE are
signaling signaling vs quiet comparison FLT/FLE are signaling (NV on ANY NaN input); FEQ is quiet (NV only on sNaN). All three return 0 when either operand is NaN.
defined in ch. I·21 — open in glossary
(NV on any NaN);
FEQ is quiet (NV only on signaling NaN).
Hardware Designer Notes
An FPU for Linux boot is mostly about the edges, not the datapath: the canonical-NaN rule, Table 27’s corners, the v2.2 min/max semantics, and after-rounding tininess are where RTL diverges from softfloat references. Wire fflags as sticky ORs accumulated at retirement (they’re accumulating CSRs — no serialization), and note frm becomes a real pipeline input only for rm=DYN instructions; a write to frm then behaves like a serializing CSR write in simple cores. mstatus.FS dirty-tracking (Vol II ch. 3) is the other half of the context-switch story.
Minimal Linux-boot hart MUST
- Produce IEEE default results in hardware (or via invisible M-mode traps) — user software never fixes up
- Emit exactly 0x7fc00000 for arithmetic NaN results; preserve payloads only through FLW/FSW/FMV/FSGNJ
- Implement v2.2 FMIN/FMAX (minimumNumber): sNaN → NV with non-NaN result
- Clip FCVT per Table 27 — NaN to MAX positive; set NV/NX correctly
- Set NV on FMA ∞×0 regardless of addend
- Detect tininess after rounding
MAY simplify / trap-and-emulate
- Recode FP values internally (subnormal handling) — FMV/loads/stores must un-recode bit-exactly
- Trap on reserved rm encodings (101/110, DYN-in-frm) or treat as reserved — document it
- Iterate FDIV/FSQRT over many cycles — nothing in Linux boot times them
- Read one register when FSGNJ has rs1=rs2 — or not; it is a micro-optimization
Check yourself — F extension
1.FADD.S produces a NaN result. What bit pattern lands in rd?
2.FCVT.W.S of NaN. What integer results, and what flag?
3.FMIN.S with one signaling NaN input and one normal number. Result and flags?
4.Why must FMADD.S set NV for ∞×0 even when rs3 is a quiet NaN?
5.On RV64, FMV.X.W moves an f-register to an x-register. What fills bits 63:32?