Factor out get/set actions to reduce duplication, execute add,sub,cmp and check flags

This commit is contained in:
Joseph Ferano 2025-03-19 21:10:22 +07:00
parent 863ccfc583
commit 266f7a7900
4 changed files with 76 additions and 28 deletions

View File

@ -5,36 +5,64 @@ import "core:fmt"
import "core:math" import "core:math"
import "core:strings" 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) { execute_instruction :: proc(inst: Instruction) {
#partial switch inst.opname { if reg,ok := inst.dst.(RegisterId); ok {
#partial switch inst.opname {
case .MOV: case .MOV:
if reg_id,ok := inst.dst.(RegisterId); ok { src_val := get_operand_value(inst.src)
// val := registers[reg_id.id].value.full set_register_value(reg, src_val)
#partial switch val in inst.src { case .ADD:
case Immediate: src_val := get_operand_value(inst.src)
if val.size == .Signed16 { val := registers[reg.id].value.full + src_val
registers[reg_id.id].value.full = (u16)(val.value) set_register_value(reg, val)
} else { check_zero_flag(val)
value := u8(val.value & 0xFF) check_sign_flag(val)
if reg_id.access == .Low { case .SUB:
registers[reg_id.id].value.low = value src_val := get_operand_value(inst.src)
} else { val := registers[reg.id].value.full - src_val
registers[reg_id.id].value.high = value set_register_value(reg, val)
} check_zero_flag(val)
} check_sign_flag(val)
case RegisterId: case .CMP:
switch val.access { src_val := get_operand_value(inst.src)
case .Low, .High: val := registers[reg.id].value.full - src_val
value := val.access == .Low ? registers[val.id].value.low : registers[val.id].value.high check_zero_flag(val)
if reg_id.access == .Low { check_sign_flag(val)
registers[reg_id.id].value.low = value
} else {
registers[reg_id.id].value.high = value
}
case .Full:
registers[reg_id.id].value.full = registers[val.id].value.full
}
}
} }
} }
} }

View File

@ -30,6 +30,11 @@ registers := [?]Register {
variable_port := registers[2] variable_port := registers[2]
SEGMENT_REGISTER_START :: 8 SEGMENT_REGISTER_START :: 8
CPU := Cpu {
memory = make([dynamic]u8, 65536)
}
// TODO: I don't like this here // TODO: I don't like this here
total_bytes_processed := 0 total_bytes_processed := 0

View File

@ -19,5 +19,10 @@ do
./sim8086 asm_files/${asm_listing}.bin registers | awk '{print $1 $4}' | sort > temp1 ./sim8086 asm_files/${asm_listing}.bin registers | awk '{print $1 $4}' | sort > temp1
cat $asm_txt | awk '/Final registers/,0' | tail -n +2 | awk '{print $1 $2}' | sort > temp2 cat $asm_txt | awk '/Final registers/,0' | tail -n +2 | awk '{print $1 $2}' | sort > temp2
diff -U0 --color temp1 temp2 diff -U0 --color temp1 temp2
if [ $? -eq 1 ]; then
echo Listing $asm_listing Failed!
else
echo Listing $asm_listing Succeded!
fi
done done
rm temp1 temp2 rm temp1 temp2

View File

@ -11,6 +11,11 @@ Register :: struct {
code: u8, code: u8,
} }
Flags :: struct {
ZF: bool,
SF: bool,
}
WordSize :: enum { WordSize :: enum {
None, None,
LastBit, LastBit,
@ -126,3 +131,8 @@ Instruction :: struct {
raw_data: []u8, raw_data: []u8,
debug_msg: string, debug_msg: string,
} }
Cpu :: struct {
flags: Flags,
memory: [dynamic]u8,
}