code wiki / _hdl_build / nx_rv64_jit_gate.nx
nx_rv64_jit_gate.nx source
↩ module page · 78 lines · 6301 B
1// nx_rv64_jit_gate.nx -- GATE: the sovereign RV64->x86-64 JIT is (a) CORRECT (a JIT'd count-loop gives the same
2// result as the predecoded interpreter -- equivalence vs the golden execution model) and (b) DRAMATICALLY FASTER
3// (a native x86 loop vs an interpreted one). Proves the SOTA emulator technique (dynamic binary translation) works
4// end-to-end sovereignly: RV64 -> native x86-64 -> mmap RWX -> CALL. expect_exit:0
5import "nx_syscalls.nx"
6import "nx_rv64_asm.nx"
7import "nx_rv64_fast.nx"
8import "nx_rv64_jit.nx"
9
10func 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 }
11func g_pn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var x: i64=v; if x<0{b[0]=45;sys_write(1,b,1);x=0-x} if x==0{b[0]=48;sys_write(1,b,1);return 0} var d: i64=0; var y: i64=x; while y>0{d=d+1;y=y/10} var i: i64=d-1; y=x; while i>=0{b[i]=(48+(y%10)) as u8;y=y/10;i=i-1} sys_write(1,b,d); return 0 }
12func ck(name: *u8, c: i64) -> i64 { if c==1 { g_puts(" PASS " as *u8) } else { g_puts(" FAIL " as *u8) } g_puts(name); g_puts("\n" as *u8); return c }
13
14func main() -> i64 {
15 g_puts("nx_rv64_jit_gate (sovereign RV64 -> x86-64 JIT: correctness vs the interpreter + measured native speedup)\n" as *u8)
16 var pass: i64=0; var total: i64=0
17
18 // the hot loop: t0 counts to 0x800000 (t1). 4 RV64 instructions, no memory ops. t0=x5, t1=x6.
19 let code: *u8 = sys_mmap(4096)
20 let nb: i64 = rvasm_assemble_str(" li t0, 0\n lui t1, 0x800\nloop:\n addi t0, t0, 1\n blt t0, t1, loop\n" as *u8, code, 4096)
21 if nb < 0 { g_puts(" ASSEMBLE FAILED\n" as *u8); sys_exit(1); return 1 }
22 let nw: i64 = nb/4
23 let opk: *i64=sys_mmap(nw*8) as *i64; let rd: *i64=sys_mmap(nw*8) as *i64; let rs1: *i64=sys_mmap(nw*8) as *i64; let rs2: *i64=sys_mmap(nw*8) as *i64; let imm: *i64=sys_mmap(nw*8) as *i64
24 let nc: i64 = fk_predecode(code, nb, opk, rd, rs1, rs2, imm)
25
26 // --- JIT: translate to native x86-64, then execute ---
27 let x86: *u8 = sys_mmap(65536); let x86off: *i64 = sys_mmap(nc*8) as *i64
28 let xlen: i64 = jit_compile(opk, rd, rs1, rs2, imm, nc, x86, x86off)
29 if xlen < 0 { g_puts(" JIT COMPILE FAILED (unsupported op)\n" as *u8); sys_exit(1); return 1 }
30 let jreg: *i64 = sys_mmap(32*8) as *i64; var z: i64=0; while z<32 { jreg[z]=0; z=z+1 }
31 let jt0: i64 = sys_now_us()
32 jit_run(x86, xlen, jreg)
33 let jt1: i64 = sys_now_us()
34 let jit_result: i64 = jreg[5]; let jit_us: i64 = jt1-jt0
35
36 // --- interpreter: run the same loop on the predecoded interpreter ---
37 let ireg: *i64 = sys_mmap(32*8) as *i64; z=0; while z<32 { ireg[z]=0; z=z+1 }
38 let imem: *u8 = sys_mmap(4096)
39 let it0: i64 = sys_now_us()
40 fk_run(opk, rd, rs1, rs2, imm, nc, ireg, imem, 4096, 200000000, (0 as i64) as *NxVirtioMmio)
41 let it1: i64 = sys_now_us()
42 let interp_result: i64 = ireg[5]; let interp_us: i64 = it1-it0
43
44 g_puts(" JIT: compiled "); g_pn(nc); g_puts(" RV64 ops -> "); g_pn(xlen); g_puts(" bytes of native x86-64\n" as *u8)
45 g_puts(" result: JIT t0="); g_pn(jit_result); g_puts(" interp t0="); g_pn(interp_result); g_puts(" (both 8388608)\n" as *u8)
46 g_puts(" time: JIT="); g_pn(jit_us); g_puts("us interp="); g_pn(interp_us); g_puts("us\n" as *u8)
47
48 var t1: i64=0; if jit_result==8388608 { if interp_result==8388608 { if jit_result==interp_result { t1=1 } } }
49 pass=pass+ck("T1: the JIT'd native loop gives the SAME result as the interpreter (dynamic binary translation is CORRECT)" as *u8, t1); total=total+1
50 var t2: i64=0; if xlen > 0 { if xlen < 200 { t2=1 } }
51 pass=pass+ck("T2: the JIT emitted a compact native x86-64 block (real code generation, per-instruction)" as *u8, t2); total=total+1
52 var speedup: i64=0; if jit_us>0 { speedup=interp_us/jit_us }
53 var speedup_x100: i64=0; if jit_us>0 { speedup_x100=(interp_us*100)/jit_us }
54 g_puts(" NATIVE SPEEDUP over the interpreter = "); g_pn(speedup_x100/100); g_puts("."); if speedup_x100%100<10 { g_puts("0" as *u8) } g_pn(speedup_x100%100); g_puts("x (JIT native code vs interpreted)\n" as *u8)
55 var t3: i64=0; if jit_us < interp_us { t3=1 }
56 pass=pass+ck("T3: the JIT is MEASURABLY FASTER than the interpreter (native execution wins -- the SOTA technique)" as *u8, t3); total=total+1
57 // teeth: an unsupported op must fail-loud (not silently miscompile). LBU (narrow load) is outside the JIT subset.
58 let bad_opk: *i64=sys_mmap(8) as *i64; bad_opk[0]=FK_LBU // a byte load: intentionally unsupported by the JIT subset
59 let bad_out: *u8=sys_mmap(64); let bad_off: *i64=sys_mmap(8) as *i64
60 let bad_rc: i64 = jit_compile(bad_opk, rd, rs1, rs2, imm, 1, bad_out, bad_off)
61 var t4: i64=0; if bad_rc==(0-1) { t4=1 }
62 pass=pass+ck("T4 (teeth): an unsupported op makes the JIT FAIL-LOUD (-1), never silently miscompiles" as *u8, t4); total=total+1
63 // forward branches are now SUPPORTED (nx_rv64_jit_fwd_gate proves if/else); a forward branch COMPILES (rc>0).
64 let fwd_opk: *i64=sys_mmap(16) as *i64; let fwd_imm: *i64=sys_mmap(16) as *i64; let fwd_z: *i64=sys_mmap(16) as *i64
65 fwd_opk[0]=FK_BEQ; fwd_imm[0]=4; fwd_opk[1]=FK_ADDI; fwd_imm[1]=0; fwd_z[0]=0; fwd_z[1]=0
66 let fwd_rc: i64 = jit_compile(fwd_opk, fwd_z, fwd_z, fwd_z, fwd_imm, 2, bad_out, bad_off)
67 var t5: i64=0; if fwd_rc>0 { t5=1 }
68 pass=pass+ck("T5: a FORWARD branch now COMPILES (rc>0) -- forward control flow supported via the fixup pass" as *u8, t5); total=total+1
69
70 var okall: i64=0; if pass==total { okall=1 }
71 g_puts("---- nx_rv64_jit_gate: passed "); g_pn(pass); g_puts(" / "); g_pn(total); g_puts(" ----\n" as *u8)
72 if okall==1 {
73 let logf: i64=sys_openat_append("knowledge/status/rv64_jit.log" as *u8, 420)
74 if logf>=0 { let z2: i64=sys_write(logf,"NXRV64JIT GREEN: sovereign RV64->x86-64 JIT (dynamic binary translation) -- JIT'd loop == interpreter result + measurably faster (native code); the SOTA emulator technique, per-instruction, RWX-exec proven\n" as *u8,203); sys_close(logf) }
75 g_puts("verdict=GREEN (sovereign RV64->x86-64 JIT: dynamic binary translation works end-to-end -- correct vs the interpreter + native speedup; the SOTA emulator rung, built on the proven RWX-exec primitive)\n" as *u8); sys_exit(0); return 0
76 }
77 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1
78}