From 49ac2d8e0ce289a46826179ea7ccb543522b0808 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 20 Oct 2023 17:00:32 -0400 Subject: [PATCH] Improve error reporting, remove some dead TODOs. --- .../Implementation/PerformImplementation.hpp | 26 ++++++++------ OSBindings/Mac/Clock SignalTests/8088Tests.mm | 34 ++++++++++++------- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index fd0360d75..ecabc8949 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -1489,8 +1489,7 @@ template < else if constexpr (data_size == DataSize::DWord) return registers.eax(); }; - // For the string versions, evaluate to either SI and DI or ESI and EDI, depending on the address size. - // [TODO on the latter]. + // For the string operations, evaluate to either SI and DI or ESI and EDI, depending on the address size. const auto eSI = [&]() -> AddressT& { if constexpr (std::is_same_v) { return registers.si(); @@ -1506,6 +1505,15 @@ template < } }; + // For counts, provide either eCX or CX depending on address size. + const auto eCX = [&]() -> AddressT& { + if constexpr (std::is_same_v) { + return registers.cx(); + } else { + return registers.ecx(); + } + }; + // Guide to the below: // // * use hard-coded register names where appropriate; @@ -1566,11 +1574,10 @@ template < case Operation::JMPabs: Primitive::jump_absolute(destination(), flow_controller); return; case Operation::JMPfar: Primitive::jump_far(instruction, flow_controller, registers, memory); return; - // TODO: use ECX rather than CX for all of below if address size is 32-bit. - case Operation::JCXZ: jcc(!registers.cx()); return; - case Operation::LOOP: Primitive::loop(registers.cx(), instruction.offset(), registers, flow_controller); return; - case Operation::LOOPE: Primitive::loope(registers.cx(), instruction.offset(), registers, status, flow_controller); return; - case Operation::LOOPNE: Primitive::loopne(registers.cx(), instruction.offset(), registers, status, flow_controller); return; + case Operation::JCXZ: jcc(!eCX()); return; + case Operation::LOOP: Primitive::loop(eCX(), instruction.offset(), registers, flow_controller); return; + case Operation::LOOPE: Primitive::loope(eCX(), instruction.offset(), registers, status, flow_controller); return; + case Operation::LOOPNE: Primitive::loopne(eCX(), instruction.offset(), registers, status, flow_controller); return; case Operation::IRET: Primitive::iret(registers, flow_controller, memory, status); return; case Operation::RETnear: Primitive::ret_near(instruction, registers, flow_controller, memory); return; @@ -1639,16 +1646,15 @@ template < } return; - case Operation::XLAT: Primitive::xlat(instruction, memory, registers); return; + case Operation::XLAT: Primitive::xlat(instruction, memory, registers); return; case Operation::POP: source() = Primitive::pop(memory, registers); break; case Operation::PUSH: Primitive::push(source(), memory, registers); break; case Operation::POPF: Primitive::popf(memory, registers, status); break; case Operation::PUSHF: Primitive::pushf(memory, registers, status); break; - // TODO: don't assume address size below. case Operation::CMPS: - Primitive::cmps(instruction, eSI(), eDI(), memory, registers, status, flow_controller); + Primitive::cmps(instruction, eSI(), eDI(), memory, registers, status, flow_controller); break; } diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index 91f487653..fc196152f 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -769,19 +769,27 @@ struct FailedExecution { } if(!registersEqual) { NSMutableArray *registers = [[NSMutableArray alloc] init]; - if(intended_registers.ax() != execution_support.registers.ax()) [registers addObject:@"ax"]; - if(intended_registers.cx() != execution_support.registers.cx()) [registers addObject:@"cx"]; - if(intended_registers.dx() != execution_support.registers.dx()) [registers addObject:@"dx"]; - if(intended_registers.bx() != execution_support.registers.bx()) [registers addObject:@"bx"]; - if(intended_registers.sp() != execution_support.registers.sp()) [registers addObject:@"sp"]; - if(intended_registers.bp() != execution_support.registers.bp()) [registers addObject:@"bp"]; - if(intended_registers.si() != execution_support.registers.si()) [registers addObject:@"si"]; - if(intended_registers.di() != execution_support.registers.di()) [registers addObject:@"di"]; - if(intended_registers.ip() != execution_support.registers.ip()) [registers addObject:@"ip"]; - if(intended_registers.es() != execution_support.registers.es()) [registers addObject:@"es"]; - if(intended_registers.cs() != execution_support.registers.cs()) [registers addObject:@"cs"]; - if(intended_registers.ds() != execution_support.registers.ds()) [registers addObject:@"ds"]; - if(intended_registers.ss() != execution_support.registers.ss()) [registers addObject:@"ss"]; +#define Reg(x) \ + if(intended_registers.x() != execution_support.registers.x()) \ + [registers addObject: \ + [NSString stringWithFormat: \ + @#x" is %04x rather than %04x", execution_support.registers.x(), intended_registers.x()]]; + + Reg(ax); + Reg(cx); + Reg(dx); + Reg(bx); + Reg(sp); + Reg(bp); + Reg(si); + Reg(di); + Reg(ip); + Reg(es); + Reg(cs); + Reg(ds); + Reg(ss); + +#undef Reg [reasons addObject:[NSString stringWithFormat: @"registers don't match: %@", [registers componentsJoinedByString:@", "] ]];