Skip to content

fcvt.d.w/fcvt.d.wu with rm=DYN and a reserved frm execute instead of raising illegal-instruction #166

Description

@wndmll643

Summary

When frm holds a reserved value (5/6/7) and an instruction uses the dynamic rounding mode (rm=111, DYN), NaxRiscv fails to raise illegal-instruction for the exact integer→double conversions fcvt.d.w and fcvt.d.wu — it commits them. Spike (used as the golden reference) raises illegal-instruction. The rounding-dependent operations are handled correctly (see below), so the divergence is limited to these two exact conversions.

Observed behavior

With frm ∈ {5,6,7} and rm=111 (DYN):

Instruction NaxRiscv Spike (reference)
fadd.d, fmul.d, … (rounding-dependent) illegal-instruction ✔ illegal-instruction
fcvt.d.w, fcvt.d.wu (exact int→double) commits (executed) illegal-instruction

So the reserved-rounding-mode check is present for the rounding path but absent for the exact int→double conversions.

Root cause

FpuFloatExecute.scala:138 and FpuIntegerExecute.scala:82 resolve rm=DYN → frm:

val roundMode = (instrRounding === B"111") ? getService[FpuWriteback].getRoundingMode() | instrRounding

with no validity check at that site. The effective reserved-rounding-mode check for the rounding-dependent path lives downstream in the rounding logic; the always-exact int→double conversions bypass rounding and therefore also bypass the check, so a reserved frm is accepted and the instruction executes.

Reproducer

Minimal sequence (M-mode, mstatus.FS enabled, fcsr=0):

    fmv.d.x f0, x0
    li   t1, 0xff
    csrw fcsr, t1          # frm := 7 (reserved)
    .4byte 0xd205f0d3      # fcvt.d.w f1,x11,rm=DYN

Result: NaxRiscv commits the fcvt.d.w; Spike raises illegal-instruction with mtval=0xd205f0d3.

Cross-checks:

  • Standalone Spike on the same sequence: both fadd.d …,dyn and fcvt.d.w …,dyn raise illegal-instruction — confirms the reference.
  • On NaxRiscv, fadd.d …,dyn with frm=7 traps (illegal, tval = the fadd), while fcvt.d.w …,dyn with frm=7 commits — this contrast isolates the missing check to the exact conversions.

Spec basis

Per the strict reading of the F/D extension — which Spike and the SAIL model implement — any FP instruction with rm=DYN while frm is reserved raises illegal-instruction, regardless of whether the operation actually rounds; NaxRiscv should therefore trap fcvt.d.w/fcvt.d.wu in this case as well. (There is a lenient reading under which an exact conversion never consults the rounding mode, so if the intended behavior is deliberately lenient here, feel free to close — but the current behavior diverges from Spike.)

Suggested fix

Apply the same reserved-rounding-mode illegal check the rounding path uses to the fcvt.d.w/fcvt.d.wu decode: reject rm=DYN when frm ∈ {5,6,7} (and static rm ∈ {5,6}).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions