1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +00:00

Implement JMP.

This commit is contained in:
Thomas Harte 2023-10-18 13:15:00 -04:00
parent 440f3bdb10
commit 90f49a6e73
2 changed files with 59 additions and 6 deletions

View File

@ -779,6 +779,11 @@ void call_absolute(IntT target, FlowControllerT &flow_controller) {
flow_controller.call(target);
}
template <typename IntT, typename FlowControllerT>
void jump_absolute(IntT target, FlowControllerT &flow_controller) {
flow_controller.jump(target);
}
template <Model model, typename InstructionT, typename FlowControllerT, typename RegistersT, typename MemoryT>
void call_far(InstructionT &instruction,
FlowControllerT &flow_controller,
@ -811,6 +816,38 @@ void call_far(InstructionT &instruction,
flow_controller.call(segment, offset);
}
template <Model model, typename InstructionT, typename FlowControllerT, typename RegistersT, typename MemoryT>
void jump_far(InstructionT &instruction,
FlowControllerT &flow_controller,
RegistersT &registers,
MemoryT &memory
) {
// TODO: eliminate 16-bit assumption below.
uint16_t source_address = 0;
const auto pointer = instruction.destination();
switch(pointer.template source<false>()) {
default:
case Source::Immediate: flow_controller.call(instruction.segment(), instruction.offset()); return;
case Source::Indirect:
source_address = address<model, Source::Indirect, uint16_t>(instruction, pointer, registers, memory);
break;
case Source::IndirectNoBase:
source_address = address<model, Source::IndirectNoBase, uint16_t>(instruction, pointer, registers, memory);
break;
case Source::DirectAddress:
source_address = address<model, Source::DirectAddress, uint16_t>(instruction, pointer, registers, memory);
break;
}
const Source source_segment = pointer.segment(instruction.segment_override());
const uint16_t offset = memory.template access<uint16_t>(source_segment, source_address);
source_address += 2;
const uint16_t segment = memory.template access<uint16_t>(source_segment, source_address);
flow_controller.jump(segment, offset);
}
template <typename FlowControllerT, typename RegistersT, typename MemoryT>
void iret(RegistersT &registers, FlowControllerT &flow_controller, MemoryT &memory, Status &status) {
// TODO: all modes other than 16-bit real mode.
@ -1412,7 +1449,11 @@ template <
Primitive::call_far<model>(instruction, flow_controller, registers, memory);
return;
case Operation::IRET: Primitive::iret(registers, flow_controller, memory, status); return;
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::IRET: Primitive::iret(registers, flow_controller, memory, status); return;
case Operation::RETnear: Primitive::ret_near(instruction, registers, flow_controller, memory); return;
case Operation::RETfar: Primitive::ret_far(instruction, registers, flow_controller, memory); return;

View File

@ -214,20 +214,24 @@ class FlowController {
void call(uint16_t address) {
push(registers_.ip_);
registers_.ip_ = address;
jump(address);
}
void call(uint16_t segment, uint16_t offset) {
push(registers_.cs_);
push(registers_.ip_);
registers_.cs_ = segment;
registers_.ip_ = offset;
jump(segment, offset);
}
void jump(uint16_t address) {
registers_.ip_ = address;
}
void jump(uint16_t segment, uint16_t address) {
registers_.cs_ = segment;
registers_.ip_ = address;
}
void halt() {}
void wait() {}
@ -365,14 +369,22 @@ struct FailedExecution {
// CALL
@"E8.json.gz", @"FF.2.json.gz",
@"9A.json.gz", @"FF.3.json.gz",
*/
// IRET
@"CF.json.gz",
@"C3.json.gz", @"C2.json.gz", // near RET
@"CB.json.gz", @"CA.json.gz", // far RET
*/
// relative JMP
@"EB.json.gz", @"E9.json.gz",
// far JMP
@"EA.josn.gz", @"FF.5.json.gz",
@"FF.4.json.gz", // absolute JMP
/*
// TODO: JMP
// TODO: JCXZ
// INTO