diff --git a/InstructionSets/x86/Decoder.cpp b/InstructionSets/x86/Decoder.cpp index 616602e33..b641a4edc 100644 --- a/InstructionSets/x86/Decoder.cpp +++ b/InstructionSets/x86/Decoder.cpp @@ -220,16 +220,10 @@ std::pair::InstructionT> Decoder::decode(con case 0x7e: Jump(JLE, DataSize::Byte); break; case 0x7f: Jump(JNLE, DataSize::Byte); break; - case 0x80: MemRegReg(Invalid, MemRegADD_to_CMP, DataSize::Byte); break; - case 0x81: MemRegReg(Invalid, MemRegADD_to_CMP, data_size_); break; - case 0x82: - MemRegReg(Invalid, MemRegADC_to_CMP, DataSize::Byte); - sign_extend_ = true; - break; - case 0x83: - MemRegReg(Invalid, MemRegADC_to_CMP, data_size_); - sign_extend_ = true; - break; + case 0x80: MemRegReg(Invalid, MemRegADD_to_CMP, DataSize::Byte); break; + case 0x81: MemRegReg(Invalid, MemRegADD_to_CMP, data_size_); break; + case 0x82: MemRegReg(Invalid, MemRegADD_to_CMP_SignExtend, DataSize::Byte); break; + case 0x83: MemRegReg(Invalid, MemRegADD_to_CMP_SignExtend, data_size_); break; case 0x84: MemRegReg(TEST, MemReg_Reg, DataSize::Byte); break; case 0x85: MemRegReg(TEST, MemReg_Reg, data_size_); break; @@ -582,8 +576,11 @@ std::pair::InstructionT> Decoder::decode(con break; case ModRegRMFormat::MemRegADD_to_CMP: + case ModRegRMFormat::MemRegADD_to_CMP_SignExtend: + source_ = Source::Immediate; destination_ = memreg; - operand_size_ = operation_size_; + operand_size_ = (modregrm_format_ == ModRegRMFormat::MemRegADD_to_CMP_SignExtend) ? DataSize::Byte : operation_size_; + sign_extend_ = true; // Will be effective only if modregrm_format_ == ModRegRMFormat::MemRegADD_to_CMP_SignExtend. switch(reg) { default: operation_ = Operation::ADD; break; @@ -597,23 +594,6 @@ std::pair::InstructionT> Decoder::decode(con } break; - case ModRegRMFormat::MemRegADC_to_CMP: - destination_ = memreg; - source_ = Source::Immediate; - operand_size_ = DataSize::Byte; // ... and always a byte; it'll be sign extended if - // the operation requires it. - - switch(reg) { - default: undefined(); - - case 0: operation_ = Operation::ADD; break; - case 2: operation_ = Operation::ADC; break; - case 3: operation_ = Operation::SBB; break; - case 5: operation_ = Operation::SUB; break; - case 7: operation_ = Operation::CMP; break; - } - break; - case ModRegRMFormat::MemRegSLDT_to_VERW: destination_ = source_ = memreg; diff --git a/InstructionSets/x86/Decoder.hpp b/InstructionSets/x86/Decoder.hpp index b50f7acd3..387bb3e05 100644 --- a/InstructionSets/x86/Decoder.hpp +++ b/InstructionSets/x86/Decoder.hpp @@ -69,11 +69,6 @@ template class Decoder { MemReg_Reg, Reg_MemReg, - // Parse for mode and register/memory fields, populating both - // source_ and destination_ fields with the result. Use the 'register' - // 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. @@ -85,9 +80,13 @@ template class Decoder { MemRegMOV, // Parse for mode and register/memory fields, populating the - // destination_ field with the result. Use the 'register' field - // to pick an operation from the ROL/ROR/RCL/RCR/SAL/SHR/SAR group. - MemRegROL_to_SAR, + // source_ field with the result. Fills destination_ with a segment + // register based on the reg field. + SegReg, + + // + // 'Group 1' + // // Parse for mode and register/memory fields, populating the // destination_ field with the result. Use the 'register' field @@ -95,37 +94,71 @@ template class Decoder { // waits for an operand equal to the operation size. MemRegADD_to_CMP, + // Acts exactly as MemRegADD_to_CMP but the operand is fixed in size + // at a single byte, which is sign extended to the operation size. + MemRegADD_to_CMP_SignExtend, + + // + // 'Group 2' + // + // Parse for mode and register/memory fields, populating the - // source_ field with the result. Fills destination_ with a segment - // register based on the reg field. - SegReg, + // destination_ field with the result. Use the 'register' field + // to pick an operation from the ROL/ROR/RCL/RCR/SAL/SHR/SAR group. + MemRegROL_to_SAR, + + // + // 'Group 3' + // + + // Parse for mode and register/memory fields, populating both + // source_ and destination_ fields with the result. Use the 'register' + // field to pick an operation from the TEST/NOT/NEG/MUL/IMUL/DIV/IDIV group. + MemRegTEST_to_IDIV, + + // + // 'Group 4' + // // Parse for mode and register/memory fields, populating the // source_ and destination_ fields with the result. Uses the // 'register' field to pick INC or DEC. MemRegINC_DEC, + // + // 'Group 5' + // + // Parse for mode and register/memory fields, populating the // source_ and destination_ fields with the result. Uses the // 'register' field to pick from INC/DEC/CALL/JMP/PUSH, altering // the source to ::Immediate and setting an operand size if necessary. MemRegINC_to_PUSH, - // Parse for mode and register/memory fields, populating the - // source_ and destination_ fields with the result. Uses the - // 'register' field to pick from ADD/ADC/SBB/SUB/CMP, altering - // the source to ::Immediate and setting an appropriate operand size. - MemRegADC_to_CMP, + // + // 'Group 6' + // // Parse for mode and register/memory field, populating both source_ // and destination_ fields with the result. Uses the 'register' field // to pick from SLDT/STR/LLDT/LTR/VERR/VERW. MemRegSLDT_to_VERW, + // + // 'Group 7' + // + // Parse for mode and register/memory field, populating both source_ // and destination_ fields with the result. Uses the 'register' field // to pick from SGDT/LGDT/SMSW/LMSW. MemRegSGDT_to_LMSW, + + // + // 'Group 8' + // + + // TODO. + MemRegBT_to_BTC, } modregrm_format_ = ModRegRMFormat::MemReg_Reg; // Ephemeral decoding state.