Add to the Encoding_Flags op_count and needs_modrm

This commit is contained in:
gingerBill
2026-06-15 22:58:06 +01:00
parent 9fead11180
commit 29594d1ed4
4 changed files with 2246 additions and 2232 deletions

View File

@@ -573,21 +573,14 @@ decode_opcode_vex :: #force_inline proc(state: ^Decoder_State) -> (entry: ^Decod
decode_operands :: proc(state: ^Decoder_State, entry: ^Decode_Entry) -> (inst: Instruction, err: Error_Code) {
inst.mnemonic = entry.mnemonic
// Check if we need ModR/M
needs_modrm := false
for enc in entry.enc {
if enc == .MR || enc == .REG || enc == .VVVV {
needs_modrm = true
break
}
}
modrm: u8 = 0
modrm_info: ModRM_Info
sib: u8 = 0
sib_info: SIB_Info
has_sib := false
needs_modrm := entry.flags.needs_modrm
if needs_modrm {
if state.position >= len(state.data) {
return {}, .BUFFER_TOO_SHORT
@@ -616,18 +609,16 @@ decode_operands :: proc(state: ^Decoder_State, entry: ^Decode_Entry) -> (inst: I
}
// Decode each operand
for op_type, i in entry.ops {
if op_type == .NONE {
break
}
op_count := entry.flags.op_count
for i in 0..<op_count {
op_enc := entry.enc[i]
// i386: default_64 entries have R64/RM64 operand types but
// really mean R32/RM32 in 32-bit mode (same encoded bytes).
effective := mode_rewrite_op_type(op_type, state.mode, entry.flags.default_64)
effective := mode_rewrite_op_type(entry.ops[i], state.mode, entry.flags.default_64)
inst.ops[i] = decode_single_operand(state, effective, op_enc, modrm_info, sib_info, has_sib) or_return
inst.operand_count += 1
}
inst.operand_count += op_count
return
}

View File

@@ -258,8 +258,12 @@ Encoding_Flags :: bit_field u32 {
rep_ok: bool | 1, // REP prefix valid
modrm_reg_ext: bool | 1, // ModR/M reg field is opcode extension (use ext field)
mode_32_only: bool | 1, // only valid in Mode._32 (e.g. short-form INC/DEC at 0x40-0x4F)
explicit_count: u8 | 3, // 0..<4 non-implicit operands
explicit_count: u8 | 2, // 0..<4 non-implicit operands
has_implicit: bool | 1, // any implicit operand
op_count: u8 | 2, // total operands including implicit (0..<4)
needs_modrm: bool | 1, // any enc is .MR/.REG/.VVVV
}
// -----------------------------------------------------------------------------

View File

@@ -228,7 +228,7 @@ gen_entries :: proc(sb: ^strings.Builder, name, typ: string, entries: []Collecte
strings.write_string(sb, "}, {")
for en, i in e.enc { print_enum_buffered(sb, en, 4, i+1 < len(e.enc)) }
strings.write_string(sb, "}, ")
write_flags(sb, nil, e.flags)
write_flags(sb, e, e.flags)
strings.write_string(sb, "},\n")
}
strings.write_string(sb, "}\n\n")
@@ -366,7 +366,7 @@ print_enum_buffered :: proc(sb: ^strings.Builder, x: $T, max_name: int, comma: b
// Complete Encoding_Flags emitter -- every field, so ENCODE_FORMS round-trips
// the SoT exactly (mode_32_only is read by the encoder).
write_flags :: proc(sb: ^strings.Builder, enc: Maybe(Encoding), flags: lib.Encoding_Flags) {
write_flags :: proc(sb: ^strings.Builder, enc: union{lib.Encoding, Collected_Entry}, flags: lib.Encoding_Flags) {
parts: [dynamic]string
defer delete(parts)
if flags.esc != .NONE { append(&parts, fmt.tprintf("esc=.%v", flags.esc)) }
@@ -382,7 +382,8 @@ write_flags :: proc(sb: ^strings.Builder, enc: Maybe(Encoding), flags: lib.Encod
if flags.modrm_reg_ext { append(&parts, "modrm_reg_ext=true") }
if flags.mode_32_only { append(&parts, "mode_32_only=true") }
if e, ok := enc.?; ok {
switch e in enc {
case lib.Encoding:
encoding_operand_count: u8 = 0
has_implict := false
for op_type in e.ops {
@@ -399,6 +400,24 @@ write_flags :: proc(sb: ^strings.Builder, enc: Maybe(Encoding), flags: lib.Encod
if has_implict {
append(&parts, "has_implict=true")
}
case Collected_Entry:
op_count: u8 = 0
needs_modrm := false
for t, i in e.ops {
if t == .NONE { break }
op_count += 1
enc := e.enc[i]
if enc == .MR || enc == .REG || enc == .VVVV {
needs_modrm = true
}
}
if op_count > 0 {
append(&parts, fmt.tprintf("op_count=%d", op_count))
}
if needs_modrm {
append(&parts, "needs_modrm=true")
}
}
strings.write_string(sb, "{")

File diff suppressed because it is too large Load Diff