refactor(code): move decoder opcodes to constexpr in header
This commit is contained in:
parent
c14c1467c0
commit
aeb9adfb33
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue