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.
| Semantics & rules | |
|---|---|
| vmand/vmnand/vmandn/vmxor/vmor/vmnor/vmorn/vmxnor .mm | Bitwise 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.m | Set-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.m | Prefix-sum of mask bits: element i = count of set bits below i — the destination indices for pack/compaction patterns. |
| vid.v | Writes each element its own index (0,1,2,…) — no source; combine with compares for range predicates. |
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?