1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-04-09 00:37:27 +00:00

Implement LOOP, LOOPE, LOOPNE.

This commit is contained in:
Thomas Harte 2023-10-18 14:04:21 -04:00
parent a8c7871b0c
commit 02cea3047e
2 changed files with 53 additions and 15 deletions

View File

@ -674,6 +674,30 @@ void jump(bool condition, IntT displacement, RegistersT &registers, FlowControll
}
}
template <typename IntT, typename OffsetT, typename RegistersT, typename FlowControllerT>
void loop(IntT &counter, OffsetT displacement, RegistersT &registers, FlowControllerT &flow_controller) {
--counter;
if(counter) {
flow_controller.jump(registers.ip() + displacement);
}
}
template <typename IntT, typename OffsetT, typename RegistersT, typename FlowControllerT>
void loope(IntT &counter, OffsetT displacement, RegistersT &registers, Status &status, FlowControllerT &flow_controller) {
--counter;
if(counter && status.flag<Flag::Zero>()) {
flow_controller.jump(registers.ip() + displacement);
}
}
template <typename IntT, typename OffsetT, typename RegistersT, typename FlowControllerT>
void loopne(IntT &counter, OffsetT displacement, RegistersT &registers, Status &status, FlowControllerT &flow_controller) {
--counter;
if(counter && !status.flag<Flag::Zero>()) {
flow_controller.jump(registers.ip() + displacement);
}
}
template <typename IntT>
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<model>(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;

View File

@ -73,11 +73,6 @@ struct Registers {
uint16_t &ds() { return ds_; }
uint16_t &ss() { return ss_; }
// uint32_t zero_ = 0;
// template <typename IntT> IntT &zero() {
// return static_cast<IntT>(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<NSString *> *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"];