Update doc files

This commit is contained in:
gingerBill
2026-06-14 18:24:59 +01:00
parent a116f69b7e
commit c49e296f5e
6 changed files with 253 additions and 252 deletions

View File

@@ -207,25 +207,25 @@ for an **opt-in** facade (§5.3) that only multi-target *tools* pay for.
```
rexcode/
isa/ # shared, architecture-independent core
labels.odin # Label, Label_Definition, Label_Map, resolution
reloc.odin # Relocation (type field is generic/u8)
status.odin # Result, Error, shared Error_Code core
print.odin # Token, Token_Kind, Print_Options, sinks, num-fmt
register.odin # distinct-u16 layout convention + reg_hw/reg_class
pipeline.odin # parametric encode_stream/decode_stream (§7)
target.odin # optional runtime Target vtable (§5.3)
labels.odin # Label, Label_Definition, Label_Map, resolution
reloc.odin # Relocation (type field is generic/u8)
status.odin # Result, Error, shared Error_Code core
print.odin # Token, Token_Kind, Print_Options, sinks, num-fmt
register.odin # distinct-u16 layout convention + reg_hw/reg_class
pipeline.odin # parametric encode_stream/decode_stream (§7)
target.odin # optional runtime Target vtable (§5.3)
x86/ # exists today; refactor to import isa
registers.odin operands.odin instructions.odin mnemonics.odin
encoding_types.odin encoder.odin decoder.odin printer.odin
encoding_table.odin decoding_tables.odin mnemonic_builders.odin
tests/ tools/
registers.odin operands.odin instructions.odin mnemonics.odin
encoding_types.odin encoder.odin decoder.odin printer.odin
encoding_table.odin decoding_tables.odin mnemonic_builders.odin
tests/ tools/
riscv/ # next: same shape as x86/
registers.odin operands.odin instructions.odin mnemonics.odin
encoding_types.odin encoder.odin decoder.odin printer.odin
encoding_table.odin decoding_tables.odin mnemonic_builders.odin
tests/ tools/
registers.odin operands.odin instructions.odin mnemonics.odin
encoding_types.odin encoder.odin decoder.odin printer.odin
encoding_table.odin decoding_tables.odin mnemonic_builders.odin
tests/ tools/
arm64/ mips/ … # future, same template
```
@@ -269,11 +269,11 @@ provides a vtable populated by each arch:
```odin
// isa/target.odin
Target :: struct {
name: string,
decode: proc(data: []u8, out: ^Decoded) -> Result, // bytes → generic Decoded
print: proc(d: ^Decoded, opts: ^Print_Options) -> string,
inst_align: u32, // 1 for x86, 4 for riscv/arm64/mips
max_inst: u32, // 15 for x86, 4 for riscv (8 for C-pairs), 4 for arm64
name: string,
decode: proc(data: []u8, out: ^Decoded) -> Result, // bytes → generic Decoded
print: proc(d: ^Decoded, opts: ^Print_Options) -> string,
inst_align: u32, // 1 for x86, 4 for riscv/arm64/mips
max_inst: u32, // 15 for x86, 4 for riscv (8 for C-pairs), 4 for arm64
}
// each arch: x86.TARGET: isa.Target = { … }
```
@@ -323,7 +323,7 @@ Builder names spell out each operand kind separated by underscores
```
inst_none / inst_r / inst_r_r / inst_r_i / inst_r_m / inst_m_r / …
emit_none / emit_r / emit_rr / emit_ri / emit_rm / emit_mr / …
# NB: emit_* uses concatenated suffixes (legacy x86 spelling)
# NB: emit_* uses concatenated suffixes (legacy x86 spelling)
inst_<mnemonic>(…) / emit_<mnemonic>(…) # generated typed overloads
```
@@ -339,8 +339,8 @@ decode(data: []u8, relocs: []Relocation,
label_defs: ^[dynamic]Label_Definition, errors: ^[dynamic]Error) -> Result
print/println/aprint/tprint/bprint/fprint/wprint(+ln)(
instructions: []Instruction, inst_info: []Instruction_Info,
label_defs: []Label_Definition, tokens=nil, options=nil, label_names=nil)
instructions: []Instruction, inst_info: []Instruction_Info,
label_defs: []Label_Definition, tokens=nil, options=nil, label_names=nil)
```
### Register/label/print helpers
@@ -366,18 +366,19 @@ these at compile time → **no runtime cost, real code sharing.**
```odin
// isa/pipeline.odin (sketch)
encode_stream :: proc(
instructions: []$I,
label_defs: []Label_Definition,
code: []u8,
relocs: ^[dynamic]Relocation,
errors: ^[dynamic]Error,
encode_one: proc(inst: ^I, out: []u8, code_pos: u32,
relocs: ^[dynamic]Relocation, errors: ^[dynamic]Error) -> (n: u32, ok: bool),
resolve := true, base_address: u64 = 0,
instructions: []$I,
label_defs: []Label_Definition,
code: []u8,
relocs: ^[dynamic]Relocation,
errors: ^[dynamic]Error,
encode_one: proc(inst: ^I, out: []u8, code_pos: u32,
relocs: ^[dynamic]Relocation, errors: ^[dynamic]Error) -> (n: u32, ok: bool),
resolve := true,
base_address: u64 = 0,
) -> Result {
// PASS 1: for each inst → record offset, call encode_one, advance
// PASS 1.5: rewrite label_defs inst-index → byte-offset (identical on every arch)
// PASS 2: resolve relocations / patch / spill unresolved (identical on every arch)
// PASS 1: for each inst → record offset, call encode_one, advance
// PASS 1.5: rewrite label_defs inst-index → byte-offset (identical on every arch)
// PASS 2: resolve relocations / patch / spill unresolved (identical on every arch)
}
```

View File

@@ -110,16 +110,16 @@ Operand_Kind :: enum u8 { NONE, REGISTER, MEMORY, IMMEDIATE, RELATIVE }
```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,
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,
}
MEM_BASE_RIP :: 30 MEM_BASE_NONE :: 31 MEM_INDEX_NONE :: 31
```
@@ -143,25 +143,25 @@ MEM_BASE_RIP :: 30 MEM_BASE_NONE :: 31 MEM_INDEX_NONE :: 31
```odin
Operand :: struct #packed { // 16 bytes
using _: struct #raw_union {
reg: Register,
mem: Memory,
immediate: i64,
relative: i64, // offset or label id
},
kind: Operand_Kind,
size: u8, // operand size in bytes (1,2,4,8,16,32,64)
flags: Operand_Flags,
_pad: [4]u8,
using _: struct #raw_union {
reg: Register,
mem: Memory,
immediate: i64,
relative: i64, // offset or label id
},
kind: Operand_Kind,
size: u8, // operand size in bytes (1,2,4,8,16,32,64)
flags: Operand_Flags,
_: [4]u8,
}
Broadcast :: enum u8 { NONE, B1TO2, B1TO4, B1TO8, B1TO16 } // EVEX
Operand_Flags :: bit_field u16 { // EVEX-specific
mask: u8 | 3, // opmask K1K7
zeroing: bool | 1, // merge vs zero masking
broadcast: Broadcast | 3,
er_sae: u8 | 2, // embedded rounding / SAE
mask: u8 | 3, // opmask K1K7
zeroing: bool | 1, // merge vs zero masking
broadcast: Broadcast | 3,
er_sae: u8 | 2, // embedded rounding / SAE
}
```
@@ -189,12 +189,12 @@ Instruction_Flags :: bit_field u8 {
}
Instruction :: struct #packed { // 72 bytes
ops: [4]Operand,
mnemonic: Mnemonic,
operand_count: u8,
flags: Instruction_Flags,
length: u8, // filled by decoder
_pad: [3]u8,
ops: [4]Operand,
mnemonic: Mnemonic,
operand_count: u8,
flags: Instruction_Flags,
length: u8, // filled by decoder
_: [3]u8,
}
```
@@ -278,16 +278,16 @@ These describe **how** an instruction is encoded; they are the schema of
```odin
Operand_Type :: enum u8 { // ~70 values
NONE, R8,R16,R32,R64, RM8,RM16,RM32,RM64, M,M8..M512,
IMM8,IMM16,IMM32,IMM64, IMM8SX, REL8,REL32,
AL_IMPL,AX_IMPL,EAX_IMPL,RAX_IMPL,CL_IMPL,DX_IMPL,ONE_IMPL,
SREG, CR, DR, XMM,YMM,ZMM, XMM_M32,XMM_M64,XMM_M128,YMM_M256,ZMM_M512,
MM,MM_M64, ST0_IMPL,STI, XMM0_IMPL, K,K_M8..K_M64,
MOFFS8..MOFFS64, PTR16_16,PTR16_32,PTR16_64, M16_16,M16_32,M16_64,
NONE, R8,R16,R32,R64, RM8,RM16,RM32,RM64, M,M8..M512,
IMM8,IMM16,IMM32,IMM64, IMM8SX, REL8,REL32,
AL_IMPL,AX_IMPL,EAX_IMPL,RAX_IMPL,CL_IMPL,DX_IMPL,ONE_IMPL,
SREG, CR, DR, XMM,YMM,ZMM, XMM_M32,XMM_M64,XMM_M128,YMM_M256,ZMM_M512,
MM,MM_M64, ST0_IMPL,STI, XMM0_IMPL, K,K_M8..K_M64,
MOFFS8..MOFFS64, PTR16_16,PTR16_32,PTR16_64, M16_16,M16_32,M16_64,
}
Operand_Encoding :: enum u8 { // where an operand's bits go
NONE, MR, REG, VVVV, OP_R, IB,IW,ID,IQ, IMPL, IS4, AAA,
NONE, MR, REG, VVVV, OP_R, IB,IW,ID,IQ, IMPL, IS4, AAA,
}
Escape :: enum u8 { NONE, _0F, _0F38, _0F3A }
@@ -296,14 +296,26 @@ VEX_W :: enum u8 { WIG, W0, W1 }
VEX_L :: enum u8 { LIG, L0, L1, L2 }
Encoding_Flags :: bit_field u16 {
esc: Escape|2, prefix: u8|2, vex_type: VEX_Type|2, vex_w: VEX_W|2,
vex_l: VEX_L|2, default_64: bool|1, force_rex_w: bool|1, no_rex: bool|1,
lock_ok: bool|1, rep_ok: bool|1, modrm_reg_ext: bool|1,
esc: Escape | 2,
prefix: u8 | 2,
vex_type: VEX_Type | 2,
vex_w: VEX_W | 2,
vex_l: VEX_L | 2,
default_64: bool | 1,
force_rex_w: bool | 1,
no_rex: bool | 1,
lock_ok: bool | 1,
rep_ok: bool | 1,
modrm_reg_ext: bool | 1,
}
Encoding :: struct #packed { // 14 bytes — one encoding form
mnemonic: Mnemonic, ops: [4]Operand_Type, enc: [4]Operand_Encoding,
opcode: u8, ext: u8, flags: Encoding_Flags,
mnemonic: Mnemonic,
ops: [4]Operand_Type,
enc: [4]Operand_Encoding,
opcode: u8,
ext: u8,
flags: Encoding_Flags,
}
PREFIX_66 :: 1 PREFIX_F3 :: 2 PREFIX_F2 :: 3
```
@@ -314,19 +326,19 @@ Helper: `encoding_flags(esc=…, prefix=…, …) -> Encoding_Flags`.
```odin
Relocation_Type :: enum u8 { NONE, REL8, REL32, ABS32, ABS64 }
Relocation :: struct #packed { // 16 bytes (ELF-rela-like)
offset: u32, label_id: u32, addend: i32,
type: Relocation_Type, size: u8, inst_idx: u16,
offset: u32, label_id: u32, addend: i32,
type: Relocation_Type, size: u8, inst_idx: u16,
}
Error_Code :: enum u8 {
NONE,
// encode
INVALID_MNEMONIC, NO_MATCHING_ENCODING, OPERAND_MISMATCH,
IMMEDIATE_OUT_OF_RANGE, BUFFER_OVERFLOW, LABEL_OUT_OF_RANGE,
INVALID_OPERAND_COUNT,
// decode
BUFFER_TOO_SHORT, INVALID_OPCODE, INVALID_MODRM, INVALID_SIB,
INVALID_PREFIX, INVALID_VEX, INVALID_EVEX, TOO_MANY_PREFIXES,
NONE,
// encode
INVALID_MNEMONIC, NO_MATCHING_ENCODING, OPERAND_MISMATCH,
IMMEDIATE_OUT_OF_RANGE, BUFFER_OVERFLOW, LABEL_OUT_OF_RANGE,
INVALID_OPERAND_COUNT,
// decode
BUFFER_TOO_SHORT, INVALID_OPCODE, INVALID_MODRM, INVALID_SIB,
INVALID_PREFIX, INVALID_VEX, INVALID_EVEX, TOO_MANY_PREFIXES,
}
Error :: struct #packed { inst_idx: u32, code: Error_Code, _pad: [3]u8 } // 8 bytes
Result :: struct { byte_count: u32, success: bool }
@@ -341,13 +353,13 @@ Helper: `op_type_to_size(Operand_Type) -> u8`.
MAX_INST_SIZE :: 15
encode :: proc(
instructions: []Instruction,
label_defs: []Label_Definition, // in: inst index; MODIFIED to byte offsets
code: []u8, // output machine code
relocs: ^[dynamic]Relocation, // unresolved relocations appended
errors: ^[dynamic]Error,
resolve: bool = true, // patch resolvable relocs in place
base_address: u64 = 0, // for ABS relocations
instructions: []Instruction,
label_defs: []Label_Definition, // in: inst index; MODIFIED to byte offsets
code: []u8, // output machine code
relocs: ^[dynamic]Relocation, // unresolved relocations appended
errors: ^[dynamic]Error,
resolve: bool = true, // patch resolvable relocs in place
base_address: u64 = 0, // for ABS relocations
) -> Result
```
@@ -371,19 +383,19 @@ Internal matcher (file-local, inlined): `encoding_matches_inline`,
```odin
Instruction_Info :: struct { // parallel metadata, one per decoded inst
offset: u32,
rex: u8, has_lock: bool, rep: Rep, segment: Register,
vex_type: VEX_Type, vex_l: VEX_L, vex_w: VEX_W,
evex_b: bool, evex_z: bool, opmask: u8,
offset: u32,
rex: u8, has_lock: bool, rep: Rep, segment: Register,
vex_type: VEX_Type, vex_l: VEX_L, vex_w: VEX_W,
evex_b: bool, evex_z: bool, opmask: u8,
}
decode :: proc(
data: []u8,
relocs: []Relocation, // optional in: name labels
instructions: ^[dynamic]Instruction, // out
inst_info: ^[dynamic]Instruction_Info, // out (parallel)
label_defs: ^[dynamic]Label_Definition, // out: inferred branch labels
errors: ^[dynamic]Error,
data: []u8,
relocs: []Relocation, // optional in: name labels
instructions: ^[dynamic]Instruction, // out
inst_info: ^[dynamic]Instruction_Info, // out (parallel)
label_defs: ^[dynamic]Label_Definition, // out: inferred branch labels
errors: ^[dynamic]Error,
) -> Result
```
@@ -406,15 +418,15 @@ Modified Intel syntax: size suffix on the mnemonic (`.b .w .d .q .x .y
```odin
Token_Kind :: enum u8 { WHITESPACE, NEWLINE, LABEL_DEF, LABEL_REF, OFFSET,
MNEMONIC, REGISTER, IMMEDIATE, MEMORY_BRACKET, MEMORY_OPERATOR,
MEMORY_DISP, MEMORY_SCALE, PUNCTUATION, COMMENT }
MNEMONIC, REGISTER, IMMEDIATE, MEMORY_BRACKET, MEMORY_OPERATOR,
MEMORY_DISP, MEMORY_SCALE, PUNCTUATION, COMMENT }
Token :: struct { offset: u32, length: u16, kind: Token_Kind, instruction_index: u16 }
Print_Options :: struct {
uppercase: bool, hex_prefix: string, hex_lowercase: bool,
label_prefix: string, show_offsets: bool, indent: string,
separator: string, space_after_comma: bool,
uppercase: bool, hex_prefix: string, hex_lowercase: bool,
label_prefix: string, show_offsets: bool, indent: string,
separator: string, space_after_comma: bool,
}
DEFAULT_PRINT_OPTIONS :: Print_Options{ }