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_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;
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
Reference in New Issue
Block a user