diff --git a/InstructionSets/x86/Decoder.cpp b/InstructionSets/x86/Decoder.cpp index 56410a244..81a369e22 100644 --- a/InstructionSets/x86/Decoder.cpp +++ b/InstructionSets/x86/Decoder.cpp @@ -442,12 +442,12 @@ std::pair::InstructionT> Decoder::decode(con if constexpr (model >= Model::i80186) { Complete(LEAVE, None, None, DataSize::Byte); } else { - Complete(RETfar, None, None, DataSize::DWord); + Complete(RETfar, None, None, DataSize::Word); } break; case 0xca: RegData(RETfar, None, data_size_); break; - case 0xcb: Complete(RETfar, None, None, DataSize::DWord); break; + case 0xcb: Complete(RETfar, None, None, DataSize::Word); break; case 0xcc: // Encode INT3 as though it were INT with an @@ -1065,7 +1065,7 @@ std::pair::InstructionT> Decoder::decode(con address_size_, segment_override_, repetition_, - DataSize(operation_size_), + operation_size_, static_cast(displacement_), static_cast(operand_), consumed_ diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index 75f470142..735337fd2 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -165,6 +165,24 @@ IntT *resolve( namespace Primitive { +template +void push(IntT value, MemoryT &memory, RegistersT ®isters) { + registers.sp_ -= sizeof(IntT); + memory.template access( + InstructionSet::x86::Source::SS, + registers.sp_) = value; + memory.template write_back(); +} + +template +IntT pop(MemoryT &memory, RegistersT ®isters) { + const auto value = memory.template access( + InstructionSet::x86::Source::SS, + registers.sp_); + registers.sp_ += sizeof(IntT); + return value; +} + // // Comments below on intended functioning of each operation come from the 1997 edition of the // Intel Architecture Software Developer’s Manual; that year all such definitions still fitted within a @@ -793,6 +811,30 @@ void call_far(InstructionT &instruction, flow_controller.call(segment, offset); } +template +void iret(RegistersT ®isters, FlowControllerT &flow_controller, MemoryT &memory, Status &status) { + // TODO: all modes other than 16-bit real mode. + registers.ip() = pop(memory, registers); + registers.cs() = pop(memory, registers); + status.set(pop(memory, registers)); + flow_controller.did_iret(); +} + +template +void ret_near(InstructionT instruction, RegistersT ®isters, FlowControllerT &flow_controller, MemoryT &memory) { + registers.ip() = pop(memory, registers); + registers.sp() += instruction.operand(); + flow_controller.did_near_ret(); +} + +template +void ret_far(InstructionT instruction, RegistersT ®isters, FlowControllerT &flow_controller, MemoryT &memory) { + registers.ip() = pop(memory, registers); + registers.cs() = pop(memory, registers); + registers.sp() += instruction.operand(); + flow_controller.did_far_ret(); +} + template void ld( InstructionT &instruction, @@ -1370,6 +1412,10 @@ template < Primitive::call_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; + case Operation::INT: Primitive::int_(instruction.operand(), flow_controller); return; case Operation::INTO: Primitive::into(status, flow_controller); return; diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index ecbf7226d..30e21bdee 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -66,7 +66,7 @@ struct Registers { uint16_t es_, cs_, ds_, ss_; uint16_t ip_; - uint16_t ip() { return ip_; } + uint16_t &ip() { return ip_; } uint16_t &es() { return es_; } uint16_t &cs() { return cs_; } @@ -190,6 +190,10 @@ 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) { const uint16_t address = static_cast(index) << 2; const uint16_t new_ip = memory_.access(address, Memory::Tag::Accessed); @@ -361,9 +365,13 @@ struct FailedExecution { // CALL @"E8.json.gz", @"FF.2.json.gz", @"9A.json.gz", @"FF.3.json.gz", +*/ + // IRET + @"CF.json.gz", - // TODO: IRET - // TODO: RET + @"C3.json.gz", @"C2.json.gz", // near RET + @"CB.json.gz", @"CA.json.gz", // far RET +/* // TODO: JMP // TODO: JCXZ @@ -379,13 +387,11 @@ struct FailedExecution { @"C5.json.gz", // LDS @"C4.json.gz", // LES @"8D.json.gz", // LEA -*/ // TODO: CMPS, LODS, MOVS, SCAS, STOS // TODO: LOOP, LOOPE, LOOPNE -/* // MOV @"88.json.gz", @"89.json.gz", @"8A.json.gz", @"8B.json.gz", @"8C.json.gz", @"8E.json.gz", @@ -434,21 +440,19 @@ struct FailedExecution { // ROR @"D0.1.json.gz", @"D2.1.json.gz", @"D1.1.json.gz", @"D3.1.json.gz", -*/ // SAL -// @"D0.4.json.gz", @"D2.4.json.gz", -// @"D1.4.json.gz", @"D3.4.json.gz", + @"D0.4.json.gz", @"D2.4.json.gz", + @"D1.4.json.gz", @"D3.4.json.gz", // SAR -// @"D0.7.json.gz", @"D2.7.json.gz", -// @"D1.7.json.gz", @"D3.7.json.gz", + @"D0.7.json.gz", @"D2.7.json.gz", + @"D1.7.json.gz", @"D3.7.json.gz", // SHR @"D0.5.json.gz", @"D2.5.json.gz", @"D1.5.json.gz", @"D3.5.json.gz", -/* @"F8.json.gz", // CLC @"FC.json.gz", // CLD @"FA.json.gz", // CLI @@ -632,7 +636,7 @@ struct FailedExecution { status.set([value[@"flags"] intValue]); } -- (void)applyExecutionTest:(NSDictionary *)test file:(NSString *)file metadata:(NSDictionary *)metadata { +- (void)applyExecutionTest:(NSDictionary *)test metadata:(NSDictionary *)metadata { InstructionSet::x86::Decoder decoder; const auto data = [self bytes:test[@"bytes"]]; const auto decoded = decoder.decode(data.data(), data.size()); @@ -656,10 +660,6 @@ struct FailedExecution { execution_support.status = initial_status; execution_support.registers = initial_registers; - if([test[@"name"] isEqual:@"rol byte ss:[bp+si+CF11h], cl"]) { - printf(""); - } - // Execute instruction. execution_support.registers.ip_ += decoded.first; InstructionSet::x86::perform( @@ -760,7 +760,7 @@ struct FailedExecution { } for(NSDictionary *test in [self testsInFile:file]) { - [self applyExecutionTest:test file:file metadata:test_metadata]; + [self applyExecutionTest:test metadata:test_metadata]; } }