Fix VEX decoding with mandatory VEX.W bit
The Intel documentation is, well, inconsistent about this: at one point, they say that the VEX.W prefix is ignored entirely in 32-bit mode, but the instruction description indicates that a VEX.W can be required in 32-bit/compatibility mode as well.
This commit is contained in:
13
decode.c
13
decode.c
@@ -138,10 +138,12 @@ decode_prefixes(const uint8_t* buffer, int len, DecodeMode mode,
|
|||||||
if (UNLIKELY(off + 2 >= len))
|
if (UNLIKELY(off + 2 >= len))
|
||||||
return -1;
|
return -1;
|
||||||
byte = buffer[off + 2];
|
byte = buffer[off + 2];
|
||||||
// SDM Vol 2A 2-16 (Dec. 2016)
|
// SDM Vol 2A 2-16 (Dec. 2016) says that:
|
||||||
// - "In 32-bit modes, VEX.W is silently ignored."
|
// - "In 32-bit modes, VEX.W is silently ignored."
|
||||||
// - VEX.W either replaces REX.W, is don't care or is reserved.
|
// - VEX.W either replaces REX.W, is don't care or is reserved.
|
||||||
prefixes |= mode == DECODE_64 && (byte & 0x80) ? PREFIX_REXW : 0;
|
// This is actually incorrect, there are instructions that
|
||||||
|
// use VEX.W as an opcode extension even in 32-bit mode.
|
||||||
|
prefixes |= byte & 0x80 ? PREFIX_REXW : 0;
|
||||||
}
|
}
|
||||||
else // 2-byte VEX
|
else // 2-byte VEX
|
||||||
prefixes |= PREFIX_ESC_0F;
|
prefixes |= PREFIX_ESC_0F;
|
||||||
@@ -459,12 +461,10 @@ decode(const uint8_t* buffer, int len, DecodeMode mode, Instr* instr)
|
|||||||
{
|
{
|
||||||
op_size_log = 1;
|
op_size_log = 1;
|
||||||
}
|
}
|
||||||
#if defined(ARCH_X86_64)
|
else if (mode == DECODE_64 && (prefixes & PREFIX_REXW))
|
||||||
else if (prefixes & PREFIX_REXW)
|
|
||||||
{
|
{
|
||||||
op_size_log = 4;
|
op_size_log = 4;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
else if (prefixes & PREFIX_OPSZ)
|
else if (prefixes & PREFIX_OPSZ)
|
||||||
{
|
{
|
||||||
op_size_log = 2;
|
op_size_log = 2;
|
||||||
@@ -609,7 +609,8 @@ decode(const uint8_t* buffer, int len, DecodeMode mode, Instr* instr)
|
|||||||
imm_size = 2;
|
imm_size = 2;
|
||||||
}
|
}
|
||||||
#if defined(ARCH_X86_64)
|
#if defined(ARCH_X86_64)
|
||||||
else if (prefixes & PREFIX_REXW && instr->type == IT_MOVABS_IMM)
|
else if (mode == DECODE_64 && (prefixes & PREFIX_REXW) &&
|
||||||
|
instr->type == IT_MOVABS_IMM)
|
||||||
{
|
{
|
||||||
imm_size = 8;
|
imm_size = 8;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user