Enforce mandatory L0/L1 in VEX prefix

This commit is contained in:
Alexis Engelke
2019-02-24 15:45:00 +01:00
parent 83988828ec
commit f7f0b322c7
2 changed files with 26 additions and 13 deletions

View File

@@ -36,6 +36,7 @@ typedef enum DecodeMode DecodeMode;
#define ENTRY_TABLE8 3 #define ENTRY_TABLE8 3
#define ENTRY_TABLE72 4 #define ENTRY_TABLE72 4
#define ENTRY_TABLE_PREFIX 5 #define ENTRY_TABLE_PREFIX 5
#define ENTRY_TABLE_VEX 6
#define ENTRY_MASK 7 #define ENTRY_MASK 7
#define ENTRY_IS_TABLE(kind) ((kind) >= ENTRY_TABLE256) #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); 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) if (kind == ENTRY_TABLE_PREFIX)
{ {
uint8_t index = mandatory_prefix; uint8_t index = mandatory_prefix;
index |= prefixes & PREFIX_REXW ? (1 << 2) : 0; index |= prefixes & PREFIX_VEX ? (1 << 2) : 0;
index |= prefixes & PREFIX_VEX ? (1 << 3) : 0;
// If a prefix is mandatory and used as opcode extension, it has no // If a prefix is mandatory and used as opcode extension, it has no
// further effect on the instruction. This is especially important // further effect on the instruction. This is especially important
// for the 0x66 prefix, which could otherwise override the operand // 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]); 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)) if (UNLIKELY(kind != ENTRY_INSTR))
{ {
return -1; return -1;

View File

@@ -5,7 +5,7 @@ from binascii import unhexlify
from collections import OrderedDict, defaultdict, namedtuple, Counter from collections import OrderedDict, defaultdict, namedtuple, Counter
from copy import copy from copy import copy
from enum import Enum, IntEnum from enum import Enum, IntEnum
from itertools import accumulate from itertools import accumulate, product
import struct import struct
def bitstruct(name, fields): def bitstruct(name, fields):
@@ -127,6 +127,7 @@ class EntryKind(Enum):
TABLE8 = 3 TABLE8 = 3
TABLE72 = 4 TABLE72 = 4
TABLE_PREFIX = 5 TABLE_PREFIX = 5
TABLE_VEX = 6
class TrieEntry(namedtuple("TrieEntry", "kind,items,payload")): class TrieEntry(namedtuple("TrieEntry", "kind,items,payload")):
__slots__ = () __slots__ = ()
@@ -134,7 +135,8 @@ class TrieEntry(namedtuple("TrieEntry", "kind,items,payload")):
EntryKind.TABLE256: 256, EntryKind.TABLE256: 256,
EntryKind.TABLE8: 8, EntryKind.TABLE8: 8,
EntryKind.TABLE72: 72, EntryKind.TABLE72: 72,
EntryKind.TABLE_PREFIX: 16 EntryKind.TABLE_PREFIX: 8,
EntryKind.TABLE_VEX: 4,
} }
@classmethod @classmethod
def table(cls, kind): def table(cls, kind):
@@ -186,18 +188,19 @@ def parse_opcode(opcode_string):
assert not extended assert not extended
legacy = {"NP": 0, "66": 1, "F3": 2, "F2": 3}[match.group("legacy")] 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"): if not match.group("vexl") and not match.group("rexw"):
print("ignored mandatory VEX.L prefix for:", opcode_string) return [tuple(opcode)]
rexw = match.group("rexw") rexw = match.group("rexw")
if not rexw: rexw = [0, 1<<0] if not rexw else [1<<0] if "W1" in rexw else [0]
return [tuple(opcode) + ((EntryKind.TABLE_PREFIX, entry),), vexl = match.group("vexl")
tuple(opcode) + ((EntryKind.TABLE_PREFIX, entry | (1 << 2)),)] 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 entries = list(map(sum, product(rexw, vexl)))
return [tuple(opcode) + ((EntryKind.TABLE_PREFIX, entry),)] return [tuple(opcode) + ((EntryKind.TABLE_VEX, k),) for k in entries]
if not extended: if not extended:
return [tuple(opcode)] return [tuple(opcode)]