31.7.4-8V VI: Unit-Stride, Strided, Indexed, FOF & Segment Memory Ops

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

The five memory-access families, from fastest to most flexible:

The vector memory instructions
Behavior & fine print
vle8/16/32/64.v · vse*.v — unit-strideContiguous from (rs1), data EEW in the mnemonic. The performance path.
vlm.v / vsm.v — mask transferByte moves of evl = ceil(vl/8) bytes (one bit per element!), EMUL=1, always tail-agnostic, vstart in bytes. Encoded as EEW=8 with special lumop/sumop.
vlse*.v / vsse*.v — constant strideElement i at (rs1) + i·x[rs2]; zero and negative strides legal; element accesses unordered.
vluxei/vloxei/vsuxei/vsoxei — indexed (gather/scatter)Address = (rs1) + vs2[i] byte offsets; index EEW in the mnemonic (ei8..ei64), data at SEW. U = unordered; O = ordered (per-element ordering for non-idempotent targets and overlapping scatters).
vle*ff.v — fault-only-firstUnit-stride load that traps ONLY on element-0 exceptions; a fault at element k>0 instead truncates vl to k. The while-loop vectorizer.
vlseg/vsseg (+ strided/indexed forms) — segmentsMove NFIELDS (= nf+1 ≤ 8) contiguous fields per segment into consecutive register groups: vlseg3e8.v de-interleaves RGB into v8/v9/v10. vl counts segments; masking per segment; EMUL·NFIELDS ≤ 8; no wrap past v31; vstart in segments.
Dotted-underlined cells have explanations — click one.

Fault-only-first: vectorizing while

# strlen(str): probe a full strip, let faults shorten it
loop:
    vsetvli a1, x0, e8, m8, ta, ma   # vl = VLMAX
    vle8ff.v v8, (a0)                # may TRUNCATE vl, never faults past elem 0
    csrr a1, vl                      # actual elements loaded
    vmseq.vi v0, v8, 0               # find NUL
    vfirst.m a2, v0
    ...

Element 0 still faults normally — guaranteeing progress — and a truncated vl feeds the loop exactly like a short final strip. (vl changes by FOF are one of only two writers of vl, alongside vset{i}vl{i}.)

Hardware Designer Notes

The FOF truncation path is the trickiest verification target in vector memory: fault reporting must be precise at element granularity but suppressed architecturally. Model it as “speculative-past-element-0” from day one and the trap logic falls out naturally.

Minimal Linux-boot hart MUST

  • Give FOF loads a non-faulting probe path: element-0 exceptions trap normally, later ones must squash and truncate vl — this needs the MMU response to flow back before architectural commit of vl
  • Honor ordered-indexed element ordering (effectively serialize) and the unordered license everywhere else
  • Enforce the segment reserved cases: EMUL·NFIELDS > 8 and register-number wrap past 31

MAY simplify / trap-and-emulate

  • Crack segments into field-wise micro-ops; a 3-field byte segment load is a natural 3-pass strided sequence with register-file transpose
  • Optimize away redundant x0-stride accesses (idempotent regions) — the explicit architectural license

Check yourself — vector memory instructions

1.vle32ff.v hits a page fault at element 5 (element 0 was fine). What happens?

2.What does vlseg3e8.v v8, (a0) do with packed RGB pixel data?

3.How do vlse64.v with x[rs2]=0 and the same instruction with rs2=x0 differ?

4.Why do vlm.v/vsm.v (mask loads/stores) use evl = ceil(vl/8)?

4 questions