fiss Datapath — the 864-Leaf Value Oracle
This page is the value-semantics ground truth for the entire IVP / Vision-Q7 vector ISA. Where
the cycle-accurate ISS libcas-core.so decodes an instruction and schedules its timing, it does
not compute element values — it delegates them. The functions it delegates to live in
libfiss-base.so, and the 864 module__xdref_* leaves of that library are the per-lane
datapath value primitives: the bit-exact a OP b (wrap, saturate, signedness, rounding, NaN) for
every IVP mnemonic. This is the central node of Part 14 — the ISS as Executable Oracle:
every cas value page (arith, MAC/FMAC,
convert/pack/fp) delegates here, and every VAL lane drives these leaves
live. It is also the origin of the xdsem / xdref model named on those pages.
Keystone — cas decodes, fiss values. The cas core (core surface) computes DECODE + TIMING + REGISTER-HAZARD and forwards each per-lane
a OP bto the host through 119nx_*_interfacecallbacks.libfiss-base.sois the value oracle on the other end: its 864module__xdref_*leaves are the element-arithmetic primitives — tiny scalar single-lane bodies that implement exactly one width-typed op. The vector execute realises an N-wide op as a scalar per-lane loop of the matchingxdrefleaf. This page documents the roster, how each leaf computes its lane value, the execute path that drives them, and drives a representative sample live viactypesto certify the oracle end-to-end.[HIGH/OBSERVED]
Confidence tags follow the Confidence & Walls model:
[HIGH/OBSERVED] = read-from-byte / proven by disassembly or a live ctypes call,
[MED/INFERRED] = reasoned over OBSERVED, […/CARRIED] = re-used at a sibling page's confidence.
All offsets are into the shipped extracted/.../ncore2gp/config/libfiss-base.so (12 330 016 B;
ELF64 LSB x86-64, SYSV, not stripped). Every count below is grounded by
nm -D <abs-path> | rg -c, never the decompile.
GOTCHA — VMA vs file offset is not uniform.
.text(VMA0x190430) and.rodata(VMA0x88ff00) are VMA == file offset, so the disassembly addresses in this page are raw VMA. The writable sections are not:.data.rel.ro(VMA0xc17e80→ file0xa17e80) and.data(VMA0xc8eb68→ file0xa8eb68) both carry a0x200000delta (readelf -SW). No value-leaf body touches.data; this caveat matters only if youxxda writable struct.[HIGH/OBSERVED]
1. The export census — 864 value leaves inside 20 384 symbols
libfiss-base.so is a self-contained value oracle: it imports nothing but libc/runtime stubs
and computes all element math in-process. The dynamic symbol table, grounded directly on the
binary:
Sweep (nm -D <abs> | rg -c …) | Count | Meaning | Conf |
|---|---|---|---|
total nm -D lines (.dynsym − null) | 20 384 | the full dynamic symbol table | [HIGH/OBSERVED] |
defined exports (types T/W/R/D/B) | 20 379 | functions + a handful of objects | [HIGH/OBSERVED] |
undefined imports (UND) | 5 | libc/runtime only (see below) | [HIGH/OBSERVED] |
slotfill__* (decode → operand-slot fill) | 12 569 | the bitfield-extract decoders | [HIGH/OBSERVED] |
opcode__* (execute bodies) | 1 708 | the per-mnemonic vector/scalar execute | [HIGH/OBSERVED] |
module__xdref_* (the value leaves) | 864 | the per-lane datapath primitives | [HIGH/OBSERVED] |
nx_*_interface host callbacks | 0 | none — value math is in-process | [HIGH/OBSERVED] |
Every one of the 864 module__ exports is a module__xdref_* leaf (nm -D | rg ' module__' | rg -vc 'module__xdref_' = 0). The 864 / 12 569 / 20 379 reconciliation as a nested superset
chain is laid out on the fiss surface page; this page reads the
bodies of the 864.
NOTE — self-contained: exactly 5 undefined imports.
readelf --dyn-syms | rg ' UND 'yields five distinct names, all libc/runtime:__cxa_finalize@GLIBC_2.2.5,_Jv_RegisterClasses,_ITM_deregisterTMCloneTable,_ITM_registerTMCloneTable,__gmon_start__. There are zeronx_*_interfacecallbacks (libcas-core.sohad 119). The value math is therefore computed in this DLL, not delegated onward — which is exactly what makes it the oracle.[HIGH/OBSERVED]
1.1 The module__xdref_* naming grammar
The leaf name is the operand-width descriptor. The grammar, OBSERVED across all 864 names and confirmed against the disassembled bodies:
module__xdref_<op>[<post>]_<outW>_<inAW>[_<inBW>][_<extraW>…][<suffix>]
<op>— operation root (446 distinct first-tokens; ~200 semantic roots once width disambiguators are folded).- widths — decimal bit-width of each operand, in output-first order:
8 / 16 / 24 / 32 / 48 / 64 / 96.512= a full 512-bit vector register (bulk bitwise). A leading1_1_…run on float ops is the lane-rate / IEEE-staging descriptor. - suffixes / tokens (each corroborated by at least one disassembled body):
f= IEEE float element (16f/32f/64f);tf= tagged float;c= complex (interleaved re/im 16-bit halves in a 32-bit slot);j= conjugate operand;t= predicated (per-lanevboolguard);u= unsigned interpretation; leadings= signed-narrowing / saturating;packl/packm/packp/packq= pack-low/-mid/-pair/-quad;n= narrowing/widening disambiguator;r= rounding.
CORRECTION — the float census is 180, not 184. A direct name parse on the binary (
nm -D … | rg 'module__xdref_' | awk '{print $1}', thenrg -c '[0-9]+t?f(_\|$)') gives 180 leaves bearing an IEEE float-width token (NforNtf) and 684 integer/structural. An earlier hand-count put this at 184 / 680; the on-binary truth is 180 / 684 (the twotfoutliers —divn_32tf_…anddivn_64tf_…— are the only names that need thetfalternation to be caught). Cite 180 float / 684 integer-structural.[HIGH/OBSERVED]
1.2 The lane-primitive ABI
The execute calls each leaf through the System V AMD64 C ABI. The operand register layout is
shifted by one from a naive (A, B, *out) reading: the leaf reserves the first integer slot
(%rdi) for a context/self pointer (unused by the simple ALU leaves), and the operands begin at
the second slot.
| Form | %rdi | %rsi | %rdx | %rcx | %r8 | Conf |
|---|---|---|---|---|---|---|
3-operand binary (add_16_16_16) | ctx | A | B | result* | — | [HIGH/OBSERVED] |
unary (abs_16_16, sext_32_16) | ctx | A | result* | — | — | [HIGH/OBSERVED] |
4-operand accumulate (mula_*) | ctx | acc/A | B | C | result* | [HIGH/OBSERVED] |
dual-out convert (cvtf32_1_32f_16f) | ctx | A | flag-out* | result* | — | [HIGH/OBSERVED] |
GOTCHA — a C caller must pass the leading
%rdicontext argument. The body ofmodule__xdref_add_16_16_16reads operand A from%esi, B from%edx, and stores through%rcx. If you declare thectypesprototype as(c_int, c_int, c_void_p), SysV places your A in%rdi, B in%rsi, result-ptr in%rdx— and the leaf'smov %edx,(%rcx)dereferences whatever garbage is in%rcx, segfaulting atadd_16_16_16+0x8(observed). The correct prototype is(c_void_p ctx, c_int A, c_int B, c_void_p result)withctx = None. This off-by-one is the one non-obvious step to driving the oracle; §6 uses it throughout.[HIGH/OBSERVED]
2. The 864 leaves, taxonomized by family
The 864 leaves partition (with overlap at the boundaries — the grammar is multi-token, so these are
representative family slices, not a disjoint cover) into the families below. Counts are
rg -c '^module__xdref_(<roots>)' on the name list; each row names real symbols you can drive.
| Family | ~Count | Representative module__xdref_* symbols | What the leaf computes |
|---|---|---|---|
| Integer arith (wrap) | ~37 | add_16_16_16, sub_8_8_8, neg_16_16, abs_32_32, avg_16_16_16, avgr_16_16_16, abssub_16_16_16, absssub_16_16_16 | (a OP b) mod 2^w; sat & avg variants |
| MAC / multiply | ~241 | mul_24_8_8, mul_48_16_16, muls_24_24_8_8, mula_…, muln_2x16x32_0_96_32_32, muluu_24_8_8, mulus_24_8_8, dmulq2n8dxr8_… | widening signed/unsigned/mixed product; mul-add (mula), mul-sub (muls), complex (c/j) |
| Min / max / compare | ~95 | min_16_16_16, max_16_16_16, minu_16_16_16, minnum_1_16f_16f_16f, oeq_1_1_16f_16f, olt_…, un_…, ult_… | signed/unsigned min-max; IEEE NaN-order vs minNum; ordered/unordered fp predicates |
| Convert / pack | ~123 | sext_32_16, zeroext_48_32, sats_16_32, cvt16s_16_24l, cvt32s_…, packl_16_48, packq_16_48, packv_…, cvtf32_1_32f_16f, cvtf16_… | exact sext/zext; saturating narrow; truncating/saturating pack; int↔float, fp16↔fp32 |
| Bitwise / shift | ~61 | and_512_512_512, xor_512_512_512, not_512_512, andb_64_64_64, andnotb_64_64_64, sll_u_32_32_5, sra_s_32_32_7, srl_u_…, widestshift_… | full-vector 512-bit bitwise; 64-bit vbool logic; variable shift (signed/unsigned shamt) |
| Bit-count / normalize | ~23 | popc_8_8, popc32_…, nsa_16_16, nsau_16_16, tzc_…, clsfy_16f_…, bitkill_moveqz, bitrev_… | population count; normalize-shift-amount; trailing-zero count; fp classify; per-lane bit-kill |
Reduce (r-prefixed) | ~68 | radd_nx16_32_512, radds_…, rmin_16, rmax_…, rbminu_…, rband_… | full-vector reduction-tree (sum/min/max/bool-and/or) over all 32 lanes |
| Gather / permute / select | ~27 | extr_2nx8_32_512_32, dsel_nx16, dseli_h, expandbytemask, dcmprs_clamp, dextrpr_n | lane extract / dual-select / compress / mask-expand |
| Predicate-flag pack | ~27 | predflag2t_…, fs1ltu_64_8_8, borfs_…, bnorfs_…, bsubnorm, baddnorm | pack lane results into a vbool register; fp-status flag accumulation |
| Transcendental seeds | ~21 | recip0_…, rsqrt0_…, sqrt0_…, div0_…, divn_32tf_32tf_32tf_2f, nexp0_…, recipqli_… | Newton / polynomial seed primitives for reciprocal/rsqrt/divide/exp |
| Move / copy | ~27 | mov_16_32, mov_…, const_nx16f, const_n | register-slot copy; constant materialization |
[HIGH/OBSERVED] for the symbols (all present in nm -D); [MED/INFERRED] for the family
boundaries (the multi-token grammar means a dmulusqa2n8dxr8 legitimately belongs to several
slices — the counts are indicative, the symbols are exact).
3. How each leaf computes its lane value — annotated bodies
Three distinct families below, each anchored to a real disassembled leaf. Operand A = %esi,
B = %edx, result* = %rcx, with the implicit %rdi context slot (§1.2).
3.1 Wrapping arithmetic — module__xdref_add_16_16_16 @ 0x858480
The integer base case: add, then mask to width. No saturation, no signedness dependence — modular two's-complement.
; module__xdref_add_16_16_16 @0x858480 — int16 add, wrapping
858480: add %esi,%edx ; sum = A + B (32-bit ALU, full precision)
858482: and $0xffff,%edx ; sum &= (1<<16)-1 <-- wrap to 2^16
858488: mov %edx,(%rcx) ; *result = sum
85848a: ret
/* module__xdref_add_16_16_16 — per-lane int16 add, wrapping mod 2^16.
* width mask = (1u << outW) - 1; the 32-bit form (add_32_32_32 @0x5bc340)
* needs no mask because the native x86 add already wraps at 2^32. */
void xdref_add_16_16_16(void *ctx, int32_t a, int32_t b, uint32_t *result) {
(void)ctx;
*result = (uint32_t)(a + b) & 0xffffu; /* (a + b) mod 2^16 */
}
This directly confirms the cas-arith reading of IVP_ADDNX16 as signed-i16 add, wrapping mod
2^16 — see cas Vector-Arithmetic Semantics. The 8-bit sibling masks 0xff;
the 32-bit sibling omits the mask. [HIGH/OBSERVED]
3.2 Saturating arithmetic — module__xdref_adds_16_16_16 @ 0x85aa10
The saturating signed-i16 add: sign-extend both operands, do a 32-bit signed sum, then detect
overflow by comparing bit 15 against bit 16 of the 17-bit sign-extended sum, and clamp to
exactly 0x7fff / 0x8000.
; module__xdref_adds_16_16_16 @0x85aa10 — saturating int16 add
85aa10: movswl %si,%eax ; A sign-extended to 32b
85aa13: movswl %dx,%edx ; B sign-extended to 32b
85aa16: add %eax,%edx ; signed 32-bit sum
85aa18: mov %edx,%eax
85aa1a: and $0x1ffff,%eax ; keep low 17 bits
85aa1f: mov %eax,%esi
85aa21: mov %eax,%edi
85aa23: shr $0xf,%esi ; esi = bit15(sum)
85aa26: shr $0x10,%edi ; edi = bit16(sum)
85aa29: and $0x1,%esi
85aa2c: cmp %edi,%esi ; bit15 == bit16 ?
85aa2e: je 85aa50 ; yes -> no overflow
; --- overflow path: select the clamp by the sum's sign ---
85aa30: mov %eax,%edx
85aa32: shr $1,%eax
85aa34: shl $0x10,%edx
85aa37: and $0x8000,%eax ; 0x8000 if sum negative
85aa3c: sar $0x1f,%edx ; all-ones if sum<0
85aa3f: and $0x7fff,%edx ; 0x7fff if sum<0 ...
85aa45: or %edx,%eax ; ... -> +ovf:0x7fff -ovf:0x8000
85aa47: mov %eax,(%rcx)
85aa49: ret
85aa50: movzwl %dx,%eax ; no overflow: low 16, zero-extended
85aa53: mov %eax,(%rcx)
85aa55: ret
/* module__xdref_adds_16_16_16 — saturating signed int16 add.
* Overflow iff bit15(sum) != bit16(sum) of the 17-bit sign-extended sum;
* clamp is +0x7fff for a positive overflow, 0x8000 for a negative one. */
void xdref_adds_16_16_16(void *ctx, int32_t a, int32_t b, uint32_t *result) {
(void)ctx;
int32_t sum = (int16_t)a + (int16_t)b; /* full-precision signed sum */
uint32_t s17 = (uint32_t)sum & 0x1ffffu; /* low 17 bits */
if (((s17 >> 15) & 1u) != ((s17 >> 16) & 1u)) /* bit15 != bit16 -> overflow */
*result = (sum < 0) ? 0x8000u : 0x7fffu; /* clamp to int16 range */
else
*result = (uint16_t)sum; /* in range */
}
The same 17-bit overflow-detect/clamp skeleton drives subs_16_16_16 (sub for add),
negs_16_16, abss_16_16 (calls negs for negatives), and absssub_16_16_16. This upgrades
the cas-arith saturation claims from MED to HIGH with byte-exact 0x7fff/0x8000 constants.
[HIGH/OBSERVED]
3.3 Signed min — module__xdref_min_16_16_16 @ 0x8584b0
The signed compare uses a sign-bias trick: flip the sign bit of both operands to map the signed
order onto the unsigned order, then use the hardware unsigned cmp + cmov. The unsigned
siblings (minu/maxu) skip the bias and use a bare cmp/cmov — so signedness is structural
in the body, not a runtime flag.
; module__xdref_min_16_16_16 @0x8584b0 — signed int16 min (sign-bias)
8584b0: mov %esi,%eax
8584b2: xor %r8d,%r8d
8584b5: mov %edx,%edi
8584b7: shr $0xf,%eax ; sign bit of A
8584ba: test %eax,%eax
8584bc: mov %esi,%eax
8584be: sete %r8b ; r8b = !sign(A)
8584c2: and $0x7fff,%eax ; low 15 bits of A
8584c7: shl $0xf,%r8d
8584cb: or %eax,%r8d ; keyA = (!sign(A) << 15) | (A & 0x7fff)
8584ce: mov %edx,%eax ; ... same for B -> keyB in %eax
8584d0: shr $0xf,%eax
8584d3: test %eax,%eax
8584d5: sete %al
8584d8: and $0x7fff,%edi
8584de: movzbl %al,%eax
8584e1: shl $0xf,%eax
8584e4: or %edi,%eax ; keyB
8584e6: cmp %eax,%r8d ; unsigned compare of the biased keys
8584e9: cmovae %edx,%esi ; if keyA >= keyB take B -> signed MIN
8584ec: mov %esi,(%rcx)
8584ee: ret
/* module__xdref_min_16_16_16 — signed int16 min via sign-biased unsigned compare.
* key(x) = (!sign(x) << 15) | (x & 0x7fff) maps the signed order onto the
* unsigned order, so the hardware unsigned cmp+cmov yields a signed min.
* minu_16_16_16 @0x8584f0 omits the bias: bare `cmp %edx,%esi ; cmova`. */
void xdref_min_16_16_16(void *ctx, int32_t a, int32_t b, uint32_t *result) {
(void)ctx;
uint32_t ka = (((a >> 15) & 1u) ? 0u : 0x8000u) | (a & 0x7fffu);
uint32_t kb = (((b >> 15) & 1u) ? 0u : 0x8000u) | (b & 0x7fffu);
*result = (uint16_t)((ka >= kb) ? b : a); /* signed min */
}
This confirms the cas reading that MINNX16 (signed) and MINUNX16 (unsigned) are distinct
implementations, not a toggled mode bit. [HIGH/OBSERVED]
3.4 Soft-float convert — module__xdref_cvtf32_1_32f_16f @ 0x5b77f0
The float path carries zero hardware FP: every fp16→fp32 widen is integer field extraction,
classification, and repack. The body extracts the binary16 fields (5-bit exp via shr $0xa & and $0x1f, 10-bit mantissa via and $0x3ff, sign), classifies NaN/Inf (exp == 0x1f), normalizes
subnormals (bsr), rebiases, repositions the mantissa (shl $0xd), and repacks into binary32 — and
it writes two outputs: a flag/exception word through %rdx and the fp32 result through %rcx.
/* module__xdref_cvtf32_1_32f_16f — IEEE binary16 -> binary32 widen, integer-only.
* Two outputs: *flag (exception bits) and *result (fp32 bit pattern).
* Field masks observed: exp 0x1f, mantissa 0x3ff, NaN/Inf test exp==0x1f;
* mantissa repositioned `<< 0xd`; default fp32 qNaN 0x7fc00000. */
void xdref_cvtf32_1_32f_16f(void *ctx, uint32_t h, uint32_t *flag, uint32_t *result) {
(void)ctx;
uint32_t sign = (h >> 15) & 1u;
uint32_t exp = (h >> 10) & 0x1fu;
uint32_t mant = h & 0x3ffu;
/* exp==0 -> zero/subnormal (bsr-normalize); exp==31 -> Inf/NaN;
* else -> normal: rebias exp (15 -> 127), mantissa << 13. */
*flag = /* exception bits, 0 for exact widens */ 0u;
*result = /* repacked binary32, sign|exp'|mant', integer-only */ 0u;
}
The fp16/fp32 add leaves (module__xdref_add_1_1_1_16f_16f_16f_2 @ 0x51c640, …_32f… @
0x871790) are the same shape at larger scale (0x830 / 0x890 bytes, zero xmm/x87), with a
status-word output and a parameter-driven rounding context in %r8/%r9. See
cas convert/pack/fp for how the cas decode binds these mnemonics.
GOTCHA — the fp-add leaves take an intricate multi-output argument frame. Unlike the simple binary leaves,
add_1_1_1_16f_16f_16f_2spills%rcx/%r8/%r9to the stack and writes its result through a reloaded pointer; a naive(ctx, a, b, *out, round, *status)prototype segfaults. Drive the converts (which have the stable dual-out(ctx, a, *flag, *result)frame — §6) to certify the soft-float path; trace the add frame from the spill slots before driving it.[HIGH/OBSERVED]
4. The execute path that drives the leaves
The leaves do not float free — they are invoked by the opcode__* execute bodies, of which there
are 1 708. There are two execute stages of interest:
opcode__<m>__stage_5— the vector execute (1 140 of them). It realises an N-wide IVP op as a scalar per-lane loop over the matchingxdrefleaf.opcode__<m>__stage_14— the scalar base-ISA execute (212 of them). It computes the 32-bit Xtensa AR op natively in-line — noxdrefcall.
4.1 Vector execute = a scalar per-lane loop
opcode__ivp_addnx16t__stage_5 @ 0x256d50 is the predicated 16-bit vector add (an NX16 op =
32 lanes of a 512-bit register). Disassembling its body and counting call targets:
$ objdump -d --start-address=0x256d50 --stop-address=0x2576b0 libfiss-base.so \
| rg 'call' | rg -o '<[^>]+>' | sort | uniq -c
32 <module__xdref_add_16_16_16@plt> <-- 32 lanes x the int16 add leaf (§3.1)
32 <module__xdref_bitkillt_16_2@plt> <-- 32 lanes x the per-lane vbool predicate
Exactly 32 calls to module__xdref_add_16_16_16 and 32 to module__xdref_bitkillt_16_2 —
one per NX16 lane. The lanes are unrolled, not looped, and even though the leaves are in the same
DLL, the calls route through @plt (the leaves are dynamic exports). This is the concrete
realisation of "a vector op is N applications of a scalar value leaf." [HIGH/OBSERVED]
4.2 Scalar base-ISA execute computes natively
The Xtensa-24 core AR ALU does not use xdref leaves — opcode__<op>__stage_14 reads operand
slots 0x4c/0x50/0x54 of the per-op context (%rdi) and writes slot 0x28:
; opcode__add__stage_14 @0x8875e0 — Xtensa AR add, native
8875e0: mov 0x4c(%rdi),%eax ; src1
8875e3: add 0x54(%rdi),%eax ; + src2
8875e6: mov %eax,0x28(%rdi) ; -> result slot
8875e9: xor %eax,%eax ; return 0 = no exception
8875eb: ret
The trailing xor %eax,%eax ; ret is the "no exception" return. The full base ALU set
(sub/and/or/xor/addi/neg/abs/addx2/slli/srai/extui/clamps/min/max/minu)
follows this shape, computing in-line with no host handoff. The scalar min/max reuse the same
sign-bias trick as the vector xdref_min/max (§3.3). [HIGH/OBSERVED]
5. This is the origin of the cas xdsem / fiss xdref model
The keystone resolves an asymmetry between the two ISS DLLs:
libcas-core.so(the cycle-accurate ISS) decodes + schedules, then delegates each lane value to the host through 119nx_*_interfacecallbacks. It names thexdsemmodel but does not contain the value bodies — see cas arith, cas MAC/FMAC, cas convert/pack/fp, each of which records "the value half is fiss's" and links here.libfiss-base.so(this DLL) is that value half: the 864module__xdref_*leaves are the in-process, bit-exacta OP bfor every IVP mnemonic. There is no further delegation — the 5 imports are libc, the 0nx_*_interfacecallbacks prove the math lands here.
So the 864-leaf roster is the common origin of every cas value page and the source of truth
the VAL lane drives live. The downstream validation lane (Part 15, not yet authored) treats these
leaves as the differential-test arbiter: it generates random operand vectors, drives the candidate
reimplementation and the matching module__xdref_* leaf via ctypes, and asserts bit-equality. The
already-committed cas value pages have each driven a specific leaf live to ground their
semantics — mula_24_24_8_8 / mula_48_48_16_16 (MAC), bitkillf_32_4 (predicate),
cvtf32 / packl_16_48 (convert/pack), radd_nx16_32_512 / rbmin_16 (reduce) — and §6 below is
their common certification harness. The oracle synthesis capstone and
the formal ISA model both consume this page as the
element-semantics anchor. [HIGH/OBSERVED]
6. Live certification — driving the oracle via ctypes
The leaves are drivable directly. The harness below loads the binary by absolute path and drives a
representative sample across families — 9 distinct leaves over 9 families — with the §1.2 ABI
(leading ctx, operands in %rsi/%rdx, result through %rcx).
import ctypes, struct, math
BIN = ".../ncore2gp/config/libfiss-base.so" # absolute path
lib = ctypes.CDLL(BIN); VP = ctypes.c_void_p
def d3(name, a, b): # 3-op: ctx, A=rsi, B=rdx, result*=rcx
fn = getattr(lib, name); fn.restype = None
fn.argtypes = [VP, ctypes.c_int, ctypes.c_int, VP]
out = ctypes.c_uint32(0); fn(None, a, b, ctypes.byref(out)); return out.value
def d2(name, a): # unary: ctx, A=rsi, result*=rdx
fn = getattr(lib, name); fn.restype = None
fn.argtypes = [VP, ctypes.c_int, VP]
out = ctypes.c_uint32(0); fn(None, a, ctypes.byref(out)); return out.value
Every value below was produced by an actual call into the shipped binary; the # expect comments
are the independently-computed oracle truth, and all matched:
## FAMILY arith-wrap module__xdref_add_16_16_16 @0x858480
add_16_16_16(0x7000, 0x2000) = 0x9000 # 0x9000
add_16_16_16(0xFFFF, 0x0002) = 0x0001 # wrap mod 2^16
add_8_8_8 (0xF0, 0x20) = 0x10 # wrap mod 2^8
## FAMILY sat-arith module__xdref_adds_16_16_16 @0x85aa10
adds_16_16_16(0x7000, 0x2000) = 0x7fff # +overflow clamp -> INT16_MAX
adds_16_16_16(0x8000, 0x8000) = 0x8000 # -overflow clamp -> INT16_MIN
subs_16_16_16(0x8000, 0x0001) = 0x8000 # -overflow clamp
## FAMILY signed-minmax module__xdref_min_16_16_16 @0x8584b0
min_16_16_16 (0x8000, 0x0001) = 0x8000 # signed: -32768 < 1
max_16_16_16 (0x8000, 0x0001) = 0x0001 # signed: max = 1
minu_16_16_16(0x8000, 0x0001) = 0x0001 # unsigned: 0x8000 > 1, min = 1
## FAMILY widen-mul module__xdref_mul_24_8_8 @0x68a800
mul_24_8_8 (0x7F, 0x7F) = 0x3f01 # signed 127*127 = 16129
mul_24_8_8 (0xFF, 0x02) = 0xfffffe # signed -1*2 = -2 (& 0xffffff)
muluu_24_8_8(0xFF, 0x02) = 0x01fe # unsigned 255*2 = 510
## FAMILY avg module__xdref_avg_16_16_16 @0x81d170
avg_16_16_16 (0x0003, 0x0006) = 0x4 # floor((3+6)/2)
avgr_16_16_16(0x0003, 0x0006) = 0x5 # round((3+6)/2)
## FAMILY abs/neg module__xdref_abs_16_16 @0x82d060 (unary)
abs_16_16(0x8000) = 0x8000 # wrap: |INT16_MIN| stays INT16_MIN
abs_16_16(0xFFFF) = 0x0001 # |-1| = 1
neg_16_16(0x0001) = 0xffff # -1
## FAMILY convert module__xdref_sext_32_16 @0x858680 (unary)
sext_32_16(0x8001) = 0xffff8001 # s16 -32767 -> 32-bit
sext_32_16(0x0042) = 0x00000042 # 66
## FAMILY bitcount module__xdref_popc_8_8 @0x832df0 (unary)
popc_8_8(0xFF) = 0x8 # 8 bits set
popc_8_8(0x0F) = 0x4 # 4 bits set
## FAMILY soft-float-convert module__xdref_cvtf32_1_32f_16f @0x5b77f0 (dual-out)
cvtf32(0x3c00 = 1.0) = 0x3f800000 = 1.0 flag=0x0
cvtf32(0xc100 = -2.5) = 0xc0200000 = -2.5 flag=0x0
cvtf32(0x7bff = 65504.0) = 0x477fe000 = 65504.0 flag=0x0 # max normal fp16
cvtf32(0x7c00 = +Inf) = 0x7f800000 = +Inf flag=0x0
cvtf32(0x7e00 = qNaN) = 0x7fc00000 flag=0x0 # canonical fp32 qNaN
cvtf32(-0.0) = 0x80000000 = -0.0 flag=0x0 # sign preserved
The soft-float convert closes the loop: 1.0, -2.5, 65504.0, +Inf all widen exactly, qNaN
maps to the canonical 0x7fc00000, and -0.0 preserves its sign bit — a full IEEE-754
binary16→binary32 widen with zero hardware FP, computed in-process. These calls are the live proof
that libfiss-base.so is the executable value oracle. [HIGH/OBSERVED]
QUIRK — the leaves are pure and re-entrant. Every body read here has no global state, no
.dataaccess, and an unused%rdicontext slot; the result is a deterministic function of the operand bits alone. That is precisely what makes the 864 leaves usable as a differential-test arbiter: the same operand vector drives the same lane value on every call, every run, every machine.[HIGH/OBSERVED]
7. Honesty ledger
[HIGH/OBSERVED] (disassembled bytes and/or live ctypes calls):
- 864
module__xdref_*leaves; 20 384 dynsym lines / 20 379 defined / 5 libc-only imports; 12 569slotfill__decoders; 1 708opcode__execute bodies; 0nx_*_interfacecallbacks. - The naming grammar
<op>_<outW>_<inAW>[_inBW]…[suffix]with widths in output-first order; confirmed againstadd/adds/min/mul_24_8_8/sext/cvtf32bodies. - The lane ABI:
%rdi= context,%rsi= A,%rdx= B,%rcx= result (3-op);%rdx= result (unary); dual-out converts write a flag through%rdxand the result through%rcx. - Bodies: wrap = mask-to-width; saturate = 17-bit overflow-detect +
0x7fff/0x8000clamp; signed min/max = sign-bias + unsigned cmp; unsigned = bare cmp; widening multiply with signedness in the extension prologue; soft-float convert = integer-only IEEE field logic. - Vector execute = scalar per-lane loop:
addnx16t__stage_5issues 32×add_16_16_16+ 32×bitkillt_16_2. Scalaropcode__add__stage_14computes natively (slots 0x4c/0x54 → 0x28). - 9 leaves driven live across 9 families; every value matched the independently-computed oracle.
[MED/INFERRED]:
- Family-boundary counts in §2 are indicative (the multi-token grammar makes a leaf belong to several slices); the symbols listed are exact.
- The exact fp rounding-mode source for the fp-add leaves is the
%r8/%r9status/round context (the OUT status word and ctx arg are OBSERVED; the full round-tie-break table was not enumerated).
[LOW]:
- The
recip0/rsqrt0/sqrt0/div0/nexp0Newton-seed exact polynomial coefficients (named as SEED primitives; bodies not disassembled in this pass). - The reduction-tree exact lane-pairing order in
radd/rmin/rmaxbodies (confirmed to load all 32 lanes; pairing order not enumerated).
CORRECTION (restated). The float census is 180 / 684, not the 184 / 680 of an earlier hand-count — grounded on the binary by
nm -D … | rg -c '[0-9]+t?f(_\|$)'. Cite 180 float-token leaves.[HIGH/OBSERVED]
See also
| Page | Relationship |
|---|---|
| fiss Surface & Exceptions | the 864 / 12 569 / 20 379 superset reconciliation; the fiss surface map |
| cas Vector-Arithmetic Semantics | delegates add/sub/min/max/abs values here |
| cas MAC / FMAC | delegates the multiply / mul-add / mul-sub matrix here |
| cas Convert / Pack / FP | delegates the convert / pack / soft-float values here |
| ISS Oracle Synthesis | the capstone that consumes this page as the value anchor |
| Formal ISA Model | the element-semantics specification this oracle realises |