| 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 / vwmulsu | Full 2·SEW products into a 2·LMUL destination group — the exact-product path (vmulh gives the same bits at same-width). |
| vmacc / vnmsac | Destructive MAC overwriting the ADDEND: vd += ±(vs1 · vs2). “sac” = subtract-from-accumulator. |
| vmadd / vnmsub | The multiplicand-overwriting twins: vd = ±(vs1 · vd) + vs2 — compilers pick the form whose dead register matches. |
| vwmaccu / vwmacc / vwmaccsu / vwmaccus | Widening MACs: 2·SEW accumulator += SEW×SEW product, every signedness combination (us is .vx-only) — the integer dot-product engine. |
| vmerge.vvm/.vxm/.vim | vd[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.i | Copy / splat-scalar / splat-immediate; encoded as vmerge with vm=1 and vs2 pinned to v0 (anything else reserved). |
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):
| 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. |
| vsmul | Signed 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 / vssra | Scaling shifts: right shift with the discarded bits vxrm-ROUNDED instead of truncated — the fixed-point renormalization step. |
| vnclip[u] .wv/.wx/.wi | Narrowing clip: 2·SEW source, scale-shift, round, SATURATE into SEW — the widen-accumulate-then-repack closer, setting vxsat on clamp. |
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?