Skip to content

riscv_fpu: RMM (roundTiesToAway) for the scalar OP-FP ops - #242

Draft
SolAstrius wants to merge 4 commits into
LekKit:stagingfrom
pufit:fix/rmm-roundtiestoaway
Draft

riscv_fpu: RMM (roundTiesToAway) for the scalar OP-FP ops#242
SolAstrius wants to merge 4 commits into
LekKit:stagingfrom
pufit:fix/rmm-roundtiestoaway

Conversation

@SolAstrius

Copy link
Copy Markdown
Contributor

Summary

Fix RMM (round to nearest, ties to max magnitude — IEEE 754 roundTiesToAway) for the scalar arithmetic ops, addressing #204. Standalone on staging; no dependency on the other in-flight FPU work.

The host FPU has no RMM mode, so under frm == RMM the host is left in round-to-nearest-even. RNE and roundTiesToAway differ only on an exact halfway tie. The previous riscv_prepare_rmm rounded toward ±inf unconditionally — correct on ties but wrong for every inexact non-tie. This replaces it with: compute in RNE, recover the exact rounding error via the library's error-free transforms (TwoSum / TwoProduct), and step one ULP outward only on a true half-ULP tie.

What's covered

  • fadd / fsub / fmul / fdiv, both .s and .d.
  • fmul near the underflow boundary, where Dekker's product error itself underflows — handled with an exact widened (f32) / scaled-residual (f64) tie test.
  • subnormal fdiv quotients, the one division case that can land on an exact tie.
  • fsqrt needs no fixup (a square root is never an exact halfway case).
  • Flag-isolated throughout: the error-free transforms do raw host arithmetic whose intermediate steps can raise spurious NV/OF, so each wrapper snapshots and restores the exception flags; the genuine flags come from the base op.

Scope / draft notes

Deliberately minimal and independent, so it can be reviewed on its own (per review feedback that RMM is too complex to evaluate bundled with the rest):

  • Dynamic RMM only (frm == RMM, rm == DYN). The static ,rmm instruction suffix needs host-rounding-mode forcing and lands with the rounding-mode rework.
  • OP-FP only — no FMA. The FMA-family ties-away fixup depends on the FMA rounding path; under RMM the FMA ops still round ties-to-even here, to be completed with the FMA work.

Draft until the companion FPU PRs settle (it lightly overlaps the fadd/fsub/fmul/fdiv read sites with the canonicalization/mal-box PR, so ordering may want a trivial rebase).

Touches src/cpu/riscv_fpu.c only.

@SolAstrius

Copy link
Copy Markdown
Contributor Author

@purplesyringa addressed the #239 comments that apply here: the RMM fixups now live in fpu_lib next to the error-free transforms, with a header note that RMM is riscv-specific (as agreed), and the div_apply naming inconsistency is gone. Dynamic-frm RMM harness passes 21826/21826; static rm handling stays a separate patch. Keeping it draft so it doesn't get merged by accident again — review when you have time.

Signed-off-by: Sol Astrius Phoenix <sol@astrius.ink>
(cherry picked from commit 685255b)
…low boundary

Signed-off-by: Sol Astrius Phoenix <sol@astrius.ink>
(cherry picked from commit 81d257c)
Review feedback on LekKit#239: the math-heavy tie fixups belong in fpu_lib
next to the error-free transform machinery they build on, with an
explicit header note that RMM is a RISC-V-specific rounding mode (a
native RISC-V host could bypass the fixups entirely). Also aligns the
fdiv fixup naming (riscv_rmm_div_apply -> fpu_rmm_div) with the add/mul
helpers. No functional change; the RMM harness still passes all 21826
dynamic-frm vectors.

Signed-off-by: Sol Astrius Phoenix <sol@astrius.ink>
@SolAstrius
SolAstrius force-pushed the fix/rmm-roundtiestoaway branch from ed93382 to 2295b9f Compare July 17, 2026 22:48
Signed-off-by: Sol Astrius Phoenix <sol@astrius.ink>
LekKit pushed a commit that referenced this pull request Jul 22, 2026
Arithmetic and conversion ops only ever ran in the mode the frm CSR left
on the host FPU; a static rm field (fadd.s ...,rtz etc.) was silently
ignored. Apply a differing static mode around the op, gated on the op
actually being rounding-capable: funct3 is an rm field only there, while
on fsgnj/fmin/fmax/fcmp/fclass/fmv it encodes the operation itself and
must not drive the host mode. Ops that take rm as an explicit argument
(fcvt to integer, fround) consume the field directly and need no wrap.

A static rmm field runs in RNE for now, which differs from
roundTiesToAway only on exact halfway ties; those are covered once the
exact RMM fixups land (#242). The dynamic-RMM preparation is gated to
rm == DYN so it no longer fires under a static field.

Signed-off-by: Sol Astrius Phoenix <sol@astrius.ink>
LekKit pushed a commit that referenced this pull request Jul 22, 2026
fpu_fma rounds in the host mode, so a static rm field on
fmadd/fmsub/fnmsub/fnmadd was silently computed in whatever mode frm
left set. Route the FMA ops through riscv_fma32/64, which apply a
differing static mode around the op using the same riscv_fpu_host_rm
rule as the OP-FP dispatch. As there, a static rmm field runs in RNE
until the exact ties-away fixups (#242) extend to FMA.

Signed-off-by: Sol Astrius Phoenix <sol@astrius.ink>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant