From 446848dffb8ed10e53e0d97c501f1eb5e104e313 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Fri, 21 Feb 2025 23:35:24 +0700 Subject: [PATCH] Generalizing data and operand bracketing, to make add instrunction work --- decoder8086.odin | 71 ++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/decoder8086.odin b/decoder8086.odin index adc7e9d..6afae9a 100644 --- a/decoder8086.odin +++ b/decoder8086.odin @@ -61,8 +61,9 @@ InstructionInfo :: struct { has_displacement: bool, has_segreg: bool, has_flip: bool, + has_bracketed_immediate: bool, has_explicit_size: bool, - has_accumulator: bool, + has_sign_extension: bool, } reg_first_last := RegInfo{ in_first_byte = true, shift_offset = 0 } @@ -74,22 +75,28 @@ instructions := [?]InstructionInfo { word_size = LastBit{}, has_flip = true }, { name = "mov", desc = "Immediate to register/memory", mask = 0b11111110, encoding = 0b11000110, has_mod_rm = true, reg_info = nil, has_data = true, has_displacement = true, - word_size = LastBit{}, has_explicit_size = true }, + word_size = LastBit{}, has_bracketed_immediate = false, has_explicit_size = true }, { name = "mov", desc = "Immediate to register", mask = 0b11110000, encoding = 0b10110000, has_mod_rm = false, reg_info = reg_first_last, has_data = true, has_displacement = false, word_size = FourthBit{} }, { name = "mov", desc = "Memory to accumulator", mask = 0b11111110, encoding = 0b10100000, has_mod_rm = false, reg_info = nil, has_data = true, has_displacement = false, has_flip = true, - word_size = LastBit{}, has_accumulator = true }, + word_size = LastBit{}, has_bracketed_immediate = true }, { name = "mov", desc = "Accumulator to memory", mask = 0b11111110, encoding = 0b10100010, has_mod_rm = false, reg_info = nil, has_data = true, has_displacement = false, has_flip = true, - word_size = LastBit{}, has_accumulator = true }, + word_size = LastBit{}, has_bracketed_immediate = true }, { name = "mov", desc = "Register/memory to segment register", mask = 0b11111111, encoding = 0b10001110, has_mod_rm = true, reg_info = nil, has_segreg = true, has_displacement = true, word_size = None{} }, { name = "mov", desc = "Segment register to register/memory", mask = 0b11111111, encoding = 0b10001100, has_mod_rm = true, reg_info = nil, has_segreg = true, has_displacement = true, word_size = None{} }, + { name = "add", desc = "Register/memory to/from register", mask = 0b11111100, encoding = 0b00000000, + has_mod_rm = true, reg_info = reg_second_middle, has_data = false, has_displacement = true, + word_size = LastBit{}, has_flip = true }, + { name = "add", desc = "Immediate to register/memory", mask = 0b11111110, encoding = 0b10000000, + has_mod_rm = true, reg_info = nil, has_data = true, has_displacement = true, + word_size = LastBit{}, has_sign_extension = true }, } None :: struct {} @@ -129,17 +136,11 @@ MemoryAddr :: struct { addr_id: u8, displacement: Displacement } -DirectAddress :: distinct i16 -Accumulator8 :: distinct i8 -Accumulator16 :: distinct i16 OperandType :: union { RegisterId, Immediate8, Immediate16, MemoryAddr, - DirectAddress, - Accumulator8, - Accumulator16, } inst_map := make(map[u8]InstructionInfo) @@ -186,24 +187,19 @@ get_memory_string :: proc(memoryAddr: MemoryAddr) -> string { return text } -get_memory_type_string :: proc(mem_type: OperandType, is_word: bool) -> string { +get_memory_type_string :: proc(mem_type: OperandType, is_word: bool, bracketed: bool) -> string { + string_val: string switch val in mem_type { case RegisterId: - return is_word ? registers[val].fullname : registers[val].bytename + string_val = is_word ? registers[val].fullname : registers[val].bytename case Immediate8: - return fmt.aprintf("%d", val) + string_val = fmt.aprintf(bracketed ? "[%d]" : "%d", val) case Immediate16: - return fmt.aprintf("%d", val) + string_val = fmt.aprintf(bracketed ? "[%d]" : "%d", val) case MemoryAddr: - return get_memory_string(val) - case DirectAddress: - return fmt.aprintf("[%d]", val) - case Accumulator8: - return fmt.aprintf("[%d]", val) - case Accumulator16: - return fmt.aprintf("[%d]", val) + string_val = get_memory_string(val) } - return "" + return string_val } get_i16 :: proc(data: []u8) -> i16 { @@ -285,7 +281,6 @@ main :: proc() { processed := 1 curr_byte := data[idx] - instruction, ok := try_find_instruction(curr_byte) if !ok { txt := "unknown instruction" @@ -299,6 +294,7 @@ main :: proc() { is_word: bool is_immediate := false flip_dst := false + bracket_operand := instruction.has_bracketed_immediate rm: u8 mod: u8 reg: u8 @@ -318,15 +314,19 @@ main :: proc() { reg = (b >> reg_info.shift_offset) & 0b111 } + data_idx := idx + 1 + if instruction.has_mod_rm { mod = data[idx+1] >> 6 rm = data[idx+1] & 0b00000111 + data_idx += 1 + ((int)(mod) % 3) processed += 1 + ((int)(mod) % 3) if mod == 0 { if rm == 0b110 { - lhs2 = (DirectAddress)(get_i16(data[idx+2:])) + lhs2 = (Immediate16)(get_i16(data[idx+2:])) + bracket_operand = true processed += 2 } else { lhs2 = MemoryAddr{ addr_id = rm , displacement = None{} } @@ -338,32 +338,25 @@ main :: proc() { } else if mod == 3 { lhs2 = (RegisterId)(registers[rm].code) } - if instruction.has_explicit_size { - imm_idx := idx + 2 + ((int)(mod) % 3) - rhs2 = (OperandType)(is_word ? (Immediate16)(get_i16(data[imm_idx:])) : (Immediate8)(data[imm_idx])) - processed += is_word ? 2 : 1 - } else { - rhs2 = (RegisterId)(reg) - } } else { lhs2 = (RegisterId)(registers[reg].code) - if instruction.has_accumulator { - rhs2 = (OperandType)(is_word ? ((Accumulator16)(get_i16(data[idx+1:]))) : ((Accumulator8)(data[idx+1]))) - } else { - rhs2 = (OperandType)(is_word ? ((Immediate16)(get_i16(data[idx+1:]))) : ((Immediate8)(data[idx+1]))) - } + } + if instruction.has_data { processed += is_word ? 2 : 1 + rhs2 = (OperandType)(is_word ? (Immediate16)(get_i16(data[data_idx:])) : (Immediate8)(data[data_idx])) + } else { + rhs2 = (RegisterId)(reg) } if flip_dst { lhs2, rhs2 = rhs2, lhs2 } - lhs := get_memory_type_string(lhs2, is_word) - rhs := get_memory_type_string(rhs2, is_word) + lhs := get_memory_type_string(lhs2, is_word, bracket_operand) + rhs := get_memory_type_string(rhs2, is_word, bracket_operand) size_string := instruction.has_explicit_size ? is_word ? "word " : "byte " : "" full_inst := fmt.aprintf("%s %s, %s%s", instruction.name, lhs, size_string, rhs) - fmt.printf("%s %*[1]s a", full_inst, RIGHT_ALIGN_AMOUNT - len(full_inst), ";;") + fmt.printf("%s %*[1]s", full_inst, RIGHT_ALIGN_AMOUNT - len(full_inst), ";;") for i in 0..