From 11ccfe78a99cc6b494206c97697a0b9efd17629b Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Fri, 21 Mar 2025 20:11:39 +0700 Subject: [PATCH] Handle Memory movs, change displacement from union to enum --- decoding.odin | 6 +++--- execution.odin | 30 +++++++++++++++++++++++++++++- printing.odin | 29 +++-------------------------- sim8086.odin | 2 +- types.odin | 10 ++-------- 5 files changed, 38 insertions(+), 39 deletions(-) diff --git a/decoding.odin b/decoding.odin index 8bee396..2c9958a 100644 --- a/decoding.odin +++ b/decoding.odin @@ -99,13 +99,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 } } } else if mod == 1 { - op = MemoryAddr{ addr_id = rm , displacement = (i8)(data[2]) } + op = MemoryAddr{ addr_id = rm , displacement_value = (i16)(data[2]) , displacement_size = .Signed8 } processed^ += 1 } else if mod == 2 { - op = MemoryAddr{ addr_id = rm , displacement = get_i16(data[2:]) } + op = MemoryAddr{ addr_id = rm , displacement_value = get_i16(data[2:]) , displacement_size = .Signed16 } processed^ += 2 } else if mod == 3 { if word { diff --git a/execution.odin b/execution.odin index 027369b..ad551e8 100644 --- a/execution.odin +++ b/execution.odin @@ -11,7 +11,6 @@ get_ip :: proc(cpu: ^Cpu) -> int { return int(cpu.registers[.ip].full) } get_operand_value :: proc(cpu: ^Cpu, operand: Operand) -> i16 { #partial switch opr in operand { case Immediate: - // fmt.printfln("0x%4x %d", i16(opr.value), opr.value) return i16(opr.value) case RegisterId: reg_val := cpu.registers[opr.name] @@ -21,6 +20,9 @@ get_operand_value :: proc(cpu: ^Cpu, operand: Operand) -> i16 { case .Full: return i16(reg_val.full) } + case DirectAddress: + value := i16(u16(cpu.memory[opr+1] << 8) | u16(cpu.memory[opr])) + return value } return 0 } @@ -107,6 +109,32 @@ execute_instruction :: proc(cpu: ^Cpu, inst: Instruction) { check_auxiliary_carry_flag(cpu, dst_val, src_val, false) check_carry_flag(cpu, dst_val, src_val, false) } + } else if addr,ok := inst.dst.(DirectAddress); ok { + #partial switch inst.opname { + case .MOV: + if imm,ok := inst.src.(Immediate); ok { + if imm.size == .Signed16 { + cpu.memory[addr] = u8(imm.value & 0x00FF) + cpu.memory[addr+1] = u8((u16(imm.value) & 0xFF00) >> 8) + } else { + cpu.memory[addr] = u8(imm.value) + } + } + } + } else if mem_addr,ok := inst.dst.(MemoryAddr); ok { + #partial switch inst.opname { + case .MOV: + if imm,ok := inst.src.(Immediate); ok { + // TODO: We need a function that returns the registers to check out + addr := cpu.registers[.bx].full + mem_addr.displacement_value + if imm.size == .Signed16 { + cpu.memory[addr] = u8(imm.value & 0x00FF) + cpu.memory[addr+1] = u8((u16(imm.value) & 0xFF00) >> 8) + } else { + cpu.memory[addr] = u8(imm.value) + } + } + } } else if jmp_offset,ok := inst.src.(Jump); ok { jump: bool #partial switch inst.opname { diff --git a/printing.odin b/printing.odin index 60d7fae..f86979b 100644 --- a/printing.odin +++ b/printing.odin @@ -39,17 +39,9 @@ calculate_effective_address :: proc(r_m: u8) -> string { get_memory_string :: proc(memoryAddr: MemoryAddr, has_segment: Maybe(RegisterId)) -> string { disp: string - switch value in memoryAddr.displacement { - case None: - disp = "" - case Disp8: - if value != 0 { - disp = fmt.aprintf(" %s %d", value > 0 ? "+" : "-", math.abs(value)) - } - case Disp16: - if value != 0 { - disp = fmt.aprintf(" %s %d", value > 0 ? "+" : "-", math.abs(value)) - } + value := memoryAddr.displacement_value + if value != 0 { + disp = fmt.aprintf(" %s %d", value > 0 ? "+" : "-", math.abs(value)) } seg_string: string if segreg, ok := has_segment.?; ok { @@ -59,21 +51,6 @@ get_memory_string :: proc(memoryAddr: MemoryAddr, has_segment: Maybe(RegisterId) return text } -get_displacement_string :: proc(displacement: Displacement) -> string { - disp := "" - #partial switch value in displacement { - case i8: - if value != 0 { - disp = fmt.aprintf(" %s %d", value > 0 ? "+" : "-", math.abs(value)) - } - case i16: - if value != 0 { - disp = fmt.aprintf(" %s %d", value > 0 ? "+" : "-", math.abs(value)) - } - } - return disp -} - get_register_name :: proc(reg_id: RegisterId) -> string { low_names := [?]string{"al", "cl", "dl", "bl"} high_names := [?]string{"ah", "ch", "dh", "bh"} diff --git a/sim8086.odin b/sim8086.odin index 2cc0403..36420c1 100644 --- a/sim8086.odin +++ b/sim8086.odin @@ -44,7 +44,7 @@ main :: proc() { } cpu := Cpu { - memory = make([dynamic]u8, 1_048_576), // Exact num per the manual + memory = make([dynamic]u8, 1024 * 1024), // 1,048,576 } execute_instructions(&cpu, decoded_insts) diff --git a/types.odin b/types.odin index 67740ee..a2fe09d 100644 --- a/types.odin +++ b/types.odin @@ -46,13 +46,6 @@ WordSize :: enum { } None :: struct {} -Disp8 :: i8 -Disp16 :: i16 -Displacement :: union { - None, - Disp8, - Disp16 -} RegisterAccess :: enum { Full, @@ -75,7 +68,8 @@ Immediate :: struct { } MemoryAddr :: struct { addr_id: u8, - displacement: Displacement, + displacement_value: i16, + displacement_size: ImmediateSize, } DirectAddress :: distinct i16 Jump :: distinct i8