diff --git a/decoder8086.odin b/decoder8086.odin index 6d1a0fc..ca8f3e7 100644 --- a/decoder8086.odin +++ b/decoder8086.odin @@ -97,7 +97,8 @@ Immediate8 :: distinct i8 Immediate16 :: distinct i16 MemoryAddr :: struct { addr_id: u8, - displacement: Displacement + displacement: Displacement, + segment: Maybe(Register), } DirectAddress :: distinct i16 SegmentRegister :: distinct i8 @@ -194,35 +195,12 @@ get_memory_string :: proc(memoryAddr: MemoryAddr) -> string { disp = fmt.aprintf(" %s %d", value > 0 ? "+" : "-", math.abs(value)) } } - text := fmt.aprintf("[%s%s]", calculate_effective_address(memoryAddr.addr_id), disp) - return text -} - -get_operand_string :: proc(operand: Operand, is_word: bool) -> string { - string_val: string - switch val in operand { - case None: - string_val = "" - case RegisterId: - string_val = is_word ? registers[val].fullname : registers[val].bytename - case Immediate8: - string_val = fmt.aprintf("%d", val) - case Immediate16: - string_val = fmt.aprintf("%d", val) - case MemoryAddr: - string_val = get_memory_string(val) - case DirectAddress: - string_val = fmt.aprintf("[%d]", val) - case SegmentRegister: - string_val = segment_registers[val].fullname - case Jump: - string_val = fmt.aprintf("$%s%d", val >= 0 ? "+" : "", val) - case VariablePort: - string_val = variable_port.fullname - case Repeat: - string_val = (string)(val) + seg_string: string + if segreg, ok := memoryAddr.segment.?; ok { + seg_string = fmt.aprintf("%s:", segreg.fullname) } - return string_val + text := fmt.aprintf("%s[%s%s]", seg_string, calculate_effective_address(memoryAddr.addr_id), disp) + return text } get_i16 :: proc(data: []u8) -> i16 { @@ -336,7 +314,7 @@ get_opname :: proc(opname: OpName, data: []u8) -> string { return name } -parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, processed: ^int, word: bool) -> Operand { +parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, processed: ^int, word: bool, has_segreg: Maybe(Register)) -> Operand { operand: Operand = None{} switch opinfo { case .None: @@ -383,13 +361,13 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr op = (DirectAddress)(get_i16(data[2:])) processed^ += 2 } else { - op = MemoryAddr{ addr_id = rm , displacement = None{} } + op = MemoryAddr{ addr_id = rm , displacement = None{} , segment = has_segreg } } } else if mod == 1 { - op = MemoryAddr{ addr_id = rm , displacement = (i8)(data[2]) } + op = MemoryAddr{ addr_id = rm , displacement = (i8)(data[2]) , segment = has_segreg } processed^ += 1 } else if mod == 2 { - op = MemoryAddr{ addr_id = rm , displacement = get_i16(data[2:]) } + op = MemoryAddr{ addr_id = rm , displacement = get_i16(data[2:]) , segment = has_segreg } processed^ += 2 } else if mod == 3 { op = (RegisterId)(registers[rm].code) @@ -424,6 +402,33 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr return operand } +get_operand_string :: proc(operand: Operand, is_word: bool) -> string { + string_val: string + switch val in operand { + case None: + string_val = "" + case RegisterId: + string_val = is_word ? registers[val].fullname : registers[val].bytename + case Immediate8: + string_val = fmt.aprintf("%d", val) + case Immediate16: + string_val = fmt.aprintf("%d", val) + case MemoryAddr: + string_val = get_memory_string(val) + case DirectAddress: + string_val = fmt.aprintf("[%d]", val) + case SegmentRegister: + string_val = segment_registers[val].fullname + case Jump: + string_val = fmt.aprintf("$%s%d", val >= 0 ? "+" : "", val) + case VariablePort: + string_val = variable_port.fullname + case Repeat: + string_val = (string)(val) + } + return string_val +} + main :: proc() { f,err := os.open(os.args[1]) if err != os.ERROR_NONE { @@ -452,7 +457,7 @@ main :: proc() { added_label := false line_count := 0 has_lock: bool - has_segment: bool + has_segment: Maybe(Register) last_opname: [3]byte repeating_op_count := 0 instruction_builder := strings.builder_make() @@ -482,11 +487,11 @@ main :: proc() { idx += 1 continue } else if inst.opname == .SEGMENT { - has_segment = true + reg := (curr_byte & 0b11000) >> 3 + has_segment = segment_registers[reg] idx += 1 continue } - has_segment = false src_opr: Operand dst_opr: Operand @@ -518,8 +523,8 @@ main :: proc() { opname = strings.to_lower(fmt.aprintf("%s", inst.opname)) } - dst_opr = parse_operand(inst, inst.dst, data[idx:], &processed, word) - src_opr = parse_operand(inst, inst.src, data[idx:], &processed, word) + dst_opr = parse_operand(inst, inst.dst, data[idx:], &processed, word, has_segment) + src_opr = parse_operand(inst, inst.src, data[idx:], &processed, word, has_segment) // TODO: This is ugly as hell _,ok_1 := src_opr.(Immediate8) @@ -558,8 +563,11 @@ main :: proc() { processed += inst.consume_extra_bytes - // fmt.sbprintf(&instruction_builder, "%s%s%s %*[2]s", lock_string, seg_string, full_inst, RIGHT_ALIGN_AMOUNT - len(full_inst), ";;") - fmt.sbprintf(&instruction_builder, "%s %*[1]s", full_inst, RIGHT_ALIGN_AMOUNT - len(full_inst), ";;") + lock_string: string + if has_lock { + lock_string = "lock " + } + fmt.sbprintf(&instruction_builder, "%s%s %*[2]s", lock_string, full_inst, RIGHT_ALIGN_AMOUNT - len(full_inst), ";;") for i in 0..