diff --git a/InstructionSets/x86/Decoder.cpp b/InstructionSets/x86/Decoder.cpp index 19b75c4b7..3a18a11e5 100644 --- a/InstructionSets/x86/Decoder.cpp +++ b/InstructionSets/x86/Decoder.cpp @@ -42,13 +42,13 @@ std::pair::InstructionT> Decoder::decode(con /// Handles instructions of the form Ax, jjkk where the latter is implicitly an address. #define RegAddr(op, dest, op_size, addr_size) \ SetOpSrcDestSize(op, DirectAddress, dest, op_size); \ - operand_size_ = addr_size; \ + operand_size_ = data_size(addr_size); \ phase_ = Phase::DisplacementOrOperand /// Handles instructions of the form jjkk, Ax where the former is implicitly an address. #define AddrReg(op, source, op_size, addr_size) \ SetOpSrcDestSize(op, source, DirectAddress, op_size); \ - operand_size_ = addr_size; \ + operand_size_ = data_size(addr_size); \ destination_ = Source::DirectAddress; \ phase_ = Phase::DisplacementOrOperand @@ -298,10 +298,10 @@ std::pair::InstructionT> Decoder::decode(con case 0x9e: Complete(SAHF, None, None, DataSize::Byte); break; case 0x9f: Complete(LAHF, None, None, DataSize::Byte); break; - case 0xa0: RegAddr(MOV, eAX, DataSize::Byte, DataSize::Byte); break; - case 0xa1: RegAddr(MOV, eAX, data_size_, data_size_); break; - case 0xa2: AddrReg(MOV, eAX, DataSize::Byte, DataSize::Byte); break; - case 0xa3: AddrReg(MOV, eAX, data_size_, data_size_); break; + case 0xa0: RegAddr(MOV, eAX, DataSize::Byte, address_size_); break; + case 0xa1: RegAddr(MOV, eAX, data_size_, address_size_); break; + case 0xa2: AddrReg(MOV, eAX, DataSize::Byte, address_size_); break; + case 0xa3: AddrReg(MOV, eAX, data_size_, address_size_); break; case 0xa4: Complete(MOVS, None, None, DataSize::Byte); break; case 0xa5: Complete(MOVS, None, None, data_size_); break; @@ -391,10 +391,10 @@ std::pair::InstructionT> Decoder::decode(con case 0xe2: Displacement(LOOP, DataSize::Byte); break; case 0xe3: Displacement(JPCX, DataSize::Byte); break; - case 0xe4: RegAddr(IN, eAX, DataSize::Byte, DataSize::Byte); break; - case 0xe5: RegAddr(IN, eAX, data_size_, DataSize::Byte); break; - case 0xe6: AddrReg(OUT, eAX, DataSize::Byte, DataSize::Byte); break; - case 0xe7: AddrReg(OUT, eAX, data_size_, DataSize::Byte); break; + case 0xe4: RegAddr(IN, eAX, DataSize::Byte, address_size_); break; + case 0xe5: RegAddr(IN, eAX, data_size_, address_size_); break; + case 0xe6: AddrReg(OUT, eAX, DataSize::Byte, address_size_); break; + case 0xe7: AddrReg(OUT, eAX, data_size_, address_size_); break; case 0xe8: RegData(CALLD, None, data_size_); break; case 0xe9: RegData(JMPN, None, data_size_); break; @@ -624,7 +624,7 @@ std::pair::InstructionT> Decoder::decode(con const DataSize sizes[] = { DataSize::None, DataSize::Byte, - address_size_ == AddressSize::b16 ? DataSize::Word : DataSize::DWord + data_size(address_size_) }; displacement_size_ = sizes[mod]; memreg = Source::Indirect; @@ -712,11 +712,11 @@ std::pair::InstructionT> Decoder::decode(con default: undefined(); case 0: operation_ = Operation::ROL; break; - case 2: operation_ = Operation::ROR; break; - case 3: operation_ = Operation::RCL; break; - case 4: operation_ = Operation::RCR; break; - case 5: operation_ = Operation::SAL; break; - case 6: operation_ = Operation::SHR; break; + case 1: operation_ = Operation::ROR; break; + case 2: operation_ = Operation::RCL; break; + case 3: operation_ = Operation::RCR; break; + case 4: operation_ = Operation::SAL; break; + case 5: operation_ = Operation::SHR; break; case 7: operation_ = Operation::SAR; break; } break; diff --git a/InstructionSets/x86/Instruction.hpp b/InstructionSets/x86/Instruction.hpp index 4af89c411..d5afd1ec9 100644 --- a/InstructionSets/x86/Instruction.hpp +++ b/InstructionSets/x86/Instruction.hpp @@ -352,6 +352,10 @@ enum class AddressSize: uint8_t { b32 = 1, }; +constexpr DataSize data_size(AddressSize size) { + return DataSize(int(size) + 1); +} + constexpr int byte_size(AddressSize size) { return 2 << int(size); } diff --git a/OSBindings/Mac/Clock SignalTests/x86DecoderTests.mm b/OSBindings/Mac/Clock SignalTests/x86DecoderTests.mm index 1333761fe..f89bdb0fa 100644 --- a/OSBindings/Mac/Clock SignalTests/x86DecoderTests.mm +++ b/OSBindings/Mac/Clock SignalTests/x86DecoderTests.mm @@ -105,7 +105,7 @@ std::vector::InstructionT> decode(c */ @implementation x86DecoderTests -- (void)testSequence1 { +- (void)test16BitSequence { // Sequences the Online Disassembler believes to exist but The 8086 Book does not: // // 0x6a 0x65 push $65 @@ -220,7 +220,7 @@ std::vector::InstructionT> decode(c // dec %bp // jbe 0xffffffcc // inc %sp - test(instructions[34], DataSize::Word, Operation::POP, Source::eAX); + test(instructions[34], DataSize::Word, Operation::POP, Source::eAX, Source::eAX); test(instructions[35], DataSize::Word, Operation::DEC, Source::eBP, Source::eBP); test(instructions[36], Operation::JBE, std::nullopt, 0xff80); test(instructions[37], DataSize::Word, Operation::INC, Source::eSP, Source::eSP); @@ -409,31 +409,50 @@ std::vector::InstructionT> decode(c //fiadd DWORD PTR [ebx-0x64f3e674] test(instructions[16], DataSize::DWord, Operation::PUSH, Source::eAX); test(instructions[17], DataSize::Byte, Operation::DEC, Source::DH); - test(instructions[18], Operation::LOOPNE, 0, -18); + test(instructions[18], Operation::LOOPNE, 0, -63); + test(instructions[19], Operation::ESC); //mov DWORD PTR [ebx],edx //xor al,0x45 //lds edx,FWORD PTR [ecx] - - // Note to self: disassembly currently diverges at or immediately after this MOV: //mov ds:0xe4dba6d3,al + test(instructions[20], DataSize::DWord, Operation::MOV, Source::eDX, ScaleIndexBase(Source::eBX)); + test(instructions[21], DataSize::Byte, Operation::XOR, Source::Immediate, Source::eAX, 0x45); + test(instructions[22], DataSize::DWord, Operation::LDS, ScaleIndexBase(Source::eCX), Source::eDX); + test(instructions[23], DataSize::Byte, Operation::MOV, Source::eAX, Source::DirectAddress, 0xe4dba6d3); + XCTAssertEqual(instructions[23].data_segment(), Source::DS); + //pop ds //movs DWORD PTR es:[edi],DWORD PTR ds:[esi] - //jns 0x00000035 - //jge 0x00000060 + //jns 0x00000035 (from 0x42) + //jge 0x00000060 (from 0x44) + test(instructions[24], DataSize::Word, Operation::POP, Source::DS, Source::DS); + test(instructions[25], DataSize::DWord, Operation::MOVS); + test(instructions[26], Operation::JNS, 0, -0xd); + test(instructions[27], Operation::JNL, 0, 0x1c); + //mov eax,0x8a766bda - //jns 0x00000073 + //jns 0x00000073 (from 0x4b) //push edx //int 0xc4 + test(instructions[28], DataSize::DWord, Operation::MOV, Source::Immediate, Source::eAX, 0x8a766bda); + test(instructions[29], Operation::JNS, 0, 0x28); + test(instructions[30], DataSize::DWord, Operation::PUSH, Source::eDX); + test(instructions[31], Operation::INT, 0xc4); + //jmp 0x29cf120d //or DWORD PTR [esi+0x1a],eax //rcr BYTE PTR [ebp-0x78],0x34 //movs DWORD PTR es:[edi],DWORD PTR ds:[esi] + test(instructions[32], Operation::JMPN, 0x29cf120d); + test(instructions[33], Operation::OR, DataSize::DWord, Source::eAX, ScaleIndexBase(Source::eSI), 0, 0x1a); + //and edx,0xffffffd0 //cmc //inc esp //popf //movs DWORD PTR es:[edi],DWORD PTR ds:[esi] + // Note to self: divergance at or just after here. //rcr DWORD PTR [esi+0x4f],0x7 //push ecx //aam 0xed