performance-aware/execution.odin

69 lines
1.9 KiB
Odin

package sim_8086
import "core:os"
import "core:fmt"
import "core:math"
import "core:strings"
get_operand_value :: proc(operand: Operand) -> u16 {
#partial switch opr in operand {
case Immediate:
return opr.value
case RegisterId:
switch opr.access {
case .Low, .High:
val := opr.access == .Low ? registers[opr.id].value.low : registers[opr.id].value.high
return u16(val)
case .Full:
return registers[opr.id].value.full
}
}
return 0
}
set_register_value :: proc(reg_id: RegisterId, value: u16) {
switch reg_id.access {
case .Low:
registers[reg_id.id].value.low = u8(value)
case .High:
registers[reg_id.id].value.high = u8(value)
case .Full:
registers[reg_id.id].value.full = u16(value)
}
}
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 := registers[reg.id].value.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 := registers[reg.id].value.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 := registers[reg.id].value.full - src_val
check_zero_flag(val)
check_sign_flag(val)
}
}
}