diff --git a/core/relinker/codegen/include/codegen/x86/X64OpcodeConstants.hpp b/core/relinker/codegen/include/codegen/x86/X64OpcodeConstants.hpp index 889d0c447..7a9a14a36 100644 --- a/core/relinker/codegen/include/codegen/x86/X64OpcodeConstants.hpp +++ b/core/relinker/codegen/include/codegen/x86/X64OpcodeConstants.hpp @@ -170,6 +170,7 @@ inline constexpr std::uint8_t TwoByteGrp6 = 0x00; inline constexpr std::uint8_t TwoByteLar = 0x02; inline constexpr std::uint8_t TwoByteLsl = 0x03; inline constexpr std::uint8_t TwoBytePrefetchw = 0x0D; +inline constexpr std::uint8_t TwoByte3DNow = 0x0F; inline constexpr std::uint8_t TwoByteMovCrDrMin = 0x20; inline constexpr std::uint8_t TwoByteMovCrDrMax = 0x23; inline constexpr std::uint8_t TwoBytePopcnt = 0xB8; diff --git a/core/relinker/codegen/src/x86/X64InstructionDecoder.cpp b/core/relinker/codegen/src/x86/X64InstructionDecoder.cpp index b894332bd..4f9ff5b3b 100644 --- a/core/relinker/codegen/src/x86/X64InstructionDecoder.cpp +++ b/core/relinker/codegen/src/x86/X64InstructionDecoder.cpp @@ -242,7 +242,7 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t hasModRm = true; } else if (opcode >= TwoByteJccRel32Min && opcode <= TwoByteJccRel32Max) { immediateSize = ImmSize32; - } else if (opcode == TwoByteMovImm8ModRm) { + } else if (opcode == TwoByteMovImm8ModRm || opcode == TwoByte3DNow) { hasModRm = true; immediateSize = ImmSize8; } else if (opcode >= TwoByteShiftImm8Min && opcode <= TwoByteShiftImm8Max) { @@ -556,7 +556,7 @@ DecodedInstructionInfo X64InstructionDecoder::DecodeInstruction( op == TwoByteImulRmModRm || op == TwoByteGrp7 || op == TwoByteGrp15 || op == TwoByteXadd || op == TwoByteGrp9 || op == TwoByteNopModRm || - op == TwoByteEndbr || op == TwoByteMovImm8ModRm || + op == TwoByteEndbr || op == TwoByteMovImm8ModRm || op == TwoByte3DNow || op == ThreeByteEscape38 || op == ThreeByteEscape3A || (op >= TwoByteShiftImm8Min && op <= TwoByteShiftImm8Max) || op == TwoByteShldImm8 || op == TwoByteShrdImm8 || diff --git a/core/relinker/codegen/tests/DecoderLengthCases.hpp b/core/relinker/codegen/tests/DecoderLengthCases.hpp index 561f3a64e..10747c9a6 100644 --- a/core/relinker/codegen/tests/DecoderLengthCases.hpp +++ b/core/relinker/codegen/tests/DecoderLengthCases.hpp @@ -33,6 +33,12 @@ inline constexpr DecoderLengthCase kDecoderLengthCases[] = { {"0f0b", 2}, {"0f0d846511223344", 8}, {"0f0e", 2}, + {"0f0fc196", 4}, + {"0f0f08b7", 4}, + {"0f0f4f80b4", 5}, + {"0f0f846511223344b4", 9}, + {"0f0f0d11223344a6", 8}, + {"410f0f1c24bf", 6}, {"0f10846511223344", 8}, {"0f11846511223344", 8}, {"0f12846511223344", 8}, diff --git a/core/relinker/codegen/tests/DecoderLengthTests.cpp b/core/relinker/codegen/tests/DecoderLengthTests.cpp index d119b3b32..e141e1539 100644 --- a/core/relinker/codegen/tests/DecoderLengthTests.cpp +++ b/core/relinker/codegen/tests/DecoderLengthTests.cpp @@ -77,6 +77,10 @@ int main() { } catch (const Codegen::CodegenException&) { } } + const auto threeDNow = parse("0f0f0d11223344a6"); + const auto threeDNowInfo = decoder.DecodeInstruction(threeDNow.data(), threeDNow.size()); + require(threeDNowInfo.HasModRm && threeDNowInfo.ModRmByte == 0x0d, "3DNow! ModRM was not reported"); + require(threeDNowInfo.HasRipRelativeDisp && threeDNowInfo.RipRelativeDispOffset == 3, "3DNow! RIP-relative displacement was not reported"); std::cout << "Decoder length tests passed\n"; } catch (const std::exception& error) { std::cerr << error.what() << '\n';