Minimize Instruction and Operand across ISAs further with struct #raw_union #packed

This commit is contained in:
gingerBill
2026-06-15 14:50:55 +01:00
parent 693fc1ec18
commit 9ec6f3e378
8 changed files with 17 additions and 18 deletions

View File

@@ -21,7 +21,7 @@ Instruction_Flags :: bit_field u8 {
}
Instruction :: struct #packed {
ops: [4]Operand `fmt:"v,operand_count"`, // 4 * 22 = 88
ops: [4]Operand `fmt:"v,operand_count"`, // 4 * 18 = 68
mnemonic: Mnemonic, // 2
cond: u8, // 0..15 (AL=14)
operand_count: u8, // 0..4
@@ -35,9 +35,9 @@ Instruction :: struct #packed {
// bits). User-constructed instructions leave it at 0; the encoder then
// falls back to first-shape-match. Stored as u16 over the two padding bytes.
form_id: u16,
_: [7]u8,
}
#assert(size_of(Instruction) == 97)
// 88 + 9 = 97 bytes (packed)
#assert(size_of(Instruction) == 88)
// =============================================================================
// Builders

View File

@@ -94,7 +94,7 @@ mem_reg_shift :: #force_inline proc "contextless" (
// ---- Operand structure -----------------------------------------------------
Operand :: struct #packed {
using _: struct #raw_union {
using _: struct #raw_union #packed {
reg: Register,
mem: Memory,
immediate: i64,
@@ -107,9 +107,7 @@ Operand :: struct #packed {
lane: u8, // SIMD lane index for DPR_ELEM / QPR_ELEM
cond: u8, // condition code 0..15 (default = AL = 14)
}
#assert(size_of(Operand) == 22)
// 16-byte raw_union (Memory is largest) + 6 bytes of trailing fields = 22 bytes
// (packed; no alignment padding).
#assert(size_of(Operand) == 18)
// ---- Operand builders ------------------------------------------------------

View File

@@ -16,8 +16,9 @@ Instruction :: struct #packed {
operand_count: u8, // 1
flags: Instruction_Flags, // 1
length: u8, // 1 -- always 4
_: [3]u8,
}
#assert(size_of(Instruction) == 77)
#assert(size_of(Instruction) == 64)
// =============================================================================
// Builders -- the most common shapes; less-common forms can be built

View File

@@ -89,7 +89,7 @@ Extended_Reg :: struct #packed {
// 16-byte tagged operand. The union holds whichever payload matches `kind`.
Operand :: struct #packed {
using _: struct #raw_union {
using _: struct #raw_union #packed {
reg: Register, // 2
mem: Memory, // 12
immediate: i64, // 8
@@ -97,11 +97,11 @@ Operand :: struct #packed {
shifted: Shifted_Reg, // 8
extended: Extended_Reg, // 8
cond: u8, // 1
}, // 16 total because of alignment
}, // 12 total because of alignment
kind: Operand_Kind, // 1
size: u8, // 1 -- carried width info; meaning varies
}
#assert(size_of(Operand) == 18)
#assert(size_of(Operand) == 14)
// -----------------------------------------------------------------------------
// Constructors -- generic

View File

@@ -20,7 +20,7 @@ Instruction_Flags :: bit_field u8 {
}
Instruction :: struct #packed {
ops: [4]Operand `fmt:"v,operand_count"`, // 4 * 18 = 68
ops: [4]Operand `fmt:"v,operand_count"`, // 4 * 14 = 56
mnemonic: Mnemonic, // 2
operand_count: u8, // 0..4
flags: Instruction_Flags, // 1
@@ -28,7 +28,7 @@ Instruction :: struct #packed {
length: u8, // 4 or 8 (prefixed)
form_id: u16, // 0 = no hint; otherwise 1 + form index
}
#assert(size_of(Instruction) == 80)
#assert(size_of(Instruction) == 64)
// =============================================================================
// Builders

View File

@@ -46,7 +46,7 @@ mem_x :: #force_inline proc "contextless" (base, index: Register) -> Memory {
}
Operand :: struct #packed {
using _: struct #raw_union {
using _: struct #raw_union #packed {
reg: Register,
mem: Memory,
immediate: i64,
@@ -55,7 +55,7 @@ Operand :: struct #packed {
kind: Operand_Kind,
size: u8, // operand size in bytes (4 = word, 8 = dword)
}
#assert(size_of(Operand) == 18)
#assert(size_of(Operand) == 14)
@(require_results)
op_reg :: #force_inline proc "contextless" (r: Register) -> Operand {

View File

@@ -26,7 +26,7 @@ Instruction :: struct #packed {
length: u8, // 2 or 4
form_id: u16,
}
#assert(size_of(Instruction) == 80)
#assert(size_of(Instruction) == 64)
@(require_results)
inst_none :: #force_inline proc "contextless" (m: Mnemonic) -> Instruction {

View File

@@ -31,7 +31,7 @@ mem_x :: #force_inline proc "contextless" (base, index: Register) -> Memory {
}
Operand :: struct #packed {
using _: struct #raw_union {
using _: struct #raw_union #packed {
reg: Register,
mem: Memory,
immediate: i64,
@@ -40,7 +40,7 @@ Operand :: struct #packed {
kind: Operand_Kind,
size: u8,
}
#assert(size_of(Operand) == 18)
#assert(size_of(Operand) == 14)
@(require_results)
op_reg :: #force_inline proc "contextless" (r: Register) -> Operand {