refactor(code): move decoder opcodes to constexpr in header

This commit is contained in:
boykopovar 2026-08-04 22:32:04 +03:00
parent c14c1467c0
commit aeb9adfb33
4 changed files with 251 additions and 122 deletions

View File

@ -26,42 +26,6 @@ private:
std::size_t FieldOffset;
};
static constexpr std::uint8_t OpcodePrefixLock = 0xF0;
static constexpr std::uint8_t OpcodePrefixRepne = 0xF2;
static constexpr std::uint8_t OpcodePrefixRep = 0xF3;
static constexpr std::uint8_t OpcodePrefixSegCs = 0x2E;
static constexpr std::uint8_t OpcodePrefixSegSs = 0x36;
static constexpr std::uint8_t OpcodePrefixSegDs = 0x3E;
static constexpr std::uint8_t OpcodePrefixSegEs = 0x26;
static constexpr std::uint8_t OpcodePrefixSegFs = 0x64;
static constexpr std::uint8_t OpcodePrefixSegGs = 0x65;
static constexpr std::uint8_t OpcodePrefixOperandSize = 0x66;
static constexpr std::uint8_t OpcodePrefixAddressSize = 0x67;
static constexpr std::uint8_t RexMin = 0x40;
static constexpr std::uint8_t RexMax = 0x4F;
static constexpr std::uint8_t TwoByteOpcodeEscape = 0x0F;
static constexpr std::uint8_t OpcodeCallRel32 = 0xE8;
static constexpr std::uint8_t OpcodeJmpRel32 = 0xE9;
static constexpr std::uint8_t OpcodeJmpRel8 = 0xEB;
static constexpr std::uint8_t OpcodeJccRel8Min = 0x70;
static constexpr std::uint8_t OpcodeJccRel8Max = 0x7F;
static constexpr std::uint8_t OpcodeJccRel32Min = 0x80;
static constexpr std::uint8_t OpcodeJccRel32Max = 0x8F;
static constexpr std::size_t Rel32InstructionLength = 5;
static constexpr std::size_t Rel8FieldSize = 1;
static constexpr std::size_t Rel32FieldSize = 4;
static constexpr std::size_t Disp32FieldSize = 4;
static constexpr std::uint8_t ModRmModShift = 6;
static constexpr std::uint8_t ModRmModMask = 0x03;
static constexpr std::uint8_t ModRmRmMask = 0x07;
static constexpr std::uint8_t ModRmModIndirect = 0x00;
static constexpr std::uint8_t ModRmRmRipRelative = 0x05;
[[nodiscard]] static ReferenceSite ClassifyInstruction(
const std::uint8_t* data,
std::size_t length

View File

@ -0,0 +1,152 @@
#ifndef CODEGEN_X86_X64OPCODECONSTANTS_HPP
#define CODEGEN_X86_X64OPCODECONSTANTS_HPP
#include <cstdint>
namespace Codegen::X64OpcodeConstants {
inline constexpr std::uint8_t PrefixLock = 0xF0;
inline constexpr std::uint8_t PrefixRepne = 0xF2;
inline constexpr std::uint8_t PrefixRep = 0xF3;
inline constexpr std::uint8_t PrefixSegCs = 0x2E;
inline constexpr std::uint8_t PrefixSegSs = 0x36;
inline constexpr std::uint8_t PrefixSegDs = 0x3E;
inline constexpr std::uint8_t PrefixSegEs = 0x26;
inline constexpr std::uint8_t PrefixSegFs = 0x64;
inline constexpr std::uint8_t PrefixSegGs = 0x65;
inline constexpr std::uint8_t PrefixOperandSize = 0x66;
inline constexpr std::uint8_t PrefixAddressSize = 0x67;
inline constexpr std::uint8_t RexMin = 0x40;
inline constexpr std::uint8_t RexMax = 0x4F;
inline constexpr std::uint8_t RexWBit = 0x08;
inline constexpr std::uint8_t TwoByteOpcodeEscape = 0x0F;
inline constexpr std::uint8_t OneByteModRmRangeAMin = 0x00;
inline constexpr std::uint8_t OneByteModRmRangeAMax = 0x03;
inline constexpr std::uint8_t OneByteModRmRangeBMin = 0x08;
inline constexpr std::uint8_t OneByteModRmRangeBMax = 0x0B;
inline constexpr std::uint8_t OneByteModRmRangeCMin = 0x10;
inline constexpr std::uint8_t OneByteModRmRangeCMax = 0x13;
inline constexpr std::uint8_t OneByteModRmRangeDMin = 0x18;
inline constexpr std::uint8_t OneByteModRmRangeDMax = 0x1B;
inline constexpr std::uint8_t OneByteModRmRangeEMin = 0x20;
inline constexpr std::uint8_t OneByteModRmRangeEMax = 0x23;
inline constexpr std::uint8_t OneByteModRmRangeFMin = 0x28;
inline constexpr std::uint8_t OneByteModRmRangeFMax = 0x2B;
inline constexpr std::uint8_t OneByteModRmRangeGMin = 0x30;
inline constexpr std::uint8_t OneByteModRmRangeGMax = 0x33;
inline constexpr std::uint8_t OneByteModRmRangeHMin = 0x38;
inline constexpr std::uint8_t OneByteModRmRangeHMax = 0x3B;
inline constexpr std::uint8_t OneByteArpl = 0x62;
inline constexpr std::uint8_t OneByteMovsxd = 0x63;
inline constexpr std::uint8_t OneByteModRmRangeIMin = 0x84;
inline constexpr std::uint8_t OneByteModRmRangeIMax = 0x8F;
inline constexpr std::uint8_t OneByteGrp2Rm8Imm8 = 0xC0;
inline constexpr std::uint8_t OneByteGrp2RmImm8 = 0xC1;
inline constexpr std::uint8_t OneByteVex3 = 0xC4;
inline constexpr std::uint8_t OneByteVex2 = 0xC5;
inline constexpr std::uint8_t OneByteMovImm8 = 0xC6;
inline constexpr std::uint8_t OneByteMovImm32 = 0xC7;
inline constexpr std::uint8_t OneByteShiftRm8By1 = 0xD0;
inline constexpr std::uint8_t OneByteShiftRmBy1 = 0xD1;
inline constexpr std::uint8_t OneByteShiftRm8ByCl = 0xD2;
inline constexpr std::uint8_t OneByteShiftRmByCl = 0xD3;
inline constexpr std::uint8_t OneByteTestGrp3Rm8 = 0xF6;
inline constexpr std::uint8_t OneByteTestGrp3Rm = 0xF7;
inline constexpr std::uint8_t OneByteIncDecRm8 = 0xFE;
inline constexpr std::uint8_t OneByteGrp5Rm = 0xFF;
inline constexpr std::uint8_t OneByteModRmRangeJMin = 0x88;
inline constexpr std::uint8_t OneByteModRmRangeJMax = 0x8B;
inline constexpr std::uint8_t OneByteImm8AluOrGrp3 = 0xC6;
inline constexpr std::uint8_t OneByteImm8AluCmp = 0x80;
inline constexpr std::uint8_t OneByteImm8AddAl = 0x04;
inline constexpr std::uint8_t OneByteImm8OrAl = 0x0C;
inline constexpr std::uint8_t OneByteImm8AdcAl = 0x14;
inline constexpr std::uint8_t OneByteImm8SbbAl = 0x1C;
inline constexpr std::uint8_t OneByteImm8AndAl = 0x24;
inline constexpr std::uint8_t OneByteImm8SubAl = 0x2C;
inline constexpr std::uint8_t OneByteImm8XorAl = 0x34;
inline constexpr std::uint8_t OneByteImm8CmpAl = 0x3C;
inline constexpr std::uint8_t OneByteMovImm8RegMin = 0xB0;
inline constexpr std::uint8_t OneByteMovImm8RegMax = 0xB7;
inline constexpr std::uint8_t OneBytePushImm8 = 0x6A;
inline constexpr std::uint8_t OneByteTestAlImm8 = 0xA8;
inline constexpr std::uint8_t OneByteImm32AluCmp = 0x81;
inline constexpr std::uint8_t OneByteImm32AddEax = 0x05;
inline constexpr std::uint8_t OneByteImm32OrEax = 0x0D;
inline constexpr std::uint8_t OneByteImm32AdcEax = 0x15;
inline constexpr std::uint8_t OneByteImm32SbbEax = 0x1D;
inline constexpr std::uint8_t OneByteImm32AndEax = 0x25;
inline constexpr std::uint8_t OneByteImm32SubEax = 0x2D;
inline constexpr std::uint8_t OneByteImm32XorEax = 0x35;
inline constexpr std::uint8_t OneByteImm32CmpEax = 0x3D;
inline constexpr std::uint8_t OneBytePushImm32 = 0x68;
inline constexpr std::uint8_t OneByteTestEaxImm32 = 0xA9;
inline constexpr std::uint8_t OneByteMovImm32RegMin = 0xB8;
inline constexpr std::uint8_t OneByteMovImm32RegMax = 0xBF;
inline constexpr std::uint8_t OneByteImm8Grp1 = 0x83;
inline constexpr std::uint8_t OneByteJccRel8Min = 0x70;
inline constexpr std::uint8_t OneByteJccRel8Max = 0x7F;
inline constexpr std::uint8_t OneByteCallRel32 = 0xE8;
inline constexpr std::uint8_t OneByteJmpRel32 = 0xE9;
inline constexpr std::uint8_t OneByteJmpRel8 = 0xEB;
inline constexpr std::uint8_t TwoByteJccRel32Min = 0x80;
inline constexpr std::uint8_t TwoByteJccRel32Max = 0x8F;
inline constexpr std::uint8_t TwoByteMovImm8ModRm = 0xBA;
inline constexpr std::uint8_t TwoByteStringOpMovs = 0xA4;
inline constexpr std::uint8_t TwoByteStringOpCmps = 0xAC;
inline constexpr std::uint8_t TwoByteCmovRangeMin = 0x40;
inline constexpr std::uint8_t TwoByteCmovRangeMax = 0x4F;
inline constexpr std::uint8_t TwoByteModRmRangeAMin = 0xA3;
inline constexpr std::uint8_t TwoByteModRmRangeAMax = 0xAB;
inline constexpr std::uint8_t TwoByteModRmRangeBMin = 0xB0;
inline constexpr std::uint8_t TwoByteModRmRangeBMax = 0xB7;
inline constexpr std::uint8_t TwoByteModRmRangeCMin = 0xBC;
inline constexpr std::uint8_t TwoByteModRmRangeCMax = 0xBF;
inline constexpr std::uint8_t TwoByteModRmRangeDMin = 0x10;
inline constexpr std::uint8_t TwoByteModRmRangeDMax = 0x17;
inline constexpr std::uint8_t TwoByteModRmRangeEMin = 0x28;
inline constexpr std::uint8_t TwoByteModRmRangeEMax = 0x2F;
inline constexpr std::uint8_t TwoByteModRmRangeFMin = 0x38;
inline constexpr std::uint8_t TwoByteModRmRangeFMax = 0x3A;
inline constexpr std::uint8_t TwoByteModRmRangeGMin = 0x54;
inline constexpr std::uint8_t TwoByteModRmRangeGMax = 0x77;
inline constexpr std::uint8_t TwoByteModRmRangeHMin = 0xD0;
inline constexpr std::uint8_t TwoByteModRmRangeHMax = 0xFE;
inline constexpr std::uint8_t TwoByteNopModRm = 0x1F;
inline constexpr std::size_t ImmSizeNone = 0;
inline constexpr std::size_t ImmSize8 = 1;
inline constexpr std::size_t ImmSize16 = 2;
inline constexpr std::size_t ImmSize32 = 4;
inline constexpr std::size_t ImmSize64 = 8;
inline constexpr std::uint8_t ModRmModShift = 6;
inline constexpr std::uint8_t ModRmModMask = 0x03;
inline constexpr std::uint8_t ModRmRmMask = 0x07;
inline constexpr std::uint8_t ModRmModIndirect = 0x00;
inline constexpr std::uint8_t ModRmModDisp8 = 0x01;
inline constexpr std::uint8_t ModRmModDisp32 = 0x02;
inline constexpr std::uint8_t ModRmModRegister = 0x03;
inline constexpr std::uint8_t ModRmRmSibPresent = 0x04;
inline constexpr std::uint8_t ModRmRmRipRelative = 0x05;
inline constexpr std::uint8_t SibBaseMask = 0x07;
inline constexpr std::uint8_t SibBaseDisp32 = 0x05;
inline constexpr std::size_t Disp8Size = 1;
inline constexpr std::size_t Disp32Size = 4;
inline constexpr std::size_t Rel32InstructionLength = 5;
}
#endif

View File

@ -1,8 +1,11 @@
#include <codegen/x86/X64InstructionDecoder.hpp>
#include <codegen/x86/X64OpcodeConstants.hpp>
#include <codegen/CodegenException.hpp>
namespace Codegen {
using namespace X64OpcodeConstants;
std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t available) const {
std::size_t pos = 0;
bool rexPresent = false;
@ -12,20 +15,20 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
while (pos < available) {
const std::uint8_t b = data[pos];
if (b == 0xF0 || b == 0xF2 || b == 0xF3 ||
b == 0x2E || b == 0x36 || b == 0x3E || b == 0x26 ||
b == 0x64 || b == 0x65) {
if (b == PrefixLock || b == PrefixRepne || b == PrefixRep ||
b == PrefixSegCs || b == PrefixSegSs || b == PrefixSegDs || b == PrefixSegEs ||
b == PrefixSegFs || b == PrefixSegGs) {
pos += 1;
continue;
}
if (b == 0x66) {
if (b == PrefixOperandSize) {
operandSizeOverride = true;
pos += 1;
continue;
}
if (b == 0x67) {
if (b == PrefixAddressSize) {
pos += 1;
continue;
}
@ -33,7 +36,7 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
break;
}
if (pos < available && data[pos] >= 0x40 && data[pos] <= 0x4F) {
if (pos < available && data[pos] >= RexMin && data[pos] <= RexMax) {
rexPresent = true;
rex = data[pos];
pos += 1;
@ -47,7 +50,7 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
pos += 1;
bool twoByteOpcode = false;
if (opcode == 0x0F) {
if (opcode == TwoByteOpcodeEscape) {
if (pos >= available) {
throw CodegenException("Instruction truncated after two-byte opcode escape");
}
@ -57,79 +60,86 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
}
bool hasModRm = false;
std::size_t immediateSize = 0;
std::size_t immediateSize = ImmSizeNone;
if (!twoByteOpcode) {
if ((opcode >= 0x00 && opcode <= 0x03) || (opcode >= 0x08 && opcode <= 0x0B) ||
(opcode >= 0x10 && opcode <= 0x13) || (opcode >= 0x18 && opcode <= 0x1B) ||
(opcode >= 0x20 && opcode <= 0x23) || (opcode >= 0x28 && opcode <= 0x2B) ||
(opcode >= 0x30 && opcode <= 0x33) || (opcode >= 0x38 && opcode <= 0x3B) ||
opcode == 0x62 || opcode == 0x63 ||
(opcode >= 0x84 && opcode <= 0x8F) ||
opcode == 0xC0 || opcode == 0xC1 ||
opcode == 0xC4 || opcode == 0xC5 || opcode == 0xC6 || opcode == 0xC7 ||
opcode == 0xD0 || opcode == 0xD1 || opcode == 0xD2 || opcode == 0xD3 ||
opcode == 0xF6 || opcode == 0xF7 ||
opcode == 0xFE || opcode == 0xFF ||
(opcode >= 0x88 && opcode <= 0x8B)) {
if ((opcode >= OneByteModRmRangeAMin && opcode <= OneByteModRmRangeAMax) ||
(opcode >= OneByteModRmRangeBMin && opcode <= OneByteModRmRangeBMax) ||
(opcode >= OneByteModRmRangeCMin && opcode <= OneByteModRmRangeCMax) ||
(opcode >= OneByteModRmRangeDMin && opcode <= OneByteModRmRangeDMax) ||
(opcode >= OneByteModRmRangeEMin && opcode <= OneByteModRmRangeEMax) ||
(opcode >= OneByteModRmRangeFMin && opcode <= OneByteModRmRangeFMax) ||
(opcode >= OneByteModRmRangeGMin && opcode <= OneByteModRmRangeGMax) ||
(opcode >= OneByteModRmRangeHMin && opcode <= OneByteModRmRangeHMax) ||
opcode == OneByteArpl || opcode == OneByteMovsxd ||
(opcode >= OneByteModRmRangeIMin && opcode <= OneByteModRmRangeIMax) ||
opcode == OneByteGrp2Rm8Imm8 || opcode == OneByteGrp2RmImm8 ||
opcode == OneByteVex3 || opcode == OneByteVex2 ||
opcode == OneByteMovImm8 || opcode == OneByteMovImm32 ||
opcode == OneByteShiftRm8By1 || opcode == OneByteShiftRmBy1 ||
opcode == OneByteShiftRm8ByCl || opcode == OneByteShiftRmByCl ||
opcode == OneByteTestGrp3Rm8 || opcode == OneByteTestGrp3Rm ||
opcode == OneByteIncDecRm8 || opcode == OneByteGrp5Rm ||
(opcode >= OneByteModRmRangeJMin && opcode <= OneByteModRmRangeJMax)) {
hasModRm = true;
}
if (opcode == 0xC6 || opcode == 0x80 ||
opcode == 0x04 || opcode == 0x0C ||
opcode == 0x14 || opcode == 0x1C ||
opcode == 0x24 || opcode == 0x2C ||
opcode == 0x34 || opcode == 0x3C ||
(opcode >= 0xB0 && opcode <= 0xB7) ||
opcode == 0x6A ||
opcode == 0xA8) {
immediateSize = 1;
} else if (opcode == 0xC7 || opcode == 0x81 ||
opcode == 0x05 || opcode == 0x0D ||
opcode == 0x15 || opcode == 0x1D ||
opcode == 0x25 || opcode == 0x2D ||
opcode == 0x35 || opcode == 0x3D ||
opcode == 0x68 ||
opcode == 0xA9 ||
(opcode >= 0xB8 && opcode <= 0xBF)) {
if (opcode >= 0xB8 && opcode <= 0xBF) {
immediateSize = (rexPresent && (rex & 0x08) != 0) ? 8 : (operandSizeOverride ? 2 : 4);
if (opcode == OneByteImm8AluOrGrp3 || opcode == OneByteImm8AluCmp ||
opcode == OneByteImm8AddAl || opcode == OneByteImm8OrAl ||
opcode == OneByteImm8AdcAl || opcode == OneByteImm8SbbAl ||
opcode == OneByteImm8AndAl || opcode == OneByteImm8SubAl ||
opcode == OneByteImm8XorAl || opcode == OneByteImm8CmpAl ||
(opcode >= OneByteMovImm8RegMin && opcode <= OneByteMovImm8RegMax) ||
opcode == OneBytePushImm8 ||
opcode == OneByteTestAlImm8) {
immediateSize = ImmSize8;
} else if (opcode == OneByteImm32AluCmp ||
opcode == OneByteImm32AddEax || opcode == OneByteImm32OrEax ||
opcode == OneByteImm32AdcEax || opcode == OneByteImm32SbbEax ||
opcode == OneByteImm32AndEax || opcode == OneByteImm32SubEax ||
opcode == OneByteImm32XorEax || opcode == OneByteImm32CmpEax ||
opcode == OneBytePushImm32 ||
opcode == OneByteTestEaxImm32 ||
(opcode >= OneByteMovImm32RegMin && opcode <= OneByteMovImm32RegMax)) {
if (opcode >= OneByteMovImm32RegMin && opcode <= OneByteMovImm32RegMax) {
immediateSize = (rexPresent && (rex & RexWBit) != 0) ? ImmSize64 :
(operandSizeOverride ? ImmSize16 : ImmSize32);
} else {
immediateSize = operandSizeOverride ? 2 : 4;
immediateSize = operandSizeOverride ? ImmSize16 : ImmSize32;
}
} else if (opcode == 0x83) {
immediateSize = 1;
} else if (opcode == OneByteImm8Grp1) {
immediateSize = ImmSize8;
}
if (opcode >= 0x70 && opcode <= 0x7F) {
immediateSize = 1;
if (opcode >= OneByteJccRel8Min && opcode <= OneByteJccRel8Max) {
immediateSize = ImmSize8;
}
if (opcode == 0xE8 || opcode == 0xE9) {
immediateSize = 4;
if (opcode == OneByteCallRel32 || opcode == OneByteJmpRel32) {
immediateSize = ImmSize32;
}
if (opcode == 0xEB) {
immediateSize = 1;
if (opcode == OneByteJmpRel8) {
immediateSize = ImmSize8;
}
} else {
if (opcode >= 0x80 && opcode <= 0x8F) {
immediateSize = 4;
} else if (opcode == 0xBA) {
if (opcode >= TwoByteJccRel32Min && opcode <= TwoByteJccRel32Max) {
immediateSize = ImmSize32;
} else if (opcode == TwoByteMovImm8ModRm) {
hasModRm = true;
immediateSize = 1;
} else if (opcode == 0xA4 || opcode == 0xAC) {
immediateSize = 1;
} else if ((opcode >= 0x40 && opcode <= 0x4F) ||
(opcode >= 0xA3 && opcode <= 0xAB) ||
(opcode >= 0xB0 && opcode <= 0xB7) ||
(opcode >= 0xBC && opcode <= 0xBF) ||
(opcode >= 0x10 && opcode <= 0x17) ||
(opcode >= 0x28 && opcode <= 0x2F) ||
(opcode >= 0x38 && opcode <= 0x3A) ||
(opcode >= 0x54 && opcode <= 0x77) ||
(opcode >= 0xD0 && opcode <= 0xFE) ||
opcode == 0x1F) {
immediateSize = ImmSize8;
} else if (opcode == TwoByteStringOpMovs || opcode == TwoByteStringOpCmps) {
immediateSize = ImmSize8;
} else if ((opcode >= TwoByteCmovRangeMin && opcode <= TwoByteCmovRangeMax) ||
(opcode >= TwoByteModRmRangeAMin && opcode <= TwoByteModRmRangeAMax) ||
(opcode >= TwoByteModRmRangeBMin && opcode <= TwoByteModRmRangeBMax) ||
(opcode >= TwoByteModRmRangeCMin && opcode <= TwoByteModRmRangeCMax) ||
(opcode >= TwoByteModRmRangeDMin && opcode <= TwoByteModRmRangeDMax) ||
(opcode >= TwoByteModRmRangeEMin && opcode <= TwoByteModRmRangeEMax) ||
(opcode >= TwoByteModRmRangeFMin && opcode <= TwoByteModRmRangeFMax) ||
(opcode >= TwoByteModRmRangeGMin && opcode <= TwoByteModRmRangeGMax) ||
(opcode >= TwoByteModRmRangeHMin && opcode <= TwoByteModRmRangeHMax) ||
opcode == TwoByteNopModRm) {
hasModRm = true;
}
}
@ -148,28 +158,28 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
const std::uint8_t modrm = data[pos];
pos += 1;
const std::uint8_t mod = static_cast<std::uint8_t>((modrm >> 6) & 0x03);
const std::uint8_t rm = static_cast<std::uint8_t>(modrm & 0x07);
const std::uint8_t mod = static_cast<std::uint8_t>((modrm >> ModRmModShift) & ModRmModMask);
const std::uint8_t rm = static_cast<std::uint8_t>(modrm & ModRmRmMask);
if (mod != 0x03 && rm == 0x04) {
if (mod != ModRmModRegister && rm == ModRmRmSibPresent) {
if (pos >= available) {
throw CodegenException("Instruction truncated before SIB byte");
}
const std::uint8_t sib = data[pos];
const std::uint8_t base = static_cast<std::uint8_t>(sib & 0x07);
const std::uint8_t base = static_cast<std::uint8_t>(sib & SibBaseMask);
pos += 1;
if (mod == 0x00 && base == 0x05) {
pos += 4;
if (mod == ModRmModIndirect && base == SibBaseDisp32) {
pos += Disp32Size;
}
}
if (mod == 0x01) {
pos += 1;
} else if (mod == 0x02) {
pos += 4;
} else if (mod == 0x00 && rm == 0x05) {
pos += 4;
if (mod == ModRmModDisp8) {
pos += Disp8Size;
} else if (mod == ModRmModDisp32) {
pos += Disp32Size;
} else if (mod == ModRmModIndirect && rm == ModRmRmRipRelative) {
pos += Disp32Size;
}
pos += immediateSize;

View File

@ -1,5 +1,6 @@
#include <codegen/x86/X64InstructionRewriter.hpp>
#include <codegen/x86/X64InstructionDecoder.hpp>
#include <codegen/x86/X64OpcodeConstants.hpp>
#include <codegen/CodegenException.hpp>
#include <codegen/IInstructionScanner.hpp>
#include <cstdint>
@ -7,6 +8,8 @@
namespace Codegen {
using namespace X64OpcodeConstants;
X64InstructionRewriter::ReferenceSite X64InstructionRewriter::ClassifyInstruction(
const std::uint8_t* data,
std::size_t length
@ -15,10 +18,10 @@ X64InstructionRewriter::ReferenceSite X64InstructionRewriter::ClassifyInstructio
while (pos < length) {
const std::uint8_t b = data[pos];
if (b == OpcodePrefixLock || b == OpcodePrefixRepne || b == OpcodePrefixRep ||
b == OpcodePrefixSegCs || b == OpcodePrefixSegSs || b == OpcodePrefixSegDs ||
b == OpcodePrefixSegEs || b == OpcodePrefixSegFs || b == OpcodePrefixSegGs ||
b == OpcodePrefixOperandSize || b == OpcodePrefixAddressSize) {
if (b == PrefixLock || b == PrefixRepne || b == PrefixRep ||
b == PrefixSegCs || b == PrefixSegSs || b == PrefixSegDs ||
b == PrefixSegEs || b == PrefixSegFs || b == PrefixSegGs ||
b == PrefixOperandSize || b == PrefixAddressSize) {
pos += 1;
continue;
}
@ -48,22 +51,22 @@ X64InstructionRewriter::ReferenceSite X64InstructionRewriter::ClassifyInstructio
}
if (!twoByteOpcode) {
if (opcode == OpcodeCallRel32 || opcode == OpcodeJmpRel32) {
if (opcode == OneByteCallRel32 || opcode == OneByteJmpRel32) {
if (length >= opcodeOffset + Rel32InstructionLength) {
return {ReferenceKind::Rel32Branch, pos};
}
return {ReferenceKind::None, 0};
}
if (opcode == OpcodeJmpRel8 || (opcode >= OpcodeJccRel8Min && opcode <= OpcodeJccRel8Max)) {
if (length >= pos + Rel8FieldSize) {
if (opcode == OneByteJmpRel8 || (opcode >= OneByteJccRel8Min && opcode <= OneByteJccRel8Max)) {
if (length >= pos + Disp8Size) {
return {ReferenceKind::Rel8Branch, pos};
}
return {ReferenceKind::None, 0};
}
} else {
if (opcode >= OpcodeJccRel32Min && opcode <= OpcodeJccRel32Max) {
if (length >= pos + Rel32FieldSize) {
if (opcode >= TwoByteJccRel32Min && opcode <= TwoByteJccRel32Max) {
if (length >= pos + Disp32Size) {
return {ReferenceKind::Rel32Branch, pos};
}
return {ReferenceKind::None, 0};
@ -80,7 +83,7 @@ X64InstructionRewriter::ReferenceSite X64InstructionRewriter::ClassifyInstructio
if (mod == ModRmModIndirect && rm == ModRmRmRipRelative) {
const std::size_t dispOffset = pos + 1;
if (length >= dispOffset + Disp32FieldSize) {
if (length >= dispOffset + Disp32Size) {
return {ReferenceKind::RipRelativeDisp32, dispOffset};
}
}