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