# rexcode `x86` — Complete API Extraction > Snapshot of the entire public surface of the `x86` subpackage > (`rexcode/x86/`), grouped by module. This is the reference the > cross-architecture design ([cross_arch_design.md](cross_arch_design.md)) > is built against. The package is **table-driven**: a hand-written master encoding table (`ENCODING_TABLE`, in `tablegen/`) is the single source of truth, from which the encode/decode tables (committed binary blobs, `#load`ed into `@(rodata)`) and the typed builder procedures are *generated*. The runtime is zero-allocation (caller owns every buffer) and the hot paths are fully inlined. ``` ENCODING_TABLE (hand-written, source of truth) │ ┌───────────────┼────────────────┐ tablegen (2-stage) gen_mnemonic_builders │ │ tables/*.bin → tables.odin mnemonic_builders.odin (#loaded into @(rodata)) (typed inst_*/emit_* helpers) ``` Pipeline at a glance: ``` []Instruction ──encode()──▶ []u8 (+ []Relocation, []Error) ▲ │ │ ▼ builders decode() │ │ inst_*/emit_* ▼ []Instruction + []Instruction_Info + []Label_Definition │ ▼ print()/tprint()/… ──▶ text (+ []Token) ``` --- ## 1. Registers (`registers.odin`) ### Core type ```odin Register :: distinct u16 // bit layout: 0b_0000_CCCC_EEEN_NNNN // NNNNN = hardware register number (0–31) // E = needs REX/VEX .B/.R/.X extension (hw >= 8) // EE = needs EVEX (hw 16–31) // CCCC = register class (high byte) ``` ### Class constants (high byte) `REG_NONE`, `REG_GPR64`, `REG_GPR32`, `REG_GPR16`, `REG_GPR8`, `REG_GPR8H` (legacy AH/CH/DH/BH), `REG_XMM`, `REG_YMM`, `REG_ZMM`, `REG_K` (opmask), `REG_SEG`, `REG_CR` (control), `REG_DR` (debug), `REG_BND` (MPX), `REG_MM` (MMX), `REG_ST` (x87). ### Sentinels `NONE :: Register(0xFFFF)`, `RIP :: Register(0xFFFE)`. ### Typed register enums (compile-time safety, value == hardware number) `GPR64`, `GPR32`, `GPR16`, `GPR8`, `GPR8H` (`AH=4..BH=7`), `XMM`, `YMM`, `ZMM` (each 0–31), `KREG` (K0–K7), `SREG` (ES,CS,SS,DS,FS,GS), `MM` (MM0–7), `CREG` (CR0,2,3,4,8), `DREG` (DR0–3,6,7), `ST` (ST0–7), `BND` (BND0–3). ### Named register constants Every register has a package-level constant: `RAX`…`R15`, `EAX`…`R15D`, `AX`…`R15W`, `AL`…`R15B`, `AH/CH/DH/BH`, `XMM0`…`XMM31`, `YMM0`…`YMM31`, `ZMM0`…`ZMM31`, `K0`…`K7`, `ES/CS/SS/DS/FS/GS`, `CR0/2/3/4/8`, `DR0/1/2/3/6/7`, `BND0`…`BND3`, `MM0`…`MM7`, `ST0`…`ST7`, plus `RIP`. ### Utility functions (all branchless, `contextless`) | Proc | Signature | Purpose | |---|---|---| | `reg_hw` | `(Register) -> u8` | hardware number (low 5 bits) | | `reg_class` | `(Register) -> u16` | class (high byte) | | `reg_needs_rex` | `(Register) -> bool` | hw >= 8 | | `reg_needs_rex_ext` | `(Register) -> bool` | hw >= 8 and class < K | | `reg_needs_evex` | `(Register) -> bool` | hw >= 16 | | `reg_is_gpr` | `(Register) -> bool` | any GPR class | | `reg_is_vector` | `(Register) -> bool` | XMM/YMM/ZMM | | `reg_is_high_byte` | `(Register) -> bool` | AH/CH/DH/BH | | `reg_size` | `(Register) -> u16` | size in **bits** | ### Register-from-number constructors `gpr64_from_num`, `gpr32_from_num`, `gpr16_from_num` `(u8) -> Register`; `gpr8_from_num(num: u8, has_rex: bool) -> Register` (handles AH↔SPL aliasing); `xmm_from_num`, `ymm_from_num`, `zmm_from_num`, `mm_from_num`. Each returns `NONE` if out of range. Pure casts, no table. --- ## 2. Operands (`operands.odin`) ### Operand kind ```odin Operand_Kind :: enum u8 { NONE, REGISTER, MEMORY, IMMEDIATE, RELATIVE } ``` ### Memory operand (packed) ```odin Memory :: bit_field u64 { base_hw: u8 | 5, base_ext: bool | 1, index_hw: u8 | 5, index_ext: bool | 1, scale_enc: u8 | 2, displacement: i32 | 32, segment: u8 | 3, addr_size_override: bool | 1, base_class: u8 | 5, index_class: u8 | 5, disp_is_label: bool | 1, // disp holds a label id -> REL32 relocation } MEM_BASE_RIP :: 30 MEM_BASE_NONE :: 31 MEM_INDEX_NONE :: 31 ``` **Constructor:** `mem_make(base, index: Register, scale: u8, displacement: i32, segment: Register) -> Memory` **Convenience constructors** (current names after the in-tree refactor): `mem_base_only(base)`, `mem_base_disp(base, disp)`, `mem_base_index(base, index, scale)`, `mem_base_index_disp(base, index, scale, disp)`, `mem_rip_disp(disp)`, `mem_rip_label(label_id)`. > **Label addressing.** `mem_rip_label(label_id)` builds a RIP-relative operand > whose displacement references a **label** rather than a literal: the encoder > writes a placeholder disp32 and emits a `REL32` relocation for `label_id` at > that field (addend 0), exactly as the `.RELATIVE` jump/call path does. This is > how `lea reg, [rip +