Enforce mandatory L0/L1 in VEX prefix
This commit is contained in:
16
decode.c
16
decode.c
@@ -36,6 +36,7 @@ typedef enum DecodeMode DecodeMode;
|
||||
#define ENTRY_TABLE8 3
|
||||
#define ENTRY_TABLE72 4
|
||||
#define ENTRY_TABLE_PREFIX 5
|
||||
#define ENTRY_TABLE_VEX 6
|
||||
#define ENTRY_MASK 7
|
||||
#define ENTRY_IS_TABLE(kind) ((kind) >= ENTRY_TABLE256)
|
||||
|
||||
@@ -384,12 +385,11 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address,
|
||||
ENTRY_UNPACK(table, kind, _decode_table, entry);
|
||||
}
|
||||
|
||||
// Finally, handle mandatory prefixes (which behave like an opcode ext.).
|
||||
// Handle mandatory prefixes (which behave like an opcode ext.).
|
||||
if (kind == ENTRY_TABLE_PREFIX)
|
||||
{
|
||||
uint8_t index = mandatory_prefix;
|
||||
index |= prefixes & PREFIX_REXW ? (1 << 2) : 0;
|
||||
index |= prefixes & PREFIX_VEX ? (1 << 3) : 0;
|
||||
index |= prefixes & PREFIX_VEX ? (1 << 2) : 0;
|
||||
// If a prefix is mandatory and used as opcode extension, it has no
|
||||
// further effect on the instruction. This is especially important
|
||||
// for the 0x66 prefix, which could otherwise override the operand
|
||||
@@ -398,6 +398,16 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address,
|
||||
ENTRY_UNPACK(table, kind, _decode_table, table[index]);
|
||||
}
|
||||
|
||||
// For VEX prefix, we have to distinguish between VEX.W and VEX.L which may
|
||||
// be part of the opcode.
|
||||
if (kind == ENTRY_TABLE_VEX)
|
||||
{
|
||||
uint8_t index = 0;
|
||||
index |= prefixes & PREFIX_REXW ? (1 << 0) : 0;
|
||||
index |= prefixes & PREFIX_VEXL ? (1 << 1) : 0;
|
||||
ENTRY_UNPACK(table, kind, _decode_table, table[index]);
|
||||
}
|
||||
|
||||
if (UNLIKELY(kind != ENTRY_INSTR))
|
||||
{
|
||||
return -1;
|
||||
|
||||
@@ -5,7 +5,7 @@ from binascii import unhexlify
|
||||
from collections import OrderedDict, defaultdict, namedtuple, Counter
|
||||
from copy import copy
|
||||
from enum import Enum, IntEnum
|
||||
from itertools import accumulate
|
||||
from itertools import accumulate, product
|
||||
import struct
|
||||
|
||||
def bitstruct(name, fields):
|
||||
@@ -127,6 +127,7 @@ class EntryKind(Enum):
|
||||
TABLE8 = 3
|
||||
TABLE72 = 4
|
||||
TABLE_PREFIX = 5
|
||||
TABLE_VEX = 6
|
||||
|
||||
class TrieEntry(namedtuple("TrieEntry", "kind,items,payload")):
|
||||
__slots__ = ()
|
||||
@@ -134,7 +135,8 @@ class TrieEntry(namedtuple("TrieEntry", "kind,items,payload")):
|
||||
EntryKind.TABLE256: 256,
|
||||
EntryKind.TABLE8: 8,
|
||||
EntryKind.TABLE72: 72,
|
||||
EntryKind.TABLE_PREFIX: 16
|
||||
EntryKind.TABLE_PREFIX: 8,
|
||||
EntryKind.TABLE_VEX: 4,
|
||||
}
|
||||
@classmethod
|
||||
def table(cls, kind):
|
||||
@@ -186,18 +188,19 @@ def parse_opcode(opcode_string):
|
||||
assert not extended
|
||||
|
||||
legacy = {"NP": 0, "66": 1, "F3": 2, "F2": 3}[match.group("legacy")]
|
||||
entry = legacy | ((1 << 3) if match.group("vex") else 0)
|
||||
entry = legacy | ((1 << 2) if match.group("vex") else 0)
|
||||
opcode.append((EntryKind.TABLE_PREFIX, entry))
|
||||
|
||||
if match.group("vexl"):
|
||||
print("ignored mandatory VEX.L prefix for:", opcode_string)
|
||||
if not match.group("vexl") and not match.group("rexw"):
|
||||
return [tuple(opcode)]
|
||||
|
||||
rexw = match.group("rexw")
|
||||
if not rexw:
|
||||
return [tuple(opcode) + ((EntryKind.TABLE_PREFIX, entry),),
|
||||
tuple(opcode) + ((EntryKind.TABLE_PREFIX, entry | (1 << 2)),)]
|
||||
rexw = [0, 1<<0] if not rexw else [1<<0] if "W1" in rexw else [0]
|
||||
vexl = match.group("vexl")
|
||||
vexl = [0, 1<<1] if not vexl else [1<<1] if "L1" in vexl else [0]
|
||||
|
||||
entry |= (1 << 2) if "W1" in rexw else 0
|
||||
return [tuple(opcode) + ((EntryKind.TABLE_PREFIX, entry),)]
|
||||
entries = list(map(sum, product(rexw, vexl)))
|
||||
return [tuple(opcode) + ((EntryKind.TABLE_VEX, k),) for k in entries]
|
||||
|
||||
if not extended:
|
||||
return [tuple(opcode)]
|
||||
|
||||
Reference in New Issue
Block a user