diff --git a/Processors/Decoders/x86/x86.cpp b/Processors/Decoders/x86/x86.cpp index af768627c..3cd0c458a 100644 --- a/Processors/Decoders/x86/x86.cpp +++ b/Processors/Decoders/x86/x86.cpp @@ -197,8 +197,7 @@ Instruction Decoder::decode(const uint8_t *source, size_t length) { // 0x8c: not used. MapMemRegReg(0x8d, LEA, Reg_MemReg, 2); // MapMemRegReg(0x8e, MOV, SegReg_MemReg, 1); // TODO: SegReg_MemReg - - // TODO: 0x8f, which requires further selection from the ModRegRM byte. + MapMemRegReg(0x8f, POP, MemRegPOP, 2); MapComplete(0x90, NOP, None, None, 0); // Or XCHG AX, AX? MapComplete(0x91, XCHG, AX, CX, 2); @@ -243,13 +242,15 @@ Instruction Decoder::decode(const uint8_t *source, size_t length) { MapRegData(0xbc, MOV, SP, 2); MapRegData(0xbd, MOV, BP, 2); MapRegData(0xbe, MOV, SI, 2); MapRegData(0xbf, MOV, DI, 2); - MapRegData(0xc2, RETIntra, None, 2); - MapComplete(0xc3, RETIntra, None, None, 2); + MapRegData(0xc2, RETN, None, 2); + MapComplete(0xc3, RETN, None, None, 2); MapMemRegReg(0xc4, LES, Reg_MemReg, 4); MapMemRegReg(0xc5, LDS, Reg_MemReg, 4); + MapMemRegReg(0xc6, MOV, MemRegMOV, 1); + MapMemRegReg(0xc7, MOV, MemRegMOV, 2); - MapRegData(0xca, RETInter, None, 2); - MapComplete(0xcb, RETInter, None, None, 4); + MapRegData(0xca, RETF, None, 2); + MapComplete(0xcb, RETF, None, None, 4); MapComplete(0xcc, INT3, None, None, 0); MapRegData(0xcd, INT, None, 1); @@ -299,8 +300,7 @@ Instruction Decoder::decode(const uint8_t *source, size_t length) { /* Unimplemented (but should be): - 0x8e, 0x8f, - 0xc6, 0xc7, + 0x8e, 0xd0, 0xd1, 0xd2, 0xd3, 0xfe, 0xff @@ -384,7 +384,7 @@ Instruction Decoder::decode(const uint8_t *source, size_t length) { switch(reg) { default: reset_parsing(); - return Instruction(); + return Instruction(consumed_); case 0: operation_ = Operation::TEST; break; case 2: operation_ = Operation::NOT; break; @@ -396,6 +396,21 @@ Instruction Decoder::decode(const uint8_t *source, size_t length) { } break; + case ModRegRMFormat::MemRegPOP: + source_ = destination_ = memreg; + + if(reg != 0) { + reset_parsing(); + return Instruction(consumed_); + } + break; + + case ModRegRMFormat::MemRegMOV: + source_ = Source::Immediate; + destination_ = memreg; + operand_size_ = operation_size_; + break; + default: assert(false); } diff --git a/Processors/Decoders/x86/x86.hpp b/Processors/Decoders/x86/x86.hpp index dfb87e8a1..dbe403756 100644 --- a/Processors/Decoders/x86/x86.hpp +++ b/Processors/Decoders/x86/x86.hpp @@ -23,6 +23,7 @@ enum class Model { enum class Operation: uint8_t { Invalid, + /// ASCII adjust for addition; AAA, AAD, AAM, AAS, ADC, ADD, AND, CALL, CBW, CLC, CLD, CLI, CMC, CMP, CMPS, CWD, DAA, DAS, DEC, DIV, ESC, HLT, IDIV, IMUL, IN, INC, INT, INT3, INTO, IRET, @@ -42,8 +43,8 @@ enum class Operation: uint8_t { WAIT, XCHG, XLAT, XOR, LES, LOOP, JPCX, - RETInter, - RETIntra, + RETF, + RETN, }; enum class Size: uint8_t { @@ -156,6 +157,16 @@ struct Decoder { // field to pick an operation from the TEST/NOT/NEG/MUL/IMUL/DIV/IDIV group. MemRegTEST_to_IDIV, + // Parse for mode and register/memory fields, populating both + // source_ and destination_ fields with the result. Use the 'register' + // field to check for the POP operation. + MemRegPOP, + + // Parse for mode and register/memory fields, populating both + // the destination_ field with the result and setting source_ to Immediate. + // Use the 'register' field to check for the MOV operation. + MemRegMOV, + } modregrm_format_ = ModRegRMFormat::MemReg_Reg; // Ephemeral decoding state.