Fix and simplify (delete) all the signage stuff
This commit is contained in:
		
							parent
							
								
									ea7b65994b
								
							
						
					
					
						commit
						831a307975
					
				@ -102,10 +102,13 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr
 | 
			
		||||
                op = MemoryAddr{ addr_id = rm }
 | 
			
		||||
            }
 | 
			
		||||
        } else if mod == 1 {
 | 
			
		||||
            op = MemoryAddr{ addr_id = rm , displacement_value = (i16)(data[2]) , displacement_size = .Signed8 }
 | 
			
		||||
            // NOTE: Per the 8086 manual in order to detect signed displacement, you have
 | 
			
		||||
            // to sign extend a byte to a word. In Odin like in other languages, first
 | 
			
		||||
            // cast to an i8, before casting to an i16 and it'll sign extend
 | 
			
		||||
            op = MemoryAddr{ addr_id = rm , displacement = i16(i8(data[2])) }
 | 
			
		||||
            processed^ += 1
 | 
			
		||||
        } else if mod == 2 {
 | 
			
		||||
            op = MemoryAddr{ addr_id = rm , displacement_value = get_i16(data[2:]) , displacement_size = .Signed16 }
 | 
			
		||||
            op = MemoryAddr{ addr_id = rm , displacement = get_i16(data[2:]) }
 | 
			
		||||
            processed^ += 2
 | 
			
		||||
        } else if mod == 3 {
 | 
			
		||||
            if word {
 | 
			
		||||
@ -122,11 +125,8 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr
 | 
			
		||||
            word_signed &&= data[0] & 0b0000_0010 == 0
 | 
			
		||||
        }
 | 
			
		||||
        value: i16 = word_signed ? get_i16(data[data_idx:]) : i16(i8(data[data_idx]))
 | 
			
		||||
        operand = Immediate { value = value, size = word_signed ? .Signed16 : .Signed8 }
 | 
			
		||||
        operand = Immediate { value = value, size = word_signed ? ._16 : ._8 }
 | 
			
		||||
        processed^ += word_signed ? 2 : 1
 | 
			
		||||
    case .ImmediateUnsigned:
 | 
			
		||||
        operand = Immediate { value = i16(data[processed^]), size = .Unsigned8 }
 | 
			
		||||
        processed^ += 1
 | 
			
		||||
    case .Accumulator:
 | 
			
		||||
        operand = RegisterId { name = .ax, access = word ? .Full : .Low }
 | 
			
		||||
    case .DirectAddress:
 | 
			
		||||
@ -148,7 +148,7 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr
 | 
			
		||||
        }
 | 
			
		||||
    case .ShiftRotate:
 | 
			
		||||
        v_flag := data[0] & 0b10 != 0
 | 
			
		||||
        operand = v_flag ? RegisterId { name = Register(1), access = .Low } : Immediate { value = 1 }
 | 
			
		||||
        operand = v_flag ? RegisterId { name = .cx, access = .Low } : Immediate { value = 1 }
 | 
			
		||||
    case .Repeat:
 | 
			
		||||
        bits := (data[1] & 0b1110) >> 1
 | 
			
		||||
        w := (data[1] & 0b1) == 1 ? "w" : "b"
 | 
			
		||||
@ -164,7 +164,7 @@ parse_operand :: proc(inst: InstructionInfo, opinfo: OperandInfo, data: []u8, pr
 | 
			
		||||
        processed^ += 1
 | 
			
		||||
    case .DirectWithinSegment:
 | 
			
		||||
        value := (int)(get_i16(data[1:])) + total_bytes_processed + 3
 | 
			
		||||
        operand = Immediate { value = i16(value), size = .Signed16 }
 | 
			
		||||
        operand = Immediate { value = i16(value), size = ._16 }
 | 
			
		||||
        processed^ += 2
 | 
			
		||||
    case .Intersegment:
 | 
			
		||||
        operand = Intersegment {
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,7 @@ import "core:fmt"
 | 
			
		||||
import "core:math"
 | 
			
		||||
import "core:strings"
 | 
			
		||||
import "core:reflect"
 | 
			
		||||
import "core:strconv"
 | 
			
		||||
 | 
			
		||||
get_ip :: proc(cpu: ^Cpu) -> int { return int(cpu.registers[.ip].full) }
 | 
			
		||||
 | 
			
		||||
@ -38,7 +39,7 @@ get_operand_value :: proc(cpu: ^Cpu, operand: Operand) -> i16 {
 | 
			
		||||
        value := i16(u16(cpu.memory[opr+1] << 8) | u16(cpu.memory[opr]))
 | 
			
		||||
        return value
 | 
			
		||||
    case MemoryAddr:
 | 
			
		||||
        idx := get_effective_address_value(cpu, opr.addr_id) + opr.displacement_value
 | 
			
		||||
        idx := get_effective_address_value(cpu, opr.addr_id) + opr.displacement
 | 
			
		||||
        value := i16(u16(cpu.memory[idx+1] << 8) | u16(cpu.memory[idx]))
 | 
			
		||||
        // fmt.println("Checking", idx)
 | 
			
		||||
        // for i in 0..<6 {
 | 
			
		||||
@ -136,7 +137,7 @@ execute_instruction :: proc(cpu: ^Cpu, inst: Instruction) {
 | 
			
		||||
        #partial switch inst.opname {
 | 
			
		||||
        case .MOV:
 | 
			
		||||
            if imm,ok := inst.src.(Immediate); ok {
 | 
			
		||||
                if imm.size == .Signed16 {
 | 
			
		||||
                if imm.size == ._16 {
 | 
			
		||||
                    cpu.memory[addr]   = u8(imm.value & 0x00FF)
 | 
			
		||||
                    cpu.memory[addr+1] = u8((u16(imm.value) & 0xFF00) >> 8)
 | 
			
		||||
                } else {
 | 
			
		||||
@ -150,7 +151,7 @@ execute_instruction :: proc(cpu: ^Cpu, inst: Instruction) {
 | 
			
		||||
            value := get_operand_value(cpu, inst.src)
 | 
			
		||||
 | 
			
		||||
            effective_addr_val := get_effective_address_value(cpu, mem_addr.addr_id)
 | 
			
		||||
            addr := effective_addr_val + mem_addr.displacement_value
 | 
			
		||||
            addr := effective_addr_val + mem_addr.displacement
 | 
			
		||||
            cpu.memory[addr]   = u8(value & 0x00FF)
 | 
			
		||||
            cpu.memory[addr+1] = u8((u16(value) & 0xFF00) >> 8)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -39,7 +39,7 @@ calculate_effective_address :: proc(r_m: u8) -> string {
 | 
			
		||||
 | 
			
		||||
get_memory_string :: proc(memoryAddr: MemoryAddr, has_segment: Maybe(RegisterId)) -> string {
 | 
			
		||||
    disp: string
 | 
			
		||||
    value := memoryAddr.displacement_value
 | 
			
		||||
    value := memoryAddr.displacement
 | 
			
		||||
    if value != 0 {
 | 
			
		||||
        disp = fmt.aprintf(" %s %d", value > 0 ? "+" : "-", math.abs(value))
 | 
			
		||||
    }
 | 
			
		||||
@ -70,14 +70,7 @@ get_operand_string :: proc(operand: Operand, has_segment: Maybe(RegisterId)) ->
 | 
			
		||||
    case RegisterId:
 | 
			
		||||
        string_val = get_register_name(val)
 | 
			
		||||
    case Immediate:
 | 
			
		||||
        switch val.size {
 | 
			
		||||
        case .Signed8:
 | 
			
		||||
            string_val = fmt.aprintf("%d", i8(val.value))
 | 
			
		||||
        case .Unsigned8:
 | 
			
		||||
            string_val = fmt.aprintf("%d", u8(val.value))
 | 
			
		||||
        case .Signed16:
 | 
			
		||||
            string_val = fmt.aprintf("%d", i16(val.value))
 | 
			
		||||
        }
 | 
			
		||||
        string_val = fmt.aprintf("%d", i16(val.value))
 | 
			
		||||
    case MemoryAddr:
 | 
			
		||||
        string_val = get_memory_string(val, has_segment)
 | 
			
		||||
    case DirectAddress:
 | 
			
		||||
@ -132,13 +125,7 @@ get_instruction_string :: proc(inst_info: InstructionInfo, instruction: Instruct
 | 
			
		||||
        }
 | 
			
		||||
        fmt.sbprintf(&instruction_builder, "%s%s %s%s", opname, interseg_string, size_string, src_str)
 | 
			
		||||
    } else {
 | 
			
		||||
        // note: i don't know why this is the case, but only the move has the word/byte
 | 
			
		||||
        // keyword next to the immediate, but other instructions have it on the memory address
 | 
			
		||||
        if opname == "mov" {
 | 
			
		||||
            fmt.sbprintf(&instruction_builder, "%s %s, %s%s", opname, dst_str, size_string, src_str)
 | 
			
		||||
        } else {
 | 
			
		||||
            fmt.sbprintf(&instruction_builder, "%s %s%s, %s", opname, size_string, dst_str, src_str)
 | 
			
		||||
        }
 | 
			
		||||
        fmt.sbprintf(&instruction_builder, "%s %s%s, %s", opname, size_string, dst_str, src_str)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Prepare padding and comment to add debug info
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								sim8086.odin
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								sim8086.odin
									
									
									
									
									
								
							@ -6,6 +6,7 @@ import "core:fmt"
 | 
			
		||||
import "core:math"
 | 
			
		||||
import "core:strings"
 | 
			
		||||
import "core:reflect"
 | 
			
		||||
import "core:strconv"
 | 
			
		||||
 | 
			
		||||
main :: proc() {
 | 
			
		||||
    f,err := os.open(os.args[1])
 | 
			
		||||
@ -47,7 +48,12 @@ main :: proc() {
 | 
			
		||||
        memory = make([dynamic]u8, 1024 * 1024), // 1,048,576
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    execute_instructions(&cpu, decoded_insts)
 | 
			
		||||
    num_idx := strings.last_index(os.args[1], "list-") + 5
 | 
			
		||||
    if listing_num,ok := strconv.parse_int(os.args[1][num_idx:num_idx+4]); ok {
 | 
			
		||||
        if listing_num > 42 {
 | 
			
		||||
            execute_instructions(&cpu, decoded_insts)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if what_to_print == "registers" || what_to_print == "all" {
 | 
			
		||||
        fmt.println("Registers")
 | 
			
		||||
@ -66,8 +72,9 @@ main :: proc() {
 | 
			
		||||
 | 
			
		||||
        failed_ref: bool
 | 
			
		||||
        path,ok := strings.replace(os.args[1], ".bin", ".txt", 1)
 | 
			
		||||
        ref_cpu,_ := extract_reference_cpu_state(path)
 | 
			
		||||
        ref_cpu,_ := parse_reference_cpu_state(path)
 | 
			
		||||
        for reg_val,name in ref_cpu.registers {
 | 
			
		||||
            if name == .ip && reg_val.full == 0 do continue
 | 
			
		||||
            if cpu.registers[name].full != reg_val.full {
 | 
			
		||||
                msg := "%s register does not match reference - Expected 0x%04x | Actual 0x%04x"
 | 
			
		||||
                fmt.printfln(msg, name, reg_val.full, cpu.registers[name].full)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								testing.odin
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								testing.odin
									
									
									
									
									
								
							@ -7,7 +7,7 @@ import "core:strings"
 | 
			
		||||
import "core:strconv"
 | 
			
		||||
import "core:reflect"
 | 
			
		||||
 | 
			
		||||
extract_reference_cpu_state :: proc(filename: string) -> (Cpu, bool) {
 | 
			
		||||
parse_reference_cpu_state :: proc(filename: string) -> (Cpu, bool) {
 | 
			
		||||
    cpu: Cpu
 | 
			
		||||
 | 
			
		||||
    data,ok := os.read_entire_file(filename)
 | 
			
		||||
@ -20,7 +20,6 @@ extract_reference_cpu_state :: proc(filename: string) -> (Cpu, bool) {
 | 
			
		||||
    lines := strings.split(content, "\n")
 | 
			
		||||
    defer delete(lines)
 | 
			
		||||
 | 
			
		||||
    ignore_ip_reg := true
 | 
			
		||||
    for line in lines {
 | 
			
		||||
        space_count := 0
 | 
			
		||||
        for c,i in line {
 | 
			
		||||
@ -42,9 +41,6 @@ extract_reference_cpu_state :: proc(filename: string) -> (Cpu, bool) {
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    reg_name := line[i:i+2]
 | 
			
		||||
                    if reg_name == "ip" {
 | 
			
		||||
                        ignore_ip_reg = false
 | 
			
		||||
                    }
 | 
			
		||||
                    reg_value := get_cpu_register_by_name(&cpu, reg_name)
 | 
			
		||||
                    hex_string := line[i+6:i+10]
 | 
			
		||||
                    if hex_num,ok := strconv.parse_int(hex_string, 16); ok {
 | 
			
		||||
@ -56,9 +52,5 @@ extract_reference_cpu_state :: proc(filename: string) -> (Cpu, bool) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ignore_ip_reg {
 | 
			
		||||
        cpu.registers[.ip] = cpu.registers[.ip]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return cpu, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -58,9 +58,8 @@ RegisterId :: struct {
 | 
			
		||||
    access: RegisterAccess,
 | 
			
		||||
}
 | 
			
		||||
ImmediateSize :: enum {
 | 
			
		||||
    Signed8,
 | 
			
		||||
    Unsigned8,
 | 
			
		||||
    Signed16,
 | 
			
		||||
    _8,
 | 
			
		||||
    _16,
 | 
			
		||||
}
 | 
			
		||||
Immediate :: struct {
 | 
			
		||||
    value: i16,
 | 
			
		||||
@ -68,8 +67,7 @@ Immediate :: struct {
 | 
			
		||||
}
 | 
			
		||||
MemoryAddr :: struct {
 | 
			
		||||
    addr_id: u8,
 | 
			
		||||
    displacement_value: i16,
 | 
			
		||||
    displacement_size: ImmediateSize,
 | 
			
		||||
    displacement: i16,
 | 
			
		||||
}
 | 
			
		||||
DirectAddress :: distinct i16
 | 
			
		||||
Jump :: distinct i8
 | 
			
		||||
@ -96,7 +94,6 @@ OperandInfo :: enum {
 | 
			
		||||
    SegmentRegister,
 | 
			
		||||
    RegisterMemory,
 | 
			
		||||
    Immediate,
 | 
			
		||||
    ImmediateUnsigned,
 | 
			
		||||
    Accumulator,
 | 
			
		||||
    DirectAddress,
 | 
			
		||||
    Jump,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user