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}