Allow prefix table at end of opcode

Some instructions, e.g. VZEROUPPER, have a prefix table but no
associated byte for that. Fix this by removing the prefix handling from
the table walking loop.
This commit is contained in:
Alexis Engelke
2019-01-13 15:53:48 +01:00
parent d1110fae6a
commit 4f4b2050c8

View File

@@ -38,6 +38,12 @@ static const uint8_t _decode_table64[] = {
#define ENTRY_MASK 7
#define ENTRY_IS_TABLE(kind) ((kind) >= ENTRY_TABLE256)
#define ENTRY_UNPACK(table,kind,decode_table,entry) do { \
uint16_t entry_copy = entry; \
table = (uint16_t*) &(decode_table)[entry_copy & ~7]; \
kind = entry_copy & ENTRY_MASK; \
} while (0)
#define INSTR_ENC_ADDR 0x08
#define INSTR_ENC_IMM 0x10
#define INSTR_ENC_MODRM 0x80
@@ -466,51 +472,38 @@ decode(const uint8_t* buffer, int len, DecodeMode mode, Instr* instr)
}
}
do
// First walk through full-byte opcodes. We do at most three iterations.
while (kind == ENTRY_TABLE256 && LIKELY(off < len))
ENTRY_UNPACK(table, kind, decode_table, table[buffer[off++]]);
// Then, walk through ModR/M-encoded opcode extensions.
if ((kind == ENTRY_TABLE8 || kind == ENTRY_TABLE72) && LIKELY(off < len))
{
uint16_t entry = 0;
if (kind == ENTRY_TABLE256)
{
entry = table[buffer[off++]];
}
else if (kind == ENTRY_TABLE8)
{
entry = table[(buffer[off] >> 3) & 7];
}
else if (kind == ENTRY_TABLE72)
{
if ((buffer[off] & 0xc0) == 0xc0)
if (kind == ENTRY_TABLE72 && (buffer[off] & 0xc0) == 0xc0)
{
entry = table[buffer[off] - 0xb8];
if ((entry & ENTRY_MASK) != ENTRY_NONE)
{
off++;
}
else
{
entry = table[(buffer[off] >> 3) & 7];
}
}
else
{
entry = table[(buffer[off] >> 3) & 7];
ENTRY_UNPACK(table, kind, decode_table, entry);
}
}
else if (kind == ENTRY_TABLE_PREFIX)
// Finally, handle mandatory prefixes (which behave like an opcode ext.).
if (kind == ENTRY_TABLE_PREFIX)
{
uint8_t index = 0;
if (prefixes & PREFIX_OPSZ)
{
index = 1;
}
else if (prefixes & PREFIX_REP)
{
index = 2;
}
else if (prefixes & PREFIX_REPNZ)
{
index = 3;
}
#if defined(ARCH_X86_64)
index |= prefixes & PREFIX_REXW ? (1 << 2) : 0;
#endif
@@ -520,16 +513,8 @@ decode(const uint8_t* buffer, int len, DecodeMode mode, Instr* instr)
// for the 0x66 prefix, which could otherwise override the operand
// size of general purpose registers.
prefixes &= ~(PREFIX_OPSZ | PREFIX_REPNZ | PREFIX_REP);
entry = table[index];
ENTRY_UNPACK(table, kind, decode_table, table[index]);
}
else
{
break;
}
kind = entry & ENTRY_MASK;
table = (uint16_t*) &decode_table[entry & ~7];
} while (LIKELY(off < len));
if (UNLIKELY(kind != ENTRY_INSTR))
{