Compare commits

..

No commits in common. "266f7a79004434526bc97088714805e700ba5faf" and "a91c3d9ba92ca2dec96e4b9adb5133f5b34d0226" have entirely different histories.

9 changed files with 38 additions and 204 deletions

View File

@ -1,28 +0,0 @@
; ========================================================================
;
; (C) Copyright 2023 by Molly Rocket, Inc., All Rights Reserved.
;
; This software is provided 'as-is', without any express or implied
; warranty. In no event will the authors be held liable for any damages
; arising from the use of this software.
;
; Please see https://computerenhance.com for further information
;
; ========================================================================
; ========================================================================
; LISTING 46
; ========================================================================
bits 16
mov bx, -4093
mov cx, 3841
sub bx, cx
mov sp, 998
mov bp, 999
cmp bp, sp
add bp, 1027
sub bp, 2026

View File

@ -1,24 +0,0 @@
--- test\listing_0046_add_sub_cmp execution ---
mov bx, 61443 ; bx:0x0->0xf003
mov cx, 3841 ; cx:0x0->0xf01
sub bx, cx ; bx:0xf003->0xe102 flags:->S
mov sp, 998 ; sp:0x0->0x3e6
mov bp, 999 ; bp:0x0->0x3e7
cmp bp, sp ; flags:S->
add bp, 1027 ; bp:0x3e7->0x7ea
sub bp, 2026 ; bp:0x7ea->0x0 flags:->PZ
Final registers:
bx: 0xe102 (57602)
cx: 0x0f01 (3841)
sp: 0x03e6 (998)
ax: 0x0000 (0)
bp: 0x0000 (0)
dx: 0x0000 (0)
si: 0x0000 (0)
di: 0x0000 (0)
es: 0x0000 (0)
ss: 0x0000 (0)
cs: 0x0000 (0)
ds: 0x0000 (0)
flags: PZ

View File

@ -4,64 +4,6 @@ import "core:fmt"
import "core:math"
import "core:strings"
get_op :: proc(inst: Instruction) -> (Op, bool) {
op: Op
interseg: bool
if inst.opname == .TBD2 {
switch inst.raw_data[1] & 0b00111000 >> 3 {
case 0b000: op = .INC
case 0b001: op = .DEC
case 0b010: op = .CALL
// TODO: We really have to fix this because we shouldn't be figuring out if this
// is an intersegment here
case 0b011: op = .CALL; interseg = true
case 0b100: op = .JMP
case 0b101: op = .JMP; interseg = true
case 0b110: op = .PUSH
}
} else if inst.opname == .TBD5 {
switch inst.raw_data[1] & 0b00111000 >> 3 {
case 0b000: op = .TEST
case 0b001: op = .DEC
case 0b010: op = .NOT
case 0b011: op = .NEG
case 0b100: op = .MUL
case 0b101: op = .IMUL
case 0b110: op = .DIV
case 0b111: op = .IDIV
}
} else if inst.opname == .TBD6 {
switch inst.raw_data[1] & 0b00111000 >> 3 {
case 0b000: op = .ROL
case 0b001: op = .ROR
case 0b010: op = .RCL
case 0b011: op = .RCR
case 0b100: op = .SHL
case 0b101: op = .SHR
case 0b111: op = .SAR
}
} else if inst.opname == .TBD1 || inst.opname == .TBD3 || inst.opname == .TBD4 {
bits: u8
if inst.opname == .TBD1 || inst.opname == .TBD3 {
bits = inst.raw_data[0] & 0b00111000 >> 3
} else {
bits = inst.raw_data[1] & 0b00111000 >> 3
}
switch bits {
case 0b000: op = .ADD
case 0b001: op = .OR
case 0b010: op = .ADC
case 0b011: op = .SBB
case 0b100: op = .AND
case 0b101: op = .SUB
case 0b110: op = .XOR
case 0b111: op = .CMP
}
} else {
op = inst.opname
}
return op, interseg
}
parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, processed: ^int, word: bool, has_segreg: Maybe(Register)) -> Operand {
operand: Operand = None{}
switch opinfo {
@ -221,6 +163,7 @@ decode_data :: proc(inst_list: ^[dynamic]Instruction, data: []u8, bytes_to_read:
processed += inst.consume_extra_bytes
instruction.opname = inst.opname
instruction.src = src_opr
instruction.dst = dst_opr
instruction.is_word = word
@ -230,8 +173,6 @@ decode_data :: proc(inst_list: ^[dynamic]Instruction, data: []u8, bytes_to_read:
instruction.info = inst
instruction.has_lock = has_lock
instruction.has_segment = has_segment
instruction.opname = inst.opname
instruction.opname,instruction.indirect_intersegment = get_op(instruction)
// fmt.println(parsed_inst)
append(inst_list, instruction)

View File

@ -5,64 +5,36 @@ 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 {
#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)
if reg_id,ok := inst.dst.(RegisterId); ok {
// val := registers[reg_id.id].value.full
#partial switch val in inst.src {
case Immediate:
if val.size == .Signed16 {
registers[reg_id.id].value.full = (u16)(val.value)
} else {
value := u8(val.value & 0xFF)
if reg_id.access == .Low {
registers[reg_id.id].value.low = value
} else {
registers[reg_id.id].value.high = value
}
}
case RegisterId:
switch val.access {
case .Low, .High:
value := val.access == .Low ? registers[val.id].value.low : registers[val.id].value.high
if reg_id.access == .Low {
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

@ -31,8 +31,6 @@ Op :: enum {
SBB,
DEC,
NEG,
MUL,
IMUL,
CMP,
AAS,
DAS,
@ -42,18 +40,8 @@ Op :: enum {
AAD,
CBW,
CWD,
ROL,
ROR,
RCL,
RCR,
SHL,
SHR,
SAR,
NOT,
TEST,
OR,
AND,
XOR,
REP,
RET,
RETF,

View File

@ -194,12 +194,16 @@ get_instruction_string :: proc(inst_info: InstructionInfo, instruction: Instruct
src_str := get_operand_string(inst.src, inst.has_segment)
opname: string
is_interseg: bool
// TODO: Do the RTTI thing here with reflection
opname = strings.to_lower(fmt.aprintf("%s", inst.opname))
if inst_info.check_second_encoding {
opname,is_interseg = get_opname(inst)
} else {
// TODO: Do the RTTI thing here with reflection
opname = strings.to_lower(fmt.aprintf("%s", inst.opname))
}
if dst_str == "" {
interseg_string: string
if instruction.indirect_intersegment {
if is_interseg {
interseg_string = " far"
}
fmt.sbprintf(&instruction_builder, "%s%s %s%s", opname, interseg_string, size_string, src_str)

View File

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

View File

@ -19,10 +19,5 @@ do
./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
diff -U0 --color temp1 temp2
if [ $? -eq 1 ]; then
echo Listing $asm_listing Failed!
else
echo Listing $asm_listing Succeded!
fi
done
rm temp1 temp2

View File

@ -11,11 +11,6 @@ Register :: struct {
code: u8,
}
Flags :: struct {
ZF: bool,
SF: bool,
}
WordSize :: enum {
None,
LastBit,
@ -25,6 +20,7 @@ WordSize :: enum {
}
None :: struct {}
Disp8 :: i8
Disp16 :: i16
Displacement :: union {
@ -122,7 +118,7 @@ Instruction :: struct {
dst: Operand,
info: InstructionInfo,
is_word: bool,
indirect_intersegment: bool,
// indirect_intersegment: bool,
// TODO: This is trickier than I thought, it's more than just the one instruction
// that uses it
has_segment: Maybe(Register),
@ -131,8 +127,3 @@ Instruction :: struct {
raw_data: []u8,
debug_msg: string,
}
Cpu :: struct {
flags: Flags,
memory: [dynamic]u8,
}