From ea7b65994b1143a841e5d2aff14cc609e9c5fb1d Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sat, 22 Mar 2025 15:20:48 +0700 Subject: [PATCH] Fix IN and OUT instructions decoding --- decoding.odin | 11 +++++++++-- instructions.odin | 11 ++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/decoding.odin b/decoding.odin index 2c9958a..644b616 100644 --- a/decoding.odin +++ b/decoding.odin @@ -128,7 +128,7 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr operand = Immediate { value = i16(data[processed^]), size = .Unsigned8 } processed^ += 1 case .Accumulator: - operand = RegisterId { name = Register(0), access = word ? .Full : .Low } + operand = RegisterId { name = .ax, access = word ? .Full : .Low } case .DirectAddress: // operand = DirectAddress { value = get_i16(data[1:]) } operand = (DirectAddress)(get_i16(data[1:])) @@ -138,7 +138,14 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr // NOTE: In order to mimic the label offset, you have to take the value you got and add two operand = (Jump)((i8)(data[1]) + 2) case .VariablePort: - operand = RegisterId { name = Register.dx, access = .Full } + // NOTE: This isn't documented in the manual, but you can tell if we need to use + // the dx register or an immediate if the 4th LSB bit is set + if (data[0] & 0b1000) >> 3 == 1 { + operand = RegisterId { name = .dx, access = .Full } + } else { + operand = Immediate { value = i16(i8(data[1])), size = ._8 } + processed^ += 1 + } case .ShiftRotate: v_flag := data[0] & 0b10 != 0 operand = v_flag ? RegisterId { name = Register(1), access = .Low } : Immediate { value = 1 } diff --git a/instructions.odin b/instructions.odin index d0685cc..75393ff 100644 --- a/instructions.odin +++ b/instructions.odin @@ -194,16 +194,13 @@ instructions := [?]InstructionInfo { dst = .Accumulator, src = .Register, reg_info = .FirstByteLast3, has_flip = true, word_size = .Always16 }, { opname = .IN, desc = "", mask = 0b11111110, encoding = 0b11100100, - dst = .Accumulator, src = .ImmediateUnsigned }, + dst = .Accumulator, src = .Immediate, word_size = .LastBit }, { opname = .IN, desc = "", mask = 0b11111110, encoding = 0b11101100, - dst = .Accumulator, src = .VariablePort, - word_size = .LastBit, }, + dst = .Accumulator, src = .VariablePort, word_size = .LastBit, }, { opname = .OUT, desc = "", mask = 0b11111110, encoding = 0b11100110, - dst = .ImmediateUnsigned, src = .Accumulator, - word_size = .LastBit, }, + dst = .VariablePort, src = .Accumulator, word_size = .LastBit }, { opname = .OUT, desc = "", mask = 0b11111110, encoding = 0b11101110, - dst = .VariablePort, src = .Accumulator, - word_size = .LastBit, }, + dst = .VariablePort, src = .Accumulator, word_size = .LastBit, }, { opname = .TEST, desc = "", mask = 0b11111110, encoding = 0b10101000, dst = .Accumulator, src = .Immediate, word_size = .LastBit }, { opname = .XLAT, desc = "", mask = 0b11111111, encoding = 0b11010111,},