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}