code wiki / _hdl_build / nx_x86_wasm_gate.nx

nx_x86_wasm_gate.nx source

↩ module page · 110 lines · 5192 B

1// nx_x86_wasm_gate.nx -- R1.0a WASM proof: compiles nx_x86.nx to wasm via the sovereign pipeline and runs 2// the same three programs in nx_wasm_vm, checking the results match native. Proves the x86 skeleton is 3// browser-ready, bit-identical to native. NISHI all the way (fork sovereign compilers -> nx_wasm_vm, no .sh). 4import "nx_syscalls.nx" 5import "nx_gate_emit_lib.nx" 6import "nx_wasm_vm.nx" 7 8const CWAT_ELF: *u8 = "/tmp/nx_compile_wat.sov.elf" 9const WATC_ELF: *u8 = "/tmp/nx_wat_compiler.sov.elf" 10const SRC_NX: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/runtime/nx_x86.nx" 11const OUT_WAT: *u8 = "/tmp/x86.wat" 12const OUT_WASM: *u8 = "/tmp/x86.wasm" 13 14func g_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 15func g_pn(v: i64) -> i64 { 16 let b: *u8 = sys_mmap(28) 17 var x: i64 = v 18 if x < 0 { b[0] = 45 as u8; sys_write(1, b, 1); x = 0 - x } 19 if x == 0 { b[0] = 48 as u8; sys_write(1, b, 1); return 0 } 20 var d: i64 = 0 21 var y: i64 = x 22 while y > 0 { d = d + 1; y = y / 10 } 23 var i: i64 = d - 1 24 y = x 25 while i >= 0 { b[i] = (48 + (y % 10)) as u8; y = y / 10; i = i - 1 } 26 sys_write(1, b, d) 27 return 0 28} 29func run_elf(elf: *u8, a1: *u8, a2: *u8) -> i64 { 30 let pid: i64 = sys_fork() 31 if pid == 0 { 32 let argv: *i64 = sys_mmap(64) as *i64 33 argv[0] = elf as i64 34 var ai: i64 = 1 35 if (a1 as i64) != 0 { argv[ai] = a1 as i64; ai = ai + 1 } 36 if (a2 as i64) != 0 { argv[ai] = a2 as i64; ai = ai + 1 } 37 argv[ai] = 0 38 let envp: *i64 = sys_mmap(16) as *i64 39 envp[0] = "PATH=/usr/bin:/bin" as *u8 as i64 40 envp[1] = 0 41 sys_execve(elf, argv, envp) 42 sys_exit(127) 43 } 44 let st: *i64 = sys_mmap(16) as *i64 45 sys_wait4(pid, st, 0) 46 return (st[0] >> 8) & 0xff 47} 48func xreset(mod: *WasmMod) -> i64 { return wm_run(mod, "x86_reset" as *u8, 0, 0, 0, 0, 0, 1) } 49func xload(mod: *WasmMod, addr: i64, byte: i64) -> i64 { return wm_run(mod, "x86_load" as *u8, 0, addr, byte, 0, 0, 3) } 50func xrun(mod: *WasmMod, cap: i64) -> i64 { return wm_run(mod, "x86_run" as *u8, 0, cap, 0, 0, 0, 2) } 51func xreg(mod: *WasmMod, r: i64) -> i64 { return wm_run(mod, "x86_reg" as *u8, 0, r, 0, 0, 0, 2) } 52func xzf(mod: *WasmMod) -> i64 { return wm_run(mod, "x86_zf" as *u8, 0, 0, 0, 0, 0, 1) } 53 54func load_ab(mod: *WasmMod, cmpval: i64) -> i64 { 55 xload(mod, 256, 184); xload(mod, 257, 0); xload(mod, 258, 0) 56 xload(mod, 259, 5); xload(mod, 260, 3); xload(mod, 261, 0) 57 xload(mod, 262, 5); xload(mod, 263, 3); xload(mod, 264, 0) 58 xload(mod, 265, 64) 59 xload(mod, 266, 64) 60 xload(mod, 267, 61); xload(mod, 268, cmpval); xload(mod, 269, 0) 61 xload(mod, 270, 116); xload(mod, 271, 3) 62 xload(mod, 272, 184); xload(mod, 273, 255); xload(mod, 274, 255) 63 xload(mod, 275, 244) 64 return 0 65} 66 67func main() -> i64 { 68 g_puts("nx_x86 WASM gate (sovereign compile -> nx_wasm_vm: real-mode skeleton, vs native)\n" as *u8) 69 var pass: i64 = 0 70 var total: i64 = 0 71 72 let rc1: i64 = run_elf(CWAT_ELF, SRC_NX, OUT_WAT) 73 g_puts(" [build] nx_compile_wat rc=" as *u8); g_pn(rc1); g_puts("\n" as *u8) 74 let rc2: i64 = run_elf(WATC_ELF, OUT_WAT, OUT_WASM) 75 g_puts(" [build] nx_wat_compiler rc=" as *u8); g_pn(rc2); g_puts("\n" as *u8) 76 77 let box: *i64 = sys_mmap(16) as *i64 78 let wasm: *u8 = sys_read_file(OUT_WASM, box) 79 if (wasm as i64) == 0 { g_puts(" FAIL cannot read x86.wasm\nverdict=RED\n" as *u8); sys_exit(1); return 1 } 80 g_puts(" [measure] wasm bytes=" as *u8); g_pn(box[0]); g_puts("\n" as *u8) 81 let mod: *WasmMod = wm_new(wasm, box[0]) 82 if wm_parse(mod) != 0 { g_puts(" FAIL wasm parse\nverdict=RED\n" as *u8); sys_exit(1); return 1 } 83 mod.mem = sys_mmap(131072) as *u8 84 85 pass = pass + g_check("nx_x86 compiled to wasm + x86_step exported" as *u8, wm_find_export(mod, "x86_step" as *u8) >= 0); total = total + 1 86 87 // A: JZ taken -> AX=8 88 xreset(mod); load_ab(mod, 8); xrun(mod, 100) 89 pass = pass + g_check("A: AX==8 + ZF==1 (wasm)" as *u8, xreg(mod, 0) == 8); total = total + 1 90 pass = pass + g_check("A: ZF==1 (wasm)" as *u8, xzf(mod) == 1); total = total + 1 91 // B: JZ not taken -> AX=0xFFFF 92 xreset(mod); load_ab(mod, 7); xrun(mod, 100) 93 pass = pass + g_check("B: AX==0xFFFF (wasm)" as *u8, xreg(mod, 0) == 65535); total = total + 1 94 // C: countdown loop -> AX=6, CX=0 95 xreset(mod) 96 xload(mod, 256, 185); xload(mod, 257, 3); xload(mod, 258, 0) 97 xload(mod, 259, 184); xload(mod, 260, 0); xload(mod, 261, 0) 98 xload(mod, 262, 5); xload(mod, 263, 2); xload(mod, 264, 0) 99 xload(mod, 265, 73) 100 xload(mod, 266, 117); xload(mod, 267, 250) 101 xload(mod, 268, 244) 102 xrun(mod, 100) 103 pass = pass + g_check("C: AX==6 (wasm loop)" as *u8, xreg(mod, 0) == 6); total = total + 1 104 pass = pass + g_check("C: CX==0 (wasm)" as *u8, xreg(mod, 1) == 0); total = total + 1 105 106 g_puts("---- x86 wasm gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 107 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 108 g_puts("verdict=RED\n" as *u8); sys_exit(1) 109 return 1 110}