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:
parent
a8c7871b0c
commit
02cea3047e
@ -674,6 +674,30 @@ void jump(bool condition, IntT displacement, RegistersT ®isters, FlowControll
|
||||
}
|
||||
}
|
||||
|
||||
template <typename IntT, typename OffsetT, typename RegistersT, typename FlowControllerT>
|
||||
void loop(IntT &counter, OffsetT displacement, RegistersT ®isters, 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 ®isters, 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 ®isters, 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;
|
||||
|
@ -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"];
|
||||
|
Loading…
x
Reference in New Issue
Block a user