fix(code): decode setcc, evex, x87, of38/3a, shld/shrd + fix c1/of a4 immediate size bugs
This commit is contained in:
parent
ab78ae90e2
commit
c3e7b4c14a
|
|
@ -61,6 +61,8 @@ inline constexpr std::uint8_t OneByteModRmRangeJMin = 0x88;
|
|||
inline constexpr std::uint8_t OneByteModRmRangeJMax = 0x8B;
|
||||
inline constexpr std::uint8_t OneByteImulRm32Imm32 = 0x69;
|
||||
inline constexpr std::uint8_t OneByteImulRm32Imm8 = 0x6B;
|
||||
inline constexpr std::uint8_t OneByteX87Min = 0xD8;
|
||||
inline constexpr std::uint8_t OneByteX87Max = 0xDF;
|
||||
|
||||
inline constexpr std::uint8_t OneByteImm8AluOrGrp3 = 0xC6;
|
||||
inline constexpr std::uint8_t OneByteImm8AluCmp = 0x80;
|
||||
|
|
@ -99,12 +101,15 @@ 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 OneByteJrcxz = 0xE3;
|
||||
inline constexpr std::uint8_t OneByteLoop = 0xE0;
|
||||
inline constexpr std::uint8_t OneByteLoopMax = 0xE2;
|
||||
inline constexpr std::uint8_t OneByteInOutImm8Min = 0xE4;
|
||||
inline constexpr std::uint8_t OneByteInOutImm8Max = 0xE7;
|
||||
|
||||
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;
|
||||
|
|
@ -120,11 +125,46 @@ 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 TwoByteModRmRangeGMax = 0x7F;
|
||||
inline constexpr std::uint8_t TwoByteModRmRangeHMin = 0xD0;
|
||||
inline constexpr std::uint8_t TwoByteModRmRangeHMax = 0xFE;
|
||||
inline constexpr std::uint8_t TwoByteNopModRm = 0x1F;
|
||||
inline constexpr std::uint8_t TwoByteEndbr = 0x1E;
|
||||
inline constexpr std::uint8_t TwoBytePrefetchGrpMin = 0x18;
|
||||
inline constexpr std::uint8_t TwoBytePrefetchGrpMax = 0x1D;
|
||||
inline constexpr std::uint8_t TwoByteSetccMin = 0x90;
|
||||
inline constexpr std::uint8_t TwoByteSetccMax = 0x9F;
|
||||
inline constexpr std::uint8_t TwoByteImulRmModRm = 0xAF;
|
||||
inline constexpr std::uint8_t TwoByteMovdMovq = 0x7E;
|
||||
inline constexpr std::uint8_t TwoByteMovqMmxXmm = 0x6F;
|
||||
inline constexpr std::uint8_t TwoByteMovdqu = 0x7F;
|
||||
inline constexpr std::uint8_t TwoByteGrp7 = 0x01;
|
||||
inline constexpr std::uint8_t TwoByteShiftImm8Min = 0x70;
|
||||
inline constexpr std::uint8_t TwoByteShiftImm8Max = 0x73;
|
||||
inline constexpr std::uint8_t ThreeByteEscape38 = 0x38;
|
||||
inline constexpr std::uint8_t ThreeByteEscape3A = 0x3A;
|
||||
|
||||
inline constexpr std::uint8_t TwoByteModRmRangeIMin = 0x50;
|
||||
inline constexpr std::uint8_t TwoByteModRmRangeIMax = 0x53;
|
||||
inline constexpr std::uint8_t TwoByteShldImm8 = 0xA4;
|
||||
inline constexpr std::uint8_t TwoByteShldCl = 0xA5;
|
||||
inline constexpr std::uint8_t TwoByteShrdImm8 = 0xAC;
|
||||
inline constexpr std::uint8_t TwoByteShrdCl = 0xAD;
|
||||
inline constexpr std::uint8_t TwoByteGrp15 = 0xAE;
|
||||
inline constexpr std::uint8_t TwoByteXadd = 0xC1;
|
||||
inline constexpr std::uint8_t TwoBytePextrw = 0xC5;
|
||||
inline constexpr std::uint8_t TwoByteShufpsImm8 = 0xC2;
|
||||
inline constexpr std::uint8_t TwoByteShufpdImm8 = 0xC6;
|
||||
inline constexpr std::uint8_t TwoByteGrp9 = 0xC7;
|
||||
|
||||
inline constexpr std::uint8_t VexNoModRmMin = 0x77;
|
||||
inline constexpr std::uint8_t VexNoModRmMax = 0x77;
|
||||
|
||||
inline constexpr std::uint8_t EvexPrefix = 0x62;
|
||||
inline constexpr std::size_t EvexPrefixLength = 4;
|
||||
inline constexpr std::uint8_t EvexMapMask = 0x03;
|
||||
inline constexpr std::uint8_t EvexMap0F3A = 0x03;
|
||||
inline constexpr std::uint8_t EvexMap0F38 = 0x02;
|
||||
|
||||
inline constexpr std::size_t ImmSizeNone = 0;
|
||||
inline constexpr std::size_t ImmSize8 = 1;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,10 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
|
|||
pos += 1;
|
||||
bool twoByteOpcode = false;
|
||||
bool vexPresent = false;
|
||||
bool evexPresent = false;
|
||||
std::uint8_t vexMap = 0;
|
||||
std::uint8_t threeByteMap = 0;
|
||||
bool threeByteEscape = false;
|
||||
|
||||
if (opcode == OneByteVex2) {
|
||||
if (pos >= available) {
|
||||
|
|
@ -70,6 +73,13 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
|
|||
throw CodegenException("Instruction truncated after VEX3 prefix");
|
||||
}
|
||||
pos += 1;
|
||||
} else if (opcode == EvexPrefix) {
|
||||
if (pos + 2 >= available) {
|
||||
throw CodegenException("Instruction truncated after EVEX prefix");
|
||||
}
|
||||
evexPresent = true;
|
||||
vexMap = static_cast<std::uint8_t>(data[pos] & EvexMapMask);
|
||||
pos += 3;
|
||||
} else if (opcode == TwoByteOpcodeEscape) {
|
||||
if (pos >= available) {
|
||||
throw CodegenException("Instruction truncated after two-byte opcode escape");
|
||||
|
|
@ -77,9 +87,18 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
|
|||
twoByteOpcode = true;
|
||||
opcode = data[pos];
|
||||
pos += 1;
|
||||
if (opcode == ThreeByteEscape38 || opcode == ThreeByteEscape3A) {
|
||||
threeByteEscape = true;
|
||||
threeByteMap = opcode;
|
||||
if (pos >= available) {
|
||||
throw CodegenException("Instruction truncated after three-byte opcode escape");
|
||||
}
|
||||
opcode = data[pos];
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (vexPresent) {
|
||||
if (vexPresent || evexPresent) {
|
||||
if (pos >= available) {
|
||||
throw CodegenException("Instruction truncated after VEX prefix");
|
||||
}
|
||||
|
|
@ -91,8 +110,22 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
|
|||
std::size_t immediateSize = ImmSizeNone;
|
||||
|
||||
if (vexPresent) {
|
||||
if (vexMap == TwoByteOpcodeEscape && opcode >= VexNoModRmMin && opcode <= VexNoModRmMax) {
|
||||
hasModRm = false;
|
||||
} else {
|
||||
hasModRm = true;
|
||||
if (vexMap == Vex3Map0F3A) {
|
||||
immediateSize = ImmSize8;
|
||||
}
|
||||
}
|
||||
} else if (evexPresent) {
|
||||
hasModRm = true;
|
||||
if (vexMap == Vex3Map0F3A) {
|
||||
if (vexMap == EvexMap0F3A) {
|
||||
immediateSize = ImmSize8;
|
||||
}
|
||||
} else if (threeByteEscape) {
|
||||
hasModRm = true;
|
||||
if (threeByteMap == ThreeByteEscape3A) {
|
||||
immediateSize = ImmSize8;
|
||||
}
|
||||
} else if (!twoByteOpcode) {
|
||||
|
|
@ -115,7 +148,8 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
|
|||
opcode == OneByteShiftRm8ByCl || opcode == OneByteShiftRmByCl ||
|
||||
opcode == OneByteTestGrp3Rm8 || opcode == OneByteTestGrp3Rm ||
|
||||
opcode == OneByteIncDecRm8 || opcode == OneByteGrp5Rm ||
|
||||
(opcode >= OneByteModRmRangeJMin && opcode <= OneByteModRmRangeJMax)) {
|
||||
(opcode >= OneByteModRmRangeJMin && opcode <= OneByteModRmRangeJMax) ||
|
||||
(opcode >= OneByteX87Min && opcode <= OneByteX87Max)) {
|
||||
hasModRm = true;
|
||||
}
|
||||
|
||||
|
|
@ -124,6 +158,7 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
|
|||
opcode == OneByteImm8AdcAl || opcode == OneByteImm8SbbAl ||
|
||||
opcode == OneByteImm8AndAl || opcode == OneByteImm8SubAl ||
|
||||
opcode == OneByteImm8XorAl || opcode == OneByteImm8CmpAl ||
|
||||
opcode == OneByteGrp2Rm8Imm8 || opcode == OneByteGrp2RmImm8 ||
|
||||
(opcode >= OneByteMovImm8RegMin && opcode <= OneByteMovImm8RegMax) ||
|
||||
opcode == OneBytePushImm8 ||
|
||||
opcode == OneByteTestAlImm8) {
|
||||
|
|
@ -155,7 +190,9 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
|
|||
immediateSize = ImmSize32;
|
||||
}
|
||||
|
||||
if (opcode == OneByteJmpRel8) {
|
||||
if (opcode == OneByteJmpRel8 || opcode == OneByteJrcxz ||
|
||||
(opcode >= OneByteLoop && opcode <= OneByteLoopMax) ||
|
||||
(opcode >= OneByteInOutImm8Min && opcode <= OneByteInOutImm8Max)) {
|
||||
immediateSize = ImmSize8;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -164,17 +201,32 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
|
|||
} else if (opcode == TwoByteMovImm8ModRm) {
|
||||
hasModRm = true;
|
||||
immediateSize = ImmSize8;
|
||||
} else if (opcode == TwoByteStringOpMovs || opcode == TwoByteStringOpCmps) {
|
||||
} else if (opcode >= TwoByteShiftImm8Min && opcode <= TwoByteShiftImm8Max) {
|
||||
hasModRm = true;
|
||||
immediateSize = ImmSize8;
|
||||
} else if (opcode == TwoByteShldImm8 || opcode == TwoByteShrdImm8 ||
|
||||
opcode == TwoByteShufpsImm8 || opcode == TwoByteShufpdImm8 ||
|
||||
opcode == TwoBytePextrw) {
|
||||
hasModRm = true;
|
||||
immediateSize = ImmSize8;
|
||||
} else if (opcode == TwoByteShldCl || opcode == TwoByteShrdCl) {
|
||||
hasModRm = true;
|
||||
} 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 >= TwoByteModRmRangeIMin && opcode <= TwoByteModRmRangeIMax) ||
|
||||
(opcode >= TwoBytePrefetchGrpMin && opcode <= TwoBytePrefetchGrpMax) ||
|
||||
(opcode >= TwoByteSetccMin && opcode <= TwoByteSetccMax) ||
|
||||
opcode == TwoByteImulRmModRm ||
|
||||
opcode == TwoByteGrp7 ||
|
||||
opcode == TwoByteGrp15 ||
|
||||
opcode == TwoByteXadd ||
|
||||
opcode == TwoByteGrp9 ||
|
||||
opcode == TwoByteNopModRm || opcode == TwoByteEndbr) {
|
||||
hasModRm = true;
|
||||
}
|
||||
|
|
@ -194,9 +246,9 @@ 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 >> ModRmModShift) & ModRmModMask);
|
||||
const std::uint8_t reg = static_cast<std::uint8_t>((modrm >> ModRmRegShift) & ModRmRegMask);
|
||||
const std::uint8_t rm = static_cast<std::uint8_t>(modrm & ModRmRmMask);
|
||||
const auto mod = static_cast<std::uint8_t>((modrm >> ModRmModShift) & ModRmModMask);
|
||||
const auto reg = static_cast<std::uint8_t>((modrm >> ModRmRegShift) & ModRmRegMask);
|
||||
const auto rm = static_cast<std::uint8_t>(modrm & ModRmRmMask);
|
||||
|
||||
if (!vexPresent && !twoByteOpcode &&
|
||||
(opcode == OneByteTestGrp3Rm8 || opcode == OneByteTestGrp3Rm) &&
|
||||
|
|
@ -211,7 +263,7 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t
|
|||
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 & SibBaseMask);
|
||||
const auto base = static_cast<std::uint8_t>(sib & SibBaseMask);
|
||||
pos += 1;
|
||||
|
||||
if (mod == ModRmModIndirect && base == SibBaseDisp32) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue