diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index aacad8c6d..cb214e35f 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -1460,6 +1460,32 @@ void stos(const InstructionT &instruction, AddressT &eCX, AddressT &eDI, IntT &e repeat(instruction, eCX, flow_controller); } +template +void outs(const InstructionT &instruction, AddressT &eCX, uint16_t port, AddressT &eSI, MemoryT &memory, IOT &io, Status &status, FlowControllerT &flow_controller) { + if(repetition_over(instruction, eCX)) { + return; + } + + Source source_segment = instruction.segment_override(); + if(source_segment == Source::None) source_segment = Source::DS; + io.template out(port, memory.template access(source_segment, eSI)); + eSI += status.direction() * sizeof(IntT); + + repeat(instruction, eCX, flow_controller); +} + +template +void ins(const InstructionT &instruction, AddressT &eCX, uint16_t port, AddressT &eDI, MemoryT &memory, IOT &io, Status &status, FlowControllerT &flow_controller) { + if(repetition_over(instruction, eCX)) { + return; + } + + memory.template access(Source::ES, eDI) = io.template in(port); + eDI += status.direction() * sizeof(IntT); + + repeat(instruction, eCX, flow_controller); +} + template void out(uint16_t port, IntT value, IOT &io) { io.template out(port, value); @@ -1571,6 +1597,14 @@ template < } }; + // Gets the port for an IN or OUT; these are always 16-bit. + const auto port = [&](Source source) -> uint16_t { + switch(source) { + case Source::DirectAddress: return instruction.operand(); + default: return registers.dx(); + } + }; + // Guide to the below: // // * use hard-coded register names where appropriate; @@ -1703,22 +1737,8 @@ template < } return; - case Operation::OUT: { - uint16_t port; - switch(instruction.destination().source()) { - case Source::DirectAddress: port = instruction.operand(); break; - default: port = registers.dx(); break; - } - Primitive::out(port, pair_low(), io); - } return; - case Operation::IN: { - uint16_t port; - switch(instruction.source().source()) { - case Source::DirectAddress: port = instruction.operand(); break; - default: port = registers.dx(); break; - } - Primitive::in(port, pair_low(), io); - } return; + case Operation::OUT: Primitive::out(port(instruction.destination().source()), pair_low(), io); return; + case Operation::IN: Primitive::in(port(instruction.source().source()), pair_low(), io); return; case Operation::XLAT: Primitive::xlat(instruction, memory, registers); return; @@ -1742,6 +1762,12 @@ template < case Operation::SCAS: Primitive::scas(instruction, eCX(), eDI(), pair_low(), memory, status, flow_controller); break; + case Operation::OUTS: + Primitive::outs(instruction, eCX(), registers.dx(), eSI(), memory, io, status, flow_controller); + break; + case Operation::INS: + Primitive::outs(instruction, eCX(), registers.dx(), eDI(), memory, io, status, flow_controller); + break; } // Write to memory if required to complete this operation. diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index d63b25555..f26210526 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -354,7 +354,7 @@ struct FailedExecution { @"4C.json.gz", @"4D.json.gz", @"4E.json.gz", @"4F.json.gz", @"FE.1.json.gz", @"FF.1.json.gz", -*/ + // OUT @"E6.json.gz", @"E7.json.gz", @"EE.json.gz", @"EF.json.gz", @@ -362,7 +362,7 @@ struct FailedExecution { // IN @"E4.json.gz", @"E5.json.gz", @"EC.json.gz", @"ED.json.gz", -/* + @"70.json.gz", // JO @"71.json.gz", // JNO @"72.json.gz", // JB @@ -423,9 +423,13 @@ struct FailedExecution { // SCAS @"AE.json.gz", @"AF.json.gz", +*/ + // OUTS + @"6E.json.gz", @"6F.json.gz", - // TODO: INS, OUTS - + // INS + @"6C.json.gz", @"6D.json.gz", +/* @"E0.json.gz", // LOOPNE @"E1.json.gz", // LOOPE @"E2.json.gz", // LOOP