mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-23 18:29:16 +00:00
Implement JMP.
This commit is contained in:
parent
440f3bdb10
commit
90f49a6e73
InstructionSets/x86/Implementation
OSBindings/Mac/Clock SignalTests
@ -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 ®isters,
|
||||
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 ®isters, 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;
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user