aboutsummaryrefslogtreecommitdiffstats
path: root/tools/objtool/arch
diff options
context:
space:
mode:
authorJosh Poimboeuf <jpoimboe@redhat.com>2016-02-28 23:22:41 -0500
committerIngo Molnar <mingo@kernel.org>2016-02-29 02:35:12 -0500
commit442f04c34a1a467759d024a1d2c1df0f744dcb06 (patch)
tree0da60b38cb2476a5d9bedd24d67f3fde8624e151 /tools/objtool/arch
parent87aaff2ae09036cf699fde20dfd52ce7d3c8eabe (diff)
objtool: Add tool to perform compile-time stack metadata validation
This adds a host tool named objtool which has a "check" subcommand which analyzes .o files to ensure the validity of stack metadata. It enforces a set of rules on asm code and C inline assembly code so that stack traces can be reliable. For each function, it recursively follows all possible code paths and validates the correct frame pointer state at each instruction. It also follows code paths involving kernel special sections, like .altinstructions, __jump_table, and __ex_table, which can add alternative execution paths to a given instruction (or set of instructions). Similarly, it knows how to follow switch statements, for which gcc sometimes uses jump tables. Here are some of the benefits of validating stack metadata: a) More reliable stack traces for frame pointer enabled kernels Frame pointers are used for debugging purposes. They allow runtime code and debug tools to be able to walk the stack to determine the chain of function call sites that led to the currently executing code. For some architectures, frame pointers are enabled by CONFIG_FRAME_POINTER. For some other architectures they may be required by the ABI (sometimes referred to as "backchain pointers"). For C code, gcc automatically generates instructions for setting up frame pointers when the -fno-omit-frame-pointer option is used. But for asm code, the frame setup instructions have to be written by hand, which most people don't do. So the end result is that CONFIG_FRAME_POINTER is honored for C code but not for most asm code. For stack traces based on frame pointers to be reliable, all functions which call other functions must first create a stack frame and update the frame pointer. If a first function doesn't properly create a stack frame before calling a second function, the *caller* of the first function will be skipped on the stack trace. For example, consider the following example backtrace with frame pointers enabled: [<ffffffff81812584>] dump_stack+0x4b/0x63 [<ffffffff812d6dc2>] cmdline_proc_show+0x12/0x30 [<ffffffff8127f568>] seq_read+0x108/0x3e0 [<ffffffff812cce62>] proc_reg_read+0x42/0x70 [<ffffffff81256197>] __vfs_read+0x37/0x100 [<ffffffff81256b16>] vfs_read+0x86/0x130 [<ffffffff81257898>] SyS_read+0x58/0xd0 [<ffffffff8181c1f2>] entry_SYSCALL_64_fastpath+0x12/0x76 It correctly shows that the caller of cmdline_proc_show() is seq_read(). If we remove the frame pointer logic from cmdline_proc_show() by replacing the frame pointer related instructions with nops, here's what it looks like instead: [<ffffffff81812584>] dump_stack+0x4b/0x63 [<ffffffff812d6dc2>] cmdline_proc_show+0x12/0x30 [<ffffffff812cce62>] proc_reg_read+0x42/0x70 [<ffffffff81256197>] __vfs_read+0x37/0x100 [<ffffffff81256b16>] vfs_read+0x86/0x130 [<ffffffff81257898>] SyS_read+0x58/0xd0 [<ffffffff8181c1f2>] entry_SYSCALL_64_fastpath+0x12/0x76 Notice that cmdline_proc_show()'s caller, seq_read(), has been skipped. Instead the stack trace seems to show that cmdline_proc_show() was called by proc_reg_read(). The benefit of "objtool check" here is that because it ensures that *all* functions honor CONFIG_FRAME_POINTER, no functions will ever[*] be skipped on a stack trace. [*] unless an interrupt or exception has occurred at the very beginning of a function before the stack frame has been created, or at the very end of the function after the stack frame has been destroyed. This is an inherent limitation of frame pointers. b) 100% reliable stack traces for DWARF enabled kernels This is not yet implemented. For more details about what is planned, see tools/objtool/Documentation/stack-validation.txt. c) Higher live patching compatibility rate This is not yet implemented. For more details about what is planned, see tools/objtool/Documentation/stack-validation.txt. To achieve the validation, "objtool check" enforces the following rules: 1. Each callable function must be annotated as such with the ELF function type. In asm code, this is typically done using the ENTRY/ENDPROC macros. If objtool finds a return instruction outside of a function, it flags an error since that usually indicates callable code which should be annotated accordingly. This rule is needed so that objtool can properly identify each callable function in order to analyze its stack metadata. 2. Conversely, each section of code which is *not* callable should *not* be annotated as an ELF function. The ENDPROC macro shouldn't be used in this case. This rule is needed so that objtool can ignore non-callable code. Such code doesn't have to follow any of the other rules. 3. Each callable function which calls another function must have the correct frame pointer logic, if required by CONFIG_FRAME_POINTER or the architecture's back chain rules. This can by done in asm code with the FRAME_BEGIN/FRAME_END macros. This rule ensures that frame pointer based stack traces will work as designed. If function A doesn't create a stack frame before calling function B, the _caller_ of function A will be skipped on the stack trace. 4. Dynamic jumps and jumps to undefined symbols are only allowed if: a) the jump is part of a switch statement; or b) the jump matches sibling call semantics and the frame pointer has the same value it had on function entry. This rule is needed so that objtool can reliably analyze all of a function's code paths. If a function jumps to code in another file, and it's not a sibling call, objtool has no way to follow the jump because it only analyzes a single file at a time. 5. A callable function may not execute kernel entry/exit instructions. The only code which needs such instructions is kernel entry code, which shouldn't be be in callable functions anyway. This rule is just a sanity check to ensure that callable functions return normally. It currently only supports x86_64. I tried to make the code generic so that support for other architectures can hopefully be plugged in relatively easily. On my Lenovo laptop with a i7-4810MQ 4-core/8-thread CPU, building the kernel with objtool checking every .o file adds about three seconds of total build time. It hasn't been optimized for performance yet, so there are probably some opportunities for better build performance. Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Bernd Petrovitsch <bernd@petrovitsch.priv.at> Cc: Borislav Petkov <bp@alien8.de> Cc: Chris J Arges <chris.j.arges@canonical.com> Cc: Jiri Slaby <jslaby@suse.cz> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Michal Marek <mmarek@suse.cz> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Pedro Alves <palves@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: live-patching@vger.kernel.org Link: http://lkml.kernel.org/r/f3efb173de43bd067b060de73f856567c0fa1174.1456719558.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/objtool/arch')
-rw-r--r--tools/objtool/arch/x86/Build12
-rw-r--r--tools/objtool/arch/x86/decode.c172
-rw-r--r--tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk387
-rw-r--r--tools/objtool/arch/x86/insn/inat.c97
-rw-r--r--tools/objtool/arch/x86/insn/inat.h221
-rw-r--r--tools/objtool/arch/x86/insn/inat_types.h29
-rw-r--r--tools/objtool/arch/x86/insn/insn.c594
-rw-r--r--tools/objtool/arch/x86/insn/insn.h201
-rw-r--r--tools/objtool/arch/x86/insn/x86-opcode-map.txt984
9 files changed, 2697 insertions, 0 deletions
diff --git a/tools/objtool/arch/x86/Build b/tools/objtool/arch/x86/Build
new file mode 100644
index 000000000000..debbdb0b5c43
--- /dev/null
+++ b/tools/objtool/arch/x86/Build
@@ -0,0 +1,12 @@
1objtool-y += decode.o
2
3inat_tables_script = arch/x86/insn/gen-insn-attr-x86.awk
4inat_tables_maps = arch/x86/insn/x86-opcode-map.txt
5
6$(OUTPUT)arch/x86/insn/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
7 $(call rule_mkdir)
8 $(Q)$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@
9
10$(OUTPUT)arch/x86/decode.o: $(OUTPUT)arch/x86/insn/inat-tables.c
11
12CFLAGS_decode.o += -I$(OUTPUT)arch/x86/insn
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
new file mode 100644
index 000000000000..c0c0b265e88e
--- /dev/null
+++ b/tools/objtool/arch/x86/decode.c
@@ -0,0 +1,172 @@
1/*
2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <stdio.h>
19#include <stdlib.h>
20
21#define unlikely(cond) (cond)
22#include "insn/insn.h"
23#include "insn/inat.c"
24#include "insn/insn.c"
25
26#include "../../elf.h"
27#include "../../arch.h"
28#include "../../warn.h"
29
30static int is_x86_64(struct elf *elf)
31{
32 switch (elf->ehdr.e_machine) {
33 case EM_X86_64:
34 return 1;
35 case EM_386:
36 return 0;
37 default:
38 WARN("unexpected ELF machine type %d", elf->ehdr.e_machine);
39 return -1;
40 }
41}
42
43int arch_decode_instruction(struct elf *elf, struct section *sec,
44 unsigned long offset, unsigned int maxlen,
45 unsigned int *len, unsigned char *type,
46 unsigned long *immediate)
47{
48 struct insn insn;
49 int x86_64;
50 unsigned char op1, op2, ext;
51
52 x86_64 = is_x86_64(elf);
53 if (x86_64 == -1)
54 return -1;
55
56 insn_init(&insn, (void *)(sec->data + offset), maxlen, x86_64);
57 insn_get_length(&insn);
58 insn_get_opcode(&insn);
59 insn_get_modrm(&insn);
60 insn_get_immediate(&insn);
61
62 if (!insn_complete(&insn)) {
63 WARN_FUNC("can't decode instruction", sec, offset);
64 return -1;
65 }
66
67 *len = insn.length;
68 *type = INSN_OTHER;
69
70 if (insn.vex_prefix.nbytes)
71 return 0;
72
73 op1 = insn.opcode.bytes[0];
74 op2 = insn.opcode.bytes[1];
75
76 switch (op1) {
77 case 0x55:
78 if (!insn.rex_prefix.nbytes)
79 /* push rbp */
80 *type = INSN_FP_SAVE;
81 break;
82
83 case 0x5d:
84 if (!insn.rex_prefix.nbytes)
85 /* pop rbp */
86 *type = INSN_FP_RESTORE;
87 break;
88
89 case 0x70 ... 0x7f:
90 *type = INSN_JUMP_CONDITIONAL;
91 break;
92
93 case 0x89:
94 if (insn.rex_prefix.nbytes == 1 &&
95 insn.rex_prefix.bytes[0] == 0x48 &&
96 insn.modrm.nbytes && insn.modrm.bytes[0] == 0xe5)
97 /* mov rsp, rbp */
98 *type = INSN_FP_SETUP;
99 break;
100
101 case 0x90:
102 *type = INSN_NOP;
103 break;
104
105 case 0x0f:
106 if (op2 >= 0x80 && op2 <= 0x8f)
107 *type = INSN_JUMP_CONDITIONAL;
108 else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
109 op2 == 0x35)
110 /* sysenter, sysret */
111 *type = INSN_CONTEXT_SWITCH;
112 else if (op2 == 0x0b || op2 == 0xb9)
113 /* ud2 */
114 *type = INSN_BUG;
115 else if (op2 == 0x0d || op2 == 0x1f)
116 /* nopl/nopw */
117 *type = INSN_NOP;
118 else if (op2 == 0x01 && insn.modrm.nbytes &&
119 (insn.modrm.bytes[0] == 0xc2 ||
120 insn.modrm.bytes[0] == 0xd8))
121 /* vmlaunch, vmrun */
122 *type = INSN_CONTEXT_SWITCH;
123
124 break;
125
126 case 0xc9: /* leave */
127 *type = INSN_FP_RESTORE;
128 break;
129
130 case 0xe3: /* jecxz/jrcxz */
131 *type = INSN_JUMP_CONDITIONAL;
132 break;
133
134 case 0xe9:
135 case 0xeb:
136 *type = INSN_JUMP_UNCONDITIONAL;
137 break;
138
139 case 0xc2:
140 case 0xc3:
141 *type = INSN_RETURN;
142 break;
143
144 case 0xc5: /* iret */
145 case 0xca: /* retf */
146 case 0xcb: /* retf */
147 *type = INSN_CONTEXT_SWITCH;
148 break;
149
150 case 0xe8:
151 *type = INSN_CALL;
152 break;
153
154 case 0xff:
155 ext = X86_MODRM_REG(insn.modrm.bytes[0]);
156 if (ext == 2 || ext == 3)
157 *type = INSN_CALL_DYNAMIC;
158 else if (ext == 4)
159 *type = INSN_JUMP_DYNAMIC;
160 else if (ext == 5) /*jmpf */
161 *type = INSN_CONTEXT_SWITCH;
162
163 break;
164
165 default:
166 break;
167 }
168
169 *immediate = insn.immediate.nbytes ? insn.immediate.value : 0;
170
171 return 0;
172}
diff --git a/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk b/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk
new file mode 100644
index 000000000000..093a892026f9
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk
@@ -0,0 +1,387 @@
1#!/bin/awk -f
2# gen-insn-attr-x86.awk: Instruction attribute table generator
3# Written by Masami Hiramatsu <mhiramat@redhat.com>
4#
5# Usage: awk -f gen-insn-attr-x86.awk x86-opcode-map.txt > inat-tables.c
6
7# Awk implementation sanity check
8function check_awk_implement() {
9 if (sprintf("%x", 0) != "0")
10 return "Your awk has a printf-format problem."
11 return ""
12}
13
14# Clear working vars
15function clear_vars() {
16 delete table
17 delete lptable2
18 delete lptable1
19 delete lptable3
20 eid = -1 # escape id
21 gid = -1 # group id
22 aid = -1 # AVX id
23 tname = ""
24}
25
26BEGIN {
27 # Implementation error checking
28 awkchecked = check_awk_implement()
29 if (awkchecked != "") {
30 print "Error: " awkchecked > "/dev/stderr"
31 print "Please try to use gawk." > "/dev/stderr"
32 exit 1
33 }
34
35 # Setup generating tables
36 print "/* x86 opcode map generated from x86-opcode-map.txt */"
37 print "/* Do not change this code. */\n"
38 ggid = 1
39 geid = 1
40 gaid = 0
41 delete etable
42 delete gtable
43 delete atable
44
45 opnd_expr = "^[A-Za-z/]"
46 ext_expr = "^\\("
47 sep_expr = "^\\|$"
48 group_expr = "^Grp[0-9A-Za-z]+"
49
50 imm_expr = "^[IJAOL][a-z]"
51 imm_flag["Ib"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
52 imm_flag["Jb"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
53 imm_flag["Iw"] = "INAT_MAKE_IMM(INAT_IMM_WORD)"
54 imm_flag["Id"] = "INAT_MAKE_IMM(INAT_IMM_DWORD)"
55 imm_flag["Iq"] = "INAT_MAKE_IMM(INAT_IMM_QWORD)"
56 imm_flag["Ap"] = "INAT_MAKE_IMM(INAT_IMM_PTR)"
57 imm_flag["Iz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
58 imm_flag["Jz"] = "INAT_MAKE_IMM(INAT_IMM_VWORD32)"
59 imm_flag["Iv"] = "INAT_MAKE_IMM(INAT_IMM_VWORD)"
60 imm_flag["Ob"] = "INAT_MOFFSET"
61 imm_flag["Ov"] = "INAT_MOFFSET"
62 imm_flag["Lx"] = "INAT_MAKE_IMM(INAT_IMM_BYTE)"
63
64 modrm_expr = "^([CDEGMNPQRSUVW/][a-z]+|NTA|T[012])"
65 force64_expr = "\\([df]64\\)"
66 rex_expr = "^REX(\\.[XRWB]+)*"
67 fpu_expr = "^ESC" # TODO
68
69 lprefix1_expr = "\\((66|!F3)\\)"
70 lprefix2_expr = "\\(F3\\)"
71 lprefix3_expr = "\\((F2|!F3|66\\&F2)\\)"
72 lprefix_expr = "\\((66|F2|F3)\\)"
73 max_lprefix = 4
74
75 # All opcodes starting with lower-case 'v' or with (v1) superscript
76 # accepts VEX prefix
77 vexok_opcode_expr = "^v.*"
78 vexok_expr = "\\(v1\\)"
79 # All opcodes with (v) superscript supports *only* VEX prefix
80 vexonly_expr = "\\(v\\)"
81
82 prefix_expr = "\\(Prefix\\)"
83 prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ"
84 prefix_num["REPNE"] = "INAT_PFX_REPNE"
85 prefix_num["REP/REPE"] = "INAT_PFX_REPE"
86 prefix_num["XACQUIRE"] = "INAT_PFX_REPNE"
87 prefix_num["XRELEASE"] = "INAT_PFX_REPE"
88 prefix_num["LOCK"] = "INAT_PFX_LOCK"
89 prefix_num["SEG=CS"] = "INAT_PFX_CS"
90 prefix_num["SEG=DS"] = "INAT_PFX_DS"
91 prefix_num["SEG=ES"] = "INAT_PFX_ES"
92 prefix_num["SEG=FS"] = "INAT_PFX_FS"
93 prefix_num["SEG=GS"] = "INAT_PFX_GS"
94 prefix_num["SEG=SS"] = "INAT_PFX_SS"
95 prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ"
96 prefix_num["VEX+1byte"] = "INAT_PFX_VEX2"
97 prefix_num["VEX+2byte"] = "INAT_PFX_VEX3"
98
99 clear_vars()
100}
101
102function semantic_error(msg) {
103 print "Semantic error at " NR ": " msg > "/dev/stderr"
104 exit 1
105}
106
107function debug(msg) {
108 print "DEBUG: " msg
109}
110
111function array_size(arr, i,c) {
112 c = 0
113 for (i in arr)
114 c++
115 return c
116}
117
118/^Table:/ {
119 print "/* " $0 " */"
120 if (tname != "")
121 semantic_error("Hit Table: before EndTable:.");
122}
123
124/^Referrer:/ {
125 if (NF != 1) {
126 # escape opcode table
127 ref = ""
128 for (i = 2; i <= NF; i++)
129 ref = ref $i
130 eid = escape[ref]
131 tname = sprintf("inat_escape_table_%d", eid)
132 }
133}
134
135/^AVXcode:/ {
136 if (NF != 1) {
137 # AVX/escape opcode table
138 aid = $2
139 if (gaid <= aid)
140 gaid = aid + 1
141 if (tname == "") # AVX only opcode table
142 tname = sprintf("inat_avx_table_%d", $2)
143 }
144 if (aid == -1 && eid == -1) # primary opcode table
145 tname = "inat_primary_table"
146}
147
148/^GrpTable:/ {
149 print "/* " $0 " */"
150 if (!($2 in group))
151 semantic_error("No group: " $2 )
152 gid = group[$2]
153 tname = "inat_group_table_" gid
154}
155
156function print_table(tbl,name,fmt,n)
157{
158 print "const insn_attr_t " name " = {"
159 for (i = 0; i < n; i++) {
160 id = sprintf(fmt, i)
161 if (tbl[id])
162 print " [" id "] = " tbl[id] ","
163 }
164 print "};"
165}
166
167/^EndTable/ {
168 if (gid != -1) {
169 # print group tables
170 if (array_size(table) != 0) {
171 print_table(table, tname "[INAT_GROUP_TABLE_SIZE]",
172 "0x%x", 8)
173 gtable[gid,0] = tname
174 }
175 if (array_size(lptable1) != 0) {
176 print_table(lptable1, tname "_1[INAT_GROUP_TABLE_SIZE]",
177 "0x%x", 8)
178 gtable[gid,1] = tname "_1"
179 }
180 if (array_size(lptable2) != 0) {
181 print_table(lptable2, tname "_2[INAT_GROUP_TABLE_SIZE]",
182 "0x%x", 8)
183 gtable[gid,2] = tname "_2"
184 }
185 if (array_size(lptable3) != 0) {
186 print_table(lptable3, tname "_3[INAT_GROUP_TABLE_SIZE]",
187 "0x%x", 8)
188 gtable[gid,3] = tname "_3"
189 }
190 } else {
191 # print primary/escaped tables
192 if (array_size(table) != 0) {
193 print_table(table, tname "[INAT_OPCODE_TABLE_SIZE]",
194 "0x%02x", 256)
195 etable[eid,0] = tname
196 if (aid >= 0)
197 atable[aid,0] = tname
198 }
199 if (array_size(lptable1) != 0) {
200 print_table(lptable1,tname "_1[INAT_OPCODE_TABLE_SIZE]",
201 "0x%02x", 256)
202 etable[eid,1] = tname "_1"
203 if (aid >= 0)
204 atable[aid,1] = tname "_1"
205 }
206 if (array_size(lptable2) != 0) {
207 print_table(lptable2,tname "_2[INAT_OPCODE_TABLE_SIZE]",
208 "0x%02x", 256)
209 etable[eid,2] = tname "_2"
210 if (aid >= 0)
211 atable[aid,2] = tname "_2"
212 }
213 if (array_size(lptable3) != 0) {
214 print_table(lptable3,tname "_3[INAT_OPCODE_TABLE_SIZE]",
215 "0x%02x", 256)
216 etable[eid,3] = tname "_3"
217 if (aid >= 0)
218 atable[aid,3] = tname "_3"
219 }
220 }
221 print ""
222 clear_vars()
223}
224
225function add_flags(old,new) {
226 if (old && new)
227 return old " | " new
228 else if (old)
229 return old
230 else
231 return new
232}
233
234# convert operands to flags.
235function convert_operands(count,opnd, i,j,imm,mod)
236{
237 imm = null
238 mod = null
239 for (j = 1; j <= count; j++) {
240 i = opnd[j]
241 if (match(i, imm_expr) == 1) {
242 if (!imm_flag[i])
243 semantic_error("Unknown imm opnd: " i)
244 if (imm) {
245 if (i != "Ib")
246 semantic_error("Second IMM error")
247 imm = add_flags(imm, "INAT_SCNDIMM")
248 } else
249 imm = imm_flag[i]
250 } else if (match(i, modrm_expr))
251 mod = "INAT_MODRM"
252 }
253 return add_flags(imm, mod)
254}
255
256/^[0-9a-f]+\:/ {
257 if (NR == 1)
258 next
259 # get index
260 idx = "0x" substr($1, 1, index($1,":") - 1)
261 if (idx in table)
262 semantic_error("Redefine " idx " in " tname)
263
264 # check if escaped opcode
265 if ("escape" == $2) {
266 if ($3 != "#")
267 semantic_error("No escaped name")
268 ref = ""
269 for (i = 4; i <= NF; i++)
270 ref = ref $i
271 if (ref in escape)
272 semantic_error("Redefine escape (" ref ")")
273 escape[ref] = geid
274 geid++
275 table[idx] = "INAT_MAKE_ESCAPE(" escape[ref] ")"
276 next
277 }
278
279 variant = null
280 # converts
281 i = 2
282 while (i <= NF) {
283 opcode = $(i++)
284 delete opnds
285 ext = null
286 flags = null
287 opnd = null
288 # parse one opcode
289 if (match($i, opnd_expr)) {
290 opnd = $i
291 count = split($(i++), opnds, ",")
292 flags = convert_operands(count, opnds)
293 }
294 if (match($i, ext_expr))
295 ext = $(i++)
296 if (match($i, sep_expr))
297 i++
298 else if (i < NF)
299 semantic_error($i " is not a separator")
300
301 # check if group opcode
302 if (match(opcode, group_expr)) {
303 if (!(opcode in group)) {
304 group[opcode] = ggid
305 ggid++
306 }
307 flags = add_flags(flags, "INAT_MAKE_GROUP(" group[opcode] ")")
308 }
309 # check force(or default) 64bit
310 if (match(ext, force64_expr))
311 flags = add_flags(flags, "INAT_FORCE64")
312
313 # check REX prefix
314 if (match(opcode, rex_expr))
315 flags = add_flags(flags, "INAT_MAKE_PREFIX(INAT_PFX_REX)")
316
317 # check coprocessor escape : TODO
318 if (match(opcode, fpu_expr))
319 flags = add_flags(flags, "INAT_MODRM")
320
321 # check VEX codes
322 if (match(ext, vexonly_expr))
323 flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY")
324 else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr))
325 flags = add_flags(flags, "INAT_VEXOK")
326
327 # check prefixes
328 if (match(ext, prefix_expr)) {
329 if (!prefix_num[opcode])
330 semantic_error("Unknown prefix: " opcode)
331 flags = add_flags(flags, "INAT_MAKE_PREFIX(" prefix_num[opcode] ")")
332 }
333 if (length(flags) == 0)
334 continue
335 # check if last prefix
336 if (match(ext, lprefix1_expr)) {
337 lptable1[idx] = add_flags(lptable1[idx],flags)
338 variant = "INAT_VARIANT"
339 }
340 if (match(ext, lprefix2_expr)) {
341 lptable2[idx] = add_flags(lptable2[idx],flags)
342 variant = "INAT_VARIANT"
343 }
344 if (match(ext, lprefix3_expr)) {
345 lptable3[idx] = add_flags(lptable3[idx],flags)
346 variant = "INAT_VARIANT"
347 }
348 if (!match(ext, lprefix_expr)){
349 table[idx] = add_flags(table[idx],flags)
350 }
351 }
352 if (variant)
353 table[idx] = add_flags(table[idx],variant)
354}
355
356END {
357 if (awkchecked != "")
358 exit 1
359 # print escape opcode map's array
360 print "/* Escape opcode map array */"
361 print "const insn_attr_t * const inat_escape_tables[INAT_ESC_MAX + 1]" \
362 "[INAT_LSTPFX_MAX + 1] = {"
363 for (i = 0; i < geid; i++)
364 for (j = 0; j < max_lprefix; j++)
365 if (etable[i,j])
366 print " ["i"]["j"] = "etable[i,j]","
367 print "};\n"
368 # print group opcode map's array
369 print "/* Group opcode map array */"
370 print "const insn_attr_t * const inat_group_tables[INAT_GRP_MAX + 1]"\
371 "[INAT_LSTPFX_MAX + 1] = {"
372 for (i = 0; i < ggid; i++)
373 for (j = 0; j < max_lprefix; j++)
374 if (gtable[i,j])
375 print " ["i"]["j"] = "gtable[i,j]","
376 print "};\n"
377 # print AVX opcode map's array
378 print "/* AVX opcode map array */"
379 print "const insn_attr_t * const inat_avx_tables[X86_VEX_M_MAX + 1]"\
380 "[INAT_LSTPFX_MAX + 1] = {"
381 for (i = 0; i < gaid; i++)
382 for (j = 0; j < max_lprefix; j++)
383 if (atable[i,j])
384 print " ["i"]["j"] = "atable[i,j]","
385 print "};"
386}
387
diff --git a/tools/objtool/arch/x86/insn/inat.c b/tools/objtool/arch/x86/insn/inat.c
new file mode 100644
index 000000000000..e4bf28e6f4c7
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/inat.c
@@ -0,0 +1,97 @@
1/*
2 * x86 instruction attribute tables
3 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21#include "insn.h"
22
23/* Attribute tables are generated from opcode map */
24#include "inat-tables.c"
25
26/* Attribute search APIs */
27insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode)
28{
29 return inat_primary_table[opcode];
30}
31
32int inat_get_last_prefix_id(insn_byte_t last_pfx)
33{
34 insn_attr_t lpfx_attr;
35
36 lpfx_attr = inat_get_opcode_attribute(last_pfx);
37 return inat_last_prefix_id(lpfx_attr);
38}
39
40insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, int lpfx_id,
41 insn_attr_t esc_attr)
42{
43 const insn_attr_t *table;
44 int n;
45
46 n = inat_escape_id(esc_attr);
47
48 table = inat_escape_tables[n][0];
49 if (!table)
50 return 0;
51 if (inat_has_variant(table[opcode]) && lpfx_id) {
52 table = inat_escape_tables[n][lpfx_id];
53 if (!table)
54 return 0;
55 }
56 return table[opcode];
57}
58
59insn_attr_t inat_get_group_attribute(insn_byte_t modrm, int lpfx_id,
60 insn_attr_t grp_attr)
61{
62 const insn_attr_t *table;
63 int n;
64
65 n = inat_group_id(grp_attr);
66
67 table = inat_group_tables[n][0];
68 if (!table)
69 return inat_group_common_attribute(grp_attr);
70 if (inat_has_variant(table[X86_MODRM_REG(modrm)]) && lpfx_id) {
71 table = inat_group_tables[n][lpfx_id];
72 if (!table)
73 return inat_group_common_attribute(grp_attr);
74 }
75 return table[X86_MODRM_REG(modrm)] |
76 inat_group_common_attribute(grp_attr);
77}
78
79insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m,
80 insn_byte_t vex_p)
81{
82 const insn_attr_t *table;
83 if (vex_m > X86_VEX_M_MAX || vex_p > INAT_LSTPFX_MAX)
84 return 0;
85 /* At first, this checks the master table */
86 table = inat_avx_tables[vex_m][0];
87 if (!table)
88 return 0;
89 if (!inat_is_group(table[opcode]) && vex_p) {
90 /* If this is not a group, get attribute directly */
91 table = inat_avx_tables[vex_m][vex_p];
92 if (!table)
93 return 0;
94 }
95 return table[opcode];
96}
97
diff --git a/tools/objtool/arch/x86/insn/inat.h b/tools/objtool/arch/x86/insn/inat.h
new file mode 100644
index 000000000000..611645e903a8
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/inat.h
@@ -0,0 +1,221 @@
1#ifndef _ASM_X86_INAT_H
2#define _ASM_X86_INAT_H
3/*
4 * x86 instruction attributes
5 *
6 * Written by Masami Hiramatsu <mhiramat@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
22 */
23#include "inat_types.h"
24
25/*
26 * Internal bits. Don't use bitmasks directly, because these bits are
27 * unstable. You should use checking functions.
28 */
29
30#define INAT_OPCODE_TABLE_SIZE 256
31#define INAT_GROUP_TABLE_SIZE 8
32
33/* Legacy last prefixes */
34#define INAT_PFX_OPNDSZ 1 /* 0x66 */ /* LPFX1 */
35#define INAT_PFX_REPE 2 /* 0xF3 */ /* LPFX2 */
36#define INAT_PFX_REPNE 3 /* 0xF2 */ /* LPFX3 */
37/* Other Legacy prefixes */
38#define INAT_PFX_LOCK 4 /* 0xF0 */
39#define INAT_PFX_CS 5 /* 0x2E */
40#define INAT_PFX_DS 6 /* 0x3E */
41#define INAT_PFX_ES 7 /* 0x26 */
42#define INAT_PFX_FS 8 /* 0x64 */
43#define INAT_PFX_GS 9 /* 0x65 */
44#define INAT_PFX_SS 10 /* 0x36 */
45#define INAT_PFX_ADDRSZ 11 /* 0x67 */
46/* x86-64 REX prefix */
47#define INAT_PFX_REX 12 /* 0x4X */
48/* AVX VEX prefixes */
49#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */
50#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */
51
52#define INAT_LSTPFX_MAX 3
53#define INAT_LGCPFX_MAX 11
54
55/* Immediate size */
56#define INAT_IMM_BYTE 1
57#define INAT_IMM_WORD 2
58#define INAT_IMM_DWORD 3
59#define INAT_IMM_QWORD 4
60#define INAT_IMM_PTR 5
61#define INAT_IMM_VWORD32 6
62#define INAT_IMM_VWORD 7
63
64/* Legacy prefix */
65#define INAT_PFX_OFFS 0
66#define INAT_PFX_BITS 4
67#define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1)
68#define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS)
69/* Escape opcodes */
70#define INAT_ESC_OFFS (INAT_PFX_OFFS + INAT_PFX_BITS)
71#define INAT_ESC_BITS 2
72#define INAT_ESC_MAX ((1 << INAT_ESC_BITS) - 1)
73#define INAT_ESC_MASK (INAT_ESC_MAX << INAT_ESC_OFFS)
74/* Group opcodes (1-16) */
75#define INAT_GRP_OFFS (INAT_ESC_OFFS + INAT_ESC_BITS)
76#define INAT_GRP_BITS 5
77#define INAT_GRP_MAX ((1 << INAT_GRP_BITS) - 1)
78#define INAT_GRP_MASK (INAT_GRP_MAX << INAT_GRP_OFFS)
79/* Immediates */
80#define INAT_IMM_OFFS (INAT_GRP_OFFS + INAT_GRP_BITS)
81#define INAT_IMM_BITS 3
82#define INAT_IMM_MASK (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS)
83/* Flags */
84#define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS)
85#define INAT_MODRM (1 << (INAT_FLAG_OFFS))
86#define INAT_FORCE64 (1 << (INAT_FLAG_OFFS + 1))
87#define INAT_SCNDIMM (1 << (INAT_FLAG_OFFS + 2))
88#define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3))
89#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4))
90#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5))
91#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6))
92/* Attribute making macros for attribute tables */
93#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS)
94#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS)
95#define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM)
96#define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS)
97
98/* Attribute search APIs */
99extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode);
100extern int inat_get_last_prefix_id(insn_byte_t last_pfx);
101extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode,
102 int lpfx_id,
103 insn_attr_t esc_attr);
104extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm,
105 int lpfx_id,
106 insn_attr_t esc_attr);
107extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode,
108 insn_byte_t vex_m,
109 insn_byte_t vex_pp);
110
111/* Attribute checking functions */
112static inline int inat_is_legacy_prefix(insn_attr_t attr)
113{
114 attr &= INAT_PFX_MASK;
115 return attr && attr <= INAT_LGCPFX_MAX;
116}
117
118static inline int inat_is_address_size_prefix(insn_attr_t attr)
119{
120 return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ;
121}
122
123static inline int inat_is_operand_size_prefix(insn_attr_t attr)
124{
125 return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ;
126}
127
128static inline int inat_is_rex_prefix(insn_attr_t attr)
129{
130 return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
131}
132
133static inline int inat_last_prefix_id(insn_attr_t attr)
134{
135 if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX)
136 return 0;
137 else
138 return attr & INAT_PFX_MASK;
139}
140
141static inline int inat_is_vex_prefix(insn_attr_t attr)
142{
143 attr &= INAT_PFX_MASK;
144 return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3;
145}
146
147static inline int inat_is_vex3_prefix(insn_attr_t attr)
148{
149 return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3;
150}
151
152static inline int inat_is_escape(insn_attr_t attr)
153{
154 return attr & INAT_ESC_MASK;
155}
156
157static inline int inat_escape_id(insn_attr_t attr)
158{
159 return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS;
160}
161
162static inline int inat_is_group(insn_attr_t attr)
163{
164 return attr & INAT_GRP_MASK;
165}
166
167static inline int inat_group_id(insn_attr_t attr)
168{
169 return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS;
170}
171
172static inline int inat_group_common_attribute(insn_attr_t attr)
173{
174 return attr & ~INAT_GRP_MASK;
175}
176
177static inline int inat_has_immediate(insn_attr_t attr)
178{
179 return attr & INAT_IMM_MASK;
180}
181
182static inline int inat_immediate_size(insn_attr_t attr)
183{
184 return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS;
185}
186
187static inline int inat_has_modrm(insn_attr_t attr)
188{
189 return attr & INAT_MODRM;
190}
191
192static inline int inat_is_force64(insn_attr_t attr)
193{
194 return attr & INAT_FORCE64;
195}
196
197static inline int inat_has_second_immediate(insn_attr_t attr)
198{
199 return attr & INAT_SCNDIMM;
200}
201
202static inline int inat_has_moffset(insn_attr_t attr)
203{
204 return attr & INAT_MOFFSET;
205}
206
207static inline int inat_has_variant(insn_attr_t attr)
208{
209 return attr & INAT_VARIANT;
210}
211
212static inline int inat_accept_vex(insn_attr_t attr)
213{
214 return attr & INAT_VEXOK;
215}
216
217static inline int inat_must_vex(insn_attr_t attr)
218{
219 return attr & INAT_VEXONLY;
220}
221#endif
diff --git a/tools/objtool/arch/x86/insn/inat_types.h b/tools/objtool/arch/x86/insn/inat_types.h
new file mode 100644
index 000000000000..cb3c20ce39cf
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/inat_types.h
@@ -0,0 +1,29 @@
1#ifndef _ASM_X86_INAT_TYPES_H
2#define _ASM_X86_INAT_TYPES_H
3/*
4 * x86 instruction attributes
5 *
6 * Written by Masami Hiramatsu <mhiramat@redhat.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 *
22 */
23
24/* Instruction attributes */
25typedef unsigned int insn_attr_t;
26typedef unsigned char insn_byte_t;
27typedef signed int insn_value_t;
28
29#endif
diff --git a/tools/objtool/arch/x86/insn/insn.c b/tools/objtool/arch/x86/insn/insn.c
new file mode 100644
index 000000000000..47314a64399c
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/insn.c
@@ -0,0 +1,594 @@
1/*
2 * x86 instruction analysis
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * Copyright (C) IBM Corporation, 2002, 2004, 2009
19 */
20
21#ifdef __KERNEL__
22#include <linux/string.h>
23#else
24#include <string.h>
25#endif
26#include "inat.h"
27#include "insn.h"
28
29/* Verify next sizeof(t) bytes can be on the same instruction */
30#define validate_next(t, insn, n) \
31 ((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr)
32
33#define __get_next(t, insn) \
34 ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
35
36#define __peek_nbyte_next(t, insn, n) \
37 ({ t r = *(t*)((insn)->next_byte + n); r; })
38
39#define get_next(t, insn) \
40 ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })
41
42#define peek_nbyte_next(t, insn, n) \
43 ({ if (unlikely(!validate_next(t, insn, n))) goto err_out; __peek_nbyte_next(t, insn, n); })
44
45#define peek_next(t, insn) peek_nbyte_next(t, insn, 0)
46
47/**
48 * insn_init() - initialize struct insn
49 * @insn: &struct insn to be initialized
50 * @kaddr: address (in kernel memory) of instruction (or copy thereof)
51 * @x86_64: !0 for 64-bit kernel or 64-bit app
52 */
53void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64)
54{
55 /*
56 * Instructions longer than MAX_INSN_SIZE (15 bytes) are invalid
57 * even if the input buffer is long enough to hold them.
58 */
59 if (buf_len > MAX_INSN_SIZE)
60 buf_len = MAX_INSN_SIZE;
61
62 memset(insn, 0, sizeof(*insn));
63 insn->kaddr = kaddr;
64 insn->end_kaddr = kaddr + buf_len;
65 insn->next_byte = kaddr;
66 insn->x86_64 = x86_64 ? 1 : 0;
67 insn->opnd_bytes = 4;
68 if (x86_64)
69 insn->addr_bytes = 8;
70 else
71 insn->addr_bytes = 4;
72}
73
74/**
75 * insn_get_prefixes - scan x86 instruction prefix bytes
76 * @insn: &struct insn containing instruction
77 *
78 * Populates the @insn->prefixes bitmap, and updates @insn->next_byte
79 * to point to the (first) opcode. No effect if @insn->prefixes.got
80 * is already set.
81 */
82void insn_get_prefixes(struct insn *insn)
83{
84 struct insn_field *prefixes = &insn->prefixes;
85 insn_attr_t attr;
86 insn_byte_t b, lb;
87 int i, nb;
88
89 if (prefixes->got)
90 return;
91
92 nb = 0;
93 lb = 0;
94 b = peek_next(insn_byte_t, insn);
95 attr = inat_get_opcode_attribute(b);
96 while (inat_is_legacy_prefix(attr)) {
97 /* Skip if same prefix */
98 for (i = 0; i < nb; i++)
99 if (prefixes->bytes[i] == b)
100 goto found;
101 if (nb == 4)
102 /* Invalid instruction */
103 break;
104 prefixes->bytes[nb++] = b;
105 if (inat_is_address_size_prefix(attr)) {
106 /* address size switches 2/4 or 4/8 */
107 if (insn->x86_64)
108 insn->addr_bytes ^= 12;
109 else
110 insn->addr_bytes ^= 6;
111 } else if (inat_is_operand_size_prefix(attr)) {
112 /* oprand size switches 2/4 */
113 insn->opnd_bytes ^= 6;
114 }
115found:
116 prefixes->nbytes++;
117 insn->next_byte++;
118 lb = b;
119 b = peek_next(insn_byte_t, insn);
120 attr = inat_get_opcode_attribute(b);
121 }
122 /* Set the last prefix */
123 if (lb && lb != insn->prefixes.bytes[3]) {
124 if (unlikely(insn->prefixes.bytes[3])) {
125 /* Swap the last prefix */
126 b = insn->prefixes.bytes[3];
127 for (i = 0; i < nb; i++)
128 if (prefixes->bytes[i] == lb)
129 prefixes->bytes[i] = b;
130 }
131 insn->prefixes.bytes[3] = lb;
132 }
133
134 /* Decode REX prefix */
135 if (insn->x86_64) {
136 b = peek_next(insn_byte_t, insn);
137 attr = inat_get_opcode_attribute(b);
138 if (inat_is_rex_prefix(attr)) {
139 insn->rex_prefix.value = b;
140 insn->rex_prefix.nbytes = 1;
141 insn->next_byte++;
142 if (X86_REX_W(b))
143 /* REX.W overrides opnd_size */
144 insn->opnd_bytes = 8;
145 }
146 }
147 insn->rex_prefix.got = 1;
148
149 /* Decode VEX prefix */
150 b = peek_next(insn_byte_t, insn);
151 attr = inat_get_opcode_attribute(b);
152 if (inat_is_vex_prefix(attr)) {
153 insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1);
154 if (!insn->x86_64) {
155 /*
156 * In 32-bits mode, if the [7:6] bits (mod bits of
157 * ModRM) on the second byte are not 11b, it is
158 * LDS or LES.
159 */
160 if (X86_MODRM_MOD(b2) != 3)
161 goto vex_end;
162 }
163 insn->vex_prefix.bytes[0] = b;
164 insn->vex_prefix.bytes[1] = b2;
165 if (inat_is_vex3_prefix(attr)) {
166 b2 = peek_nbyte_next(insn_byte_t, insn, 2);
167 insn->vex_prefix.bytes[2] = b2;
168 insn->vex_prefix.nbytes = 3;
169 insn->next_byte += 3;
170 if (insn->x86_64 && X86_VEX_W(b2))
171 /* VEX.W overrides opnd_size */
172 insn->opnd_bytes = 8;
173 } else {
174 /*
175 * For VEX2, fake VEX3-like byte#2.
176 * Makes it easier to decode vex.W, vex.vvvv,
177 * vex.L and vex.pp. Masking with 0x7f sets vex.W == 0.
178 */
179 insn->vex_prefix.bytes[2] = b2 & 0x7f;
180 insn->vex_prefix.nbytes = 2;
181 insn->next_byte += 2;
182 }
183 }
184vex_end:
185 insn->vex_prefix.got = 1;
186
187 prefixes->got = 1;
188
189err_out:
190 return;
191}
192
193/**
194 * insn_get_opcode - collect opcode(s)
195 * @insn: &struct insn containing instruction
196 *
197 * Populates @insn->opcode, updates @insn->next_byte to point past the
198 * opcode byte(s), and set @insn->attr (except for groups).
199 * If necessary, first collects any preceding (prefix) bytes.
200 * Sets @insn->opcode.value = opcode1. No effect if @insn->opcode.got
201 * is already 1.
202 */
203void insn_get_opcode(struct insn *insn)
204{
205 struct insn_field *opcode = &insn->opcode;
206 insn_byte_t op;
207 int pfx_id;
208 if (opcode->got)
209 return;
210 if (!insn->prefixes.got)
211 insn_get_prefixes(insn);
212
213 /* Get first opcode */
214 op = get_next(insn_byte_t, insn);
215 opcode->bytes[0] = op;
216 opcode->nbytes = 1;
217
218 /* Check if there is VEX prefix or not */
219 if (insn_is_avx(insn)) {
220 insn_byte_t m, p;
221 m = insn_vex_m_bits(insn);
222 p = insn_vex_p_bits(insn);
223 insn->attr = inat_get_avx_attribute(op, m, p);
224 if (!inat_accept_vex(insn->attr) && !inat_is_group(insn->attr))
225 insn->attr = 0; /* This instruction is bad */
226 goto end; /* VEX has only 1 byte for opcode */
227 }
228
229 insn->attr = inat_get_opcode_attribute(op);
230 while (inat_is_escape(insn->attr)) {
231 /* Get escaped opcode */
232 op = get_next(insn_byte_t, insn);
233 opcode->bytes[opcode->nbytes++] = op;
234 pfx_id = insn_last_prefix_id(insn);
235 insn->attr = inat_get_escape_attribute(op, pfx_id, insn->attr);
236 }
237 if (inat_must_vex(insn->attr))
238 insn->attr = 0; /* This instruction is bad */
239end:
240 opcode->got = 1;
241
242err_out:
243 return;
244}
245
246/**
247 * insn_get_modrm - collect ModRM byte, if any
248 * @insn: &struct insn containing instruction
249 *
250 * Populates @insn->modrm and updates @insn->next_byte to point past the
251 * ModRM byte, if any. If necessary, first collects the preceding bytes
252 * (prefixes and opcode(s)). No effect if @insn->modrm.got is already 1.
253 */
254void insn_get_modrm(struct insn *insn)
255{
256 struct insn_field *modrm = &insn->modrm;
257 insn_byte_t pfx_id, mod;
258 if (modrm->got)
259 return;
260 if (!insn->opcode.got)
261 insn_get_opcode(insn);
262
263 if (inat_has_modrm(insn->attr)) {
264 mod = get_next(insn_byte_t, insn);
265 modrm->value = mod;
266 modrm->nbytes = 1;
267 if (inat_is_group(insn->attr)) {
268 pfx_id = insn_last_prefix_id(insn);
269 insn->attr = inat_get_group_attribute(mod, pfx_id,
270 insn->attr);
271 if (insn_is_avx(insn) && !inat_accept_vex(insn->attr))
272 insn->attr = 0; /* This is bad */
273 }
274 }
275
276 if (insn->x86_64 && inat_is_force64(insn->attr))
277 insn->opnd_bytes = 8;
278 modrm->got = 1;
279
280err_out:
281 return;
282}
283
284
285/**
286 * insn_rip_relative() - Does instruction use RIP-relative addressing mode?
287 * @insn: &struct insn containing instruction
288 *
289 * If necessary, first collects the instruction up to and including the
290 * ModRM byte. No effect if @insn->x86_64 is 0.
291 */
292int insn_rip_relative(struct insn *insn)
293{
294 struct insn_field *modrm = &insn->modrm;
295
296 if (!insn->x86_64)
297 return 0;
298 if (!modrm->got)
299 insn_get_modrm(insn);
300 /*
301 * For rip-relative instructions, the mod field (top 2 bits)
302 * is zero and the r/m field (bottom 3 bits) is 0x5.
303 */
304 return (modrm->nbytes && (modrm->value & 0xc7) == 0x5);
305}
306
307/**
308 * insn_get_sib() - Get the SIB byte of instruction
309 * @insn: &struct insn containing instruction
310 *
311 * If necessary, first collects the instruction up to and including the
312 * ModRM byte.
313 */
314void insn_get_sib(struct insn *insn)
315{
316 insn_byte_t modrm;
317
318 if (insn->sib.got)
319 return;
320 if (!insn->modrm.got)
321 insn_get_modrm(insn);
322 if (insn->modrm.nbytes) {
323 modrm = (insn_byte_t)insn->modrm.value;
324 if (insn->addr_bytes != 2 &&
325 X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) {
326 insn->sib.value = get_next(insn_byte_t, insn);
327 insn->sib.nbytes = 1;
328 }
329 }
330 insn->sib.got = 1;
331
332err_out:
333 return;
334}
335
336
337/**
338 * insn_get_displacement() - Get the displacement of instruction
339 * @insn: &struct insn containing instruction
340 *
341 * If necessary, first collects the instruction up to and including the
342 * SIB byte.
343 * Displacement value is sign-expanded.
344 */
345void insn_get_displacement(struct insn *insn)
346{
347 insn_byte_t mod, rm, base;
348
349 if (insn->displacement.got)
350 return;
351 if (!insn->sib.got)
352 insn_get_sib(insn);
353 if (insn->modrm.nbytes) {
354 /*
355 * Interpreting the modrm byte:
356 * mod = 00 - no displacement fields (exceptions below)
357 * mod = 01 - 1-byte displacement field
358 * mod = 10 - displacement field is 4 bytes, or 2 bytes if
359 * address size = 2 (0x67 prefix in 32-bit mode)
360 * mod = 11 - no memory operand
361 *
362 * If address size = 2...
363 * mod = 00, r/m = 110 - displacement field is 2 bytes
364 *
365 * If address size != 2...
366 * mod != 11, r/m = 100 - SIB byte exists
367 * mod = 00, SIB base = 101 - displacement field is 4 bytes
368 * mod = 00, r/m = 101 - rip-relative addressing, displacement
369 * field is 4 bytes
370 */
371 mod = X86_MODRM_MOD(insn->modrm.value);
372 rm = X86_MODRM_RM(insn->modrm.value);
373 base = X86_SIB_BASE(insn->sib.value);
374 if (mod == 3)
375 goto out;
376 if (mod == 1) {
377 insn->displacement.value = get_next(char, insn);
378 insn->displacement.nbytes = 1;
379 } else if (insn->addr_bytes == 2) {
380 if ((mod == 0 && rm == 6) || mod == 2) {
381 insn->displacement.value =
382 get_next(short, insn);
383 insn->displacement.nbytes = 2;
384 }
385 } else {
386 if ((mod == 0 && rm == 5) || mod == 2 ||
387 (mod == 0 && base == 5)) {
388 insn->displacement.value = get_next(int, insn);
389 insn->displacement.nbytes = 4;
390 }
391 }
392 }
393out:
394 insn->displacement.got = 1;
395
396err_out:
397 return;
398}
399
400/* Decode moffset16/32/64. Return 0 if failed */
401static int __get_moffset(struct insn *insn)
402{
403 switch (insn->addr_bytes) {
404 case 2:
405 insn->moffset1.value = get_next(short, insn);
406 insn->moffset1.nbytes = 2;
407 break;
408 case 4:
409 insn->moffset1.value = get_next(int, insn);
410 insn->moffset1.nbytes = 4;
411 break;
412 case 8:
413 insn->moffset1.value = get_next(int, insn);
414 insn->moffset1.nbytes = 4;
415 insn->moffset2.value = get_next(int, insn);
416 insn->moffset2.nbytes = 4;
417 break;
418 default: /* opnd_bytes must be modified manually */
419 goto err_out;
420 }
421 insn->moffset1.got = insn->moffset2.got = 1;
422
423 return 1;
424
425err_out:
426 return 0;
427}
428
429/* Decode imm v32(Iz). Return 0 if failed */
430static int __get_immv32(struct insn *insn)
431{
432 switch (insn->opnd_bytes) {
433 case 2:
434 insn->immediate.value = get_next(short, insn);
435 insn->immediate.nbytes = 2;
436 break;
437 case 4:
438 case 8:
439 insn->immediate.value = get_next(int, insn);
440 insn->immediate.nbytes = 4;
441 break;
442 default: /* opnd_bytes must be modified manually */
443 goto err_out;
444 }
445
446 return 1;
447
448err_out:
449 return 0;
450}
451
452/* Decode imm v64(Iv/Ov), Return 0 if failed */
453static int __get_immv(struct insn *insn)
454{
455 switch (insn->opnd_bytes) {
456 case 2:
457 insn->immediate1.value = get_next(short, insn);
458 insn->immediate1.nbytes = 2;
459 break;
460 case 4:
461 insn->immediate1.value = get_next(int, insn);
462 insn->immediate1.nbytes = 4;
463 break;
464 case 8:
465 insn->immediate1.value = get_next(int, insn);
466 insn->immediate1.nbytes = 4;
467 insn->immediate2.value = get_next(int, insn);
468 insn->immediate2.nbytes = 4;
469 break;
470 default: /* opnd_bytes must be modified manually */
471 goto err_out;
472 }
473 insn->immediate1.got = insn->immediate2.got = 1;
474
475 return 1;
476err_out:
477 return 0;
478}
479
480/* Decode ptr16:16/32(Ap) */
481static int __get_immptr(struct insn *insn)
482{
483 switch (insn->opnd_bytes) {
484 case 2:
485 insn->immediate1.value = get_next(short, insn);
486 insn->immediate1.nbytes = 2;
487 break;
488 case 4:
489 insn->immediate1.value = get_next(int, insn);
490 insn->immediate1.nbytes = 4;
491 break;
492 case 8:
493 /* ptr16:64 is not exist (no segment) */
494 return 0;
495 default: /* opnd_bytes must be modified manually */
496 goto err_out;
497 }
498 insn->immediate2.value = get_next(unsigned short, insn);
499 insn->immediate2.nbytes = 2;
500 insn->immediate1.got = insn->immediate2.got = 1;
501
502 return 1;
503err_out:
504 return 0;
505}
506
507/**
508 * insn_get_immediate() - Get the immediates of instruction
509 * @insn: &struct insn containing instruction
510 *
511 * If necessary, first collects the instruction up to and including the
512 * displacement bytes.
513 * Basically, most of immediates are sign-expanded. Unsigned-value can be
514 * get by bit masking with ((1 << (nbytes * 8)) - 1)
515 */
516void insn_get_immediate(struct insn *insn)
517{
518 if (insn->immediate.got)
519 return;
520 if (!insn->displacement.got)
521 insn_get_displacement(insn);
522
523 if (inat_has_moffset(insn->attr)) {
524 if (!__get_moffset(insn))
525 goto err_out;
526 goto done;
527 }
528
529 if (!inat_has_immediate(insn->attr))
530 /* no immediates */
531 goto done;
532
533 switch (inat_immediate_size(insn->attr)) {
534 case INAT_IMM_BYTE:
535 insn->immediate.value = get_next(char, insn);
536 insn->immediate.nbytes = 1;
537 break;
538 case INAT_IMM_WORD:
539 insn->immediate.value = get_next(short, insn);
540 insn->immediate.nbytes = 2;
541 break;
542 case INAT_IMM_DWORD:
543 insn->immediate.value = get_next(int, insn);
544 insn->immediate.nbytes = 4;
545 break;
546 case INAT_IMM_QWORD:
547 insn->immediate1.value = get_next(int, insn);
548 insn->immediate1.nbytes = 4;
549 insn->immediate2.value = get_next(int, insn);
550 insn->immediate2.nbytes = 4;
551 break;
552 case INAT_IMM_PTR:
553 if (!__get_immptr(insn))
554 goto err_out;
555 break;
556 case INAT_IMM_VWORD32:
557 if (!__get_immv32(insn))
558 goto err_out;
559 break;
560 case INAT_IMM_VWORD:
561 if (!__get_immv(insn))
562 goto err_out;
563 break;
564 default:
565 /* Here, insn must have an immediate, but failed */
566 goto err_out;
567 }
568 if (inat_has_second_immediate(insn->attr)) {
569 insn->immediate2.value = get_next(char, insn);
570 insn->immediate2.nbytes = 1;
571 }
572done:
573 insn->immediate.got = 1;
574
575err_out:
576 return;
577}
578
579/**
580 * insn_get_length() - Get the length of instruction
581 * @insn: &struct insn containing instruction
582 *
583 * If necessary, first collects the instruction up to and including the
584 * immediates bytes.
585 */
586void insn_get_length(struct insn *insn)
587{
588 if (insn->length)
589 return;
590 if (!insn->immediate.got)
591 insn_get_immediate(insn);
592 insn->length = (unsigned char)((unsigned long)insn->next_byte
593 - (unsigned long)insn->kaddr);
594}
diff --git a/tools/objtool/arch/x86/insn/insn.h b/tools/objtool/arch/x86/insn/insn.h
new file mode 100644
index 000000000000..dd12da0f4593
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/insn.h
@@ -0,0 +1,201 @@
1#ifndef _ASM_X86_INSN_H
2#define _ASM_X86_INSN_H
3/*
4 * x86 instruction analysis
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 * Copyright (C) IBM Corporation, 2009
21 */
22
23/* insn_attr_t is defined in inat.h */
24#include "inat.h"
25
26struct insn_field {
27 union {
28 insn_value_t value;
29 insn_byte_t bytes[4];
30 };
31 /* !0 if we've run insn_get_xxx() for this field */
32 unsigned char got;
33 unsigned char nbytes;
34};
35
36struct insn {
37 struct insn_field prefixes; /*
38 * Prefixes
39 * prefixes.bytes[3]: last prefix
40 */
41 struct insn_field rex_prefix; /* REX prefix */
42 struct insn_field vex_prefix; /* VEX prefix */
43 struct insn_field opcode; /*
44 * opcode.bytes[0]: opcode1
45 * opcode.bytes[1]: opcode2
46 * opcode.bytes[2]: opcode3
47 */
48 struct insn_field modrm;
49 struct insn_field sib;
50 struct insn_field displacement;
51 union {
52 struct insn_field immediate;
53 struct insn_field moffset1; /* for 64bit MOV */
54 struct insn_field immediate1; /* for 64bit imm or off16/32 */
55 };
56 union {
57 struct insn_field moffset2; /* for 64bit MOV */
58 struct insn_field immediate2; /* for 64bit imm or seg16 */
59 };
60
61 insn_attr_t attr;
62 unsigned char opnd_bytes;
63 unsigned char addr_bytes;
64 unsigned char length;
65 unsigned char x86_64;
66
67 const insn_byte_t *kaddr; /* kernel address of insn to analyze */
68 const insn_byte_t *end_kaddr; /* kernel address of last insn in buffer */
69 const insn_byte_t *next_byte;
70};
71
72#define MAX_INSN_SIZE 15
73
74#define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6)
75#define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3)
76#define X86_MODRM_RM(modrm) ((modrm) & 0x07)
77
78#define X86_SIB_SCALE(sib) (((sib) & 0xc0) >> 6)
79#define X86_SIB_INDEX(sib) (((sib) & 0x38) >> 3)
80#define X86_SIB_BASE(sib) ((sib) & 0x07)
81
82#define X86_REX_W(rex) ((rex) & 8)
83#define X86_REX_R(rex) ((rex) & 4)
84#define X86_REX_X(rex) ((rex) & 2)
85#define X86_REX_B(rex) ((rex) & 1)
86
87/* VEX bit flags */
88#define X86_VEX_W(vex) ((vex) & 0x80) /* VEX3 Byte2 */
89#define X86_VEX_R(vex) ((vex) & 0x80) /* VEX2/3 Byte1 */
90#define X86_VEX_X(vex) ((vex) & 0x40) /* VEX3 Byte1 */
91#define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */
92#define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */
93/* VEX bit fields */
94#define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */
95#define X86_VEX2_M 1 /* VEX2.M always 1 */
96#define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */
97#define X86_VEX_P(vex) ((vex) & 0x03) /* VEX3 Byte2, VEX2 Byte1 */
98#define X86_VEX_M_MAX 0x1f /* VEX3.M Maximum value */
99
100extern void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64);
101extern void insn_get_prefixes(struct insn *insn);
102extern void insn_get_opcode(struct insn *insn);
103extern void insn_get_modrm(struct insn *insn);
104extern void insn_get_sib(struct insn *insn);
105extern void insn_get_displacement(struct insn *insn);
106extern void insn_get_immediate(struct insn *insn);
107extern void insn_get_length(struct insn *insn);
108
109/* Attribute will be determined after getting ModRM (for opcode groups) */
110static inline void insn_get_attribute(struct insn *insn)
111{
112 insn_get_modrm(insn);
113}
114
115/* Instruction uses RIP-relative addressing */
116extern int insn_rip_relative(struct insn *insn);
117
118/* Init insn for kernel text */
119static inline void kernel_insn_init(struct insn *insn,
120 const void *kaddr, int buf_len)
121{
122#ifdef CONFIG_X86_64
123 insn_init(insn, kaddr, buf_len, 1);
124#else /* CONFIG_X86_32 */
125 insn_init(insn, kaddr, buf_len, 0);
126#endif
127}
128
129static inline int insn_is_avx(struct insn *insn)
130{
131 if (!insn->prefixes.got)
132 insn_get_prefixes(insn);
133 return (insn->vex_prefix.value != 0);
134}
135
136/* Ensure this instruction is decoded completely */
137static inline int insn_complete(struct insn *insn)
138{
139 return insn->opcode.got && insn->modrm.got && insn->sib.got &&
140 insn->displacement.got && insn->immediate.got;
141}
142
143static inline insn_byte_t insn_vex_m_bits(struct insn *insn)
144{
145 if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
146 return X86_VEX2_M;
147 else
148 return X86_VEX3_M(insn->vex_prefix.bytes[1]);
149}
150
151static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
152{
153 if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
154 return X86_VEX_P(insn->vex_prefix.bytes[1]);
155 else
156 return X86_VEX_P(insn->vex_prefix.bytes[2]);
157}
158
159/* Get the last prefix id from last prefix or VEX prefix */
160static inline int insn_last_prefix_id(struct insn *insn)
161{
162 if (insn_is_avx(insn))
163 return insn_vex_p_bits(insn); /* VEX_p is a SIMD prefix id */
164
165 if (insn->prefixes.bytes[3])
166 return inat_get_last_prefix_id(insn->prefixes.bytes[3]);
167
168 return 0;
169}
170
171/* Offset of each field from kaddr */
172static inline int insn_offset_rex_prefix(struct insn *insn)
173{
174 return insn->prefixes.nbytes;
175}
176static inline int insn_offset_vex_prefix(struct insn *insn)
177{
178 return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes;
179}
180static inline int insn_offset_opcode(struct insn *insn)
181{
182 return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes;
183}
184static inline int insn_offset_modrm(struct insn *insn)
185{
186 return insn_offset_opcode(insn) + insn->opcode.nbytes;
187}
188static inline int insn_offset_sib(struct insn *insn)
189{
190 return insn_offset_modrm(insn) + insn->modrm.nbytes;
191}
192static inline int insn_offset_displacement(struct insn *insn)
193{
194 return insn_offset_sib(insn) + insn->sib.nbytes;
195}
196static inline int insn_offset_immediate(struct insn *insn)
197{
198 return insn_offset_displacement(insn) + insn->displacement.nbytes;
199}
200
201#endif /* _ASM_X86_INSN_H */
diff --git a/tools/objtool/arch/x86/insn/x86-opcode-map.txt b/tools/objtool/arch/x86/insn/x86-opcode-map.txt
new file mode 100644
index 000000000000..d388de72eaca
--- /dev/null
+++ b/tools/objtool/arch/x86/insn/x86-opcode-map.txt
@@ -0,0 +1,984 @@
1# x86 Opcode Maps
2#
3# This is (mostly) based on following documentations.
4# - Intel(R) 64 and IA-32 Architectures Software Developer's Manual Vol.2C
5# (#326018-047US, June 2013)
6#
7#<Opcode maps>
8# Table: table-name
9# Referrer: escaped-name
10# AVXcode: avx-code
11# opcode: mnemonic|GrpXXX [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
12# (or)
13# opcode: escape # escaped-name
14# EndTable
15#
16#<group maps>
17# GrpTable: GrpXXX
18# reg: mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
19# EndTable
20#
21# AVX Superscripts
22# (v): this opcode requires VEX prefix.
23# (v1): this opcode only supports 128bit VEX.
24#
25# Last Prefix Superscripts
26# - (66): the last prefix is 0x66
27# - (F3): the last prefix is 0xF3
28# - (F2): the last prefix is 0xF2
29# - (!F3) : the last prefix is not 0xF3 (including non-last prefix case)
30# - (66&F2): Both 0x66 and 0xF2 prefixes are specified.
31
32Table: one byte opcode
33Referrer:
34AVXcode:
35# 0x00 - 0x0f
3600: ADD Eb,Gb
3701: ADD Ev,Gv
3802: ADD Gb,Eb
3903: ADD Gv,Ev
4004: ADD AL,Ib
4105: ADD rAX,Iz
4206: PUSH ES (i64)
4307: POP ES (i64)
4408: OR Eb,Gb
4509: OR Ev,Gv
460a: OR Gb,Eb
470b: OR Gv,Ev
480c: OR AL,Ib
490d: OR rAX,Iz
500e: PUSH CS (i64)
510f: escape # 2-byte escape
52# 0x10 - 0x1f
5310: ADC Eb,Gb
5411: ADC Ev,Gv
5512: ADC Gb,Eb
5613: ADC Gv,Ev
5714: ADC AL,Ib
5815: ADC rAX,Iz
5916: PUSH SS (i64)
6017: POP SS (i64)
6118: SBB Eb,Gb
6219: SBB Ev,Gv
631a: SBB Gb,Eb
641b: SBB Gv,Ev
651c: SBB AL,Ib
661d: SBB rAX,Iz
671e: PUSH DS (i64)
681f: POP DS (i64)
69# 0x20 - 0x2f
7020: AND Eb,Gb
7121: AND Ev,Gv
7222: AND Gb,Eb
7323: AND Gv,Ev
7424: AND AL,Ib
7525: AND rAx,Iz
7626: SEG=ES (Prefix)
7727: DAA (i64)
7828: SUB Eb,Gb
7929: SUB Ev,Gv
802a: SUB Gb,Eb
812b: SUB Gv,Ev
822c: SUB AL,Ib
832d: SUB rAX,Iz
842e: SEG=CS (Prefix)
852f: DAS (i64)
86# 0x30 - 0x3f
8730: XOR Eb,Gb
8831: XOR Ev,Gv
8932: XOR Gb,Eb
9033: XOR Gv,Ev
9134: XOR AL,Ib
9235: XOR rAX,Iz
9336: SEG=SS (Prefix)
9437: AAA (i64)
9538: CMP Eb,Gb
9639: CMP Ev,Gv
973a: CMP Gb,Eb
983b: CMP Gv,Ev
993c: CMP AL,Ib
1003d: CMP rAX,Iz
1013e: SEG=DS (Prefix)
1023f: AAS (i64)
103# 0x40 - 0x4f
10440: INC eAX (i64) | REX (o64)
10541: INC eCX (i64) | REX.B (o64)
10642: INC eDX (i64) | REX.X (o64)
10743: INC eBX (i64) | REX.XB (o64)
10844: INC eSP (i64) | REX.R (o64)
10945: INC eBP (i64) | REX.RB (o64)
11046: INC eSI (i64) | REX.RX (o64)
11147: INC eDI (i64) | REX.RXB (o64)
11248: DEC eAX (i64) | REX.W (o64)
11349: DEC eCX (i64) | REX.WB (o64)
1144a: DEC eDX (i64) | REX.WX (o64)
1154b: DEC eBX (i64) | REX.WXB (o64)
1164c: DEC eSP (i64) | REX.WR (o64)
1174d: DEC eBP (i64) | REX.WRB (o64)
1184e: DEC eSI (i64) | REX.WRX (o64)
1194f: DEC eDI (i64) | REX.WRXB (o64)
120# 0x50 - 0x5f
12150: PUSH rAX/r8 (d64)
12251: PUSH rCX/r9 (d64)
12352: PUSH rDX/r10 (d64)
12453: PUSH rBX/r11 (d64)
12554: PUSH rSP/r12 (d64)
12655: PUSH rBP/r13 (d64)
12756: PUSH rSI/r14 (d64)
12857: PUSH rDI/r15 (d64)
12958: POP rAX/r8 (d64)
13059: POP rCX/r9 (d64)
1315a: POP rDX/r10 (d64)
1325b: POP rBX/r11 (d64)
1335c: POP rSP/r12 (d64)
1345d: POP rBP/r13 (d64)
1355e: POP rSI/r14 (d64)
1365f: POP rDI/r15 (d64)
137# 0x60 - 0x6f
13860: PUSHA/PUSHAD (i64)
13961: POPA/POPAD (i64)
14062: BOUND Gv,Ma (i64)
14163: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64)
14264: SEG=FS (Prefix)
14365: SEG=GS (Prefix)
14466: Operand-Size (Prefix)
14567: Address-Size (Prefix)
14668: PUSH Iz (d64)
14769: IMUL Gv,Ev,Iz
1486a: PUSH Ib (d64)
1496b: IMUL Gv,Ev,Ib
1506c: INS/INSB Yb,DX
1516d: INS/INSW/INSD Yz,DX
1526e: OUTS/OUTSB DX,Xb
1536f: OUTS/OUTSW/OUTSD DX,Xz
154# 0x70 - 0x7f
15570: JO Jb
15671: JNO Jb
15772: JB/JNAE/JC Jb
15873: JNB/JAE/JNC Jb
15974: JZ/JE Jb
16075: JNZ/JNE Jb
16176: JBE/JNA Jb
16277: JNBE/JA Jb
16378: JS Jb
16479: JNS Jb
1657a: JP/JPE Jb
1667b: JNP/JPO Jb
1677c: JL/JNGE Jb
1687d: JNL/JGE Jb
1697e: JLE/JNG Jb
1707f: JNLE/JG Jb
171# 0x80 - 0x8f
17280: Grp1 Eb,Ib (1A)
17381: Grp1 Ev,Iz (1A)
17482: Grp1 Eb,Ib (1A),(i64)
17583: Grp1 Ev,Ib (1A)
17684: TEST Eb,Gb
17785: TEST Ev,Gv
17886: XCHG Eb,Gb
17987: XCHG Ev,Gv
18088: MOV Eb,Gb
18189: MOV Ev,Gv
1828a: MOV Gb,Eb
1838b: MOV Gv,Ev
1848c: MOV Ev,Sw
1858d: LEA Gv,M
1868e: MOV Sw,Ew
1878f: Grp1A (1A) | POP Ev (d64)
188# 0x90 - 0x9f
18990: NOP | PAUSE (F3) | XCHG r8,rAX
19091: XCHG rCX/r9,rAX
19192: XCHG rDX/r10,rAX
19293: XCHG rBX/r11,rAX
19394: XCHG rSP/r12,rAX
19495: XCHG rBP/r13,rAX
19596: XCHG rSI/r14,rAX
19697: XCHG rDI/r15,rAX
19798: CBW/CWDE/CDQE
19899: CWD/CDQ/CQO
1999a: CALLF Ap (i64)
2009b: FWAIT/WAIT
2019c: PUSHF/D/Q Fv (d64)
2029d: POPF/D/Q Fv (d64)
2039e: SAHF
2049f: LAHF
205# 0xa0 - 0xaf
206a0: MOV AL,Ob
207a1: MOV rAX,Ov
208a2: MOV Ob,AL
209a3: MOV Ov,rAX
210a4: MOVS/B Yb,Xb
211a5: MOVS/W/D/Q Yv,Xv
212a6: CMPS/B Xb,Yb
213a7: CMPS/W/D Xv,Yv
214a8: TEST AL,Ib
215a9: TEST rAX,Iz
216aa: STOS/B Yb,AL
217ab: STOS/W/D/Q Yv,rAX
218ac: LODS/B AL,Xb
219ad: LODS/W/D/Q rAX,Xv
220ae: SCAS/B AL,Yb
221# Note: The May 2011 Intel manual shows Xv for the second parameter of the
222# next instruction but Yv is correct
223af: SCAS/W/D/Q rAX,Yv
224# 0xb0 - 0xbf
225b0: MOV AL/R8L,Ib
226b1: MOV CL/R9L,Ib
227b2: MOV DL/R10L,Ib
228b3: MOV BL/R11L,Ib
229b4: MOV AH/R12L,Ib
230b5: MOV CH/R13L,Ib
231b6: MOV DH/R14L,Ib
232b7: MOV BH/R15L,Ib
233b8: MOV rAX/r8,Iv
234b9: MOV rCX/r9,Iv
235ba: MOV rDX/r10,Iv
236bb: MOV rBX/r11,Iv
237bc: MOV rSP/r12,Iv
238bd: MOV rBP/r13,Iv
239be: MOV rSI/r14,Iv
240bf: MOV rDI/r15,Iv
241# 0xc0 - 0xcf
242c0: Grp2 Eb,Ib (1A)
243c1: Grp2 Ev,Ib (1A)
244c2: RETN Iw (f64)
245c3: RETN
246c4: LES Gz,Mp (i64) | VEX+2byte (Prefix)
247c5: LDS Gz,Mp (i64) | VEX+1byte (Prefix)
248c6: Grp11A Eb,Ib (1A)
249c7: Grp11B Ev,Iz (1A)
250c8: ENTER Iw,Ib
251c9: LEAVE (d64)
252ca: RETF Iw
253cb: RETF
254cc: INT3
255cd: INT Ib
256ce: INTO (i64)
257cf: IRET/D/Q
258# 0xd0 - 0xdf
259d0: Grp2 Eb,1 (1A)
260d1: Grp2 Ev,1 (1A)
261d2: Grp2 Eb,CL (1A)
262d3: Grp2 Ev,CL (1A)
263d4: AAM Ib (i64)
264d5: AAD Ib (i64)
265d6:
266d7: XLAT/XLATB
267d8: ESC
268d9: ESC
269da: ESC
270db: ESC
271dc: ESC
272dd: ESC
273de: ESC
274df: ESC
275# 0xe0 - 0xef
276# Note: "forced64" is Intel CPU behavior: they ignore 0x66 prefix
277# in 64-bit mode. AMD CPUs accept 0x66 prefix, it causes RIP truncation
278# to 16 bits. In 32-bit mode, 0x66 is accepted by both Intel and AMD.
279e0: LOOPNE/LOOPNZ Jb (f64)
280e1: LOOPE/LOOPZ Jb (f64)
281e2: LOOP Jb (f64)
282e3: JrCXZ Jb (f64)
283e4: IN AL,Ib
284e5: IN eAX,Ib
285e6: OUT Ib,AL
286e7: OUT Ib,eAX
287# With 0x66 prefix in 64-bit mode, for AMD CPUs immediate offset
288# in "near" jumps and calls is 16-bit. For CALL,
289# push of return address is 16-bit wide, RSP is decremented by 2
290# but is not truncated to 16 bits, unlike RIP.
291e8: CALL Jz (f64)
292e9: JMP-near Jz (f64)
293ea: JMP-far Ap (i64)
294eb: JMP-short Jb (f64)
295ec: IN AL,DX
296ed: IN eAX,DX
297ee: OUT DX,AL
298ef: OUT DX,eAX
299# 0xf0 - 0xff
300f0: LOCK (Prefix)
301f1:
302f2: REPNE (Prefix) | XACQUIRE (Prefix)
303f3: REP/REPE (Prefix) | XRELEASE (Prefix)
304f4: HLT
305f5: CMC
306f6: Grp3_1 Eb (1A)
307f7: Grp3_2 Ev (1A)
308f8: CLC
309f9: STC
310fa: CLI
311fb: STI
312fc: CLD
313fd: STD
314fe: Grp4 (1A)
315ff: Grp5 (1A)
316EndTable
317
318Table: 2-byte opcode (0x0f)
319Referrer: 2-byte escape
320AVXcode: 1
321# 0x0f 0x00-0x0f
32200: Grp6 (1A)
32301: Grp7 (1A)
32402: LAR Gv,Ew
32503: LSL Gv,Ew
32604:
32705: SYSCALL (o64)
32806: CLTS
32907: SYSRET (o64)
33008: INVD
33109: WBINVD
3320a:
3330b: UD2 (1B)
3340c:
335# AMD's prefetch group. Intel supports prefetchw(/1) only.
3360d: GrpP
3370e: FEMMS
338# 3DNow! uses the last imm byte as opcode extension.
3390f: 3DNow! Pq,Qq,Ib
340# 0x0f 0x10-0x1f
341# NOTE: According to Intel SDM opcode map, vmovups and vmovupd has no operands
342# but it actually has operands. And also, vmovss and vmovsd only accept 128bit.
343# MOVSS/MOVSD has too many forms(3) on SDM. This map just shows a typical form.
344# Many AVX instructions lack v1 superscript, according to Intel AVX-Prgramming
345# Reference A.1
34610: vmovups Vps,Wps | vmovupd Vpd,Wpd (66) | vmovss Vx,Hx,Wss (F3),(v1) | vmovsd Vx,Hx,Wsd (F2),(v1)
34711: vmovups Wps,Vps | vmovupd Wpd,Vpd (66) | vmovss Wss,Hx,Vss (F3),(v1) | vmovsd Wsd,Hx,Vsd (F2),(v1)
34812: vmovlps Vq,Hq,Mq (v1) | vmovhlps Vq,Hq,Uq (v1) | vmovlpd Vq,Hq,Mq (66),(v1) | vmovsldup Vx,Wx (F3) | vmovddup Vx,Wx (F2)
34913: vmovlps Mq,Vq (v1) | vmovlpd Mq,Vq (66),(v1)
35014: vunpcklps Vx,Hx,Wx | vunpcklpd Vx,Hx,Wx (66)
35115: vunpckhps Vx,Hx,Wx | vunpckhpd Vx,Hx,Wx (66)
35216: vmovhps Vdq,Hq,Mq (v1) | vmovlhps Vdq,Hq,Uq (v1) | vmovhpd Vdq,Hq,Mq (66),(v1) | vmovshdup Vx,Wx (F3)
35317: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1)
35418: Grp16 (1A)
35519:
356# Intel SDM opcode map does not list MPX instructions. For now using Gv for
357# bnd registers and Ev for everything else is OK because the instruction
358# decoder does not use the information except as an indication that there is
359# a ModR/M byte.
3601a: BNDCL Gv,Ev (F3) | BNDCU Gv,Ev (F2) | BNDMOV Gv,Ev (66) | BNDLDX Gv,Ev
3611b: BNDCN Gv,Ev (F2) | BNDMOV Ev,Gv (66) | BNDMK Gv,Ev (F3) | BNDSTX Ev,Gv
3621c:
3631d:
3641e:
3651f: NOP Ev
366# 0x0f 0x20-0x2f
36720: MOV Rd,Cd
36821: MOV Rd,Dd
36922: MOV Cd,Rd
37023: MOV Dd,Rd
37124:
37225:
37326:
37427:
37528: vmovaps Vps,Wps | vmovapd Vpd,Wpd (66)
37629: vmovaps Wps,Vps | vmovapd Wpd,Vpd (66)
3772a: cvtpi2ps Vps,Qpi | cvtpi2pd Vpd,Qpi (66) | vcvtsi2ss Vss,Hss,Ey (F3),(v1) | vcvtsi2sd Vsd,Hsd,Ey (F2),(v1)
3782b: vmovntps Mps,Vps | vmovntpd Mpd,Vpd (66)
3792c: cvttps2pi Ppi,Wps | cvttpd2pi Ppi,Wpd (66) | vcvttss2si Gy,Wss (F3),(v1) | vcvttsd2si Gy,Wsd (F2),(v1)
3802d: cvtps2pi Ppi,Wps | cvtpd2pi Qpi,Wpd (66) | vcvtss2si Gy,Wss (F3),(v1) | vcvtsd2si Gy,Wsd (F2),(v1)
3812e: vucomiss Vss,Wss (v1) | vucomisd Vsd,Wsd (66),(v1)
3822f: vcomiss Vss,Wss (v1) | vcomisd Vsd,Wsd (66),(v1)
383# 0x0f 0x30-0x3f
38430: WRMSR
38531: RDTSC
38632: RDMSR
38733: RDPMC
38834: SYSENTER
38935: SYSEXIT
39036:
39137: GETSEC
39238: escape # 3-byte escape 1
39339:
3943a: escape # 3-byte escape 2
3953b:
3963c:
3973d:
3983e:
3993f:
400# 0x0f 0x40-0x4f
40140: CMOVO Gv,Ev
40241: CMOVNO Gv,Ev
40342: CMOVB/C/NAE Gv,Ev
40443: CMOVAE/NB/NC Gv,Ev
40544: CMOVE/Z Gv,Ev
40645: CMOVNE/NZ Gv,Ev
40746: CMOVBE/NA Gv,Ev
40847: CMOVA/NBE Gv,Ev
40948: CMOVS Gv,Ev
41049: CMOVNS Gv,Ev
4114a: CMOVP/PE Gv,Ev
4124b: CMOVNP/PO Gv,Ev
4134c: CMOVL/NGE Gv,Ev
4144d: CMOVNL/GE Gv,Ev
4154e: CMOVLE/NG Gv,Ev
4164f: CMOVNLE/G Gv,Ev
417# 0x0f 0x50-0x5f
41850: vmovmskps Gy,Ups | vmovmskpd Gy,Upd (66)
41951: vsqrtps Vps,Wps | vsqrtpd Vpd,Wpd (66) | vsqrtss Vss,Hss,Wss (F3),(v1) | vsqrtsd Vsd,Hsd,Wsd (F2),(v1)
42052: vrsqrtps Vps,Wps | vrsqrtss Vss,Hss,Wss (F3),(v1)
42153: vrcpps Vps,Wps | vrcpss Vss,Hss,Wss (F3),(v1)
42254: vandps Vps,Hps,Wps | vandpd Vpd,Hpd,Wpd (66)
42355: vandnps Vps,Hps,Wps | vandnpd Vpd,Hpd,Wpd (66)
42456: vorps Vps,Hps,Wps | vorpd Vpd,Hpd,Wpd (66)
42557: vxorps Vps,Hps,Wps | vxorpd Vpd,Hpd,Wpd (66)
42658: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1)
42759: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1)
4285a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1)
4295b: vcvtdq2ps Vps,Wdq | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3)
4305c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1)
4315d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1)
4325e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1)
4335f: vmaxps Vps,Hps,Wps | vmaxpd Vpd,Hpd,Wpd (66) | vmaxss Vss,Hss,Wss (F3),(v1) | vmaxsd Vsd,Hsd,Wsd (F2),(v1)
434# 0x0f 0x60-0x6f
43560: punpcklbw Pq,Qd | vpunpcklbw Vx,Hx,Wx (66),(v1)
43661: punpcklwd Pq,Qd | vpunpcklwd Vx,Hx,Wx (66),(v1)
43762: punpckldq Pq,Qd | vpunpckldq Vx,Hx,Wx (66),(v1)
43863: packsswb Pq,Qq | vpacksswb Vx,Hx,Wx (66),(v1)
43964: pcmpgtb Pq,Qq | vpcmpgtb Vx,Hx,Wx (66),(v1)
44065: pcmpgtw Pq,Qq | vpcmpgtw Vx,Hx,Wx (66),(v1)
44166: pcmpgtd Pq,Qq | vpcmpgtd Vx,Hx,Wx (66),(v1)
44267: packuswb Pq,Qq | vpackuswb Vx,Hx,Wx (66),(v1)
44368: punpckhbw Pq,Qd | vpunpckhbw Vx,Hx,Wx (66),(v1)
44469: punpckhwd Pq,Qd | vpunpckhwd Vx,Hx,Wx (66),(v1)
4456a: punpckhdq Pq,Qd | vpunpckhdq Vx,Hx,Wx (66),(v1)
4466b: packssdw Pq,Qd | vpackssdw Vx,Hx,Wx (66),(v1)
4476c: vpunpcklqdq Vx,Hx,Wx (66),(v1)
4486d: vpunpckhqdq Vx,Hx,Wx (66),(v1)
4496e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1)
4506f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqu Vx,Wx (F3)
451# 0x0f 0x70-0x7f
45270: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1)
45371: Grp12 (1A)
45472: Grp13 (1A)
45573: Grp14 (1A)
45674: pcmpeqb Pq,Qq | vpcmpeqb Vx,Hx,Wx (66),(v1)
45775: pcmpeqw Pq,Qq | vpcmpeqw Vx,Hx,Wx (66),(v1)
45876: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1)
459# Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX.
46077: emms | vzeroupper | vzeroall
46178: VMREAD Ey,Gy
46279: VMWRITE Gy,Ey
4637a:
4647b:
4657c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2)
4667d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2)
4677e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1)
4687f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqu Wx,Vx (F3)
469# 0x0f 0x80-0x8f
470# Note: "forced64" is Intel CPU behavior (see comment about CALL insn).
47180: JO Jz (f64)
47281: JNO Jz (f64)
47382: JB/JC/JNAE Jz (f64)
47483: JAE/JNB/JNC Jz (f64)
47584: JE/JZ Jz (f64)
47685: JNE/JNZ Jz (f64)
47786: JBE/JNA Jz (f64)
47887: JA/JNBE Jz (f64)
47988: JS Jz (f64)
48089: JNS Jz (f64)
4818a: JP/JPE Jz (f64)
4828b: JNP/JPO Jz (f64)
4838c: JL/JNGE Jz (f64)
4848d: JNL/JGE Jz (f64)
4858e: JLE/JNG Jz (f64)
4868f: JNLE/JG Jz (f64)
487# 0x0f 0x90-0x9f
48890: SETO Eb
48991: SETNO Eb
49092: SETB/C/NAE Eb
49193: SETAE/NB/NC Eb
49294: SETE/Z Eb
49395: SETNE/NZ Eb
49496: SETBE/NA Eb
49597: SETA/NBE Eb
49698: SETS Eb
49799: SETNS Eb
4989a: SETP/PE Eb
4999b: SETNP/PO Eb
5009c: SETL/NGE Eb
5019d: SETNL/GE Eb
5029e: SETLE/NG Eb
5039f: SETNLE/G Eb
504# 0x0f 0xa0-0xaf
505a0: PUSH FS (d64)
506a1: POP FS (d64)
507a2: CPUID
508a3: BT Ev,Gv
509a4: SHLD Ev,Gv,Ib
510a5: SHLD Ev,Gv,CL
511a6: GrpPDLK
512a7: GrpRNG
513a8: PUSH GS (d64)
514a9: POP GS (d64)
515aa: RSM
516ab: BTS Ev,Gv
517ac: SHRD Ev,Gv,Ib
518ad: SHRD Ev,Gv,CL
519ae: Grp15 (1A),(1C)
520af: IMUL Gv,Ev
521# 0x0f 0xb0-0xbf
522b0: CMPXCHG Eb,Gb
523b1: CMPXCHG Ev,Gv
524b2: LSS Gv,Mp
525b3: BTR Ev,Gv
526b4: LFS Gv,Mp
527b5: LGS Gv,Mp
528b6: MOVZX Gv,Eb
529b7: MOVZX Gv,Ew
530b8: JMPE (!F3) | POPCNT Gv,Ev (F3)
531b9: Grp10 (1A)
532ba: Grp8 Ev,Ib (1A)
533bb: BTC Ev,Gv
534bc: BSF Gv,Ev (!F3) | TZCNT Gv,Ev (F3)
535bd: BSR Gv,Ev (!F3) | LZCNT Gv,Ev (F3)
536be: MOVSX Gv,Eb
537bf: MOVSX Gv,Ew
538# 0x0f 0xc0-0xcf
539c0: XADD Eb,Gb
540c1: XADD Ev,Gv
541c2: vcmpps Vps,Hps,Wps,Ib | vcmppd Vpd,Hpd,Wpd,Ib (66) | vcmpss Vss,Hss,Wss,Ib (F3),(v1) | vcmpsd Vsd,Hsd,Wsd,Ib (F2),(v1)
542c3: movnti My,Gy
543c4: pinsrw Pq,Ry/Mw,Ib | vpinsrw Vdq,Hdq,Ry/Mw,Ib (66),(v1)
544c5: pextrw Gd,Nq,Ib | vpextrw Gd,Udq,Ib (66),(v1)
545c6: vshufps Vps,Hps,Wps,Ib | vshufpd Vpd,Hpd,Wpd,Ib (66)
546c7: Grp9 (1A)
547c8: BSWAP RAX/EAX/R8/R8D
548c9: BSWAP RCX/ECX/R9/R9D
549ca: BSWAP RDX/EDX/R10/R10D
550cb: BSWAP RBX/EBX/R11/R11D
551cc: BSWAP RSP/ESP/R12/R12D
552cd: BSWAP RBP/EBP/R13/R13D
553ce: BSWAP RSI/ESI/R14/R14D
554cf: BSWAP RDI/EDI/R15/R15D
555# 0x0f 0xd0-0xdf
556d0: vaddsubpd Vpd,Hpd,Wpd (66) | vaddsubps Vps,Hps,Wps (F2)
557d1: psrlw Pq,Qq | vpsrlw Vx,Hx,Wx (66),(v1)
558d2: psrld Pq,Qq | vpsrld Vx,Hx,Wx (66),(v1)
559d3: psrlq Pq,Qq | vpsrlq Vx,Hx,Wx (66),(v1)
560d4: paddq Pq,Qq | vpaddq Vx,Hx,Wx (66),(v1)
561d5: pmullw Pq,Qq | vpmullw Vx,Hx,Wx (66),(v1)
562d6: vmovq Wq,Vq (66),(v1) | movq2dq Vdq,Nq (F3) | movdq2q Pq,Uq (F2)
563d7: pmovmskb Gd,Nq | vpmovmskb Gd,Ux (66),(v1)
564d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1)
565d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1)
566da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1)
567db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1)
568dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1)
569dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1)
570de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1)
571df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1)
572# 0x0f 0xe0-0xef
573e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1)
574e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1)
575e2: psrad Pq,Qq | vpsrad Vx,Hx,Wx (66),(v1)
576e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1)
577e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1)
578e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1)
579e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtpd2dq Vx,Wpd (F2)
580e7: movntq Mq,Pq | vmovntdq Mx,Vx (66)
581e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1)
582e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1)
583ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1)
584eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1)
585ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1)
586ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1)
587ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1)
588ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1)
589# 0x0f 0xf0-0xff
590f0: vlddqu Vx,Mx (F2)
591f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1)
592f2: pslld Pq,Qq | vpslld Vx,Hx,Wx (66),(v1)
593f3: psllq Pq,Qq | vpsllq Vx,Hx,Wx (66),(v1)
594f4: pmuludq Pq,Qq | vpmuludq Vx,Hx,Wx (66),(v1)
595f5: pmaddwd Pq,Qq | vpmaddwd Vx,Hx,Wx (66),(v1)
596f6: psadbw Pq,Qq | vpsadbw Vx,Hx,Wx (66),(v1)
597f7: maskmovq Pq,Nq | vmaskmovdqu Vx,Ux (66),(v1)
598f8: psubb Pq,Qq | vpsubb Vx,Hx,Wx (66),(v1)
599f9: psubw Pq,Qq | vpsubw Vx,Hx,Wx (66),(v1)
600fa: psubd Pq,Qq | vpsubd Vx,Hx,Wx (66),(v1)
601fb: psubq Pq,Qq | vpsubq Vx,Hx,Wx (66),(v1)
602fc: paddb Pq,Qq | vpaddb Vx,Hx,Wx (66),(v1)
603fd: paddw Pq,Qq | vpaddw Vx,Hx,Wx (66),(v1)
604fe: paddd Pq,Qq | vpaddd Vx,Hx,Wx (66),(v1)
605ff:
606EndTable
607
608Table: 3-byte opcode 1 (0x0f 0x38)
609Referrer: 3-byte escape 1
610AVXcode: 2
611# 0x0f 0x38 0x00-0x0f
61200: pshufb Pq,Qq | vpshufb Vx,Hx,Wx (66),(v1)
61301: phaddw Pq,Qq | vphaddw Vx,Hx,Wx (66),(v1)
61402: phaddd Pq,Qq | vphaddd Vx,Hx,Wx (66),(v1)
61503: phaddsw Pq,Qq | vphaddsw Vx,Hx,Wx (66),(v1)
61604: pmaddubsw Pq,Qq | vpmaddubsw Vx,Hx,Wx (66),(v1)
61705: phsubw Pq,Qq | vphsubw Vx,Hx,Wx (66),(v1)
61806: phsubd Pq,Qq | vphsubd Vx,Hx,Wx (66),(v1)
61907: phsubsw Pq,Qq | vphsubsw Vx,Hx,Wx (66),(v1)
62008: psignb Pq,Qq | vpsignb Vx,Hx,Wx (66),(v1)
62109: psignw Pq,Qq | vpsignw Vx,Hx,Wx (66),(v1)
6220a: psignd Pq,Qq | vpsignd Vx,Hx,Wx (66),(v1)
6230b: pmulhrsw Pq,Qq | vpmulhrsw Vx,Hx,Wx (66),(v1)
6240c: vpermilps Vx,Hx,Wx (66),(v)
6250d: vpermilpd Vx,Hx,Wx (66),(v)
6260e: vtestps Vx,Wx (66),(v)
6270f: vtestpd Vx,Wx (66),(v)
628# 0x0f 0x38 0x10-0x1f
62910: pblendvb Vdq,Wdq (66)
63011:
63112:
63213: vcvtph2ps Vx,Wx,Ib (66),(v)
63314: blendvps Vdq,Wdq (66)
63415: blendvpd Vdq,Wdq (66)
63516: vpermps Vqq,Hqq,Wqq (66),(v)
63617: vptest Vx,Wx (66)
63718: vbroadcastss Vx,Wd (66),(v)
63819: vbroadcastsd Vqq,Wq (66),(v)
6391a: vbroadcastf128 Vqq,Mdq (66),(v)
6401b:
6411c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1)
6421d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1)
6431e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1)
6441f:
645# 0x0f 0x38 0x20-0x2f
64620: vpmovsxbw Vx,Ux/Mq (66),(v1)
64721: vpmovsxbd Vx,Ux/Md (66),(v1)
64822: vpmovsxbq Vx,Ux/Mw (66),(v1)
64923: vpmovsxwd Vx,Ux/Mq (66),(v1)
65024: vpmovsxwq Vx,Ux/Md (66),(v1)
65125: vpmovsxdq Vx,Ux/Mq (66),(v1)
65226:
65327:
65428: vpmuldq Vx,Hx,Wx (66),(v1)
65529: vpcmpeqq Vx,Hx,Wx (66),(v1)
6562a: vmovntdqa Vx,Mx (66),(v1)
6572b: vpackusdw Vx,Hx,Wx (66),(v1)
6582c: vmaskmovps Vx,Hx,Mx (66),(v)
6592d: vmaskmovpd Vx,Hx,Mx (66),(v)
6602e: vmaskmovps Mx,Hx,Vx (66),(v)
6612f: vmaskmovpd Mx,Hx,Vx (66),(v)
662# 0x0f 0x38 0x30-0x3f
66330: vpmovzxbw Vx,Ux/Mq (66),(v1)
66431: vpmovzxbd Vx,Ux/Md (66),(v1)
66532: vpmovzxbq Vx,Ux/Mw (66),(v1)
66633: vpmovzxwd Vx,Ux/Mq (66),(v1)
66734: vpmovzxwq Vx,Ux/Md (66),(v1)
66835: vpmovzxdq Vx,Ux/Mq (66),(v1)
66936: vpermd Vqq,Hqq,Wqq (66),(v)
67037: vpcmpgtq Vx,Hx,Wx (66),(v1)
67138: vpminsb Vx,Hx,Wx (66),(v1)
67239: vpminsd Vx,Hx,Wx (66),(v1)
6733a: vpminuw Vx,Hx,Wx (66),(v1)
6743b: vpminud Vx,Hx,Wx (66),(v1)
6753c: vpmaxsb Vx,Hx,Wx (66),(v1)
6763d: vpmaxsd Vx,Hx,Wx (66),(v1)
6773e: vpmaxuw Vx,Hx,Wx (66),(v1)
6783f: vpmaxud Vx,Hx,Wx (66),(v1)
679# 0x0f 0x38 0x40-0x8f
68040: vpmulld Vx,Hx,Wx (66),(v1)
68141: vphminposuw Vdq,Wdq (66),(v1)
68242:
68343:
68444:
68545: vpsrlvd/q Vx,Hx,Wx (66),(v)
68646: vpsravd Vx,Hx,Wx (66),(v)
68747: vpsllvd/q Vx,Hx,Wx (66),(v)
688# Skip 0x48-0x57
68958: vpbroadcastd Vx,Wx (66),(v)
69059: vpbroadcastq Vx,Wx (66),(v)
6915a: vbroadcasti128 Vqq,Mdq (66),(v)
692# Skip 0x5b-0x77
69378: vpbroadcastb Vx,Wx (66),(v)
69479: vpbroadcastw Vx,Wx (66),(v)
695# Skip 0x7a-0x7f
69680: INVEPT Gy,Mdq (66)
69781: INVPID Gy,Mdq (66)
69882: INVPCID Gy,Mdq (66)
6998c: vpmaskmovd/q Vx,Hx,Mx (66),(v)
7008e: vpmaskmovd/q Mx,Vx,Hx (66),(v)
701# 0x0f 0x38 0x90-0xbf (FMA)
70290: vgatherdd/q Vx,Hx,Wx (66),(v)
70391: vgatherqd/q Vx,Hx,Wx (66),(v)
70492: vgatherdps/d Vx,Hx,Wx (66),(v)
70593: vgatherqps/d Vx,Hx,Wx (66),(v)
70694:
70795:
70896: vfmaddsub132ps/d Vx,Hx,Wx (66),(v)
70997: vfmsubadd132ps/d Vx,Hx,Wx (66),(v)
71098: vfmadd132ps/d Vx,Hx,Wx (66),(v)
71199: vfmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
7129a: vfmsub132ps/d Vx,Hx,Wx (66),(v)
7139b: vfmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
7149c: vfnmadd132ps/d Vx,Hx,Wx (66),(v)
7159d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
7169e: vfnmsub132ps/d Vx,Hx,Wx (66),(v)
7179f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
718a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v)
719a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v)
720a8: vfmadd213ps/d Vx,Hx,Wx (66),(v)
721a9: vfmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
722aa: vfmsub213ps/d Vx,Hx,Wx (66),(v)
723ab: vfmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
724ac: vfnmadd213ps/d Vx,Hx,Wx (66),(v)
725ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
726ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v)
727af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
728b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v)
729b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v)
730b8: vfmadd231ps/d Vx,Hx,Wx (66),(v)
731b9: vfmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
732ba: vfmsub231ps/d Vx,Hx,Wx (66),(v)
733bb: vfmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
734bc: vfnmadd231ps/d Vx,Hx,Wx (66),(v)
735bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
736be: vfnmsub231ps/d Vx,Hx,Wx (66),(v)
737bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
738# 0x0f 0x38 0xc0-0xff
739c8: sha1nexte Vdq,Wdq
740c9: sha1msg1 Vdq,Wdq
741ca: sha1msg2 Vdq,Wdq
742cb: sha256rnds2 Vdq,Wdq
743cc: sha256msg1 Vdq,Wdq
744cd: sha256msg2 Vdq,Wdq
745db: VAESIMC Vdq,Wdq (66),(v1)
746dc: VAESENC Vdq,Hdq,Wdq (66),(v1)
747dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1)
748de: VAESDEC Vdq,Hdq,Wdq (66),(v1)
749df: VAESDECLAST Vdq,Hdq,Wdq (66),(v1)
750f0: MOVBE Gy,My | MOVBE Gw,Mw (66) | CRC32 Gd,Eb (F2) | CRC32 Gd,Eb (66&F2)
751f1: MOVBE My,Gy | MOVBE Mw,Gw (66) | CRC32 Gd,Ey (F2) | CRC32 Gd,Ew (66&F2)
752f2: ANDN Gy,By,Ey (v)
753f3: Grp17 (1A)
754f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v)
755f6: ADCX Gy,Ey (66) | ADOX Gy,Ey (F3) | MULX By,Gy,rDX,Ey (F2),(v)
756f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v)
757EndTable
758
759Table: 3-byte opcode 2 (0x0f 0x3a)
760Referrer: 3-byte escape 2
761AVXcode: 3
762# 0x0f 0x3a 0x00-0xff
76300: vpermq Vqq,Wqq,Ib (66),(v)
76401: vpermpd Vqq,Wqq,Ib (66),(v)
76502: vpblendd Vx,Hx,Wx,Ib (66),(v)
76603:
76704: vpermilps Vx,Wx,Ib (66),(v)
76805: vpermilpd Vx,Wx,Ib (66),(v)
76906: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v)
77007:
77108: vroundps Vx,Wx,Ib (66)
77209: vroundpd Vx,Wx,Ib (66)
7730a: vroundss Vss,Wss,Ib (66),(v1)
7740b: vroundsd Vsd,Wsd,Ib (66),(v1)
7750c: vblendps Vx,Hx,Wx,Ib (66)
7760d: vblendpd Vx,Hx,Wx,Ib (66)
7770e: vpblendw Vx,Hx,Wx,Ib (66),(v1)
7780f: palignr Pq,Qq,Ib | vpalignr Vx,Hx,Wx,Ib (66),(v1)
77914: vpextrb Rd/Mb,Vdq,Ib (66),(v1)
78015: vpextrw Rd/Mw,Vdq,Ib (66),(v1)
78116: vpextrd/q Ey,Vdq,Ib (66),(v1)
78217: vextractps Ed,Vdq,Ib (66),(v1)
78318: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v)
78419: vextractf128 Wdq,Vqq,Ib (66),(v)
7851d: vcvtps2ph Wx,Vx,Ib (66),(v)
78620: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1)
78721: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1)
78822: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1)
78938: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v)
79039: vextracti128 Wdq,Vqq,Ib (66),(v)
79140: vdpps Vx,Hx,Wx,Ib (66)
79241: vdppd Vdq,Hdq,Wdq,Ib (66),(v1)
79342: vmpsadbw Vx,Hx,Wx,Ib (66),(v1)
79444: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1)
79546: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v)
7964a: vblendvps Vx,Hx,Wx,Lx (66),(v)
7974b: vblendvpd Vx,Hx,Wx,Lx (66),(v)
7984c: vpblendvb Vx,Hx,Wx,Lx (66),(v1)
79960: vpcmpestrm Vdq,Wdq,Ib (66),(v1)
80061: vpcmpestri Vdq,Wdq,Ib (66),(v1)
80162: vpcmpistrm Vdq,Wdq,Ib (66),(v1)
80263: vpcmpistri Vdq,Wdq,Ib (66),(v1)
803cc: sha1rnds4 Vdq,Wdq,Ib
804df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1)
805f0: RORX Gy,Ey,Ib (F2),(v)
806EndTable
807
808GrpTable: Grp1
8090: ADD
8101: OR
8112: ADC
8123: SBB
8134: AND
8145: SUB
8156: XOR
8167: CMP
817EndTable
818
819GrpTable: Grp1A
8200: POP
821EndTable
822
823GrpTable: Grp2
8240: ROL
8251: ROR
8262: RCL
8273: RCR
8284: SHL/SAL
8295: SHR
8306:
8317: SAR
832EndTable
833
834GrpTable: Grp3_1
8350: TEST Eb,Ib
8361:
8372: NOT Eb
8383: NEG Eb
8394: MUL AL,Eb
8405: IMUL AL,Eb
8416: DIV AL,Eb
8427: IDIV AL,Eb
843EndTable
844
845GrpTable: Grp3_2
8460: TEST Ev,Iz
8471:
8482: NOT Ev
8493: NEG Ev
8504: MUL rAX,Ev
8515: IMUL rAX,Ev
8526: DIV rAX,Ev
8537: IDIV rAX,Ev
854EndTable
855
856GrpTable: Grp4
8570: INC Eb
8581: DEC Eb
859EndTable
860
861GrpTable: Grp5
8620: INC Ev
8631: DEC Ev
864# Note: "forced64" is Intel CPU behavior (see comment about CALL insn).
8652: CALLN Ev (f64)
8663: CALLF Ep
8674: JMPN Ev (f64)
8685: JMPF Mp
8696: PUSH Ev (d64)
8707:
871EndTable
872
873GrpTable: Grp6
8740: SLDT Rv/Mw
8751: STR Rv/Mw
8762: LLDT Ew
8773: LTR Ew
8784: VERR Ew
8795: VERW Ew
880EndTable
881
882GrpTable: Grp7
8830: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B)
8841: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B)
8852: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B)
8863: LIDT Ms
8874: SMSW Mw/Rv
8885: rdpkru (110),(11B) | wrpkru (111),(11B)
8896: LMSW Ew
8907: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B)
891EndTable
892
893GrpTable: Grp8
8944: BT
8955: BTS
8966: BTR
8977: BTC
898EndTable
899
900GrpTable: Grp9
9011: CMPXCHG8B/16B Mq/Mdq
9023: xrstors
9034: xsavec
9045: xsaves
9056: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B)
9067: VMPTRST Mq | VMPTRST Mq (F3) | RDSEED Rv (11B)
907EndTable
908
909GrpTable: Grp10
910EndTable
911
912# Grp11A and Grp11B are expressed as Grp11 in Intel SDM
913GrpTable: Grp11A
9140: MOV Eb,Ib
9157: XABORT Ib (000),(11B)
916EndTable
917
918GrpTable: Grp11B
9190: MOV Eb,Iz
9207: XBEGIN Jz (000),(11B)
921EndTable
922
923GrpTable: Grp12
9242: psrlw Nq,Ib (11B) | vpsrlw Hx,Ux,Ib (66),(11B),(v1)
9254: psraw Nq,Ib (11B) | vpsraw Hx,Ux,Ib (66),(11B),(v1)
9266: psllw Nq,Ib (11B) | vpsllw Hx,Ux,Ib (66),(11B),(v1)
927EndTable
928
929GrpTable: Grp13
9302: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1)
9314: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1)
9326: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1)
933EndTable
934
935GrpTable: Grp14
9362: psrlq Nq,Ib (11B) | vpsrlq Hx,Ux,Ib (66),(11B),(v1)
9373: vpsrldq Hx,Ux,Ib (66),(11B),(v1)
9386: psllq Nq,Ib (11B) | vpsllq Hx,Ux,Ib (66),(11B),(v1)
9397: vpslldq Hx,Ux,Ib (66),(11B),(v1)
940EndTable
941
942GrpTable: Grp15
9430: fxsave | RDFSBASE Ry (F3),(11B)
9441: fxstor | RDGSBASE Ry (F3),(11B)
9452: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B)
9463: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B)
9474: XSAVE
9485: XRSTOR | lfence (11B)
9496: XSAVEOPT | clwb (66) | mfence (11B)
9507: clflush | clflushopt (66) | sfence (11B) | pcommit (66),(11B)
951EndTable
952
953GrpTable: Grp16
9540: prefetch NTA
9551: prefetch T0
9562: prefetch T1
9573: prefetch T2
958EndTable
959
960GrpTable: Grp17
9611: BLSR By,Ey (v)
9622: BLSMSK By,Ey (v)
9633: BLSI By,Ey (v)
964EndTable
965
966# AMD's Prefetch Group
967GrpTable: GrpP
9680: PREFETCH
9691: PREFETCHW
970EndTable
971
972GrpTable: GrpPDLK
9730: MONTMUL
9741: XSHA1
9752: XSHA2
976EndTable
977
978GrpTable: GrpRNG
9790: xstore-rng
9801: xcrypt-ecb
9812: xcrypt-cbc
9824: xcrypt-cfb
9835: xcrypt-ofb
984EndTable