From 90f49a6e73ca1843d63e0ae61b0be4c9418d9dbf Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 18 Oct 2023 13:15:00 -0400 Subject: [PATCH] Implement JMP. --- .../Implementation/PerformImplementation.hpp | 43 ++++++++++++++++++- OSBindings/Mac/Clock SignalTests/8088Tests.mm | 22 +++++++--- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index 735337fd2..c4d2e00a2 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -779,6 +779,11 @@ void call_absolute(IntT target, FlowControllerT &flow_controller) { flow_controller.call(target); } +template +void jump_absolute(IntT target, FlowControllerT &flow_controller) { + flow_controller.jump(target); +} + template void call_far(InstructionT &instruction, FlowControllerT &flow_controller, @@ -811,6 +816,38 @@ void call_far(InstructionT &instruction, flow_controller.call(segment, offset); } +template +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()) { + default: + case Source::Immediate: flow_controller.call(instruction.segment(), instruction.offset()); return; + + case Source::Indirect: + source_address = address(instruction, pointer, registers, memory); + break; + case Source::IndirectNoBase: + source_address = address(instruction, pointer, registers, memory); + break; + case Source::DirectAddress: + source_address = address(instruction, pointer, registers, memory); + break; + } + + const Source source_segment = pointer.segment(instruction.segment_override()); + + const uint16_t offset = memory.template access(source_segment, source_address); + source_address += 2; + const uint16_t segment = memory.template access(source_segment, source_address); + flow_controller.jump(segment, offset); +} + template 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(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(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; diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index 0f9db80f8..f4228ca3b 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -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