From 02cea3047ee5691dd6511efa7344d47effefd957 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 18 Oct 2023 14:04:21 -0400 Subject: [PATCH] Implement LOOP, LOOPE, LOOPNE. --- .../Implementation/PerformImplementation.hpp | 34 ++++++++++++++++--- OSBindings/Mac/Clock SignalTests/8088Tests.mm | 34 +++++++++++++------ 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index fdab87e8c..d75a848e0 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -674,6 +674,30 @@ void jump(bool condition, IntT displacement, RegistersT ®isters, FlowControll } } +template +void loop(IntT &counter, OffsetT displacement, RegistersT ®isters, FlowControllerT &flow_controller) { + --counter; + if(counter) { + flow_controller.jump(registers.ip() + displacement); + } +} + +template +void loope(IntT &counter, OffsetT displacement, RegistersT ®isters, Status &status, FlowControllerT &flow_controller) { + --counter; + if(counter && status.flag()) { + flow_controller.jump(registers.ip() + displacement); + } +} + +template +void loopne(IntT &counter, OffsetT displacement, RegistersT ®isters, Status &status, FlowControllerT &flow_controller) { + --counter; + if(counter && !status.flag()) { + flow_controller.jump(registers.ip() + displacement); + } +} + template void dec(IntT &destination, Status &status) { /* @@ -1452,10 +1476,12 @@ template < case Operation::JMPrel: jcc(true); return; case Operation::JMPabs: Primitive::jump_absolute(destination(), flow_controller); return; case Operation::JMPfar: Primitive::jump_far(instruction, flow_controller, registers, memory); return; - case Operation::JCXZ: - // TODO: use ECX rather than CX if address size is 32-bit. - jcc(!registers.cx()); - 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::IRET: Primitive::iret(registers, flow_controller, memory, status); return; case Operation::RETnear: Primitive::ret_near(instruction, registers, flow_controller, memory); return; diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index 85f8da4c9..9c1d3129b 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -73,11 +73,6 @@ struct Registers { uint16_t &ds() { return ds_; } uint16_t &ss() { return ss_; } -// uint32_t zero_ = 0; -// template IntT &zero() { -// return static_cast(zero); -// } - bool operator ==(const Registers &rhs) const { return ax_.full == rhs.ax_.full && @@ -380,9 +375,8 @@ struct FailedExecution { @"EA.josn.gz", @"FF.5.json.gz", // far JMP @"FF.4.json.gz", // absolute JMP -*/ @"E3.json.gz", // JCXZ -/* + // INTO @"CE.json.gz", @@ -397,9 +391,11 @@ struct FailedExecution { @"8D.json.gz", // LEA // TODO: CMPS, LODS, MOVS, SCAS, STOS - - // TODO: LOOP, LOOPE, LOOPNE - +*/ + @"E0.json.gz", // LOOPNE + @"E1.json.gz", // LOOPE + @"E2.json.gz", // LOOP +/* // MOV @"88.json.gz", @"89.json.gz", @"8A.json.gz", @"8B.json.gz", @"8C.json.gz", @"8E.json.gz", @@ -717,7 +713,23 @@ struct FailedExecution { difference.to_string().c_str()]]; } if(!registersEqual) { - [reasons addObject:@"registers don't match"]; + 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"]; + [reasons addObject:[NSString stringWithFormat: + @"registers don't match: %@", [registers componentsJoinedByString:@", "] + ]]; } if(!ramEqual) { [reasons addObject:@"RAM contents don't match"];