ISA Batch 11 — vbool ALU / predicate (boolean algebra · fold-into-FS · predicate scan)
This is the per-instruction reference for the vbool-consuming, vbool/FS-producing forms — the
pure boolean-algebra ALU over predicate masks and the predicate-reduce / predicate-scan
primitives. It is the consumer complement of the compare batches:
B01/B02/B03 produce a vbool
predicate from a vec→vbool comparison; B11 owns what you do with the predicate once you have it —
andb/orb/xorb/notb/andnotb/ornotb over two masks, the bnorfs/borfs reduce that collapses
eight vbool registers into one IVP_FS* predicate-state register, the movvfs/movfsv vbool↔FS
512-bit bridge, the popc/count* population-scan that turns a mask into an AR scalar, and the
single-bit (BR-register) notb1/andnotb1/ornotb1 forms. B03 explicitly defers these here
("vbool→vbool boolean logic and the vbool-folding ivp_bnorfs2n/ivp_borfs2n are B11").
Concretely, B11 owns 27 mnemonics / 189 placements of the certified-perfect 1534 / 12569 cover
(coverage-tally), in five sub-families:
- vbool boolean algebra (
andb/orb/xorb/notb/andnotb/ornotb/joinb) —vbool→vbool, 7 mnemonics. The pure 64-bit-mask bitwise operators. - Single-bit
BRboolean (notb1/andnotb1/ornotb1) — the 1-bit scalar-boolean (BRfile) siblings of the mask forms, 3 mnemonics. - Predicate move / make / extract (
mb/movab1/movba1/ext0ib) —AR↔vbool↔BRstructural bridges and bit-extract, 4 mnemonics. - Fold-into-FS reduce (
bnorfs2n/borfs2n) — OR/NOR-reduce eightvboolregisters into oneIVP_FS*predicate-state register, 2 mnemonics. - vbool↔FS bridge + predicate scan (
movvfs/movfsv;popc2nx8; the eightcount*4nx8) — the 512-bit lane-mask↔FS-state bit-permutation and the population/match-count scans, 11 mnemonics.
The encoding is read byte-exact from the non-stripped libisa-core.so (Opcode_*_encode selector
templates, the ivp_sem_vbool_alu_ltr_{vbt,vbr,vbs} field thunks); the value semantics are proven by
execution by driving the matching module__xdref_* leaves in libfiss-base.so live via ctypes
(license-free value lane). Every numeric claim is anchored to a binary address or a live call; the page
default is [HIGH/OBSERVED] and claims that depart from it carry an explicit tag. The prose is derived
from static analysis and in-process execution of the shipped artifacts only.
The B01/B03/B08/B11/fp-sub-isa partition boundary (read this first). The predicate datapath is split by what reads / writes the predicate, with zero mnemonic overlap:
batch op shape reads writes examples B01/B02 vec→vecbitwisevecvecivp_and2nx8,ivp_or2nx8,ivp_xor2nx8,ivp_not2nx8B03 compare / B-variant / *tvec(+vboolfor*t)vbool/vec-mergeivp_eqnx16,ivp_bmaxnx16,ivp_addnx16tB08 cross-lane reduce within one mask vboolvboolivp_randb2n,ivp_rorbn(the "all/any within a mask" reduce)B11 (this page) boolean algebra · multi-reg fold · scan vbool/BRvbool/FS/ARivp_andb,ivp_borfs2n,ivp_movvfs,ivp_popc2nx8fp-sub-isa FCR/FSR arith-control state — FCR/FSR wur.fcr,rur.fsr(the IEEE rounding/sticky state — not theIVP_FS*predicate file)The vec-bitwise
ivp_and2nx8/ivp_or2nx8/ivp_xor2nx8/ivp_not2nx8are B01 (vec→vec, element-width-typed); the boolean-typedivp_andb/ivp_orb/ivp_xorb/ivp_notb(vbool→vbool) are B11 — they are different opcodes with different files, separated by thebsuffix and the_64_64_64value-leaf signature (a flat 64-bit mask, no element width). The within-mask reduceivp_randb/ivp_rorb("is every / any lane of this one mask set?") is B08; B11'sivp_borfs2n/ivp_bnorfs2nreduce eight separatevboolregisters into one FS register (§4.2). TheIVP_FS0..FS7predicate-accumulator file B11 targets is not the FCR/FSR arithmetic-control state — that 5-flag IEEE sticky block lives in fp-sub-isa and is a different state file (fp-sub-isa §5.4). The full family-prefix assignment is §7.
1. Batch facts
| Fact | Value | Binary witness |
|---|---|---|
| Mnemonics in batch | 27 (7 logic + 3 b1 + 4 bridge/extract + 2 fold + 11 bridge/scan) | nm | rg roster, §2/§8 |
| Placements in batch | 189 | Σ per-mnemonic Opcode_ivp_*_Slot_*_encode counts, §8 |
| Predicate file (logic/fold) | vbool idx 3, 16 × 64-bit | register-files §3 |
| Predicate-state file (fold/bridge dst) | IVP_FS0..FS7, 8 × 64-bit, separate | fp-sub-isa §5.4 |
Single-bit file (*b1) | BR idx 1, 16 × 1-bit, file pkg xt_booleans, op pkg xt_ivp32 | register-files §3 line 102 |
| Issue slot (boolean logic) | f0_s1_ld — the Load pipe, not the ALU | encode-thunk slot token, §3 |
Issue slot (count*, movfsv, movab1) | f0_s3_alu | §3 |
Issue slot (popc2nx8) | f1_s2_mul (the Mul pipe) | §3 |
| vbool operand fields (3-op logic) | vbt=dst [16:13], vbr=src1 [3:0], vbs=src2 [11:8] | Field_fld_ivp_sem_vbool_alu_ltr_*_get, §3.3 |
| Predicate width per lane | 1 bit / 8-bit lane (one vbool bit per 8-bit sub-lane of 512b) | register-files §3 line 162 |
| Pipeline depth (logic, Ld pipe) | reaches stage 12 (vbool write @10/@11) | libcas-core.so IVP_ANDB_inst_stage* |
Pipeline depth (popc, Mul) | reaches stage 15 | libcas-core.so IVP_POPC2NX8_inst_stage* |
| Value leaves driven live | andb/orb/xorb/notb/andnotb/ornotb, bnorfs/borfs, popc8/popc64, extbi, joinb, notb1/andnotb1/ornotb1 | §4–§5 |
| Confidence | [HIGH/OBSERVED] (encoding + execution) | — |
Every B11 mnemonic is package xt_ivp32 (parsed opcodes[i].package at offset +0x08 for all 27 —
all return xt_ivp32). So the whole batch counts toward the 1065 ivp_-prefix vector
axis, not the xt_booleans package — that package holds the base-Xtensa scalar BR ops
(all4/any8/branch-on-bool), which are owned by B28. The *b1 ops here use the BR register
file but are themselves xt_ivp32 Vision-ISA forms, not xt_booleans.
CORRECTION — the partition row's "
xt_ivp32+xt_booleans" package anchor is half right. The template §4.1 row for B11 names the package anchor as "xt_ivp32+xt_booleans". All 27 B11 mnemonics resolve to packagext_ivp32— none arext_booleans. Thext_booleanspackage (the 16×1-bitBRfile's own instruction set: scalarall/any/branch-on-bool) is a base-Xtensa package owned by B28 (template §4.1 B28 row), not by B11. B11 merely references theBRfile from threext_ivp32Vision ops (notb1/andnotb1/ornotb1). Pin the package anchor asxt_ivp32only for B11 (package parse of all 27 rows).
2. Roster
FLIX format·slot names the canonical placement used for the selector column (the Load slot
f0_s1_ld for the boolean-logic group; f0_s3_alu / f1_s2_mul for the scan/bridge group).
opcode-sel imm is word0 of the representative Opcode_ivp_<mn>_Slot_<slot>_encode template
(C7 07 imm32 — flix-encoding §6.1). files (dir) names the operand files
the op touches and the dst direction. Every row is [HIGH/OBSERVED] unless flagged.
2.1 vbool boolean algebra — vbool→vbool (7 mnemonics, 56 placements)
| mnemonic | format·slot | opcode-sel word0 | files (dir) | size | one-line semantics | n |
|---|---|---|---|---|---|---|
ivp_andb | F0·S1_Ld | 0x70104a00 | vbt(o),vbr(i),vbs(i) | 8 B | vbt = vbr & vbs (64-bit mask) | 8 |
ivp_orb | F0·S1_Ld | 0xb0104a00 | vbt(o),vbr(i),vbs(i) | 8 B | vbt = vbr | vbs | 8 |
ivp_xorb | F0·S1_Ld | 0xd0004a00 | vbt(o),vbr(i),vbs(i) | 8 B | vbt = vbr ^ vbs | 8 |
ivp_andnotb | F0·S1_Ld | 0xa0004a00 | vbt(o),vbr(i),vbs(i) | 8 B | vbt = vbr & ~vbs (AND-NOT) | 8 |
ivp_ornotb | F0·S1_Ld | 0xc0004a00 | vbt(o),vbr(i),vbs(i) | 8 B | vbt = vbr | ~vbs (OR-NOT) | 8 |
ivp_notb | F0·S1_Ld | 0xe0104a00 | vbt(o),vbr(i) | 8 B | vbt = ~vbr (2-op, no vbs) | 9 |
ivp_joinb | F0·S1_Ld | 0xb0004a00 | vbt(o),vbr(i),vbs(i) | 8 B | interleave/zip two masks (lane re-pack) | 8 |
All seven issue in the Load slot (f0_s1_ld) and share the low 16 bits …4a00 — the boolean-logic
iclass selector in the Ld slot. The high byte is the operator selector (0x70=AND, 0xb0=OR,
0xd0=XOR, 0xa0=ANDNOT, 0xc0=ORNOT, 0xe0=NOT). The value leaves are flat-64-bit
(andb_64_64_64, etc.) — no element width: the boolean op treats the mask as 64 raw bits, agnostic
to whether the producing compare wrote 1/2/4-bit-per-lane (§4.4).
2.2 Single-bit BR boolean — BR→BR (3 mnemonics, 26 placements)
| mnemonic | format·slot | opcode-sel word0 | files (dir) | size | one-line semantics | n |
|---|---|---|---|---|---|---|
ivp_notb1 | F0·S1_Ld | 0xe0114a00 | BR(o),BR(i) | 8 B | b_out = (b_in == 0) | 9 |
ivp_andnotb1 | F0·S1_Ld | 0xa0104a00 | BR(o),BR(i),BR(i) | 8 B | b_out = a & ~b (1-bit) | 8 |
ivp_ornotb1 | F0·S1_Ld | 0xc0104a00 | BR(o),BR(i),BR(i) | 8 B | b_out = a | ~b (1-bit) | 8 |
The 1 suffix marks the single-bit (BR) sibling: same operator, on a 1-bit scalar boolean rather
than a 64-bit lane mask. Value leaves notb1_1_1, andnotb1_1_1_1, ornotb1_1_1_1 (the _1 = 1-bit
width). Their selector words differ from the mask forms only in byte-2 (0x11/0x10 vs 0x10/0x00),
the BR-vs-vbool operand-class bit. (No plain andb1/orb1/xorb1 mnemonic exists — only the
NOT-fused forms ship a *b1; plain single-bit AND/OR/XOR are base-Xtensa xt_booleans, B28.)
2.3 Predicate move / make / extract (4 mnemonics, 35 placements)
| mnemonic | format·slot | opcode-sel word0 | files (dir) | one-line semantics | n |
|---|---|---|---|---|---|
ivp_mb | F0·S1_Ld | 0xe00f4a00 | vbt(o), imm | make-bool: mask from an immediate / AR pattern | 9 |
ivp_movab1 | F0·S3_ALU | 0x00508164 | AR(o), BR(i) | move a single BR bit → an AR scalar | 9 |
ivp_movba1 | F0·S1_Ld | 0xe00c4a00 | BR(o), AR(i) | move an AR bit → a BR boolean | 8 |
ivp_ext0ib | F0·S1_Ld | 0xd0104a00 | vbt(o),vbr(i),imm7 | extract bit i (7-bit index) of a mask | 9 |
mb/movab1/movba1 have no dedicated module__xdref_* value leaf — they are structural
moves (bit copies between files) the ISS resolves by composition, so their behaviour is validated by the
objdump round-trip and the field thunks, not by xdref execution ([HIGH/OBSERVED] on encoding,
[MED/INFERRED] on value). ext0ib does have a leaf (ext0ib_64_64_7, §4.3) — it extracts bit i
(a 7-bit index operand) of the source mask.
2.4 Fold-into-FS reduce (2 mnemonics, 4 placements)
| mnemonic | format·slot | opcode-sel word0 | files (dir) | one-line semantics | n |
|---|---|---|---|---|---|
ivp_borfs2n | F0·S1_Ld | 0xe1184a00 | FS(o), 8×vbool(i) | FS = vb0 | vb1 | … | vb7 (OR-reduce 8 regs) | 2 |
ivp_bnorfs2n | F0·S1_Ld | 0xe0184a00 | FS(o), 8×vbool(i) | FS = ~(vb0 | … | vb7) (NOR-reduce) | 2 |
The 2n suffix is the lane geometry (2n = the 64×8b mask shape, 64 lanes over 512 bits). Each op
reads eight consecutive vbool registers and writes one IVP_FS* predicate-state register
(only 2 placements each — legal only in the Ld slot of two formats; §6). This is the only B11
family whose destination is the FS file rather than vbool.
2.5 vbool↔FS bridge + predicate scan (11 mnemonics, 68 placements)
| mnemonic | format·slot | opcode-sel word0 | files (dir) | one-line semantics | n |
|---|---|---|---|---|---|
ivp_movvfs | F0·S1_Ld | 0xac206000 | FS(o,512b) ← 8×vbool(i) | pack 8 vbool regs → one FS-state (lane→FS geometry) | 8 |
ivp_movfsv | F0·S3_ALU | 0x00de9864 | 8×vbool(o) ← FS(i,512b) | unpack one FS-state → 8 vbool regs (FS→lane geometry) | 9 |
ivp_popc2nx8 | F1·S2_Mul | 0x8020fc02 | AR(o) ← vec(i) | population count: # set bits per 8-bit lane | 3 |
ivp_counteq4nx8 | F0·S3_ALU | 0x00006086 | AR(o) ← vec,vec | count lanes where a == b | 8 |
ivp_counteqz4nx8 | F0·S3_ALU | 0x00026086 | AR(o) ← vec | count lanes where a == 0 | 8 |
ivp_counteqm4nx8 | (alu) | — | AR(o) ← vec,vec,vbool | count a==b under a mask | 4 |
ivp_counteqmz4nx8 | (alu) | — | AR(o) ← vec,vbool | count a==0 under a mask | 4 |
ivp_countle4nx8 | F0·S3_ALU | 0x00007086 | AR(o) ← vec,vec | count lanes where a <= b | 8 |
ivp_countlez4nx8 | F0·S3_ALU | 0x00027086 | AR(o) ← vec | count lanes where a <= 0 | 8 |
ivp_countlem4nx8 | (alu) | — | AR(o) ← vec,vec,vbool | count a<=b under a mask | 4 |
ivp_countlemz4nx8 | (alu) | — | AR(o) ← vec,vbool | count a<=0 under a mask | 4 |
QUIRK —
popc/count*cross a file boundary: vector in, scalar out. Unlike the boolean-logic group (mask→mask), the scan ops read avec/vbooland write anARscalar (a count, 0..64). This is the register-files §6.4vbool→ARextraction path ("a population/index count … the path that produces a scalarARresult"). Them-infixed forms (counteqm/countlem) additionally read avboolmask to gate which lanes are counted; thezforms compare against the implicit zero (one fewervecoperand).
3. Encoding
3.1 The boolean-logic group lives in the Load slot, selected by the high byte
All seven §2.1 logic ops and all three §2.2 *b1 ops issue in f0_s1_ld — the Load pipe — and
share the low 16 bits 0x4a00 (the vbool-ALU iclass marker in the Ld slot). The discriminator is
the high byte of word0 (read byte-exact from the encode thunks @0x341…/@0x353…/@0x361…):
andb 0x70104a00 andnotb 0xa0004a00 notb 0xe0104a00 joinb 0xb0004a00
orb 0xb0104a00 ornotb 0xc0004a00 mb 0xe00f4a00 ext0ib 0xd0104a00
xorb 0xd0004a00
andnotb1 0xa0104a00 notb1 0xe0114a00 ornotb1 0xc0104a00
GOTCHA — the boolean ops are NOT in the ALU slot; they co-issue with a load. A reimplementer who assumes "boolean ALU ⇒ ALU slot" mis-schedules every B11 logic op. They are placed in
f0_s1_ld(the LSU's S1 sub-slot), so avboolandbco-issues with a vector load, not with a vector ALU op. This is why B03 calls them "ld-pipe" ops, and why their placement count is low (8–9, vs 15–21 for a vec-ALU op) — they are legal in far fewer slots. The compiler that wants to overlap predicate bookkeeping with data movement gets it for free; one that tries to issueandbin the ALU slot finds no placement — the slot token appears in everyOpcode_ivp_<logic>_Slot_f0_s1_ld_encode.
The byte-2 nibble distinguishes the operand class: 0x_0_ for the XOR/ANDNOT/ORNOT/joinb/mb
forms (byte-2 0x00), 0x_1_ for AND/OR/NOT and the *b1 forms (byte-2 0x10/0x11). There is no
single flat counter — encode by table lookup, exactly as
flix-encoding §6.2's two-tier selector model prescribes.
3.2 The fold and bridge ops drift to other selector bands
borfs/bnorfs/movvfs stay in the Ld slot but carry distinct high bytes (0xe1/0xe0 with byte-2
0x18 for the fold; 0xac20 for movvfs). movfsv/movab1 move to f0_s3_alu (their word0 is
the ALU-slot template 0x00……64). popc2nx8 is in f1_s2_mul (0x8020fc02) — it borrows the
multiply pipe's lane-reduction tree to sum the set bits. The count*4nx8 ops are ALU-slot
(0x0000_086 / 0x0002_086 band, the count-iclass). The selector band per op is the ground truth in
§2; do not compute it.
3.3 The three vbool operand fields — vbt/vbr/vbs, distinct bit-windows
A 3-operand boolean op (andb vbt, vbr, vbs) names three vbool registers via the
ivp_sem_vbool_alu_ltr_{vbt,vbr,vbs} field group. The get thunk bodies, disassembled, give the exact
bit-windows in the Ld-slot word0:
// Field_fld_ivp_sem_vbool_alu_ltr_vbt_Slot_f0_s1_ld_get @ 0x330250 (DESTINATION)
uint32_t vbt_get(uint32_t w0) { return (w0 << 0x0f) >> 0x1c; } // isolate bits [16:13] -> 4-bit reg
// _set @ 0x330260 : (w0 & 0xfffe1fff) | ((vbt & 0xf) << 13)
// Field_fld_ivp_sem_vbool_alu_ltr_vbr_Slot_f0_s1_ld_get @ 0x32fe40 (SOURCE 1)
uint32_t vbr_get(uint32_t w0) { return w0 & 0xf; } // bits [3:0]
// Field_fld_ivp_sem_vbool_alu_ltr_vbs_Slot_f0_s1_ld_get @ 0x330150 (SOURCE 2)
uint32_t vbs_get(uint32_t w0) { return (w0 << 0x14) >> 0x1c; } // isolate bits [11:8]
So the three 4-bit register fields are vbt = dst @[16:13], vbr = src1 @[3:0], vbs = src2
@[11:8] — each naming one of the 16 vbool registers. The 2-operand notb/mb/ext0ib omit vbs.
The fields are deposited separately by field_set, not by the C7 07 imm32 thunk (which carries
only the opcode selector) — template §3.2 NOTE. [HIGH/OBSERVED]
GOTCHA — the dst field
vbtsits at the top of the word ([16:13]), the sources at the bottom. The operand-window order is not dst-first in the bitstream:vbr(src1) is the low nibble[3:0],vbs(src2) is[11:8], and the destinationvbtis the highest field[16:13]. A reimplementer who lays the operands out left-to-right (dst, src1, src2) will deposit the destination register into the source nibble and silently compute into the wrongvbool. Read the windows from the field thunks, never from operand order.
3.4 Operand count and direction
The *_operands descriptor and num_args immediate pin the shape. andb is num_args = 3
(o, i, i — vbt out, vbr/vbs in); notb is num_args = 2 (o, i); borfs/bnorfs are
num_args = 9 (one FS o + eight vbool i); popc/count* write an AR o. The destination is a
plain out (0x6f, 'o') in every B11 op — there is no m/inout merge here (that is the B03
*t family). A B11 boolean op fully overwrites its destination mask; it never reads-modifies-writes.
4. Per-lane / per-mask semantics — annotated C
The four required pseudocode shapes — (a) the bitwise predicate logic, (b) the bnorfs/borfs
reduce-into-FS, (c) the population/scan, (d) the predicate-width semantics — each annotated against the
live-driven module__xdref_* leaf.
4.1 (a) Bitwise predicate logic — ivp_andb / ivp_orb / ivp_xorb / ivp_andnotb
The mask is a 64-bit value the leaf processes as two 32-bit words (low (%rsi), high 0x4(%rsi)).
Disassembled bodies, unified:
// module__xdref_andb_64_64_64 @ 0x856f80 (ABI: rdi=ctx unused, rsi=a, rdx=b, rcx=out)
void andb_mask(const uint32_t a[2], const uint32_t b[2], uint32_t out[2]) {
out[0] = a[0] & b[0]; // 856f80: mov (%rsi) ; and (%rdx) ; mov ->(%rcx)
out[1] = a[1] & b[1]; // 856f86: same on the high word
}
// orb @0x856f90 : out = a | b (0x0b: 'or' opcode)
// xorb @0x856fa0 : out = a ^ b (0x33: 'xor')
// notb @0x856f70 : out = ~a (2-op, rdx=out; f7 d0 = 'not')
// module__xdref_andnotb_64_64_64 @ 0x856fb0 — AND with the *complement* of b
void andnotb_mask(const uint32_t a[2], const uint32_t b[2], uint32_t out[2]) {
out[0] = a[0] & ~b[0]; // 856fb5: not %edx ; and (%rsi)
out[1] = a[1] & ~b[1];
}
// module__xdref_ornotb_64_64_64 @ 0x814fc0 : out = a | ~b (identical shape, 'or' instead of 'and')
The op is pure 64-bit bitwise — no element width, no saturation, no sign. The andnotb/ornotb
forms invert the second source before the bitwise op (a OP ~b), the canonical "mask a minus the
lanes flagged by b" idiom (andnotb) and "force-set the lanes b does not flag" (ornotb).
Live-validated (§5.1): andb(f0f0…,00ff…)=00f0…, and a 4096-pair differential vs
a&b/a|b/a^b/a&~b returned 0 mismatches.
4.2 (b) Fold-into-FS reduce — ivp_borfs2n / ivp_bnorfs2n
borfs is a horizontal OR across eight vbool registers, written to one FS-state register;
bnorfs is the same with a final complement. The body (@0x8327f0/@0x832870) ORs eight
64-bit masks word-by-word:
// module__xdref_borfs_2n_64_64_64_64_64_64_64_64_64 @ 0x8327f0
// ABI: rdi=ctx, then 8 mask ptrs (rsi,rdx,rcx,r8,r9 + 3 on stack), then out ptr (stack)
void borfs_fold(const uint32_t *m[8], uint32_t fs_out[2]) {
uint32_t lo = 0, hi = 0;
for (int k = 0; k < 8; k++) { // 832819..83284f: a long chain of 'or' over the 8 masks
lo |= m[k][0]; // low word of each mask
hi |= m[k][1]; // high word of each mask
}
fs_out[0] = lo; fs_out[1] = hi; // 832852/832854: store to the FS register
}
// module__xdref_bnorfs_2n_... @ 0x832870 : identical OR-tree, then fs = ~fs (8328b8: not %eax/%edx)
The semantic is "collapse eight predicate registers into one FS predicate-state register by lane-wise
OR" — FS[bit] = vb0[bit] | vb1[bit] | … | vb7[bit]. A reimplementer reads this as the
predicate-accumulator update: after a loop that produces up to 8 partial masks (vb0..vb7), one
borfs2n merges them into the persistent IVP_FS* state in a single op, and bnorfs2n gives the
complement (the "no register set this lane" mask). Live-validated (§5.2): borfs of eight
single-bit masks {1,2,4,8,16,32,64,1<<63} → 0x800000000000007f (the bitwise OR), bnorfs →
0x7fffffffffffff80 (its complement); all-zero inputs → borfs=0, bnorfs=0xffff…ffff.
QUIRK —
borfsreduces across registers, not within a register. This is the sharp line vs B08'srandb/rorb. B08'sivp_randb2ntests whether one mask is all-ones (module__xdref_randb2n_64_64 @0x81cc40:cmpl $0xffffffff,(%rsi)→ a within-mask "all-set?" reduce). B11'sborfsORs eight separate masks into one FS register — an inter-register fold. Same word "reduce", orthogonal axis: B08 folds lanes within a mask, B11 folds registers into FS. Never merge the two tallies.
4.3 (c) Population / match scan — ivp_popc2nx8, ivp_counteq4nx8, ivp_ext0ib
popc is per-lane population count; count* sums a per-lane predicate to an AR scalar; ext0ib
extracts one bit. The simplest leaf (popc_8_8 @0x832df0) is a textbook 8-bit popcount:
// module__xdref_popc_8_8 @ 0x832df0 (rsi=byte, rdx=out) — count set bits, saturate to a 4-bit field
uint8_t popc8(uint8_t x) {
int c = (x & 1);
for (int s = 1; s <= 7; s++) c += (x >> s) & 1; // 832df4..832e33: unrolled shr/and/add over bits
return (uint8_t)(c & 0xf); // 832e35: and $0xf (0..8 fits in 4 bits)
}
// module__xdref_popc64_7_64 @0x8236c0 : same idea over a 64-bit mask -> count 0..64
// module__xdref_ext0ib_64_64_7 @ 0x856dd0 — extract bit `i` (a 7-bit index) of a mask
// reads the index, masks/shifts to isolate one lane bit, writes it (a 'select one predicate lane' op)
popc over a mask answers "how many lanes are set" — the building block for any (popc != 0),
all (popc == lanecount), and density-driven control flow. There is no dedicated anyb/allb/
firstb mnemonic in the Q7 ISA (nm | rg -i 'any|allb|firstb' over the roster = 0); any/all/first
are synthesised from popc/borfs/bnorfs + ext0ib + a scalar compare. Live-validated (§5.3):
popc8 over all 256 inputs = 0 mismatches; popc64 over 2000 random masks = 0 mismatches;
ext0ib extracts the indexed bit with the correct width scaling.
4.4 (d) Predicate-width semantics — one vbool bit per 8-bit sub-lane
The boolean-logic ops are width-agnostic (flat 64-bit), but the masks they consume were written
by a compare at a definite lane width: a 2nx8 compare sets 1 bit/lane, an nx16 compare 2
bits/lane, an n_2x32 compare 4 bits/lane (B03 §5.2). The geometry is
one vbool bit per 8-bit sub-lane of the 512-bit vector (register-files §3
line 162), so a 64-lane vbool covers 512/8 = 64 sub-lanes. The extbi extract-to-scalar leaf shows
the width scaling directly:
// module__xdref_extbi_1_8_32 : extract a 1-bit-per-lane predicate -> returns 0/1
// module__xdref_extbi_2_16_32 : extract a 2-bit-per-lane predicate -> returns 0/3
Driven live, extbi_1_8_32(mask=0b10110, i) over i=0..5 → [0,1,1,0,1,0] (the raw bit), while
extbi_2_16_32 over the same mask → [0,3,3,0,3,0] (the bit replicated to its 2-bit lane field).
A B11 boolean op operating on a 16-bit-lane mask therefore manipulates pairs of bits per lane; an
andb over two such masks is still correct bit-for-bit because both operands carry the same 2-bit lane
encoding. The reimplementer's invariant: the boolean op is bit-parallel; the lane-width contract lives
in the producing compare, not in the boolean op — so andb of an nx16-compare mask and a
2nx8-compare mask is encodable but meaningless (mismatched lane geometries), exactly as a C & of
two differently-strided bitsets would be. [HIGH/OBSERVED]
5. Driven live — libfiss-base.so value leaves via ctypes
libfiss-base.so (sha256 260b110c…, 864 module__xdref_* value leaves) is callable in-process with
no license. The per-element/per-mask leaf ABI is System-V with rdi reserved (a ctx pointer the
mask leaves ignore): mask args are uint32_t[2] pointers, scalar args pass by value, outputs are
pointer args. Six leaf families driven live; the transcripts below reproduce with
ctypes.CDLL(...).
5.1 vbool boolean algebra over two 64-bit masks (the required logic case)
a = f0f0f0f0f0f0f0f0
b = 00ff00ff00ff00ff
andb = 00f000f000f000f0 (= a & b)
orb = f0fff0fff0fff0ff (= a | b)
xorb = f00ff00ff00ff00f (= a ^ b)
andnotb = f000f000f000f000 (= a & ~b)
ornotb = fff0fff0fff0fff0 (= a | ~b)
notb = 0f0f0f0f0f0f0f0f (= ~a)
4096-pair differential and/or/xor/andnot vs C model : 0 mismatches
Every operator matches its bitwise C model exactly. [HIGH/OBSERVED by execution]
5.2 Fold-into-FS — borfs / bnorfs over 8 vbool registers (the required reduce case)
masks = [0x…01, 0x…02, 0x…04, 0x…08, 0x…10, 0x…20, 0x…40, 0x8000000000000000]
borfs = 800000000000007f (= OR of all 8 masks) match
bnorfs = 7fffffffffffff80 (= ~OR) match
borfs (all-zero masks) = 0000000000000000 (no register set this lane)
bnorfs(all-zero masks) = ffffffffffffffff (every lane: "none of the 8 set it")
borfs is the inter-register OR-reduce into the FS register; bnorfs its complement. The all-zero case
is the FS "nothing matched" sentinel.
5.3 Population / extract scan — popc, extbi (the required scan case)
popc8(0x00)=0 popc8(0x0f)=4 popc8(0xff)=8 popc8(0x80)=1 popc8(0xaa)=4
popc8 full 256-input sweep : 0 mismatches
popc64(0x0)=0 popc64(0xff)=8 popc64(0xffffffffffffffff)=64 popc64(0xaaaa…)=32
popc64 2000-input random sweep : 0 mismatches
extbi_1_8_32 (mask 0b10110, i=0..5) = [0,1,1,0,1,0] (raw predicate bit)
extbi_2_16_32(mask 0b10110, i=0..5) = [0,3,3,0,3,0] (bit replicated into the 2-bit lane field)
popc answers "how many lanes set"; extbi extracts one indexed predicate lane (with lane-width
replication). Together they synthesise any/all/first-set, for which the ISA ships no dedicated
opcode.
5.4 Single-bit BR boolean — notb1 / andnotb1 / ornotb1
notb1(0)=1 notb1(1)=0 (= b == 0)
andnotb1(a,b) over {0,1}² : 0&~0=0 0&~1=0 1&~0=1 1&~1=0 (= a & ~b)
ornotb1(a,b) over {0,1}² : 0|~0=1 0|~1=0 1|~0=1 1|~1=1 (= a | ~b)
The 1-bit BR-file forms reproduce their mask siblings on a scalar boolean — notb1 is "is the bit
clear?", andnotb1/ornotb1 invert b then AND/OR.
6. Slot legality and co-issue
- Boolean logic (
andb/…/notb/joinb/*b1/mb/ext0ib) carry 8–9 placements each, all in the Load slot (f0_s1_ld+ the same sub-slot of a few other formats). They co-issue with a vector load, not a vector ALU op — the predicate-bookkeeping pipe overlaps data movement (register-files §6.5). - Fold (
borfs/bnorfs) carry only 2 placements each — legal in the Ld slot of two formats only. The 8-register read is expensive; the hardware exposes it in a narrow placement set. - Bridge (
movvfs8,movfsv9) split across Ld (movvfs) and ALU (movfsv). - Scan (
popc3 in the Mul slot;count*4–8 in the ALU slot) —popcborrows the multiply pipe's reduction tree, so it reaches stage 15 (libcas-coreIVP_POPC2NX8_inst_stage15) vs the boolean ops' stage 12 (IVP_ANDB_inst_stage12).
GOTCHA — a
vbool/FS written by a B11 fold is read at stage @10, not forwarded within the bundle. Per register-files §5,vboolwrites land @10/@11 and reads @10, with a 2-port read limit. Aborfs2nthat consumes eightvboolregisters saturates the predicate read ports for the bundle — two predicate-consuming ops cannot co-issue with it. A downstream op that reads the produced FS state must be in a later bundle. Thelibcas-corestage models (IVP_BNORFS2N_inst_stage12,IVP_MOVVFS_inst_stage11) confirm the Ld-pipe depth.[HIGH/OBSERVED]on the stages; intra-bundle forwarding is scheduler policy.
7. Partition discipline — the exact family-prefix assignment
To guarantee no mnemonic is double-counted across the predicate-adjacent batches, the per-prefix ownership, derived against the roster:
| family / prefix | example | owner | why |
|---|---|---|---|
vec→vec bitwise, element-width-typed | ivp_and2nx8, ivp_not2nx8 | B01 | reads/writes vec, has a 2nx8/nx16 element-width suffix |
compare vec→vbool, B-variant, *t merge | ivp_eqnx16, ivp_bmaxnx16, ivp_addnx16t | B03 | produces/consumes vbool around an arithmetic op |
within-mask reduce (all/any of one mask) | ivp_randb2n, ivp_rorbn, ivp_rorbn_2 | B08 | _64_64 single-mask horizontal reduce |
vbool boolean algebra andb/orb/xorb/notb/andnotb/ornotb/joinb | ivp_andb | B11 | vbool→vbool, _64_64_64 flat-mask leaf, Ld slot |
single-bit BR notb1/andnotb1/ornotb1 | ivp_notb1 | B11 | xt_ivp32 op on the BR file, _1_1 leaf |
predicate move/make/extract mb/movab1/movba1/ext0ib | ivp_mb | B11 | AR↔vbool↔BR structural bridge |
fold-into-FS borfs2n/bnorfs2n | ivp_borfs2n | B11 | 8×vbool → FS-state OR/NOR-reduce |
vbool↔FS bridge + scan movvfs/movfsv/popc2nx8/count*4nx8 | ivp_movvfs | B11 | 512-bit lane↔FS permute; vec/vbool→AR count |
FS-producing compare fsNltu2nx8 | ivp_fs3ltu2nx8 | fp-sub-isa / B03-sibling | vec compare → FS slot (a producer, like B03) |
FCR/FSR arith-control state wur.fcr/rur.fsr | wur.fcr | fp-sub-isa (B24) | IEEE rounding/sticky, not the IVP_FS* predicate file |
select/merge by mask sel/dsel/shuffle | ivp_selnx16 | B21 | 3-input mux on vec data |
scatter/gather *t | ivp_scatternx16t | B19 | memory, b32_pr mask |
The arithmetic that makes the partition airtight: B11's boolean group is the b-suffixed,
vbool-typed complement of B01's 2nx8/nx16 element-typed bitwise ops — different opcodes,
different files, different leaves (andb_64_64_64 vs and_2nx8). B08's randb/rorb are
within-mask reduces (_64_64, one mask); B11's borfs/bnorfs are inter-register folds
(_64×8→FS). The eight fsNltu2nx8 ops are FS-state-producing compares — structurally a B03/fp
producer (module__xdref_fsNltu_64_8_8 is a thin wrapper over ltu_1_8_8), so they are documented at
the boundary but not counted in B11's 27. [HIGH/OBSERVED]
NOTE — why
fsNltu2nx8is a boundary case, not a B11 member.ivp_fs0ltu2nx8 … fs7ltu2nx8(8 mnemonics, 5 placements each) write theIVP_FS*predicate file from an unsignedveccompare —module__xdref_fs0ltu_64_8_8 @0x8328d0is literallycall ltu_1_8_8; store into FS[0]. They are the producers into the FS file thatmovfsvlater unpacks; they are siblings of B03'svec→vboolcompares (just with an FS destination and a fixed slot index). B11 owns the consumers ofvbool/FS, so these belong with the compare/classify producers (fp-sub-isa §5.4 / B03). They are excluded from the §8 tally to avoid double-counting a producer the compare batches already own.
8. Batch tally vs nm
| sub-family | mnemonics | placements | leaf prefix (libfiss) |
|---|---|---|---|
| vbool boolean algebra | 7 | 56 | andb/orb/xorb/notb/andnotb/ornotb/joinb_64_64_64 |
single-bit BR boolean | 3 | 26 | notb1/andnotb1/ornotb1_1_1 |
| predicate move/make/extract | 4 | 35 | ext0ib_64_64_7 (rest: structural, no leaf) |
| fold-into-FS reduce | 2 | 4 | borfs/bnorfs_2n_64×9 |
| vbool↔FS bridge + scan | 11 | 68 | movvfs/movfsv_512_64×8, popc{8,16,32,64}, count* (composed) |
| B11 total | 27 | 189 | — |
Σ placements over the 27 mnemonics = 189 (nm libisa-core.so | rg -c 'Opcode_ivp_<mn>_Slot_.*_encode' summed; the per-mnemonic counts in §2). The 27 mnemonics are a strict
subset of the 1065 ivp_-prefix vector ops and of package xt_ivp32 (all 27 parse
xt_ivp32). Together with B01/B02/B03 (the vec/compare/merge ALU) and B08 (within-mask reduce) they
cover the predicate datapath without overlap (§7). No B11 mnemonic appears in any other batch's prefix
set. The 189 placements are part of — never additive beyond — the certified-perfect 12569
(coverage-tally); the valid pairing stays 1534 ↔ 12569, never
12642.
Value-leaf contribution. B11 resolves to ≈14 distinct module__xdref_* leaves (7 logic + 3 b1
ext0ib+borfs/bnorfs+popc{8,16,32,64}+movvfs/movfsv), of which the 6 logic-family, the 2 fold, the 2 popc widths driven, the 3 b1, andextbiwere driven live to 0 mismatches;mb/movab1/movba1/count*are structural/composed (no dedicated leaf — validated by the objdump round-trip, notxdrefexecution). All counted in the 864 leaf denominator (coverage-tally §5).
9. Adversarial self-verification — five strongest claims re-challenged
- "The boolean ops are
vbool→vboolflat-64-bit, issued in the Load slot, distinct from thevec→vecbitwise B01 ops." Two independent checks: (a) the value leaves areandb_64_64_64(flat 64-bit, no element-width token) vs B01'sand_2nx8(element-typed) — different leaves; (b) everyOpcode_ivp_andb_Slot_*_encodesymbol carries the slot tokenf0_s1_ld(the Load sub-slot), confirmed by theword0low bytes0x4a00, and thelibcas-coremodelF0_F0_S1_Ld_16_inst_IVP_ANDB_issue. A reimplementer schedulingandbin the ALU slot finds no placement. Holds. - "
borfs/bnorfsOR/NOR-reduce eightvboolregisters into one FS register, not a within-mask reduce." Driving the leaf live:borfsof eight distinct single-bit masks →0x800000000000007f(the bitwise OR of all eight),bnorfs→ its complement; all-zero inputs →0/0xffff…ffff. The disasm shows a chain of 8orops over 8 pointer args then a store. Contrast B08'srandb2n(cmpl $0xffffffff,(%rsi)— a within-one-mask all-set test). The two reduces are on orthogonal axes. Holds. - "
popc/count*cross a file boundary:vec/vboolin,ARscalar out — and there is no dedicatedany/all/first-setopcode."popc8over all 256 inputs andpopc64over 2000 random masks both returned 0 mismatches againstbin(x).count('1'); the destination is anARregister (register-files §6.4vbool→ARpath).nm | rg -i 'any|allb|firstb'over the roster = 0 — any/all/first are synthesised frompopc/borfs/ext0ib+ a scalar compare, not shipped as opcodes. Holds. - "The three
vbooloperand fields sit at non-adjacent windows:vbt(dst)@[16:13],vbr(src1)@[3:0],vbs(src2)@[11:8] — dst is not first in the bitstream." Disassembling the threeField_fld_ivp_sem_vbool_alu_ltr_*_Slot_f0_s1_ld_getthunks:vbt=(w0<<0xf)>>0x1c(bits [16:13]),vbr=w0 & 0xf(bits [3:0]),vbs=(w0<<0x14)>>0x1c(bits [11:8]). A left-to-right (dst,src1,src2) layout would deposit the destination into thevbrsource nibble. The windows are read from the thunks, not operand order. Holds (and corrects the naive layout). - "Every B11 mnemonic is package
xt_ivp32, notxt_booleans— the partition row's package anchor is half-wrong." Parsingopcodes[i].package(+0x08) for all 27 B11 rows directly from the.data.rel.rotable (file = VMA −0x200000): all 27 returnxt_ivp32;andb/notb1/movvfs/borfs2n/popc2nx8/counteq4nx8all parsedxt_ivp32. Thext_booleanspackage is the base-XtensaBRinstruction set (B28), which the*b1ops only reference. The template's "xt_ivp32+xt_booleans" anchor is corrected toxt_ivp32only (§1 CORRECTION). Holds.
Ungrounded / flagged items. (i) ivp_mb/ivp_movab1/ivp_movba1/ivp_count*4nx8 have no
dedicated module__xdref_* value leaf — their value semantics are [MED/INFERRED] (composed from
primitives; validated by encoding + the objdump round-trip, not by xdref execution). The count*
encoding and slot are [HIGH/OBSERVED]; the exact saturation of the count output to its AR field
width is [MED/INFERRED]. (ii) ivp_joinb's precise lane-interleave map was read from the disasm
(shr/and 0x2,0x4,0x8… bit-spread) and spot-driven, but the full 64-bit permutation table was not
exhaustively swept — [MED/OBSERVED] on the exact permutation. (iii) The eight fsNltu2nx8 ops are
producers into the FS file (a B03/fp boundary, §7 NOTE) and are deliberately excluded from the 27
to avoid double-counting; their semantics are validated (fsNltu_64_8_8 = ltu_1_8_8 wrapper) but they
are tallied by the compare batches, not here. (iv) popc16_5_16/popc32_6_32 leaves exist in
libfiss-base (the width family of popc) even though only the popc2nx8 mnemonic ships — the
multi-width leaves serve the one mnemonic's per-lane element width; counted once.
10. Cross-references
- The Eight Register Files —
vboolidx3 (16×64-bit, the mask file),BRidx1 (16×1-bit, the*b1file), thevbool→ARextraction path (§6.4) thepopc/count*ops use, and thevboolwrite@10/@11 / read@10 stages that bound co-issue (§6). - The FP Sub-ISA (FCR/FSR, RNE/RZ) — the
IVP_FS0..FS7predicate-accumulator file (§5.4) thatborfs/bnorfs/movvfs/movfsvtarget, kept separate from the FCR/FSR arithmetic-control state (the boundary §1/§7 enforce). - FLIX VLIW Encoding — the 14 formats / 46 slots, the
C7 07 imm32encode-thunk ABI (§6.1), and the two-tier high-byte selector model (§6.2) this batch instantiates in the Load slot. - ISA Coverage & the 1534/12642 Tally — the certified-perfect 12569 placement denominator this batch's 189 are part of, the no-cross-pair law, the 864 value leaves.
- B01 — Vector ALU int core (the
vec→vecbitwiseand2nx8/or2nx8) · B03 — Vector ALU rest (thevec→vboolcompare producers that feed B11) · B08 — Cross-Lane Reduce (the within-maskrandb/rorbreduce, disjoint from B11's inter-registerborfs/bnorfs) · B21 — Select / Shuffle (predicated data-lanesel/dsel) · B19 — Scatter / Gather (b32_prmask path) — the predicate-adjacent batches B11 is disjoint from. - ISA Reference Template & 30-Batch Partition — the canonical B01–B30 schema (§3), the partition (§4) whose B11 package anchor §1 here corrects, and the §6 roll-up B11's 27/189 close onto.
- The libisa Table Schema & Codec ABI — the
opcodes[]/opcodedefs[]/_operandsstruct layouts and the field-thunk ABI the §3 extraction reads. - The Confidence & Walls Model — the tags and the free in-process
value lane (
libfiss-base) that makes §4–§5OBSERVED by execution.
Provenance: selector templates, num_args/_operands direction bytes, the
ivp_sem_vbool_alu_ltr_{vbt,vbr,vbs} field thunks, and the package parse of all 27 opcodes[] rows are
disassembled and read from libisa-core.so (sha256 8fe68bf4…, ncore2gp/config/, not stripped);
the value leaves in §4–§5 (andb/orb/xorb/notb/andnotb/ornotb, borfs/bnorfs,
popc8/popc64, extbi, notb1/andnotb1/ornotb1, joinb) are driven live via ctypes against
libfiss-base.so (sha256 260b110c…), license-free; pipeline stages from libcas-core.so (DWARF).
Counts via nm | rg -c; .data.rel.ro file = VMA − 0x200000 (confirmed readelf -SW: .data.rel.ro
VMA 0x67bb00 ↔ file 0x47bb00); the extracted/ tree is gitignored (reached with absolute paths).
All prose is derived from static analysis and in-process execution of the shipped artifacts only;
nothing here is read from a vendor source tree.