nxasm_x86_enc.nx
buildroot/runtime/nxasm_x86_enc.nx
about
nxasm_x86_enc.nx -- x86_64 instruction encoder + minimal ELF writer,
written in NishiLang. The x86_64 sibling of asm_enc.nx (RV64).
First brick of the SOVEREIGN x86_64 backend: replaces GNU `as` + `ld`
on the output path. Pure bit-manipulation -- no syscalls, no file
I/O here, so it stays architecture-neutral and the encoder KAT runs
under any lane. Live emit (write the ELF to a fd) is composed in the
test/driver via the syscall layer.
Scope (this iteration): the exact constructs needed to emit a
runnable static ELF -- enough to prove the whole sovereign chain
end-to-end with an exit(N) binary. The full 29-mnemonic AT&T subset
nxc2 emits (movq/movabsq/add/sub/and/or/cmp/test/imul/idiv/cqo/shl/
sar/lea/call/jmp/jcc/setcc/movzbq/...) lands incrementally on this
same REX/ModRM/SIB foundation, each gated by a byte-exact KAT vs the
objdump oracle (Wheeler/benchmark reference only -- NEVER in our
output path).
Encoding model (Intel SDM Vol.2):
REX prefix 0100 WRXB (0x40 base; W=64-bit, B=reg ext bit3)
ModRM mod(2) reg(3) rm(3)
immediates little-endian
genealogy_id: intel_sdm_vol2 + amd_apm + osdev_elf (Wheeler refs)
lineage_id: nishi_sovereign_x86_64_backend_m1
license_tier: ORIGINAL
dependencies 0 imports · 1 importers
imports: none
imported by: nxasm_x86.nx
structs
| none |
consts
| 29 | const X86_RAX: i64 = 0 |
| 30 | const X86_RCX: i64 = 1 |
| 31 | const X86_RDX: i64 = 2 |
| 32 | const X86_RBX: i64 = 3 |
| 33 | const X86_RSP: i64 = 4 |
| 34 | const X86_RBP: i64 = 5 |
| 35 | const X86_RSI: i64 = 6 |
| 36 | const X86_RDI: i64 = 7 |
| 37 | const X86_R8: i64 = 8 |
| 38 | const X86_R9: i64 = 9 |
| 39 | const X86_R10: i64 = 10 |
| 40 | const X86_R11: i64 = 11 |
| 41 | const X86_R12: i64 = 12 |
| 42 | const X86_R13: i64 = 13 |
| 43 | const X86_R14: i64 = 14 |
| 44 | const X86_R15: i64 = 15 |
| 47 | const EM_X86_64: i64 = 62 |
| 48 | const X86_BASE: i64 = 0x400000 // conventional static ET_EXEC base |
| 49 | const X86_HDRLEN: i64 = 120 // 64 (ehdr) + 56 (one phdr) |
| 388 | const X86_OP_ADD: i64 = 0x01 |
| 389 | const X86_OP_SUB: i64 = 0x29 |
| 390 | const X86_OP_AND: i64 = 0x21 |
| 391 | const X86_OP_OR: i64 = 0x09 |
| 392 | const X86_OP_XOR: i64 = 0x31 |
| 393 | const X86_OP_CMP: i64 = 0x39 |
| 394 | const X86_OP_TEST: i64 = 0x85 |
| 396 | const X86_EXT_ADD: i64 = 0 |
| 397 | const X86_EXT_OR: i64 = 1 |
| 398 | const X86_EXT_AND: i64 = 4 |
| 399 | const X86_EXT_SUB: i64 = 5 |
| 400 | const X86_EXT_CMP: i64 = 7 |
| 402 | const X86_EXT_SHL: i64 = 4 |
| 403 | const X86_EXT_SHR: i64 = 5 |
| 404 | const X86_EXT_SAR: i64 = 7 |
| 406 | const X86_CC_E: i64 = 4 |
| 407 | const X86_CC_NE: i64 = 5 |
| 408 | const X86_CC_L: i64 = 0xC |
| 409 | const X86_CC_LE: i64 = 0xE |
| 410 | const X86_CC_G: i64 = 0xF |
| 411 | const X86_CC_GE: i64 = 0xD |
| 412 | const X86_CC_S: i64 = 8 // SF=1 (negative) -- the G22 bias-select |
| 413 | const X86_CC_NS: i64 = 9 // SF=0 |
functions
| 52 | func x86_put_u16le(out: *u8, o: i64, v: i64) -> i64 called by 1: x86_build_elf_at |
| 58 | func x86_put_u32le(out: *u8, o: i64, v: i64) -> i64 |
| 66 | func x86_put_u64le(out: *u8, o: i64, v: i64) -> i64 |
| 80 | func x86_rex_w(reg_field: i64, rm_field: i64) -> i64 |
| 88 | func x86_modrm(mod: i64, reg: i64, rm: i64) -> i64 |
| 97 | func x86_sse_rr(out: *u8, o: i64, pfx: i64, esc: i64, opc: i64, reg: i64, rm: i64) -> i64 |
| 123 | func x86_vex2_rr(out: *u8, o: i64, opc: i64, dst: i64, src1: i64, src2: i64, l: i64, pp: i64) -> i64 calls 1: x86_modrm |
| 136 | func x86_vex3_rr(out: *u8, o: i64, mmmmm: i64, w: i64, opc: i64, dst: i64, src1: i64, src2: i64, l: i64, pp: i64) -> i64 |
| 150 | func x86_sse_rr_w(out: *u8, o: i64, pfx: i64, esc: i64, opc: i64, reg: i64, rm: i64) -> i64 |
| 173 | func x86_sse_mem(out: *u8, o: i64, pfx: i64, opc: i64, reg: i64, base: i64, disp: i64) -> i64 |
| 192 | func x86_sse_shift_imm(out: *u8, o: i64, opc: i64, ext: i64, xmm: i64, imm8: i64) -> i64 |
| 207 | func x86_sse_rri(out: *u8, o: i64, pfx: i64, opc: i64, reg: i64, rm: i64, imm8: i64) -> i64 |
| 231 | func x86_vex_rrr(out: *u8, o: i64, pp: i64, mmmmm: i64, w: i64, vexL: i64, opc: i64, dst: i64, src1: i64, src2: i64) -> i64 |
| 251 | func x86_vex_rm(out: *u8, o: i64, pp: i64, mmmmm: i64, w: i64, vexL: i64, opc: i64, reg: i64, base: i64, disp: i64) -> i64 |
| 273 | func x86_vex_shift_imm(out: *u8, o: i64, pp: i64, mmmmm: i64, vexL: i64, opc: i64, ext: i64, dst: i64, src: i64, imm8: i64) -> i64 |
| 295 | func x86_vex_rmi(out: *u8, o: i64, pp: i64, mmmmm: i64, w: i64, vexL: i64, opc: i64, dst: i64, src: i64, imm8: i64) -> i64 |
| 317 | func x86_movabs(out: *u8, o: i64, reg: i64, imm: i64) -> i64 |
| 327 | func x86_mov_imm32(out: *u8, o: i64, reg: i64, imm: i64) -> i64 |
| 339 | func x86_mov_reg(out: *u8, o: i64, dst: i64, src: i64) -> i64 |
| 350 | func x86_syscall(out: *u8, o: i64) -> i64 called by 1: axc_emit |
| 359 | func x86_rdtsc(out: *u8, o: i64) -> i64 called by 1: axc_emit |
| 366 | func x86_ret(out: *u8, o: i64) -> i64 called by 1: axc_emit |
| 372 | func x86_push(out: *u8, o: i64, reg: i64) -> i64 called by 1: axc_emit |
| 380 | func x86_pop(out: *u8, o: i64, reg: i64) -> i64 called by 1: axc_emit |
| 416 | func x86_alu_rr(out: *u8, o: i64, opcode: i64, dst: i64, src: i64) -> i64 |
| 426 | func x86_alu_imm(out: *u8, o: i64, ext: i64, dst: i64, imm: i64) -> i64 |
| 446 | func x86_mem_operand(out: *u8, o: i64, reg_field: i64, base: i64, disp: i64) -> i64 called by 14: x86_sse_memx86_vex_rmx86_mov_loadx86_mov_storex86_movl_storex86_movl_load+8 calls 2: x86_modrmx86_put_u32le |
| 457 | func x86_mov_load(out: *u8, o: i64, dst: i64, base: i64, disp: i64) -> i64 |
| 465 | func x86_mov_store(out: *u8, o: i64, base: i64, disp: i64, src: i64) -> i64 |
| 475 | func x86_rex_wx(reg_field: i64, index_field: i64, base_field: i64) -> i64 |
| 484 | func x86_scale_log2(scale: i64) -> i64 called by 1: x86_mem_operand_sib |
| 495 | func x86_mem_operand_sib(out: *u8, o: i64, reg_field: i64, base: i64, called by 3: x86_mov_load_sibx86_mov_store_sibx86_lea_sib calls 3: x86_modrmx86_scale_log2x86_put_u32le |
| 509 | func x86_mov_load_sib(out: *u8, o: i64, dst: i64, base: i64, index: i64, scale: i64, disp: i64) -> i64 |
| 517 | func x86_mov_store_sib(out: *u8, o: i64, base: i64, index: i64, scale: i64, disp: i64, src: i64) -> i64 |
| 526 | func x86_movl_rex_if(out: *u8, o: i64, reg: i64, rm: i64) -> i64 |
| 534 | func x86_movl_store(out: *u8, o: i64, base: i64, disp: i64, src: i64) -> i64 |
| 539 | func x86_movl_load(out: *u8, o: i64, dst: i64, base: i64, disp: i64) -> i64 |
| 545 | func x86_movl_rr(out: *u8, o: i64, dst: i64, src: i64) -> i64 |
| 553 | func x86_lea(out: *u8, o: i64, dst: i64, base: i64, disp: i64) -> i64 |
| 565 | func x86_lea_sib(out: *u8, o: i64, dst: i64, base: i64, index: i64, scale: i64, disp: i64) -> i64 |
| 574 | func x86_lea_rip(out: *u8, o: i64, dst: i64, disp32: i64) -> i64 |
| 585 | func x86_imul_rr(out: *u8, o: i64, dst: i64, src: i64) -> i64 |
| 595 | func x86_movzbq(out: *u8, o: i64, dst: i64, src: i64) -> i64 |
| 604 | func x86_movzbq_mem(out: *u8, o: i64, dst: i64, base: i64, disp: i64) -> i64 |
| 619 | func x86_movsbq(out: *u8, o: i64, dst: i64, src: i64) -> i64 |
| 628 | func x86_movsbq_mem(out: *u8, o: i64, dst: i64, base: i64, disp: i64) -> i64 |
| 636 | func x86_movswq(out: *u8, o: i64, dst: i64, src: i64) -> i64 |
| 645 | func x86_movswq_mem(out: *u8, o: i64, dst: i64, base: i64, disp: i64) -> i64 |
| 653 | func x86_movzwq(out: *u8, o: i64, dst: i64, src: i64) -> i64 |
| 662 | func x86_movzwq_mem(out: *u8, o: i64, dst: i64, base: i64, disp: i64) -> i64 |
| 670 | func x86_movslq(out: *u8, o: i64, dst: i64, src: i64) -> i64 |
| 678 | func x86_movslq_mem(out: *u8, o: i64, dst: i64, base: i64, disp: i64) -> i64 |
| 686 | func x86_cqo(out: *u8, o: i64) -> i64 called by 1: axc_emit |
| 692 | func x86_idiv(out: *u8, o: i64, reg: i64) -> i64 |
| 704 | func x86_mul(out: *u8, o: i64, reg: i64) -> i64 |
| 718 | func x86_crc32_r64(out: *u8, o: i64, dst: i64, src: i64) -> i64 |
| 735 | func x86_pdep_r64(out: *u8, o: i64, dst: i64, src1: i64, src2: i64) -> i64 |
| 744 | func x86_pext_r64(out: *u8, o: i64, dst: i64, src1: i64, src2: i64) -> i64 |
| 756 | func x86_mulx_r64(out: *u8, o: i64, dst_hi: i64, dst_lo: i64, src: i64) -> i64 |
| 768 | func x86_adcx_r64(out: *u8, o: i64, dst: i64, src: i64) -> i64 |
| 778 | func x86_adox_r64(out: *u8, o: i64, dst: i64, src: i64) -> i64 |
| 790 | func x86_shift_imm(out: *u8, o: i64, ext: i64, reg: i64, imm8: i64) -> i64 |
| 800 | func x86_jmp_rel32(out: *u8, o: i64, rel: i64) -> i64 |
| 806 | func x86_call_rel32(out: *u8, o: i64, rel: i64) -> i64 |
| 812 | func x86_jcc_rel32(out: *u8, o: i64, cc: i64, rel: i64) -> i64 |
| 821 | func x86_cmovcc(out: *u8, o: i64, cc: i64, dst: i64, src: i64) -> i64 |
| 831 | func x86_setcc(out: *u8, o: i64, cc: i64, reg: i64) -> i64 |
| 842 | func x86_rot_imm(out: *u8, o: i64, is_ror: i64, reg: i64, imm8: i64) -> i64 |
| 851 | func x86_rot_cl(out: *u8, o: i64, is_ror: i64, reg: i64) -> i64 |
| 859 | func x86_shift_cl(out: *u8, o: i64, ext: i64, reg: i64) -> i64 |
| 867 | func x86_bswap(out: *u8, o: i64, reg: i64) -> i64 called by 1: axc_emit |
| 875 | func x86_popcnt(out: *u8, o: i64, dst: i64, src: i64) -> i64 |
| 887 | func x86_cnt32(out: *u8, o: i64, opc: i64, dst: i64, src: i64) -> i64 |
| 901 | func x86_lzcnt32(out: *u8, o: i64, dst: i64, src: i64) -> i64 { return x86_cnt32(out, o, 0xBD, dst, src) } |
| 902 | func x86_tzcnt32(out: *u8, o: i64, dst: i64, src: i64) -> i64 { return x86_cnt32(out, o, 0xBC, dst, src) } |
| 904 | func x86_unary_f7(out: *u8, o: i64, ext: i64, reg: i64) -> i64 |
| 911 | func x86_neg(out: *u8, o: i64, reg: i64) -> i64 { return x86_unary_f7(out, o, 3, reg) } |
| 912 | func x86_not(out: *u8, o: i64, reg: i64) -> i64 { return x86_unary_f7(out, o, 2, reg) } |
| 914 | func x86_incdec(out: *u8, o: i64, ext: i64, reg: i64) -> i64 |
| 922 | func x86_movb_imm(out: *u8, o: i64, base: i64, disp: i64, imm8: i64) -> i64 |
| 933 | func x86_movb_imm_reg(out: *u8, o: i64, reg: i64, imm8: i64) -> i64 |
| 944 | func x86_movb_store(out: *u8, o: i64, base: i64, disp: i64, src: i64) -> i64 |
| 955 | func x86_call_indirect(out: *u8, o: i64, reg: i64) -> i64 |
| 962 | func x86_jmp_indirect(out: *u8, o: i64, reg: i64) -> i64 |
| 976 | func x86_build_elf_at(code: *u8, code_len: i64, entry_off: i64, out: *u8) -> i64 |
| 1020 | func x86_build_elf(code: *u8, code_len: i64, out: *u8) -> i64 calls 1: x86_build_elf_at |