31.11.11-6V IX: Divide, MAC, Merge & Fixed-Point

Part III Linux boot: recommended Vol. I (Unprivileged) pp. 329–336 · ~3 min read

Integer arithmetic §31.11.11-16
Semantics & rules
vdiv[u] / vrem[u]Element-wise divide/remainder with the scalar M extension’s exact extreme-case results (÷0 → all-1s quotient, dividend remainder; signed-overflow wrap). No traps.
vwmul / vwmulu / vwmulsuFull 2·SEW products into a 2·LMUL destination group — the exact-product path (vmulh gives the same bits at same-width).
vmacc / vnmsacDestructive MAC overwriting the ADDEND: vd += ±(vs1 · vs2). “sac” = subtract-from-accumulator.
vmadd / vnmsubThe multiplicand-overwriting twins: vd = ±(vs1 · vd) + vs2 — compilers pick the form whose dead register matches.
vwmaccu / vwmacc / vwmaccsu / vwmaccusWidening MACs: 2·SEW accumulator += SEW×SEW product, every signedness combination (us is .vx-only) — the integer dot-product engine.
vmerge.vvm/.vxm/.vimvd[i] = v0.mask[i] ? second-source : vs2[i] on ALL body elements — the mask is a data SELECT, not predication (encoded vm=0).
vmv.v.v / vmv.v.x / vmv.v.iCopy / splat-scalar / splat-immediate; encoded as vmerge with vm=1 and vs2 pinned to v0 (anything else reserved).
Dotted-underlined cells have explanations — click one.

The mask-widening idiom the spec calls out: vmv.v.i vd, 0 then vmerge.vim vd, vd, 1, v0 turns a mask into 0/1 SEW-wide elements.

Fixed-point arithmetic (§31.12)

Fixed-point numbers are integers with a software-managed implicit denominator; the hardware contributes scaling, rounding (vxrm), and saturation (vxsat):

The fixed-point family
Semantics
vsadd[u] / vssub[u]Saturating add/subtract: overflow clamps to the format edge and sets vxsat (no wraparound surprises in DSP kernels).
vaadd[u] / vasub[u]Averaging: (a ± b) >> 1 with vxrm rounding, computed in infinite precision — vaadd can never overflow; vasub wraps its one corner case.
vsmulSigned fractional multiply: 2·SEW product, shift right SEW−1 (one less than SEW keeps an extra precision bit — only −1.0×−1.0 saturates), vxrm-round, clip, vxsat on saturation. Q-format multiplication in one op.
vssrl / vssraScaling shifts: right shift with the discarded bits vxrm-ROUNDED instead of truncated — the fixed-point renormalization step.
vnclip[u] .wv/.wx/.wiNarrowing clip: 2·SEW source, scale-shift, round, SATURATE into SEW — the widen-accumulate-then-repack closer, setting vxsat on clamp.
Dotted-underlined cells have explanations — click one.

Hardware Designer Notes

One multiplier array serves the entire family: SEW×SEW→2·SEW hardware with writeback selects (low half, high half, full to pair, accumulate). Size it once, verify the signedness matrix once.

Minimal Linux-boot hart MUST

  • Reuse the scalar divider’s extreme-case logic per lane — results must match M exactly
  • Route vmerge/vmv through the mask-as-data path (all body elements written), distinct from ordinary predication
  • Enforce vmv’s vs2=v0 reservation and the widening-MAC overlap rules from §31.5

MAY simplify / trap-and-emulate

  • Iterate divides one element per cycle on a shared divider — nobody vectorizes for vdiv throughput
  • Elide vmv.v.v vd, vd dynamically (resetting vstart) if you don’t internally rearrange
  • Build the widening MAC as your one full-width multiplier array — vmul/vmulh/vwmul/vsmul all read from it

Check yourself — divide, MACs, merge, fixed-point

1.vmacc and vmadd both fuse multiply-add. What differs?

2.How does vmerge relate to the masked-instruction machinery, and what's special about its element coverage?

3.What is vmv.v.v vd, vd for, and why isn't it a HINT?

4.vdiv by zero in a vector — what happens?

4 questions