nx_isa_sparc64_gate.nx
buildroot/runtime/nx_isa_sparc64_gate.nx
about
nx_isa_sparc64_gate.nx -- THE SPARC64 CONFORMANCE RULER.
WHY IT EXISTS: nx_isa_conform_gate measures five of the estate's ten
sovereign ISA emulators and names the other five in one line --
"UNMEASURED: armv7a cortexm loongarch64 s390x sparc64 -- each owes a
manual-derived KAT block here". This organ pays that debt for
sparc64. It is a SEPARATE organ rather than an edit to the incumbent
because five lanes are writing five arch blocks at once and
concurrent edits to one file silently clobber each other in this
tree; the shape is copied deliberately so the two rulers agree.
THE LAW IT OBEYS: a capability asserted and never measured is a
claim, not coverage. "We emulate sparc64" is decided by running
SPARC V9 machine code, in process, against values taken FROM THE
SPARC V9 MANUAL -- never from the emulator's own source, which would
calibrate the ruler to the subject it exists to judge. The decoder
was read first, but ONLY to learn which instruction classes are
implemented versus missing; every expected value below is derived
from the manual's encoding tables and its Bicc/BPcc condition table.
WHAT THE READ FOUND, AND WHAT WAS BUILT BECAUSE OF IT. On
2026-09-03 nx_emu_sparc64 decoded CALL, SETHI, ADD/SUB/AND/OR/XOR,
MULX, SDIVX/UDIVX, two shifts, SAVE/RESTORE, JMPL, Tcc and four
load/store forms -- and NOTHING ELSE in format 2. It carried no
condition-code state and no branch of any kind, so it could not run a
LOOP: the sparc64 claim covered straight-line code only. Four
further defects sat in the classes it did decode:
1. op3 0x08 is LDSW in V9 and was decoded as an UNSIGNED load, so
the only 32-bit load available answered with the wrong sign
extension; the real LDUW (op3 0x00) was absent entirely, so a
correct program reported UNSUPPORTED.
2. SRL/SRLX (op3 0x26) was written with this dialect's arithmetic
right shift and SRA/SRAX (op3 0x27) was absent -- so the logical
and the arithmetic right shift were ONE expression and one of
the two was necessarily wrong for every negative operand.
3. The shift count came from the sign-extended 13-bit simm without
reading the X bit, so the 32-bit shift forms could not be told
apart from the 64-bit ones.
4. No sub-word loads or stores at all (LDUB/LDSB/LDUH/LDSH/STB/STH).
All of it was implemented in nx_emu_sparc64 -- condition codes for
dependencies 3 imports · 0 importers
imports: nx_gate_verdict.nxnx_syscalls.nxnx_emu_sparc64.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 75 | const IS_GUEST_BYTES: i64 = 1048576 // 1 MiB guest image |
| 76 | const IS_ENTRY: i64 = 0 // KAT code is loaded at guest vaddr 0 |
| 77 | const IS_SP: i64 = 983040 // 960 KiB: above the code, inside the image |
| 78 | const IS_MODE_FILE: i64 = 420 // 0644; 420 and 0x1a4 are the SAME constant |
| 82 | const IS_UNSUPPORTED: i64 = -1 // SPE_UNSUPPORTED |
| 83 | const IS_RANOFF: i64 = -2 // this emulator never returns it (see header) |
| 84 | const IS_FAULT: i64 = -3 // SPE_FAULT |
| 86 | const IS_O_PASS: i64 = 0 |
| 87 | const IS_O_WRONG: i64 = 1 |
| 88 | const IS_O_UNSUP: i64 = 2 |
| 89 | const IS_O_FAULT: i64 = 3 |
| 90 | const IS_O_RANOFF: i64 = 4 |
| 95 | const IS_NB_BYTES: i64 = 2048 |
| 96 | const IS_NB_OFF: i64 = 0 |
| 97 | const IS_NB_PTR: i64 = 1 |
| 98 | const IS_NB_ROW_MAX: i64 = 256 |
| 99 | const IS_BOX_BYTES: i64 = 32 |
| 101 | const IS_NL: i64 = 10 |
| 102 | const IS_SPACE: i64 = 32 |
| 103 | const IS_DIG_LO: i64 = 48 |
| 104 | const IS_DIG_HI: i64 = 57 |
| 105 | const IS_UNSEEDED: i64 = -1 |
| 113 | const IS_OP_F2: i64 = 0 |
| 114 | const IS_OP_CALL: i64 = 1 |
| 115 | const IS_OP_ALU: i64 = 2 |
| 116 | const IS_OP_MEM: i64 = 3 |
| 118 | const IS_M13: i64 = 8191 // 0x1FFF simm13 |
| 119 | const IS_M19: i64 = 524287 // 0x7FFFF disp19 |
| 120 | const IS_M22: i64 = 4194303 // 0x3FFFFF imm22 and disp22 |
| 121 | const IS_M30: i64 = 1073741823 // 0x3FFFFFFF disp30 |
| 122 | const IS_XBIT: i64 = 4096 // bit 12: selects the 64-bit shift form |
| 124 | const IS_OP2_BPCC: i64 = 1 |
| 125 | const IS_OP2_BICC: i64 = 2 |
| 126 | const IS_OP2_SETHI: i64 = 4 |
| 130 | const IS_G0: i64 = 0 |
| 131 | const IS_G1: i64 = 1 |
| 132 | const IS_O0: i64 = 8 |
| 133 | const IS_O1: i64 = 9 |
| 134 | const IS_O2: i64 = 10 |
| 135 | const IS_O3: i64 = 11 |
| 136 | const IS_O6: i64 = 14 |
| 137 | const IS_O7: i64 = 15 |
| 138 | const IS_L0: i64 = 16 |
| 139 | const IS_I0: i64 = 24 |
| 141 | const IS_A_ADD: i64 = 0x00 |
| 142 | const IS_A_AND: i64 = 0x01 |
| 143 | const IS_A_OR: i64 = 0x02 |
| 144 | const IS_A_XOR: i64 = 0x03 |
| 145 | const IS_A_SUB: i64 = 0x04 |
| 146 | const IS_A_ANDN: i64 = 0x05 |
| 147 | const IS_A_MULX: i64 = 0x09 |
| 148 | const IS_A_ADDCC: i64 = 0x10 |
| 149 | const IS_A_SUBCC: i64 = 0x14 |
| 150 | const IS_A_SLLX: i64 = 0x25 |
| 151 | const IS_A_SRLX: i64 = 0x26 |
| 152 | const IS_A_SRAX: i64 = 0x27 |
| 153 | const IS_A_JMPL: i64 = 0x38 |
| 154 | const IS_A_TCC: i64 = 0x3a |
| 155 | const IS_A_SAVE: i64 = 0x3c |
| 156 | const IS_A_REST: i64 = 0x3d |
| 157 | const IS_A_FPOP1: i64 = 0x34 // deliberately NOT implemented |
| 159 | const IS_M_LDUW: i64 = 0x00 |
| 160 | const IS_M_LDUB: i64 = 0x01 |
| 161 | const IS_M_STW: i64 = 0x04 |
| 162 | const IS_M_STB: i64 = 0x05 |
| 163 | const IS_M_LDSW: i64 = 0x08 |
| 164 | const IS_M_LDSB: i64 = 0x09 |
| 165 | const IS_M_LDX: i64 = 0x0b |
| 166 | const IS_M_STX: i64 = 0x0e |
| 168 | const IS_C_E: i64 = 1 // BE / BZ Z |
| 169 | const IS_C_L: i64 = 3 // BL N xor V |
| 170 | const IS_C_CS: i64 = 5 // BCS / BLU C |
| 171 | const IS_C_A: i64 = 8 // BA always |
| 172 | const IS_C_NE: i64 = 9 // BNE / BNZ not Z |
| 173 | const IS_CCSEL_ICC: i64 = 0 |
| 174 | const IS_CCSEL_XCC: i64 = 2 |
| 178 | const IS_SYS_EXIT: i64 = 1 |
| 179 | const IS_TRAP_NR: i64 = 16 // ta 0x10 |
| 688 | const IS_RATCHET: *u8 = "knowledge/status/isa_sparc64.ratchet" |
| 689 | const IS_ARCH: *u8 = "sparc64" |
functions
| 183 | func is_nl() -> i64 |
| 194 | func is_put_be32(code: *u8, off: i64, w: i64) -> i64 |
| 202 | func is_guest() -> *u8 { return sys_mmap(IS_GUEST_BYTES) } |
| 204 | func is_f3i(op: i64, rd: i64, op3: i64, rs1: i64, simm: i64) -> i64 |
| 207 | func is_f3r(op: i64, rd: i64, op3: i64, rs1: i64, rs2: i64) -> i64 |
| 211 | func is_shx(rd: i64, op3: i64, rs1: i64, cnt: i64) -> i64 |
| 214 | func is_sethi(rd: i64, imm22: i64) -> i64 |
| 217 | func is_nop() -> i64 { return is_sethi(IS_G0, 0) } called by 5: is_k_branch_loopis_k_icc_vs_xccis_k_carry_polarityis_k_call_retis_k_fault_probe calls 1: is_sethi |
| 218 | func is_bicc(a: i64, cond: i64, disp22: i64) -> i64 |
| 221 | func is_bpcc(a: i64, cond: i64, ccsel: i64, p: i64, disp19: i64) -> i64 called by 1: is_k_icc_vs_xcc |
| 224 | func is_call(disp30: i64) -> i64 { return (IS_OP_CALL << 30) | (disp30 & IS_M30) } called by 1: is_k_call_ret |
| 229 | func is_exit(m: *u8, off: i64) -> i64 called by 22: is_k_imm_arithis_k_sub_regis_k_xoris_k_andnis_k_mulxis_k_sethi+16 calls 2: is_put_be32is_f3i |
| 235 | func is_run(m: *u8) -> i64 { return emu_sparc64_run_mem(m, IS_GUEST_BYTES, IS_ENTRY, IS_SP) } called by 22: is_k_imm_arithis_k_sub_regis_k_xoris_k_andnis_k_mulxis_k_sethi+16 calls 1: emu_sparc64_run_mem |
| 239 | func is_classify(got: i64, want: i64) -> i64 |
| 247 | func is_outcome_name(o: i64) -> *u8 |
| 258 | func is_report(kat: *u8, got: i64, want: i64, bx: *i64) -> i64 |
| 297 | func is_k_imm_arith() -> i64 { // want 42 |
| 306 | func is_k_sub_reg() -> i64 { // want 42; operand order reversed gives 214 |
| 319 | func is_k_xor() -> i64 { // want 89 |
| 333 | func is_k_andn() -> i64 { // want 72; plain and gives 36, xor 89 |
| 343 | func is_k_mulx() -> i64 { // want 42 |
| 355 | func is_k_sethi() -> i64 { // want 42; a missing shift gives 0 |
| 369 | func is_k_srlx() -> i64 { // want 15; an arithmetic shift gives 255 |
| 378 | func is_k_srax() -> i64 { // want 255; a logical shift gives 15 |
| 401 | func is_k_branch_loop() -> i64 { // want 45 |
| 425 | func is_k_delay_slot() -> i64 { // want 42; slot dropped 35; branch missed 134 |
| 449 | func is_k_annul() -> i64 { // want 42; slot not annulled 37; taken 200 |
| 479 | func is_k_icc_vs_xcc() -> i64 { // want 42; xcc for both 142; icc for both 40 |
| 514 | func is_k_carry_polarity() -> i64 { // want 42; inverted carry 32; no signed test 142 |
| 543 | func is_k_call_ret() -> i64 { // want 42 |
| 567 | func is_k_save_restore() -> i64 { // want 42 |
| 580 | func is_k_ldx_stx() -> i64 { // want 42 |
| 595 | func is_k_ldsw_sign_extends() -> i64 { // want 42; zero-extending load 43 |
| 610 | func is_k_lduw_zero_extends() -> i64 { // want 42; sign-extending load 41 |
| 622 | func is_k_stb_ldub() -> i64 { // want 42 |
| 637 | func is_k_ldsb_sign_extends() -> i64 { // want 42; unsigned load 43 |
| 658 | func is_k_unsupported_probe() -> i64 |
| 668 | func is_k_fault_probe() -> i64 |
| 691 | func is_match_at(buf: *u8, n: i64, p: i64, s: *u8) -> i64 called by 1: is_ratchet_read |
| 705 | func is_digits_at(buf: *u8, n: i64, p0: i64) -> i64 called by 1: is_ratchet_read |
| 729 | func is_ratchet_read() -> i64 |
| 759 | func is_ratchet_write(np: i64) -> i64 |
| 776 | func main(argc: i64, argv: *i64) -> i64 |