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