75 lines
2.0 KiB
Odin
75 lines
2.0 KiB
Odin
package sim_8086
|
|
|
|
import "core:os"
|
|
import "core:fmt"
|
|
import "core:math"
|
|
import "core:strings"
|
|
import "core:reflect"
|
|
|
|
get_operand_value :: proc(operand: Operand) -> u16 {
|
|
#partial switch opr in operand {
|
|
case Immediate:
|
|
return opr.value
|
|
case RegisterId:
|
|
reg_val := CPU.registers[opr.idx]
|
|
switch opr.access {
|
|
case .Low, .High:
|
|
return u16(opr.access == .Low ? reg_val.low : reg_val.high)
|
|
case .Full:
|
|
return reg_val.full
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
set_register_value :: proc(reg: RegisterId, value: u16) {
|
|
switch reg.access {
|
|
case .Low:
|
|
CPU.registers[reg.idx].low = u8(value)
|
|
case .High:
|
|
CPU.registers[reg.idx].high = u8(value)
|
|
case .Full:
|
|
CPU.registers[reg.idx].full = u16(value)
|
|
}
|
|
}
|
|
|
|
get_cpu_register_by_name :: proc(cpu: ^Cpu, name: string) -> ^RegisterValue {
|
|
reg,_ := reflect.enum_from_name(Register, name)
|
|
return &cpu.registers[int(reg)]
|
|
}
|
|
|
|
check_zero_flag :: proc(value: u16) {
|
|
CPU.flags.ZF = value == 0
|
|
}
|
|
|
|
check_sign_flag :: proc(value: u16) {
|
|
CPU.flags.SF = value >> 15 == 1
|
|
}
|
|
|
|
execute_instruction :: proc(inst: Instruction) {
|
|
if reg,ok := inst.dst.(RegisterId); ok {
|
|
#partial switch inst.opname {
|
|
case .MOV:
|
|
src_val := get_operand_value(inst.src)
|
|
set_register_value(reg, src_val)
|
|
case .ADD:
|
|
src_val := get_operand_value(inst.src)
|
|
val := CPU.registers[reg.idx].full + src_val
|
|
set_register_value(reg, val)
|
|
check_zero_flag(val)
|
|
check_sign_flag(val)
|
|
case .SUB:
|
|
src_val := get_operand_value(inst.src)
|
|
val := CPU.registers[reg.idx].full - src_val
|
|
set_register_value(reg, val)
|
|
check_zero_flag(val)
|
|
check_sign_flag(val)
|
|
case .CMP:
|
|
src_val := get_operand_value(inst.src)
|
|
val := CPU.registers[reg.idx].full - src_val
|
|
check_zero_flag(val)
|
|
check_sign_flag(val)
|
|
}
|
|
}
|
|
}
|