nx_emu_rv64_test.nx source
↩ module page · 68 lines · 2771 B
1// nx_emu_rv64_test.nx -- prove the sovereign RV64 interpreter runs real
2// RV64 machine code (no qemu). Hand-encodes RV64I words (verified vs the
3// RISC-V ISA manual; the 0x02a00513 word is the same one asm_enc.nx's KAT
4// uses) and asserts the emulated exit code.
5//
6// expect_exit: 0
7// license_tier: ORIGINAL
8
9import "nx_emu_rv64.nx"
10import "nx_syscalls_x86_64.nx"
11
12func emu_put_w(code: *u8, off: i64, w: i64) -> i64 {
13 code[off] = w & 0xff
14 code[off + 1] = (w >> 8) & 0xff
15 code[off + 2] = (w >> 16) & 0xff
16 code[off + 3] = (w >> 24) & 0xff
17 return off + 4
18}
19
20func main() -> i64 {
21 // Program 1: li a0,40 ; li t0,2 ; add a0,a0,t0 ; li a7,93 ; ecall -> exit 42
22 let code: *u8 = sys_mmap(64)
23 var o: i64 = 0
24 o = emu_put_w(code, o, 0x02800513) // addi a0,zero,40 (li a0,40)
25 o = emu_put_w(code, o, 0x00200293) // addi t0,zero,2 (li t0,2; t0=x5)
26 o = emu_put_w(code, o, 0x00550533) // add a0,a0,t0 -> 42
27 o = emu_put_w(code, o, 0x05d00893) // addi a7,zero,93 (li a7,93 = exit)
28 o = emu_put_w(code, o, 0x00000073) // ecall
29 let r: i64 = emu_rv64_run(code, o)
30 if r != 42 { return 1 }
31
32 // Program 2: the canonical KAT word addi a0,zero,42 (0x02a00513) ; exit
33 let c2: *u8 = sys_mmap(64)
34 var o2: i64 = 0
35 o2 = emu_put_w(c2, o2, 0x02a00513) // addi a0,zero,42
36 o2 = emu_put_w(c2, o2, 0x05d00893) // li a7,93
37 o2 = emu_put_w(c2, o2, 0x00000073) // ecall
38 let r2: i64 = emu_rv64_run(c2, o2)
39 if r2 != 42 { return 2 }
40
41 // Program 3: sub path -- li a0,50 ; li t0,8 ; sub a0,a0,t0 -> 42
42 let c3: *u8 = sys_mmap(64)
43 var o3: i64 = 0
44 o3 = emu_put_w(c3, o3, 0x03200513) // addi a0,zero,50
45 o3 = emu_put_w(c3, o3, 0x00800293) // addi t0,zero,8
46 o3 = emu_put_w(c3, o3, 0x40550533) // sub a0,a0,t0 (funct7=0x20) -> 42
47 o3 = emu_put_w(c3, o3, 0x05d00893) // li a7,93
48 o3 = emu_put_w(c3, o3, 0x00000073) // ecall
49 let r3: i64 = emu_rv64_run(c3, o3)
50 if r3 != 42 { return 3 }
51
52 // Program 4: REAL control flow -- sum 0..9 via a bne back-branch loop -> 45.
53 // Words are exactly what riscv64-as emits (oracle-verified); qemu exits 45.
54 let c4: *u8 = sys_mmap(64)
55 var o4: i64 = 0
56 o4 = emu_put_w(c4, o4, 0x00000513) // li a0,0
57 o4 = emu_put_w(c4, o4, 0x00000293) // li t0,0
58 o4 = emu_put_w(c4, o4, 0x00a00313) // li t1,10
59 o4 = emu_put_w(c4, o4, 0x00550533) // loop: add a0,a0,t0
60 o4 = emu_put_w(c4, o4, 0x00128293) // addi t0,t0,1
61 o4 = emu_put_w(c4, o4, 0xfe629ce3) // bne t0,t1,loop (offset -8)
62 o4 = emu_put_w(c4, o4, 0x05d00893) // li a7,93
63 o4 = emu_put_w(c4, o4, 0x00000073) // ecall
64 let r4: i64 = emu_rv64_run(c4, o4)
65 if r4 != 45 { return 4 }
66
67 return 0
68}