mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-19 08:32:33 +00:00
Add to the Encoding_Flags op_count and needs_modrm
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user