Compare commits
No commits in common. "266f7a79004434526bc97088714805e700ba5faf" and "a91c3d9ba92ca2dec96e4b9adb5133f5b34d0226" have entirely different histories.
266f7a7900
...
a91c3d9ba9
@ -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
|
|
@ -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
|
|
@ -4,64 +4,6 @@ import "core:fmt"
|
|||||||
import "core:math"
|
import "core:math"
|
||||||
import "core:strings"
|
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 {
|
parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, processed: ^int, word: bool, has_segreg: Maybe(Register)) -> Operand {
|
||||||
operand: Operand = None{}
|
operand: Operand = None{}
|
||||||
switch opinfo {
|
switch opinfo {
|
||||||
@ -221,6 +163,7 @@ decode_data :: proc(inst_list: ^[dynamic]Instruction, data: []u8, bytes_to_read:
|
|||||||
|
|
||||||
processed += inst.consume_extra_bytes
|
processed += inst.consume_extra_bytes
|
||||||
|
|
||||||
|
instruction.opname = inst.opname
|
||||||
instruction.src = src_opr
|
instruction.src = src_opr
|
||||||
instruction.dst = dst_opr
|
instruction.dst = dst_opr
|
||||||
instruction.is_word = word
|
instruction.is_word = word
|
||||||
@ -230,8 +173,6 @@ decode_data :: proc(inst_list: ^[dynamic]Instruction, data: []u8, bytes_to_read:
|
|||||||
instruction.info = inst
|
instruction.info = inst
|
||||||
instruction.has_lock = has_lock
|
instruction.has_lock = has_lock
|
||||||
instruction.has_segment = has_segment
|
instruction.has_segment = has_segment
|
||||||
instruction.opname = inst.opname
|
|
||||||
instruction.opname,instruction.indirect_intersegment = get_op(instruction)
|
|
||||||
|
|
||||||
// fmt.println(parsed_inst)
|
// fmt.println(parsed_inst)
|
||||||
append(inst_list, instruction)
|
append(inst_list, instruction)
|
||||||
|
@ -5,64 +5,36 @@ 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) {
|
||||||
if reg,ok := inst.dst.(RegisterId); ok {
|
|
||||||
#partial switch inst.opname {
|
#partial switch inst.opname {
|
||||||
case .MOV:
|
case .MOV:
|
||||||
src_val := get_operand_value(inst.src)
|
if reg_id,ok := inst.dst.(RegisterId); ok {
|
||||||
set_register_value(reg, src_val)
|
// val := registers[reg_id.id].value.full
|
||||||
case .ADD:
|
#partial switch val in inst.src {
|
||||||
src_val := get_operand_value(inst.src)
|
case Immediate:
|
||||||
val := registers[reg.id].value.full + src_val
|
if val.size == .Signed16 {
|
||||||
set_register_value(reg, val)
|
registers[reg_id.id].value.full = (u16)(val.value)
|
||||||
check_zero_flag(val)
|
} else {
|
||||||
check_sign_flag(val)
|
value := u8(val.value & 0xFF)
|
||||||
case .SUB:
|
if reg_id.access == .Low {
|
||||||
src_val := get_operand_value(inst.src)
|
registers[reg_id.id].value.low = value
|
||||||
val := registers[reg.id].value.full - src_val
|
} else {
|
||||||
set_register_value(reg, val)
|
registers[reg_id.id].value.high = value
|
||||||
check_zero_flag(val)
|
}
|
||||||
check_sign_flag(val)
|
}
|
||||||
case .CMP:
|
case RegisterId:
|
||||||
src_val := get_operand_value(inst.src)
|
switch val.access {
|
||||||
val := registers[reg.id].value.full - src_val
|
case .Low, .High:
|
||||||
check_zero_flag(val)
|
value := val.access == .Low ? registers[val.id].value.low : registers[val.id].value.high
|
||||||
check_sign_flag(val)
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,6 @@ Op :: enum {
|
|||||||
SBB,
|
SBB,
|
||||||
DEC,
|
DEC,
|
||||||
NEG,
|
NEG,
|
||||||
MUL,
|
|
||||||
IMUL,
|
|
||||||
CMP,
|
CMP,
|
||||||
AAS,
|
AAS,
|
||||||
DAS,
|
DAS,
|
||||||
@ -42,18 +40,8 @@ Op :: enum {
|
|||||||
AAD,
|
AAD,
|
||||||
CBW,
|
CBW,
|
||||||
CWD,
|
CWD,
|
||||||
ROL,
|
|
||||||
ROR,
|
|
||||||
RCL,
|
|
||||||
RCR,
|
|
||||||
SHL,
|
|
||||||
SHR,
|
|
||||||
SAR,
|
|
||||||
NOT,
|
NOT,
|
||||||
TEST,
|
TEST,
|
||||||
OR,
|
|
||||||
AND,
|
|
||||||
XOR,
|
|
||||||
REP,
|
REP,
|
||||||
RET,
|
RET,
|
||||||
RETF,
|
RETF,
|
||||||
|
@ -194,12 +194,16 @@ get_instruction_string :: proc(inst_info: InstructionInfo, instruction: Instruct
|
|||||||
src_str := get_operand_string(inst.src, inst.has_segment)
|
src_str := get_operand_string(inst.src, inst.has_segment)
|
||||||
opname: string
|
opname: string
|
||||||
is_interseg: bool
|
is_interseg: bool
|
||||||
|
if inst_info.check_second_encoding {
|
||||||
|
opname,is_interseg = get_opname(inst)
|
||||||
|
} else {
|
||||||
// TODO: Do the RTTI thing here with reflection
|
// TODO: Do the RTTI thing here with reflection
|
||||||
opname = strings.to_lower(fmt.aprintf("%s", inst.opname))
|
opname = strings.to_lower(fmt.aprintf("%s", inst.opname))
|
||||||
|
}
|
||||||
|
|
||||||
if dst_str == "" {
|
if dst_str == "" {
|
||||||
interseg_string: string
|
interseg_string: string
|
||||||
if instruction.indirect_intersegment {
|
if is_interseg {
|
||||||
interseg_string = " far"
|
interseg_string = " far"
|
||||||
}
|
}
|
||||||
fmt.sbprintf(&instruction_builder, "%s%s %s%s", opname, interseg_string, size_string, src_str)
|
fmt.sbprintf(&instruction_builder, "%s%s %s%s", opname, interseg_string, size_string, src_str)
|
||||||
|
@ -30,11 +30,6 @@ 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
|
||||||
|
|
||||||
|
@ -19,10 +19,5 @@ 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
|
||||||
|
13
types.odin
13
types.odin
@ -11,11 +11,6 @@ Register :: struct {
|
|||||||
code: u8,
|
code: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
Flags :: struct {
|
|
||||||
ZF: bool,
|
|
||||||
SF: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
WordSize :: enum {
|
WordSize :: enum {
|
||||||
None,
|
None,
|
||||||
LastBit,
|
LastBit,
|
||||||
@ -25,6 +20,7 @@ WordSize :: enum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
None :: struct {}
|
None :: struct {}
|
||||||
|
|
||||||
Disp8 :: i8
|
Disp8 :: i8
|
||||||
Disp16 :: i16
|
Disp16 :: i16
|
||||||
Displacement :: union {
|
Displacement :: union {
|
||||||
@ -122,7 +118,7 @@ Instruction :: struct {
|
|||||||
dst: Operand,
|
dst: Operand,
|
||||||
info: InstructionInfo,
|
info: InstructionInfo,
|
||||||
is_word: bool,
|
is_word: bool,
|
||||||
indirect_intersegment: bool,
|
// indirect_intersegment: bool,
|
||||||
// TODO: This is trickier than I thought, it's more than just the one instruction
|
// TODO: This is trickier than I thought, it's more than just the one instruction
|
||||||
// that uses it
|
// that uses it
|
||||||
has_segment: Maybe(Register),
|
has_segment: Maybe(Register),
|
||||||
@ -131,8 +127,3 @@ Instruction :: struct {
|
|||||||
raw_data: []u8,
|
raw_data: []u8,
|
||||||
debug_msg: string,
|
debug_msg: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
Cpu :: struct {
|
|
||||||
flags: Flags,
|
|
||||||
memory: [dynamic]u8,
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user