code wiki / _hdl_build / nx_emu_x86_test.nx
nx_emu_x86_test.nx source
↩ module page · 96 lines · 4958 B
1// nx_emu_x86_test.nx -- (#3) prove the sovereign x86-64 interpreter, and use it as
2// the THIRD execution target for the generator. (1) a KAT exits 42; (2) the NAF
3// generator authors x86-64 machine code for x*C and emu_x86_run PROVES it computes
4// x*C. The oracle (native x*C) is independent of both the encoding and the
5// emulator, so agreement convicts a bug in either. Three target families now:
6// RV64 + AArch64 + x86-64. Known answer: KAT + every constant verified -> exit 0.
7
8import "nx_emu_x86.nx"
9
10func x_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
11func x_num(v: i64) -> i64 {
12 let b: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m }
13 let t: *u8 = sys_mmap(28); var k: i64 = 0
14 if m == 0 { t[0] = 48; k = 1 }
15 while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 }
16 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 }
17 sys_write(1, b, k); return 0
18}
19func x_put_b(code: *u8, o: i64, byte: i64) -> i64 { code[o] = byte & 0xff; return o + 1 }
20func x_put_i32(code: *u8, o: i64, v: i64) -> i64 {
21 code[o] = v & 0xff; code[o+1] = (v >> 8) & 0xff; code[o+2] = (v >> 16) & 0xff; code[o+3] = (v >> 24) & 0xff
22 return o + 4
23}
24
25// NAF generator (same recoding) -> term (pos, sign).
26func x_naf(C: i64, pos: *i64, sign: *i64) -> i64 {
27 var n: i64 = 0; var c: i64 = C; var i: i64 = 0
28 while c != 0 {
29 if (c & 1) == 1 { let d: i64 = 2 - (c & 3); pos[n] = i; sign[n] = d; n = n + 1; c = c - d }
30 c = c >> 1; i = i + 1
31 }
32 return n
33}
34
35// emit x86-64 for x*C (NAF terms): rcx=x, rax=result, rdx=temp. Run -> result.
36func x_run(x: i64, pos: *i64, sign: *i64, nt: i64) -> i64 {
37 let code: *u8 = sys_mmap(256); var o: i64 = 0
38 o = x_put_b(code, o, 0x48); o = x_put_b(code, o, 0xC7); o = x_put_b(code, o, 0xC1); o = x_put_i32(code, o, x) // mov rcx, x
39 o = x_put_b(code, o, 0x48); o = x_put_b(code, o, 0xC7); o = x_put_b(code, o, 0xC0); o = x_put_i32(code, o, 0) // mov rax, 0
40 var k: i64 = 0
41 while k < nt {
42 o = x_put_b(code, o, 0x48); o = x_put_b(code, o, 0x89); o = x_put_b(code, o, 0xCA) // mov rdx, rcx
43 o = x_put_b(code, o, 0x48); o = x_put_b(code, o, 0xC1); o = x_put_b(code, o, 0xE2); o = x_put_b(code, o, pos[k]) // shl rdx, pos
44 if sign[k] > 0 { o = x_put_b(code, o, 0x48); o = x_put_b(code, o, 0x01); o = x_put_b(code, o, 0xD0) } // add rax, rdx
45 else { o = x_put_b(code, o, 0x48); o = x_put_b(code, o, 0x29); o = x_put_b(code, o, 0xD0) } // sub rax, rdx
46 k = k + 1
47 }
48 o = x_put_b(code, o, 0x48); o = x_put_b(code, o, 0x89); o = x_put_b(code, o, 0xC7) // mov rdi, rax
49 o = x_put_b(code, o, 0x48); o = x_put_b(code, o, 0xC7); o = x_put_b(code, o, 0xC0); o = x_put_i32(code, o, 60) // mov rax, 60
50 o = x_put_b(code, o, 0x0F); o = x_put_b(code, o, 0x05) // syscall
51 return emu_x86_run(code, o)
52}
53
54func main() -> i64 {
55 x_puts("=== sovereign x86-64 interpreter: third target family ===\n" as *u8)
56
57 // KAT: mov rdi,42 ; mov rax,60 ; syscall -> exit 42.
58 let kat: *u8 = sys_mmap(64); var o: i64 = 0
59 o = x_put_b(kat, o, 0x48); o = x_put_b(kat, o, 0xC7); o = x_put_b(kat, o, 0xC7); o = x_put_i32(kat, o, 42) // mov rdi,42
60 o = x_put_b(kat, o, 0x48); o = x_put_b(kat, o, 0xC7); o = x_put_b(kat, o, 0xC0); o = x_put_i32(kat, o, 60) // mov rax,60
61 o = x_put_b(kat, o, 0x0F); o = x_put_b(kat, o, 0x05) // syscall
62 let kr: i64 = emu_x86_run(kat, o)
63 x_puts(" KAT (exit 42) -> " as *u8); x_num(kr); x_puts("\n" as *u8)
64
65 // generator authors x86 for x*C, emulator proves it.
66 let consts: *i64 = sys_mmap(8 * 8) as *i64
67 var n: i64 = 0
68 consts[n] = 7; n = n + 1
69 consts[n] = 9; n = n + 1
70 consts[n] = 11; n = n + 1
71 consts[n] = 100; n = n + 1
72 let pos: *i64 = sys_mmap(8 * 32) as *i64
73 let sign: *i64 = sys_mmap(8 * 32) as *i64
74 var ok: i64 = 0
75 var i: i64 = 0
76 while i < n {
77 let C: i64 = consts[i]
78 let nt: i64 = x_naf(C, pos, sign)
79 let maxx: i64 = 255 / C
80 var good: i64 = 1
81 var x: i64 = 0
82 while x <= maxx { if x_run(x, pos, sign, nt) != x * C { good = 0 } x = x + 1 }
83 x_puts(" x*" as *u8); x_num(C); x_puts(" (x86-64 authored) " as *u8)
84 if good == 1 { ok = ok + 1; x_puts("exec-ok\n" as *u8) } else { x_puts("FAIL\n" as *u8) }
85 i = i + 1
86 }
87
88 x_puts("----------------------------------------------------------------\n" as *u8)
89 x_puts(" x86-64 proven: " as *u8); x_num(ok); x_puts("/" as *u8); x_num(n)
90 x_puts(" -- three target families now execute the team's machine code (RV64/ARM64/x86).\n" as *u8)
91
92 if kr != 42 { sys_exit(1); return 1 }
93 if ok != n { sys_exit(2); return 2 }
94 sys_exit(0)
95 return 0
96}