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:strings"
|
||||
|
||||
get_i16 :: proc(data: []u8) -> i16 {
|
||||
return (i16)(data[1]) << 8 | (i16)(data[0])
|
||||
}
|
||||
|
||||
get_op :: proc(inst: Instruction) -> (Op, bool) {
|
||||
op: Op
|
||||
interseg: bool
|
||||
@ -12,8 +16,6 @@ get_op :: proc(inst: Instruction) -> (Op, bool) {
|
||||
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
|
||||
@ -137,10 +139,20 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr
|
||||
v_flag := data[0] & 0b10 != 0
|
||||
operand = v_flag ? RegisterId { id = 1, access = .Low } : Immediate { value = 1 }
|
||||
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
|
||||
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 }
|
||||
processed^ += 2
|
||||
case .Intersegment:
|
||||
@ -162,8 +174,16 @@ decode_data :: proc(inst_list: ^[dynamic]Instruction, data: []u8, bytes_to_read:
|
||||
processed := 1
|
||||
curr_byte := data[idx]
|
||||
|
||||
inst, ok := try_find_instruction(curr_byte)
|
||||
if !ok {
|
||||
found_inst: bool
|
||||
inst: InstructionInfo
|
||||
for i in instructions {
|
||||
if i.encoding == (curr_byte & i.mask) {
|
||||
found_inst = true
|
||||
inst = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found_inst {
|
||||
instruction = {
|
||||
opname = .UNKNOWN,
|
||||
bytes_read = 1,
|
||||
@ -240,6 +260,6 @@ decode_data :: proc(inst_list: ^[dynamic]Instruction, data: []u8, bytes_to_read:
|
||||
|
||||
has_lock = false
|
||||
has_segment = nil
|
||||
total_bytes_processed = idx
|
||||
CPU.total_bytes_processed = idx
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,17 @@ package sim_8086
|
||||
import "core:fmt"
|
||||
import "core:math"
|
||||
import "core:strings"
|
||||
import "core:reflect"
|
||||
|
||||
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 {
|
||||
val: string
|
||||
switch r_m {
|
||||
@ -66,63 +74,6 @@ get_displacement_string :: proc(displacement: Displacement) -> string {
|
||||
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 {
|
||||
low_names := [?]string{"al", "cl", "dl", "bl"}
|
||||
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)
|
||||
opname: string
|
||||
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 == "" {
|
||||
interseg_string: string
|
||||
|
42
sim8086.odin
42
sim8086.odin
@ -5,13 +5,6 @@ import "core:fmt"
|
||||
import "core:math"
|
||||
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 {
|
||||
{fullname = "ax", code = 0b000},
|
||||
{fullname = "cx", code = 0b001},
|
||||
@ -35,41 +28,6 @@ CPU := Cpu {
|
||||
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() {
|
||||
f,err := os.open(os.args[1])
|
||||
if err != os.ERROR_NONE {
|
||||
|
@ -135,4 +135,5 @@ Instruction :: struct {
|
||||
Cpu :: struct {
|
||||
flags: Flags,
|
||||
memory: [dynamic]u8,
|
||||
total_bytes_processed: int
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user