code wiki / _hdl_build / nx_memalloc_emit.nx
nx_memalloc_emit.nx source
↩ module page · 118 lines · 7362 B
1// nx_memalloc_emit.nx -- KERNEL MEMORY ALLOCATOR (bump) + store/load round-trip, the foundational
2// memory-management rung (toward census kernel-memory-allocator; foundation for K-R3 self-host:
3// organs need a heap). AUTHOR=ORGAN: table-computes a bare-metal rv64 image (zero hand-written
4// machine code) that runs a KAT: alloc a1 + a2 from a bump heap, store distinct values, LOAD them
5// back, and verify (a) each byte round-trips and (b) a2 == a1 + size (distinct allocations). Emits
6// 'M' iff every check passes, else 'X'. The GOLDEN ("M") is TABLE-COMPUTED, byte-reproducible.
7// Adds the LOAD encoder (lbu) the kernel emitter family lacked -- needed for all real kernel state.
8// nx_memalloc_emit -> runtime/_hdl_build/_memalloc_virt.bin + .gold
9// Sovereign, no gcc/.sh. license_tier: ORIGINAL
10import "nx_syscalls.nx"
11const MA_MAGIC_4096: i64 = 4096
12
13const MA_OUT: *u8 = "runtime/_hdl_build/_memalloc_virt.bin"
14const MA_GOLD: *u8 = "runtime/_hdl_build/_memalloc_virt.bin.gold"
15const MA_LOG: *u8 = "knowledge/status/memalloc.log"
16
17const MA_UART: i64 = 0x10000000
18const MA_FIN: i64 = 0x100000
19const MA_PASS: i64 = 0x5555
20const MA_HEAP: i64 = 0x80002000 // bump-heap base (valid guest RAM on the emu)
21const MA_SZ: i64 = 0x10 // allocation size
22const MA_VAL_A: i64 = 0xAA
23const MA_VAL_B: i64 = 0xBB
24const MA_CH_M: i64 = 77 // 'M' success
25const MA_CH_K: i64 = 75 // 'K' (success marker "MK", distinct from runner's "EMU")
26const MA_CH_X: i64 = 88 // 'X' fail
27// section offsets (table-computed layout)
28const MA_FAIL: i64 = 92
29const MA_HALT: i64 = 104
30// rv64 registers
31const RV_X0: i64 = 0
32const RV_T0: i64 = 5
33const RV_T1: i64 = 6
34const RV_T2: i64 = 7
35const RV_T3: i64 = 28
36const RV_T4: i64 = 29
37const RV_T5: i64 = 30
38
39func ma_lui(rd: i64, imm20: i64) -> i64 { return ((imm20 & 0xFFFFF) << 12) | (rd << 7) | 0x37 }
40func ma_addi(rd: i64, rs1: i64, imm: i64) -> i64 { return ((imm & 0xFFF) << 20) | (rs1 << 15) | (rd << 7) | 0x13 }
41func ma_store(rs2: i64, rs1: i64, f3: i64, imm: i64) -> i64 {
42 let hi: i64 = ((imm >> 5) & 0x7f) << 25
43 let lo: i64 = (imm & 0x1f) << 7
44 return hi | (rs2 << 20) | (rs1 << 15) | (f3 << 12) | lo | 0x23
45}
46// I-type LOAD (NEW): f3=0 lb,1 lh,2 lw,3 ld,4 lbu,5 lhu,6 lwu.
47func ma_load(rd: i64, rs1: i64, f3: i64, imm: i64) -> i64 { return ((imm & 0xFFF) << 20) | (rs1 << 15) | (f3 << 12) | (rd << 7) | 0x03 }
48func ma_branch(rs1: i64, rs2: i64, f3: i64, imm: i64) -> i64 {
49 let b12: i64 = ((imm >> 12) & 0x1) << 31
50 let b11: i64 = ((imm >> 11) & 0x1) << 7
51 let b10_5: i64 = ((imm >> 5) & 0x3f) << 25
52 let b4_1: i64 = ((imm >> 1) & 0xf) << 8
53 return b12 | b10_5 | (rs2 << 20) | (rs1 << 15) | (f3 << 12) | b4_1 | b11 | 0x63
54}
55func ma_jal(rd: i64, imm: i64) -> i64 {
56 let b20: i64 = ((imm >> 20) & 0x1) << 31
57 let b19_12: i64 = ((imm >> 12) & 0xff) << 12
58 let b11: i64 = ((imm >> 11) & 0x1) << 20
59 let b10_1: i64 = ((imm >> 1) & 0x3ff) << 21
60 return b20 | b10_1 | b11 | b19_12 | (rd << 7) | 0x6f
61}
62func ma_w32(buf: *u8, off: i64, w: i64) -> i64 {
63 buf[off]=(w & 0xff) as u8; buf[off+1]=((w>>8)&0xff) as u8; buf[off+2]=((w>>16)&0xff) as u8; buf[off+3]=((w>>24)&0xff) as u8
64 return off + 4
65}
66func ma_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
67func ma_fp(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
68func ma_fn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 }
69
70func main() -> i64 {
71 let buf: *u8 = sys_mmap(MA_MAGIC_4096)
72 var o: i64 = 0
73 o = ma_w32(buf, o, ma_lui(RV_T5, MA_HEAP >> 12)) // 0 lui t5,heap
74 o = ma_w32(buf, o, ma_addi(RV_T3, RV_T5, 0)) // 4 addi t3,t5,0 a1=heap
75 o = ma_w32(buf, o, ma_addi(RV_T5, RV_T5, MA_SZ)) // 8 addi t5,t5,SZ bump
76 o = ma_w32(buf, o, ma_addi(RV_T1, RV_X0, MA_VAL_A)) // 12 addi t1,0xAA
77 o = ma_w32(buf, o, ma_store(RV_T1, RV_T3, 0, 0)) // 16 sb t1,0(t3) *a1=0xAA
78 o = ma_w32(buf, o, ma_addi(RV_T4, RV_T5, 0)) // 20 addi t4,t5,0 a2=heap+SZ
79 o = ma_w32(buf, o, ma_addi(RV_T5, RV_T5, MA_SZ)) // 24 addi t5,t5,SZ bump
80 o = ma_w32(buf, o, ma_addi(RV_T1, RV_X0, MA_VAL_B)) // 28 addi t1,0xBB
81 o = ma_w32(buf, o, ma_store(RV_T1, RV_T4, 0, 0)) // 32 sb t1,0(t4) *a2=0xBB
82 o = ma_w32(buf, o, ma_load(RV_T2, RV_T3, 4, 0)) // 36 lbu t2,0(t3) t2=*a1
83 o = ma_w32(buf, o, ma_addi(RV_T1, RV_X0, MA_VAL_A)) // 40 addi t1,0xAA
84 o = ma_w32(buf, o, ma_branch(RV_T2, RV_T1, 1, MA_FAIL - 44)) // 44 bne t2,t1,FAIL
85 o = ma_w32(buf, o, ma_load(RV_T2, RV_T4, 4, 0)) // 48 lbu t2,0(t4) t2=*a2
86 o = ma_w32(buf, o, ma_addi(RV_T1, RV_X0, MA_VAL_B)) // 52 addi t1,0xBB
87 o = ma_w32(buf, o, ma_branch(RV_T2, RV_T1, 1, MA_FAIL - 56)) // 56 bne t2,t1,FAIL
88 o = ma_w32(buf, o, ma_addi(RV_T2, RV_T3, MA_SZ)) // 60 addi t2,t3,SZ expect a1+SZ
89 o = ma_w32(buf, o, ma_branch(RV_T4, RV_T2, 1, MA_FAIL - 64)) // 64 bne t4,t2,FAIL (a2 distinct)
90 o = ma_w32(buf, o, ma_lui(RV_T0, MA_UART >> 12)) // 68 lui t0,UART SUCCESS
91 o = ma_w32(buf, o, ma_addi(RV_T1, RV_X0, MA_CH_M)) // 72 addi t1,'M'
92 o = ma_w32(buf, o, ma_store(RV_T1, RV_T0, 0, 0)) // 76 sb t1,0(t0) emit 'M'
93 o = ma_w32(buf, o, ma_addi(RV_T1, RV_X0, MA_CH_K)) // 80 addi t1,'K'
94 o = ma_w32(buf, o, ma_store(RV_T1, RV_T0, 0, 0)) // 84 sb t1,0(t0) emit 'K'
95 o = ma_w32(buf, o, ma_jal(RV_X0, MA_HALT - 88)) // 88 jal HALT
96 o = ma_w32(buf, o, ma_lui(RV_T0, MA_UART >> 12)) // 92 lui t0,UART FAIL
97 o = ma_w32(buf, o, ma_addi(RV_T1, RV_X0, MA_CH_X)) // 96 addi t1,'X'
98 o = ma_w32(buf, o, ma_store(RV_T1, RV_T0, 0, 0)) // 100 sb t1,0(t0) emit 'X'
99 o = ma_w32(buf, o, ma_lui(RV_T1, MA_PASS >> 12)) // 104 lui t1,0x5 HALT
100 o = ma_w32(buf, o, ma_addi(RV_T1, RV_T1, MA_PASS & 0xFFF)) // 100 addi t1,t1,0x555
101 o = ma_w32(buf, o, ma_lui(RV_T2, MA_FIN >> 12)) // 104 lui t2,0x100
102 o = ma_w32(buf, o, ma_store(RV_T1, RV_T2, 2, 0)) // 108 sw t1,0(t2) finisher
103 o = ma_w32(buf, o, ma_jal(RV_X0, 0)) // 112 jal x0,0 guard
104
105 let fd: i64 = sys_openat_wr(MA_OUT, 420)
106 if fd < 0 { ma_p("MEMALLOCEMIT verdict=RED reason=out-unwritable\n" as *u8); return 1 }
107 sys_write(fd, buf, o)
108 sys_close(fd)
109 let gold: *u8 = sys_mmap(8)
110 gold[0] = MA_CH_M as u8
111 gold[1] = MA_CH_K as u8
112 let gfd: i64 = sys_openat_wr(MA_GOLD, 420)
113 if gfd >= 0 { sys_write(gfd, gold, 2); sys_close(gfd) }
114 ma_p("MEMALLOCEMIT name=" as *u8); ma_p(MA_OUT); ma_p(" machine=virt bytes=" as *u8); ma_fn(1, o); ma_p(" golden=MK heap=0x80002000\n" as *u8)
115 let lf: i64 = sys_openat_append(MA_LOG, 420)
116 if lf >= 0 { ma_fp(lf, "MEMALLOCEMIT name=" as *u8); ma_fp(lf, MA_OUT); ma_fp(lf, " machine=virt bytes=" as *u8); ma_fn(lf, o); ma_fp(lf, " golden=M epoch=" as *u8); ma_fn(lf, sys_now_realtime_sec()); ma_fp(lf, "\n" as *u8); sys_close(lf) }
117 return 0
118}