Clean up/inline functions and clear out TODOs
This commit is contained in:
parent
266f7a7900
commit
b511c6a620
@ -4,6 +4,10 @@ import "core:fmt"
|
|||||||
import "core:math"
|
import "core:math"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
|
||||||
|
get_i16 :: proc(data: []u8) -> i16 {
|
||||||
|
return (i16)(data[1]) << 8 | (i16)(data[0])
|
||||||
|
}
|
||||||
|
|
||||||
get_op :: proc(inst: Instruction) -> (Op, bool) {
|
get_op :: proc(inst: Instruction) -> (Op, bool) {
|
||||||
op: Op
|
op: Op
|
||||||
interseg: bool
|
interseg: bool
|
||||||
@ -12,8 +16,6 @@ get_op :: proc(inst: Instruction) -> (Op, bool) {
|
|||||||
case 0b000: op = .INC
|
case 0b000: op = .INC
|
||||||
case 0b001: op = .DEC
|
case 0b001: op = .DEC
|
||||||
case 0b010: op = .CALL
|
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 0b011: op = .CALL; interseg = true
|
||||||
case 0b100: op = .JMP
|
case 0b100: op = .JMP
|
||||||
case 0b101: op = .JMP; interseg = true
|
case 0b101: op = .JMP; interseg = true
|
||||||
@ -137,10 +139,20 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr
|
|||||||
v_flag := data[0] & 0b10 != 0
|
v_flag := data[0] & 0b10 != 0
|
||||||
operand = v_flag ? RegisterId { id = 1, access = .Low } : Immediate { value = 1 }
|
operand = v_flag ? RegisterId { id = 1, access = .Low } : Immediate { value = 1 }
|
||||||
case .Repeat:
|
case .Repeat:
|
||||||
operand = get_repeat_op(data[1])
|
bits := (data[1] & 0b1110) >> 1
|
||||||
|
w := (data[1] & 0b1) == 1 ? "w" : "b"
|
||||||
|
rep: string
|
||||||
|
switch bits {
|
||||||
|
case 0b010: rep = "movs"
|
||||||
|
case 0b011: rep = "cmps"
|
||||||
|
case 0b101: rep = "stos"
|
||||||
|
case 0b110: rep = "lods"
|
||||||
|
case 0b111: rep = "scas"
|
||||||
|
}
|
||||||
|
operand = Repeat(fmt.aprintf("%s%s", rep, w))
|
||||||
processed^ += 1
|
processed^ += 1
|
||||||
case .DirectWithinSegment:
|
case .DirectWithinSegment:
|
||||||
value := (int)(get_i16(data[1:])) + total_bytes_processed + 3
|
value := (int)(get_i16(data[1:])) + CPU.total_bytes_processed + 3
|
||||||
operand = Immediate { value = u16(value), size = .Signed16 }
|
operand = Immediate { value = u16(value), size = .Signed16 }
|
||||||
processed^ += 2
|
processed^ += 2
|
||||||
case .Intersegment:
|
case .Intersegment:
|
||||||
@ -162,8 +174,16 @@ decode_data :: proc(inst_list: ^[dynamic]Instruction, data: []u8, bytes_to_read:
|
|||||||
processed := 1
|
processed := 1
|
||||||
curr_byte := data[idx]
|
curr_byte := data[idx]
|
||||||
|
|
||||||
inst, ok := try_find_instruction(curr_byte)
|
found_inst: bool
|
||||||
if !ok {
|
inst: InstructionInfo
|
||||||
|
for i in instructions {
|
||||||
|
if i.encoding == (curr_byte & i.mask) {
|
||||||
|
found_inst = true
|
||||||
|
inst = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found_inst {
|
||||||
instruction = {
|
instruction = {
|
||||||
opname = .UNKNOWN,
|
opname = .UNKNOWN,
|
||||||
bytes_read = 1,
|
bytes_read = 1,
|
||||||
@ -240,6 +260,6 @@ decode_data :: proc(inst_list: ^[dynamic]Instruction, data: []u8, bytes_to_read:
|
|||||||
|
|
||||||
has_lock = false
|
has_lock = false
|
||||||
has_segment = nil
|
has_segment = nil
|
||||||
total_bytes_processed = idx
|
CPU.total_bytes_processed = idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,17 @@ package sim_8086
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:math"
|
import "core:math"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
import "core:reflect"
|
||||||
|
|
||||||
instruction_builder := strings.builder_make()
|
instruction_builder := strings.builder_make()
|
||||||
|
|
||||||
|
RIGHT_ALIGN_AMOUNT := 35
|
||||||
|
|
||||||
|
operand_is :: proc($T: typeid, opr: Operand) -> bool {
|
||||||
|
_, ok := opr.(T)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
calculate_effective_address :: proc(r_m: u8) -> string {
|
calculate_effective_address :: proc(r_m: u8) -> string {
|
||||||
val: string
|
val: string
|
||||||
switch r_m {
|
switch r_m {
|
||||||
@ -66,63 +74,6 @@ get_displacement_string :: proc(displacement: Displacement) -> string {
|
|||||||
return disp
|
return disp
|
||||||
}
|
}
|
||||||
|
|
||||||
get_opname :: proc(inst: Instruction) -> (string, bool) {
|
|
||||||
name: string
|
|
||||||
interseg: bool
|
|
||||||
if inst.opname == .TBD2 {
|
|
||||||
switch inst.raw_data[1] & 0b00111000 >> 3 {
|
|
||||||
case 0b000: name = "inc"
|
|
||||||
case 0b001: name = "dec"
|
|
||||||
case 0b010: name = "call"
|
|
||||||
// TODO: We really have to fix this because we shouldn't be figuring out if this
|
|
||||||
// is an intersegment here
|
|
||||||
case 0b011: name = "call"; interseg = true
|
|
||||||
case 0b100: name = "jmp"
|
|
||||||
case 0b101: name = "jmp"; interseg = true
|
|
||||||
case 0b110: name = "push"
|
|
||||||
}
|
|
||||||
} else if inst.opname == .TBD5 {
|
|
||||||
switch inst.raw_data[1] & 0b00111000 >> 3 {
|
|
||||||
case 0b000: name = "test"
|
|
||||||
case 0b001: name = "dec"
|
|
||||||
case 0b010: name = "not"
|
|
||||||
case 0b011: name = "neg"
|
|
||||||
case 0b100: name = "mul"
|
|
||||||
case 0b101: name = "imul"
|
|
||||||
case 0b110: name = "div"
|
|
||||||
case 0b111: name = "idiv"
|
|
||||||
}
|
|
||||||
} else if inst.opname == .TBD6 {
|
|
||||||
switch inst.raw_data[1] & 0b00111000 >> 3 {
|
|
||||||
case 0b000: name = "rol"
|
|
||||||
case 0b001: name = "ror"
|
|
||||||
case 0b010: name = "rcl"
|
|
||||||
case 0b011: name = "rcr"
|
|
||||||
case 0b100: name = "shl"
|
|
||||||
case 0b101: name = "shr"
|
|
||||||
case 0b111: name = "sar"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
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: name = "add"
|
|
||||||
case 0b001: name = "or"
|
|
||||||
case 0b010: name = "adc"
|
|
||||||
case 0b011: name = "sbb"
|
|
||||||
case 0b100: name = "and"
|
|
||||||
case 0b101: name = "sub"
|
|
||||||
case 0b110: name = "xor"
|
|
||||||
case 0b111: name = "cmp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return name, interseg
|
|
||||||
}
|
|
||||||
|
|
||||||
get_register_name :: proc(reg_id: RegisterId) -> string {
|
get_register_name :: proc(reg_id: RegisterId) -> string {
|
||||||
low_names := [?]string{"al", "cl", "dl", "bl"}
|
low_names := [?]string{"al", "cl", "dl", "bl"}
|
||||||
high_names := [?]string{"ah", "ch", "dh", "bh"}
|
high_names := [?]string{"ah", "ch", "dh", "bh"}
|
||||||
@ -194,8 +145,8 @@ 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
|
||||||
// TODO: Do the RTTI thing here with reflection
|
|
||||||
opname = strings.to_lower(fmt.aprintf("%s", inst.opname))
|
opname = strings.to_lower(reflect.enum_string(inst.opname))
|
||||||
|
|
||||||
if dst_str == "" {
|
if dst_str == "" {
|
||||||
interseg_string: string
|
interseg_string: string
|
||||||
|
42
sim8086.odin
42
sim8086.odin
@ -5,13 +5,6 @@ import "core:fmt"
|
|||||||
import "core:math"
|
import "core:math"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
|
||||||
RIGHT_ALIGN_AMOUNT := 35
|
|
||||||
|
|
||||||
// TODO: We completely botched this; ah and al refer to the ax register, they are not
|
|
||||||
// the low parts to sp, bp, si, di registers apparently you can't access those like that.
|
|
||||||
// We have to change how we coded this out. Likely we have to remove bytename as an option
|
|
||||||
// and then have some kind of flag when you're doing a dst or src operand specifying
|
|
||||||
// if it's the high or low part, not sure how to go about that
|
|
||||||
registers := [?]Register {
|
registers := [?]Register {
|
||||||
{fullname = "ax", code = 0b000},
|
{fullname = "ax", code = 0b000},
|
||||||
{fullname = "cx", code = 0b001},
|
{fullname = "cx", code = 0b001},
|
||||||
@ -35,41 +28,6 @@ CPU := Cpu {
|
|||||||
memory = make([dynamic]u8, 65536)
|
memory = make([dynamic]u8, 65536)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: I don't like this here
|
|
||||||
total_bytes_processed := 0
|
|
||||||
|
|
||||||
get_i16 :: proc(data: []u8) -> i16 {
|
|
||||||
return (i16)(data[1]) << 8 | (i16)(data[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
operand_is :: proc($T: typeid, opr: Operand) -> bool {
|
|
||||||
_, ok := opr.(T)
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
get_repeat_op :: proc(data: u8) -> Repeat {
|
|
||||||
bits := (data & 0b1110) >> 1
|
|
||||||
w := (data & 0b1) == 1 ? "w" : "b"
|
|
||||||
rep: string
|
|
||||||
switch bits {
|
|
||||||
case 0b010: rep = "movs"
|
|
||||||
case 0b011: rep = "cmps"
|
|
||||||
case 0b101: rep = "stos"
|
|
||||||
case 0b110: rep = "lods"
|
|
||||||
case 0b111: rep = "scas"
|
|
||||||
}
|
|
||||||
return Repeat(fmt.aprintf("%s%s", rep, w))
|
|
||||||
}
|
|
||||||
|
|
||||||
try_find_instruction :: proc(b: u8) -> (InstructionInfo, bool) {
|
|
||||||
for inst in instructions {
|
|
||||||
if inst.encoding == (b & inst.mask) {
|
|
||||||
return inst, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return InstructionInfo{}, false
|
|
||||||
}
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
f,err := os.open(os.args[1])
|
f,err := os.open(os.args[1])
|
||||||
if err != os.ERROR_NONE {
|
if err != os.ERROR_NONE {
|
||||||
|
@ -135,4 +135,5 @@ Instruction :: struct {
|
|||||||
Cpu :: struct {
|
Cpu :: struct {
|
||||||
flags: Flags,
|
flags: Flags,
|
||||||
memory: [dynamic]u8,
|
memory: [dynamic]u8,
|
||||||
|
total_bytes_processed: int
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user