The whole extension fits in three major opcodes: loads and stores squat in LOAD-FP/STORE-FP (repurposing the FP immediate bits), everything else lives in the new OP-V (1010111), where funct3 selects the operand pattern:
Scalars come from immediates, x-registers, f-registers, or element 0 of any vector register (any LMUL). The f-on-v overlay was deliberately rejected — register pressure, calling convention, fast-scalar-FP design, and Zfinx compatibility all argued for separate files.
EEW/EMUL and the overlap rules
Every operand carries an effective width and multiplier — usually EEW=SEW, EMUL=LMUL, but widening ops write EEW=2·SEW at EMUL=2·LMUL (and narrowing reads the same). Groups are named by their lowest register; EMUL > 8 is reserved. One register may not be read at two different EEWs in one instruction. Destination/source overlap is legal only when:
| Allowed when | |
|---|---|
| Same EEW | Anywhere — ordinary in-place operations. |
| Destination narrower | Overlap only at the LOWEST register of the source group: vnsrl.wi v0, v0, 3 legal; destination v1 reserved. |
| Destination wider | Source EMUL ≥ 1 and overlap only at the HIGHEST register: at LMUL=8, vzext.vf4 v0, v6 legal; source v0/v2/v4 reserved. |
| Mask register v0 (EEW=1) | A masked instruction’s destination may not overlap v0 — unless the result IS a mask (compares) or a reduction scalar. |
Overlapping different-EEW cases execute tail- and mask-agnostic regardless of vtype — the old values are architecturally gone.
The element taxonomy
Every destination index falls into exactly one set: prestart (< vstart: never faults, never writes), body — split into active (mask on: computes, faults, writes) and inactive (mask off: vma policy) — and tail (≥ vl: vta policy). When vstart ≥ vl there is no body and nothing writes (even agnostic fills) — though instructions producing x/f-register results still deliver them, vl=0 included. Slides and gathers may read past vl; out-of-VLMAX source reads return 0.
Hardware Designer Notes
The overlap rules are the resumability contract: verify them as a matrix (EEW relation × register positions), because compilers lean on the legal corners (in-place narrowing especially) and reserved corners must trap, not corrupt.
Minimal Linux-boot hart MUST
- Enforce every reserved-encoding rule (group alignment, EEW-conflict, overlap, EMUL>8) with traps — software probes these
- Implement the element-taxonomy predicate exactly; active(x) gates exceptions as well as writes, so a masked-off lane must suppress its page fault
- Handle the vstart ≥ vl no-write case including the scalar-result exception
MAY simplify / trap-and-emulate
- Decode the seven funct3 patterns into a uniform internal op with an operand-source mux — the format regularity is deliberate
Check yourself — formats, masking, element sets
1.Why is vnsrl.wi v0, v0, 3 legal at LMUL=1 but a destination of v1 reserved?
2.How is masking encoded, and which register supplies the mask?
3.Classify element x during execution: vstart=2, vl=6, VLMAX=8, v0.mask = 0b10101010. What are elements 1, 3, 4, and 7?
4.Why do scalar operands live in element 0 of a vector register (for .vs forms) rather than overlaying f-registers on v-registers?