31.15V XIII: Mask Instructions

Part III Linux boot: recommended Vol. I (Unprivileged) pp. 355–361 · ~2 min read

Masks are the vector ISA’s control flow; §31.15 is its boolean algebra and bit-scanning toolkit. Because masks are one bit per element in a single register, everything here ignores LMUL.

The mask toolkit
Semantics & rules
vmand/vmnand/vmandn/vmxor/vmor/vmnor/vmorn/vmxnor .mmBitwise mask logicals — the 8 ops span all 16 two-input boolean functions.
vcpop.m rd, vs2[, v0.t]Count set (active) mask bits into x[rd]; writes rd even at vl=0 (result 0). vstart must be 0.
vfirst.m rd, vs2[, v0.t]Index of the first active set bit, or −1 if none — the branch fuel for search loops.
vmsbf.m / vmsif.m / vmsof.mSet-Before-First / Including-First / Only-First: prefix masks derived from the first set bit — how “found the NUL” becomes “operate on everything before it.”
viota.mPrefix-sum of mask bits: element i = count of set bits below i — the destination indices for pack/compaction patterns.
vid.vWrites each element its own index (0,1,2,…) — no source; combine with compares for range predicates.
Dotted-underlined cells have explanations — click one.

The strlen finale, continuing the FOF page’s loop:

    vmseq.vi v0, v8, 0        # mask of NUL positions
    vfirst.m a2, v0           # index of first NUL (or -1)
    bgez     a2, found        # found within this strip

Common rules across the scanning ops (vcpop, vfirst, vmsbf/sif/sof, viota): they trap only with vstart=0 (nonzero → illegal instruction), and the prefix-mask producers are mask-writers, hence always tail-agnostic.

Hardware Designer Notes

viota + masked vrgather (or vcompress, next page) is the stream-compaction pattern — filter-and-pack in three instructions. If your target workloads include databases or sparse formats, make viota fast; it’s the difference between vectorized and scalar filtering.

Minimal Linux-boot hart MUST

  • Implement the mask ops on a single-register bit-vector path with the always-unmasked/tail-agnostic rules baked in
  • Enforce vstart=0 for the scanning instructions (illegal otherwise)
  • vcpop must write rd at vl=0 — the one guaranteed write in an empty strip

MAY simplify / trap-and-emulate

  • Fuse vmmv.m/vmand.mm into a following masked op (the spec’s intended pattern)
  • Share the popcount/find-first trees with your scalar Zbb cpop/ctz logic at mask width

Check yourself — mask instructions

1.Why do the eight vm*.mm logicals ignore LMUL entirely?

2.What do vmsbf/vmsif/vmsof compute from a mask, and what's the canonical use?

3.What does viota.m produce, and what makes it the compaction workhorse?

3 questions