riscv: resolve frm for dynamic rounding of fcvt float-to-int - #260
riscv: resolve frm for dynamic rounding of fcvt float-to-int#260carlosqwqqwq wants to merge 1 commit into
Conversation
|
@SolAstrius please review, thank you |
|
This is not an isolated problem, if we don't handle this more generally it's going to surface again. The root issue is that fpu_lib assumes DYN denotes the current host mode, while in reality we pretty much always want the current emulated mode. I think every function in fpu_lib needs to have a contract that the passed rounding mode is never DYN, it should never try to default to the host mode, and that logic needs to be moved to the caller that knows what the state of the emulated FPU is. |
|
Technically the host rounding mode is the guest However, this comes with two important exceptions:
|
I think we're in agreement, but to elaborate: in most instruction handlers, like addition, which don't normally need to bother with the rounding mode, it is indeed a good idea to mostly ignore it and special-case RMM separately. In functions like |
|
Agreed with the discussion outcome. This PR resolves DYN at the caller (eff_rm = frm CSR when rm==DYN) and passes a concrete mode into fpu_round_*; the helpers never see DYN on the fcvt path, and a guest frm=RMM is honored by the software rounding path. That matches the proposal to move DYN resolution to the caller and keep fpu_lib's contract mode != DYN. No changes needed from the discussion; happy to adjust if you prefer the resolution in a shared helper. |
|
The reason I wrote that comment is that |
40ef7cb to
bc5f5e4
Compare
Resolve rm==DYN to the guest frm CSR before rounding in all fcvt
float-to-int and fround (Zfa) paths, so a guest frm=RMM is honored by
the software rounding path instead of silently using the host mode.
fpu_round_{f32,f64}_internal now always receive a concrete mode; their
internal DYN fallback is removed and documented accordingly.
bc5f5e4 to
c3001be
Compare
|
Good catch - verified it. Two things: (1) the fround.s/fround.d (Zfa) paths also fed rm directly into fpu_round_{f32,f64}_to_i64, so the DYN fallback was still reachable; those now use eff_rm too. (2) With every caller resolving DYN, the mode > FPU_LIB_ROUND_MM fallback inside fpu_round_f32_internal / fpu_round_f64_internal is indeed dead: removed it from both and updated the doc comments to state the caller contract (mode is always a concrete mode, RMM included). Rebuilt cleanly and force-pushed. |
Summary
The float-to-integer conversions (
fcvt.w.s,fcvt.wu.s,fcvt.l.s,fcvt.lu.sand the.dsiblings) pass the rawrmfield to the rounding helpers. Forrm=dynthe helper falls back to the host-tracked mode, but RMM has no host equivalent and is mapped to RNE, sofrm=RMMcollapses to round-to-nearest-even instead of round-to-nearest-ties-away. The Zfafround.s/fround.dpaths had the same issue.Resolve the effective mode from
frmwhen the field isdynand pass it to the rounding helpers (fcvt float-to-int and fround); staticrmvalues, including RMM, are unchanged. With every caller now resolving DYN, the internalmode > RMMfallback infpu_round_f32_internal/fpu_round_f64_internalis unreachable and has been removed; the functions now document that the caller always passes a concrete mode (RMM included).Validation
+2.5/-2.5) under static RMM anddyn + frm=RMMfor all eight conversion forms match native RISC-V hardware and QEMU.RNE/RDN/RUPcontrols are unchanged.Fixes #255