instrs: Add reserved NOP/PREFETCH as weak opcodes
This commit is contained in:
26
instrs.txt
26
instrs.txt
@@ -347,11 +347,8 @@ F2.0f09 NP - - - - WBINVD
|
|||||||
0f0d/0m M MEM8 - - - PREFETCH
|
0f0d/0m M MEM8 - - - PREFETCH
|
||||||
0f0d/1m M MEM8 - - - PREFETCHW
|
0f0d/1m M MEM8 - - - PREFETCHW
|
||||||
0f0d/2m M MEM8 - - - PREFETCHWT1
|
0f0d/2m M MEM8 - - - PREFETCHWT1
|
||||||
0f0d/3m M MEM8 - - - RESERVED_PREFETCH
|
# All other slots are reserved, AMD maps them to /0
|
||||||
0f0d/4m M MEM8 - - - RESERVED_PREFETCH
|
*0f0d/m M MEM8 - - - RESERVED_PREFETCH ONLYAMD
|
||||||
0f0d/5m M MEM8 - - - RESERVED_PREFETCH
|
|
||||||
0f0d/6m M MEM8 - - - RESERVED_PREFETCH
|
|
||||||
0f0d/7m M MEM8 - - - RESERVED_PREFETCH
|
|
||||||
0f0e NP - - - - FEMMS ONLYAMD
|
0f0e NP - - - - FEMMS ONLYAMD
|
||||||
# TODO: actually decode 3DNow! instructions. Given that 3DNow! no longer exists,
|
# TODO: actually decode 3DNow! instructions. Given that 3DNow! no longer exists,
|
||||||
# this is unlikely to happen, though.
|
# this is unlikely to happen, though.
|
||||||
@@ -360,15 +357,16 @@ F2.0f09 NP - - - - WBINVD
|
|||||||
0f18/1m M MEM8 - - - PREFETCHT0
|
0f18/1m M MEM8 - - - PREFETCHT0
|
||||||
0f18/2m M MEM8 - - - PREFETCHT1
|
0f18/2m M MEM8 - - - PREFETCHT1
|
||||||
0f18/3m M MEM8 - - - PREFETCHT2
|
0f18/3m M MEM8 - - - PREFETCHT2
|
||||||
0f18/0r M GP - - - RESERVED_NOP
|
# Reserved NOPs are weak, they can be overridden by other instructions.
|
||||||
0f18/1r M GP - - - RESERVED_NOP
|
*0f18 MR GP GP - - RESERVED_NOP
|
||||||
0f18/2r M GP - - - RESERVED_NOP
|
*0f19 MR GP GP - - RESERVED_NOP
|
||||||
0f18/3r M GP - - - RESERVED_NOP
|
*0f1a MR GP GP - - RESERVED_NOP
|
||||||
0f18/4 M GP - - - RESERVED_NOP
|
*0f1b MR GP GP - - RESERVED_NOP
|
||||||
0f18/5 M GP - - - RESERVED_NOP
|
*0f1c MR GP GP - - RESERVED_NOP
|
||||||
0f18/6 M GP - - - RESERVED_NOP
|
*0f1d MR GP GP - - RESERVED_NOP
|
||||||
0f18/7 M GP - - - RESERVED_NOP
|
*0f1e MR GP GP - - RESERVED_NOP
|
||||||
0f1f M GP - - - NOP
|
*0f1f MR GP GP - - RESERVED_NOP
|
||||||
|
0f1f/0 M GP - - - NOP
|
||||||
0f20 MR GP CR - - MOV_CR DEF64 IGN66
|
0f20 MR GP CR - - MOV_CR DEF64 IGN66
|
||||||
0f21 MR GP DR - - MOV_DR DEF64 IGN66
|
0f21 MR GP DR - - MOV_DR DEF64 IGN66
|
||||||
0f22 RM CR GP - - MOV_CR DEF64 IGN66
|
0f22 RM CR GP - - MOV_CR DEF64 IGN66
|
||||||
|
|||||||
@@ -345,7 +345,7 @@ class Table:
|
|||||||
new_items = old.items[:idx] + (entry_name,) + old.items[idx+1:]
|
new_items = old.items[:idx] + (entry_name,) + old.items[idx+1:]
|
||||||
self.data[name] = TrieEntry(old.kind, new_items, None)
|
self.data[name] = TrieEntry(old.kind, new_items, None)
|
||||||
|
|
||||||
def add_opcode(self, opcode, instr_encoding, root_idx=0):
|
def _walk_opcode(self, opcode, root_idx):
|
||||||
name = "t{},{}".format(root_idx, format_opcode(opcode))
|
name = "t{},{}".format(root_idx, format_opcode(opcode))
|
||||||
|
|
||||||
tn = "root%d"%root_idx
|
tn = "root%d"%root_idx
|
||||||
@@ -361,12 +361,33 @@ class Table:
|
|||||||
if self.data[tn].kind != kind:
|
if self.data[tn].kind != kind:
|
||||||
raise Exception("{}, have {}, want {}".format(
|
raise Exception("{}, have {}, want {}".format(
|
||||||
name, self.data[tn].kind, kind))
|
name, self.data[tn].kind, kind))
|
||||||
|
return tn
|
||||||
|
|
||||||
|
def _add_encoding(self, instr_encoding):
|
||||||
desc_idx = self.descs_map.get(instr_encoding)
|
desc_idx = self.descs_map.get(instr_encoding)
|
||||||
if desc_idx is None:
|
if desc_idx is None:
|
||||||
desc_idx = self.descs_map[instr_encoding] = len(self.descs)
|
desc_idx = self.descs_map[instr_encoding] = len(self.descs)
|
||||||
self.descs.append(instr_encoding)
|
self.descs.append(instr_encoding)
|
||||||
self._update_table(tn, opcode[-1][1], name, TrieEntry.instr(desc_idx))
|
return TrieEntry.instr(desc_idx)
|
||||||
|
|
||||||
|
def add_opcode(self, opcode, instr_encoding, root_idx=0):
|
||||||
|
name = "t{},{}".format(root_idx, format_opcode(opcode))
|
||||||
|
tn = self._walk_opcode(opcode, root_idx)
|
||||||
|
desc_entry = self._add_encoding(instr_encoding)
|
||||||
|
self._update_table(tn, opcode[-1][1], name, desc_entry)
|
||||||
|
|
||||||
|
def fill_free(self, opcode, instr_encoding, root_idx=0):
|
||||||
|
desc_entry = self._add_encoding(instr_encoding)
|
||||||
|
tn = self._walk_opcode(opcode, root_idx)
|
||||||
|
queue = [(tn, opcode[-1][1])]
|
||||||
|
while queue:
|
||||||
|
tn, idx = queue.pop()
|
||||||
|
entry = self.data[tn].items[idx]
|
||||||
|
if not entry:
|
||||||
|
self._update_table(tn, idx, f"tn,*{idx:x}", desc_entry)
|
||||||
|
else:
|
||||||
|
for i in range(len(self.data[entry].items)):
|
||||||
|
queue.append((entry, i))
|
||||||
|
|
||||||
def deduplicate(self):
|
def deduplicate(self):
|
||||||
parents = defaultdict(set)
|
parents = defaultdict(set)
|
||||||
@@ -468,10 +489,8 @@ template = """// Auto-generated file -- do not modify!
|
|||||||
def encode_table(entries):
|
def encode_table(entries):
|
||||||
mnemonics = defaultdict(list)
|
mnemonics = defaultdict(list)
|
||||||
mnemonics["FE_NOP"].append(("NP", 0, 0, "0x90"))
|
mnemonics["FE_NOP"].append(("NP", 0, 0, "0x90"))
|
||||||
for opcode, desc in entries:
|
for weak, opcode, desc in entries:
|
||||||
if desc.mnemonic[:9] == "RESERVED_":
|
if weak or "ONLY32" in desc.flags:
|
||||||
continue
|
|
||||||
if "ONLY32" in desc.flags:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
opsizes = {8} if "SIZE_8" in desc.flags else {16, 32, 64}
|
opsizes = {8} if "SIZE_8" in desc.flags else {16, 32, 64}
|
||||||
@@ -629,30 +648,37 @@ if __name__ == "__main__":
|
|||||||
entries = []
|
entries = []
|
||||||
for line in args.table.read().splitlines():
|
for line in args.table.read().splitlines():
|
||||||
if not line or line[0] == "#": continue
|
if not line or line[0] == "#": continue
|
||||||
|
line, weak = (line, False) if line[0] != "*" else (line[1:], True)
|
||||||
opcode_string, desc_string = tuple(line.split(maxsplit=1))
|
opcode_string, desc_string = tuple(line.split(maxsplit=1))
|
||||||
opcode, desc = Opcode.parse(opcode_string), InstrDesc.parse(desc_string)
|
opcode, desc = Opcode.parse(opcode_string), InstrDesc.parse(desc_string)
|
||||||
if "UNDOC" not in desc.flags or args.with_undoc:
|
if "UNDOC" not in desc.flags or args.with_undoc:
|
||||||
entries.append((opcode, desc))
|
entries.append((weak, opcode, desc))
|
||||||
|
|
||||||
mnemonics = sorted({desc.mnemonic for _, desc in entries})
|
mnemonics = sorted({desc.mnemonic for _, _, desc in entries})
|
||||||
|
|
||||||
decode_mnems_lines = [f"FD_MNEMONIC({m},{i})\n" for i, m in enumerate(mnemonics)]
|
decode_mnems_lines = [f"FD_MNEMONIC({m},{i})\n" for i, m in enumerate(mnemonics)]
|
||||||
args.decode_mnems.write("".join(decode_mnems_lines))
|
args.decode_mnems.write("".join(decode_mnems_lines))
|
||||||
|
|
||||||
modes = [32, 64]
|
modes = [32, 64]
|
||||||
table = Table(root_count=len(args.modes))
|
table = Table(root_count=len(args.modes))
|
||||||
for opcode, desc in entries:
|
weak_opcodes = []
|
||||||
|
for weak, opcode, desc in entries:
|
||||||
for i, mode in enumerate(args.modes):
|
for i, mode in enumerate(args.modes):
|
||||||
if "ONLY%d"%(96-mode) not in desc.flags:
|
if "ONLY%d"%(96-mode) not in desc.flags:
|
||||||
ign66 = opcode.prefix in ("NP", "66", "F2", "F3")
|
ign66 = opcode.prefix in ("NP", "66", "F2", "F3")
|
||||||
for opcode_path in opcode.for_trie():
|
for opcode_path in opcode.for_trie():
|
||||||
|
if weak:
|
||||||
|
weak_opcodes.append((opcode_path, desc.encode(ign66), i))
|
||||||
|
else:
|
||||||
table.add_opcode(opcode_path, desc.encode(ign66), i)
|
table.add_opcode(opcode_path, desc.encode(ign66), i)
|
||||||
|
for k in weak_opcodes:
|
||||||
|
table.fill_free(*k)
|
||||||
|
|
||||||
table.deduplicate()
|
table.deduplicate()
|
||||||
table_data, annotations, root_offsets, descs = table.compile()
|
table_data, annotations, root_offsets, descs = table.compile()
|
||||||
|
|
||||||
mnemonics_intel = [m.replace("SSE_", "").replace("MMX_", "")
|
mnemonics_intel = [m.replace("SSE_", "").replace("MMX_", "")
|
||||||
.replace("MOVABS", "MOV")
|
.replace("MOVABS", "MOV").replace("RESERVED_", "")
|
||||||
.replace("JMPF", "JMP FAR").replace("CALLF", "CALL FAR")
|
.replace("JMPF", "JMP FAR").replace("CALLF", "CALL FAR")
|
||||||
.replace("_S2G", "").replace("_G2S", "")
|
.replace("_S2G", "").replace("_G2S", "")
|
||||||
.replace("_CR", "").replace("_DR", "")
|
.replace("_CR", "").replace("_DR", "")
|
||||||
|
|||||||
@@ -111,6 +111,8 @@ main(int argc, char** argv)
|
|||||||
TEST64("\x44\x8c\xf8", "UD"); // no segment register 7
|
TEST64("\x44\x8c\xf8", "UD"); // no segment register 7
|
||||||
TEST("\x8e\xc0", "mov es, ax");
|
TEST("\x8e\xc0", "mov es, ax");
|
||||||
TEST("\x8e\xc8", "UD"); // No mov cs, eax
|
TEST("\x8e\xc8", "UD"); // No mov cs, eax
|
||||||
|
TEST("\x0f\x1e\xc0", "nop eax, eax"); // reserved nop
|
||||||
|
TEST("\x0f\x1e\x04\x25\x01\x00\x00\x00", "nop dword ptr [0x1], eax"); // reserved nop
|
||||||
TEST("\xd8\xc1", "fadd st(0), st(1)");
|
TEST("\xd8\xc1", "fadd st(0), st(1)");
|
||||||
TEST("\xdc\xc1", "fadd st(1), st(0)");
|
TEST("\xdc\xc1", "fadd st(1), st(0)");
|
||||||
TEST64("\x41\xd8\xc1", "fadd st(0), st(1)"); // REX.B ignored
|
TEST64("\x41\xd8\xc1", "fadd st(0), st(1)"); // REX.B ignored
|
||||||
|
|||||||
Reference in New Issue
Block a user