diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index 03c7ae25c..cee2863ed 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -821,14 +821,16 @@ void not_(IntT &destination) { destination = ~destination; } -template -void call_relative(IntT offset, RegistersT ®isters, FlowControllerT &flow_controller) { - flow_controller.call(registers.ip() + offset); +template +void call_relative(IntT offset, RegistersT ®isters, MemoryT &memory, FlowControllerT &flow_controller) { + push(registers.ip(), memory, registers); + flow_controller.jump(registers.ip() + offset); } -template -void call_absolute(IntT target, FlowControllerT &flow_controller) { - flow_controller.call(target); +template +void call_absolute(IntT target, RegistersT ®isters, MemoryT &memory, FlowControllerT &flow_controller) { + push(registers.ip(), memory, registers); + flow_controller.jump(target); } template @@ -843,11 +845,18 @@ void call_far(InstructionT &instruction, MemoryT &memory ) { // TODO: eliminate 16-bit assumption below. - uint16_t source_address = 0; + const Source source_segment = instruction.data_segment(); + memory.preauthorise_stack_write(sizeof(uint16_t) * 2); + + uint16_t source_address; const auto pointer = instruction.destination(); switch(pointer.source()) { default: - case Source::Immediate: flow_controller.call(instruction.segment(), instruction.offset()); return; + case Source::Immediate: + push(registers.cs(), memory, registers); + push(registers.ip(), memory, registers); + flow_controller.jump(instruction.segment(), instruction.offset()); + return; case Source::Indirect: source_address = address(instruction, pointer, registers, memory); @@ -860,13 +869,14 @@ void call_far(InstructionT &instruction, break; } - const Source source_segment = instruction.data_segment(); + memory.preauthorise_read(source_segment, source_address, sizeof(uint16_t) * 2); + push(registers.cs(), memory, registers); + push(registers.ip(), memory, registers); - // TODO: preauthorise reads. - const uint16_t offset = memory.template access(source_segment, source_address); + 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.call(segment, offset); + const uint16_t segment = memory.template access(source_segment, source_address); + flow_controller.jump(segment, offset); } template @@ -904,27 +914,27 @@ void jump_far(InstructionT &instruction, template void iret(RegistersT ®isters, FlowControllerT &flow_controller, MemoryT &memory, Status &status) { // TODO: all modes other than 16-bit real mode. - memory.preauthorise_stack(sizeof(uint16_t) * 3); - registers.ip() = pop(memory, registers); - registers.cs() = pop(memory, registers); + memory.preauthorise_stack_read(sizeof(uint16_t) * 3); + const auto ip = pop(memory, registers); + const auto cs = pop(memory, registers); status.set(pop(memory, registers)); - flow_controller.did_iret(); + flow_controller.jump(cs, ip); } template void ret_near(InstructionT instruction, RegistersT ®isters, FlowControllerT &flow_controller, MemoryT &memory) { - registers.ip() = pop(memory, registers); + const auto ip = pop(memory, registers); registers.sp() += instruction.operand(); - flow_controller.did_near_ret(); + flow_controller.jump(ip); } template void ret_far(InstructionT instruction, RegistersT ®isters, FlowControllerT &flow_controller, MemoryT &memory) { - memory.preauthorise_stack(sizeof(uint16_t) * 2); - registers.ip() = pop(memory, registers); - registers.cs() = pop(memory, registers); + memory.preauthorise_stack_read(sizeof(uint16_t) * 2); + const auto ip = pop(memory, registers); + const auto cs = pop(memory, registers); registers.sp() += instruction.operand(); - flow_controller.did_far_ret(); + flow_controller.jump(cs, ip); } template @@ -1691,10 +1701,10 @@ template < case Operation::NOT: Primitive::not_(source_rmw()); break; // TODO: should be a destination. case Operation::CALLrel: - Primitive::call_relative(instruction.displacement(), registers, flow_controller); + Primitive::call_relative(instruction.displacement(), registers, memory, flow_controller); return; case Operation::CALLabs: - Primitive::call_absolute(destination_r(), flow_controller); + Primitive::call_absolute(destination_r(), registers, memory, flow_controller); return; case Operation::CALLfar: Primitive::call_far(instruction, flow_controller, registers, memory); diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index 2fefee383..88623dfe0 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -133,7 +133,9 @@ struct Memory { return physical_address << 4; } - void preauthorise_stack(uint32_t) {} + void preauthorise_stack_write(uint32_t) {} + void preauthorise_stack_read(uint32_t) {} + void preauthorise_read(InstructionSet::x86::Source, uint16_t, uint32_t) {} // Entry point used by the flow controller so that it can mark up locations at which the flags were written, // so that defined-flag-only masks can be applied while verifying RAM contents. @@ -233,10 +235,6 @@ class FlowController { FlowController(Memory &memory, Registers ®isters, Status &status) : memory_(memory), registers_(registers), status_(status) {} - void did_iret() {} - void did_near_ret() {} - void did_far_ret() {} - void interrupt(int index) { // TODO: reauthorise and possibly double fault? const uint16_t address = static_cast(index) << 2; @@ -256,17 +254,6 @@ class FlowController { registers_.ip_ = new_ip; } - void call(uint16_t address) { - push(registers_.ip_); - jump(address); - } - - void call(uint16_t segment, uint16_t offset) { - push(registers_.cs_); - push(registers_.ip_); - jump(segment, offset); - } - void jump(uint16_t address) { registers_.ip_ = address; }