code wiki / _hdl_build / nx_author.nx

nx_author.nx source

↩ module page · 84 lines · 3816 B

1// nx_author.nx -- the team AUTHORS a new technique from its own diagnosis, by EXPERIMENT. 2// Last loops the team diagnosed "the competitor used a mnemonic I lack: imul" and I had to 3// tell it (or pre-stock) what imul does. This removes me: the team LEARNS the instruction's 4// semantics itself. It emits the instruction (in the form it observed in the competitor's 5// objdump: `imulq $K, %rdi, %rax`), RUNS it on several (K,x) probes, observes the outputs, 6// and INFERS which operation it computes by testing hypotheses {mul,add,sub,xor,and,or,shl} 7// against the observed input->output pairs. The hypothesis that matches ALL probes is the 8// learned semantics. Discovery by experiment -- the team teaches ITSELF a new primitive. 9// license_tier: ORIGINAL 10 11import "nx_engineer_crash.nx" // eng_link + eng_run (emit -> assemble -> run -> observe) 12import "nx_superopt_emit.nx" // se_str + se_num (emit the probe asm) 13const AU_MAGIC_1024: i64 = 1024 14 15const AU_MUL: i64 = 0 16const AU_ADD: i64 = 1 17const AU_SUB: i64 = 2 18const AU_XOR: i64 = 3 19const AU_AND: i64 = 4 20const AU_OR: i64 = 5 21const AU_SHL: i64 = 6 22const AU_NONE: i64 = 0 - 1 23 24func au_name(op: i64) -> *u8 { 25 if op == AU_MUL { return "MULTIPLY (x*K)" as *u8 } 26 if op == AU_ADD { return "ADD (x+K)" as *u8 } 27 if op == AU_SUB { return "SUB (x-K)" as *u8 } 28 if op == AU_XOR { return "XOR (x^K)" as *u8 } 29 if op == AU_AND { return "AND (x&K)" as *u8 } 30 if op == AU_OR { return "OR (x|K)" as *u8 } 31 if op == AU_SHL { return "SHIFT (x<<K)" as *u8 } 32 return "UNKNOWN" as *u8 33} 34 35// emit a probe: synth applies the observed instruction form to x; _start exits with the 36// low byte of synth(x). (Here the form learned from the diagnosis is `imulq $K,%rdi,%rax`.) 37func au_emit_probe(mnem: *u8, K: i64, x: i64, buf: *u8) -> i64 { 38 var oi: i64 = 0 39 oi = se_str(buf, oi, " .att_syntax prefix\n .text\n .globl _start\n_start:\n movabsq $" as *u8) 40 oi = se_num(buf, oi, x) 41 oi = se_str(buf, oi, ", %rdi\n call synth\n andq $255, %rax\n movq %rax, %rdi\n movabsq $60, %rax\n syscall\nsynth:\n " as *u8) 42 oi = se_str(buf, oi, mnem); oi = se_str(buf, oi, " $" as *u8); oi = se_num(buf, oi, K) 43 oi = se_str(buf, oi, ", %rdi, %rax\n ret\n" as *u8) 44 return oi 45} 46 47// run one probe: emit the instruction with (K,x), assemble, run, return the observed low byte. 48func au_observe(mnem: *u8, K: i64, x: i64) -> i64 { 49 let buf: *u8 = sys_mmap(AU_MAGIC_1024) 50 let blen: i64 = au_emit_probe(mnem, K, x, buf) 51 let fd: i64 = sys_openat_wr("/tmp/au.s" as *u8, 0x1a4) 52 if fd < 0 { return 0 - 2 } 53 sys_write(fd, buf, blen); sys_close(fd) 54 if eng_link("/tmp/au.s" as *u8, "/tmp/au.elf" as *u8) != 0 { return 0 - 2 } 55 return eng_run("/tmp/au.elf" as *u8, 0 as *u8) 56} 57 58// what each hypothesis predicts for (x,K), masked to the observed low byte. 59func au_predict(op: i64, x: i64, K: i64) -> i64 { 60 if op == AU_MUL { return (x * K) & 255 } 61 if op == AU_ADD { return (x + K) & 255 } 62 if op == AU_SUB { return (x - K) & 255 } 63 if op == AU_XOR { return (x ^ K) & 255 } 64 if op == AU_AND { return (x & K) & 255 } 65 if op == AU_OR { return (x | K) & 255 } 66 if op == AU_SHL { return (x << K) & 255 } 67 return 0 - 1 68} 69 70// LEARN the instruction's semantics by experiment: probe N (K,x) pairs, then return the one 71// hypothesis whose prediction matches EVERY observation. AU_NONE if nothing matches. 72func au_learn(mnem: *u8, Ks: *i64, Xs: *i64, n: i64, obs: *i64) -> i64 { 73 var i: i64 = 0 74 while i < n { obs[i] = au_observe(mnem, Ks[i], Xs[i]); i = i + 1 } 75 var op: i64 = 0 76 while op < 7 { 77 var ok: i64 = 1 78 var j: i64 = 0 79 while j < n { if au_predict(op, Xs[j], Ks[j]) != obs[j] { ok = 0 } j = j + 1 } 80 if ok == 1 { return op } 81 op = op + 1 82 } 83 return AU_NONE 84}