nx_isa_armv7a_gate.nx
buildroot/runtime/nx_isa_armv7a_gate.nx
about
nx_isa_armv7a_gate.nx -- THE ARMv7-A CONFORMANCE RULER.
WHY IT EXISTS: nx_emu_armv7a.nx is one of ten sovereign ISA
emulators in this estate and, until 2026-09-03, it was one of the
EIGHT that had never been measured by anything. nx_isa_conform_gate
listed armv7a under "UNMEASURED: armv7a cortexm loongarch64 s390x
sparc64 -- each owes a manual-derived KAT block here". This organ is
that block, kept as its OWN gate so that armv7a can be built,
promoted, run and ratcheted without touching a file five other
lanes are editing at the same time.
THE LAW THIS ORGAN OBEYS: expectations come FROM THE ARM
ARCHITECTURE REFERENCE MANUAL (ARMv7-A/R, sections A5.1 data
processing, A5.2 load/store, A8.3 condition codes, A8.8 instruction
details), never from reading the emulator and writing down what it
happens to do. Reading the decoder tells you which classes are
IMPLEMENTED; it must never tell you what the answer is, or the
ruler is calibrated to the subject it is meant to judge.
FIVE OUTCOMES, NEVER ONE. Collapsing them into "FAIL" makes a gap
unactionable: an unimplemented class and a miscomputed value need
OPPOSITE fixes, and a program that walked off its image is neither.
PASS ran and matched the manual-derived expectation
WRONG-ANSWER ran to completion and computed the wrong value
UNSUPPORTED hit an instruction class the emulator does not decode
RAN-OFF-END pc left the image with no exit syscall
FAULT bad pc, out-of-range access, or the step budget
The sentinels are read out of nx_emu_armv7a.nx's own constant table
(A7_UNSUPPORTED -1, A7_RANOFF -2, A7_FAULT -3) and an EABI exit
status is masked to 0..255, so no sentinel can collide with an
answer.
EVERY KAT IS BUILT SO A WRONG IMPLEMENTATION GIVES A DIFFERENT
NUMBER, and the exit-status mask is the trap that makes that hard:
& 0xff hides every difference that lives above bit 7. So the
byte-load KAT shifts the loaded value down before exiting (a word
load and a byte load have the SAME low byte and are otherwise
indistinguishable), and the rotated-immediate KAT does the same.
WHAT THIS RUN CAUSED TO BE BUILT: the first draft of these KATs
dependencies 3 imports · 0 importers
imports: nx_gate_verdict.nxnx_syscalls.nxnx_emu_armv7a.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
| 72 | const AG7_GUEST_BYTES: i64 = 1048576 // 1 MiB guest image |
| 73 | const AG7_ENTRY: i64 = 0 // KAT code is loaded at guest vaddr 0 |
| 74 | const AG7_SP: i64 = 983040 // 960 KiB: above the code, inside the image |
| 75 | const AG7_MODE_FILE: i64 = 420 // 0644. 420 and 0x1a4 are the SAME |
| 80 | const AG7_UNSUPPORTED: i64 = -1 |
| 81 | const AG7_RANOFF: i64 = -2 |
| 82 | const AG7_FAULT: i64 = -3 |
| 85 | const AG7_O_PASS: i64 = 0 |
| 86 | const AG7_O_WRONG: i64 = 1 |
| 87 | const AG7_O_UNSUP: i64 = 2 |
| 88 | const AG7_O_FAULT: i64 = 3 |
| 89 | const AG7_O_RANOFF: i64 = 4 |
| 95 | const AG7_NB_BYTES: i64 = 2048 |
| 96 | const AG7_NB_OFF: i64 = 0 |
| 97 | const AG7_NB_PTR: i64 = 1 |
| 98 | const AG7_NB_ROW_MAX: i64 = 256 |
| 99 | const AG7_BOX_BYTES: i64 = 32 |
| 100 | const AG7_SCRATCH: i64 = 256 |
| 102 | const AG7_NL: i64 = 10 |
| 103 | const AG7_SPACE: i64 = 32 |
| 104 | const AG7_DIG_LO: i64 = 48 |
| 105 | const AG7_DIG_HI: i64 = 57 |
| 106 | const AG7_UNSEEDED: i64 = -1 |
| 107 | const AG7_B10: i64 = 10 |
| 117 | const AG7_MOV_I: i64 = 0xE3A00000 // mov Rd, imm |
| 118 | const AG7_MVN_I: i64 = 0xE3E00000 // mvn Rd, imm |
| 119 | const AG7_ADD_I: i64 = 0xE2800000 // add Rd, Rn, imm |
| 120 | const AG7_SUB_I: i64 = 0xE2400000 // sub Rd, Rn, imm |
| 121 | const AG7_RSB_I: i64 = 0xE2600000 // rsb Rd, Rn, imm (imm - Rn) |
| 122 | const AG7_ORR_I: i64 = 0xE3800000 // orr Rd, Rn, imm |
| 123 | const AG7_EOR_I: i64 = 0xE2200000 // eor Rd, Rn, imm |
| 124 | const AG7_BIC_I: i64 = 0xE3C00000 // bic Rd, Rn, imm |
| 125 | const AG7_CMP_I: i64 = 0xE3500000 // cmp Rn, imm (S=1, no writeback) |
| 126 | const AG7_ADD_R: i64 = 0xE0800000 // add Rd, Rn, Rm |
| 127 | const AG7_SUB_R: i64 = 0xE0400000 // sub Rd, Rn, Rm |
| 128 | const AG7_AND_R: i64 = 0xE0000000 // and Rd, Rn, Rm |
| 129 | const AG7_MOV_R: i64 = 0xE1A00000 // mov Rd, Rm, shift |
| 130 | const AG7_CMP_R: i64 = 0xE1500000 // cmp Rn, Rm |
| 131 | const AG7_MLA: i64 = 0xE0200000 // mla Rd, Rn, Rm, Ra (+0x90 marker) |
| 132 | const AG7_STR_D: i64 = 0xE5000000 // str Rd,[Rn,-imm] P=1 U=0 B=0 W=0 L=0 |
| 133 | const AG7_LDR_D: i64 = 0xE5100000 // ldr Rd,[Rn,-imm] P=1 U=0 B=0 W=0 L=1 |
| 134 | const AG7_LDRB_D: i64 = 0xE5500000 // ldrb Rd,[Rn,-imm] P=1 U=0 B=1 W=0 L=1 |
| 135 | const AG7_PUSH: i64 = 0xE92D0000 // stmdb sp!, list |
| 136 | const AG7_POP: i64 = 0xE8BD0000 // ldmia sp!, list |
| 137 | const AG7_STMIB: i64 = 0xE9A00000 // stmib Rn!, list P=1 U=1 W=1 L=0 |
| 138 | const AG7_LDR_U: i64 = 0xE5900000 // ldr Rd,[Rn,+imm] P=1 U=1 B=0 W=0 L=1 |
| 139 | const AG7_BNE: i64 = 0x1A000000 // bne (cond NE = 0001) |
| 140 | const AG7_MOVEQ: i64 = 0x03A00000 // moveq Rd, imm (cond EQ = 0000) |
| 141 | const AG7_MOVNE: i64 = 0x13A00000 // movne Rd, imm (cond NE = 0001) |
| 142 | const AG7_MOVLT: i64 = 0xB3A00000 // movlt Rd, imm (cond LT = 1011) |
| 143 | const AG7_MOVGE: i64 = 0xA3A00000 // movge Rd, imm (cond GE = 1010) |
| 144 | const AG7_SVC: i64 = 0xEF000000 // svc 0 |
| 145 | const AG7_MRC: i64 = 0xEE100F10 // mrc p15,0,r0,c0,c0,0 -- a class this |
| 147 | const AG7_LDRH: i64 = 0xE15D00B2 // ldrh r0,[sp,-2] -- the EXTRA load/store |
| 151 | const AG7_DSB: i64 = 0xF57FF01F // dsb sy -- cond 0b1111, the unconditional |
| 155 | const AG7_P_RD: i64 = 12 |
| 156 | const AG7_P_RN: i64 = 16 |
| 157 | const AG7_P_RM8: i64 = 8 |
| 158 | const AG7_P_SHAMT: i64 = 7 |
| 159 | const AG7_P_SHTY: i64 = 5 |
| 160 | const AG7_MUL_MARK: i64 = 0x90 |
| 161 | const AG7_SHTY_LSR: i64 = 1 |
| 164 | const AG7_ANS: i64 = 42 // every KAT that can returns 42 |
| 165 | const AG7_WRONGANS: i64 = 41 // the deliberately wrong want |
| 166 | const AG7_SUMTO9: i64 = 45 // 0+1+..+9, the loop KAT answer |
| 167 | const AG7_SIXTY: i64 = 60 |
| 168 | const AG7_C40: i64 = 40 |
| 169 | const AG7_C50: i64 = 50 |
| 170 | const AG7_C99: i64 = 99 |
| 171 | const AG7_C240: i64 = 240 |
| 172 | const AG7_C255: i64 = 255 |
| 173 | const AG7_C15: i64 = 15 |
| 174 | const AG7_C10: i64 = 10 |
| 175 | const AG7_C8: i64 = 8 |
| 176 | const AG7_C7: i64 = 7 |
| 177 | const AG7_C6: i64 = 6 |
| 178 | const AG7_C5: i64 = 5 |
| 179 | const AG7_C3: i64 = 3 |
| 180 | const AG7_C2: i64 = 2 |
| 181 | const AG7_C1: i64 = 1 |
| 182 | const AG7_C0: i64 = 0 |
| 183 | const AG7_XD5: i64 = 0xD5 // 0xFF eor 0xD5 = 0x2A = 42 |
| 184 | const AG7_ROT12: i64 = 0xC00 // rot field 12 -> imm8 ror 24 |
| 185 | const AG7_STKOFF: i64 = 8 // scratch slot below sp |
| 186 | const AG7_LIST01: i64 = 3 // register list r0 and r1 |
| 187 | const AG7_LIST0: i64 = 1 // register list r0 alone |
| 188 | const AG7_C64: i64 = 64 // scratch base, 64 bytes below sp |
| 189 | const AG7_SVCNUM: i64 = 7 // r7 carries the EABI syscall number |
| 190 | const AG7_EXITNUM: i64 = 1 // EABI exit |
| 191 | const AG7_BNE_BACK5: i64 = 0xFFFFFB // imm24 = -5 words: back over 4 words + pipeline |
| 192 | const AG7_SH8: i64 = 8 |
| 193 | const AG7_SH3: i64 = 3 |
| 194 | const AG7_R_SP: i64 = 13 // the ARM stack pointer is r13 |
| 195 | const AG7_KAT_COUNT: i64 = 17 // bind the aggregate assertion to its denominator |
| 197 | const AG7_RATCHET: *u8 = "knowledge/status/isa_armv7a.ratchet" |
functions
| 201 | func ag7_nl() -> i64 |
| 211 | func ag7_put_le32(code: *u8, off: i64, w: i64) -> i64 |
| 219 | func ag7_guest() -> *u8 { return sys_mmap(AG7_GUEST_BYTES) } |
| 222 | func ag7_exit(m: *u8, o0: i64) -> i64 called by 20: ag7_k_imm_arithag7_k_subag7_k_logicag7_k_eorag7_k_bicag7_k_rsb+14 calls 1: ag7_put_le32 |
| 229 | func ag7_run(m: *u8) -> i64 { return emu_armv7a_run_mem(m, AG7_GUEST_BYTES, AG7_ENTRY, AG7_SP) } called by 21: ag7_k_imm_arithag7_k_subag7_k_logicag7_k_eorag7_k_bicag7_k_rsb+15 calls 1: emu_armv7a_run_mem |
| 233 | func ag7_classify(got: i64, want: i64) -> i64 |
| 241 | func ag7_outcome_name(o: i64) -> *u8 |
| 252 | func ag7_report(kat: *u8, got: i64, want: i64, bx: *i64) -> i64 |
| 289 | func ag7_k_imm_arith() -> i64 |
| 299 | func ag7_k_sub() -> i64 |
| 311 | func ag7_k_logic() -> i64 |
| 324 | func ag7_k_eor() -> i64 |
| 334 | func ag7_k_bic() -> i64 |
| 347 | func ag7_k_rsb() -> i64 |
| 360 | func ag7_k_pred_taken() -> i64 |
| 373 | func ag7_k_pred_skipped() -> i64 |
| 387 | func ag7_k_branch_loop() -> i64 |
| 405 | func ag7_k_signed_cond() -> i64 |
| 420 | func ag7_k_shifted_operand() -> i64 |
| 436 | func ag7_k_rot_imm() -> i64 |
| 447 | func ag7_k_mla() -> i64 |
| 460 | func ag7_k_load_store() -> i64 |
| 475 | func ag7_k_ldrb() -> i64 |
| 493 | func ag7_k_push_pop() -> i64 |
| 511 | func ag7_k_block_ib() -> i64 |
| 527 | func ag7_neg_coproc() -> i64 |
| 539 | func ag7_neg_extra_ldst() -> i64 |
| 548 | func ag7_neg_uncond_space() -> i64 |
| 559 | func ag7_neg_no_exit() -> i64 |
| 573 | func ag7_match_at(buf: *u8, n: i64, p: i64, s: *u8) -> i64 called by 1: ag7_ratchet_read |
| 587 | func ag7_digits_at(buf: *u8, n: i64, p0: i64) -> i64 called by 1: ag7_ratchet_read |
| 611 | func ag7_ratchet_read() -> i64 |
| 641 | func ag7_ratchet_write(v: i64) -> i64 |
| 658 | func main(argc: i64, argv: *i64) -> i64 |