fix(relinker): decode 3DNow! instructions with their ModRM and opcode suffix

0F 0F was decoded as a two-byte instruction. 3DNow! instructions are
0F 0F ModRM [SIB] [displacement] imm8, the trailing byte selecting the
operation (AMD64 Architecture Programmer's Manual Volume 3, Appendix A,
3DNow! opcodes).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
This commit is contained in:
Claude 2026-10-11 22:21:32 +00:00
parent dc70a66cbd
commit feb19a844d
No known key found for this signature in database
3 changed files with 8 additions and 1 deletions

View File

@ -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;

View File

@ -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) {

View File

@ -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},