aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2015-08-13 03:14:55 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-08-17 10:11:36 -0400
commit237fae79f50d2d0c7bdeb039bc2c87fc6d52c7e7 (patch)
tree5f1f7e4b16547526c955a7f05db793c6d92daae5
parenta4e925905c98fb83538c164878946d77d0df1433 (diff)
perf tools: Add Intel PT instruction decoder
Add support for decoding instructions for Intel Processor Trace. The kernel x86 instruction decoder is copied for this. This essentially provides intel_pt_get_insn() which takes a binary buffer, uses the kernel's x86 instruction decoder to get details of the instruction and then categorizes it for consumption by an Intel PT decoder. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: Jiri Olsa <jolsa@redhat.com> Link: http://lkml.kernel.org/r/1439450095-30122-1-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/build/Makefile.build2
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Makefile.perf12
-rw-r--r--tools/perf/util/intel-pt-decoder/Build12
-rw-r--r--tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk386
-rw-r--r--tools/perf/util/intel-pt-decoder/inat.c96
-rw-r--r--tools/perf/util/intel-pt-decoder/inat.h221
-rw-r--r--tools/perf/util/intel-pt-decoder/insn.c594
-rw-r--r--tools/perf/util/intel-pt-decoder/insn.h201
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c246
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h65
-rw-r--r--tools/perf/util/intel-pt-decoder/x86-opcode-map.txt970
12 files changed, 2803 insertions, 3 deletions
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
index faca2bf6a430..8120af9c0341 100644
--- a/tools/build/Makefile.build
+++ b/tools/build/Makefile.build
@@ -57,6 +57,8 @@ quiet_cmd_cc_i_c = CPP $@
57quiet_cmd_cc_s_c = AS $@ 57quiet_cmd_cc_s_c = AS $@
58 cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $< 58 cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $<
59 59
60quiet_cmd_gen = GEN $@
61
60# Link agregate command 62# Link agregate command
61# If there's nothing to link, create empty $@ object. 63# If there's nothing to link, create empty $@ object.
62quiet_cmd_ld_multi = LD $@ 64quiet_cmd_ld_multi = LD $@
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 09db62ba5786..3d1bb802dbf4 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -29,3 +29,4 @@ config.mak.autogen
29*.pyc 29*.pyc
30*.pyo 30*.pyo
31.config-detected 31.config-detected
32util/intel-pt-decoder/inat-tables.c
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 4b58daeff881..d9863cb96f59 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -76,6 +76,12 @@ include config/utilities.mak
76# 76#
77# Define NO_AUXTRACE if you do not want AUX area tracing support 77# Define NO_AUXTRACE if you do not want AUX area tracing support
78 78
79# As per kernel Makefile, avoid funny character set dependencies
80unexport LC_ALL
81LC_COLLATE=C
82LC_NUMERIC=C
83export LC_COLLATE LC_NUMERIC
84
79ifeq ($(srctree),) 85ifeq ($(srctree),)
80srctree := $(patsubst %/,%,$(dir $(shell pwd))) 86srctree := $(patsubst %/,%,$(dir $(shell pwd)))
81srctree := $(patsubst %/,%,$(dir $(srctree))) 87srctree := $(patsubst %/,%,$(dir $(srctree)))
@@ -135,6 +141,7 @@ INSTALL = install
135FLEX = flex 141FLEX = flex
136BISON = bison 142BISON = bison
137STRIP = strip 143STRIP = strip
144AWK = awk
138 145
139LIB_DIR = $(srctree)/tools/lib/api/ 146LIB_DIR = $(srctree)/tools/lib/api/
140TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ 147TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
@@ -289,7 +296,7 @@ strip: $(PROGRAMS) $(OUTPUT)perf
289 296
290PERF_IN := $(OUTPUT)perf-in.o 297PERF_IN := $(OUTPUT)perf-in.o
291 298
292export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX 299export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
293build := -f $(srctree)/tools/build/Makefile.build dir=. obj 300build := -f $(srctree)/tools/build/Makefile.build dir=. obj
294 301
295$(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE 302$(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE
@@ -565,7 +572,8 @@ clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean
565 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 572 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
566 $(Q)$(RM) $(OUTPUT).config-detected 573 $(Q)$(RM) $(OUTPUT).config-detected
567 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 574 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
568 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* 575 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \
576 $(OUTPUT)util/intel-pt-decoder/inat-tables.c
569 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 577 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
570 $(python-clean) 578 $(python-clean)
571 579
diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build
index 9d67381a9bd3..5a46ce13c1f8 100644
--- a/tools/perf/util/intel-pt-decoder/Build
+++ b/tools/perf/util/intel-pt-decoder/Build
@@ -1 +1,11 @@
1libperf-$(CONFIG_AUXTRACE) += intel-pt-pkt-decoder.o 1libperf-$(CONFIG_AUXTRACE) += intel-pt-pkt-decoder.o intel-pt-insn-decoder.o
2
3inat_tables_script = util/intel-pt-decoder/gen-insn-attr-x86.awk
4inat_tables_maps = util/intel-pt-decoder/x86-opcode-map.txt
5
6$(OUTPUT)util/intel-pt-decoder/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
7 @$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@
8
9$(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/inat.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c
10
11CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder -Wno-override-init
diff --git a/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk b/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk
new file mode 100644
index 000000000000..517567347aac
--- /dev/null
+++ b/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk
@@ -0,0 +1,386 @@
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}
diff --git a/tools/perf/util/intel-pt-decoder/inat.c b/tools/perf/util/intel-pt-decoder/inat.c
new file mode 100644
index 000000000000..feeaa509dfe4
--- /dev/null
+++ b/tools/perf/util/intel-pt-decoder/inat.c
@@ -0,0 +1,96 @@
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 <asm/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}
diff --git a/tools/perf/util/intel-pt-decoder/inat.h b/tools/perf/util/intel-pt-decoder/inat.h
new file mode 100644
index 000000000000..74a2e312e8a2
--- /dev/null
+++ b/tools/perf/util/intel-pt-decoder/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 <asm/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/perf/util/intel-pt-decoder/insn.c b/tools/perf/util/intel-pt-decoder/insn.c
new file mode 100644
index 000000000000..8f72b334aea0
--- /dev/null
+++ b/tools/perf/util/intel-pt-decoder/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 <asm/inat.h>
27#include <asm/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/perf/util/intel-pt-decoder/insn.h b/tools/perf/util/intel-pt-decoder/insn.h
new file mode 100644
index 000000000000..e7814b74caf8
--- /dev/null
+++ b/tools/perf/util/intel-pt-decoder/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 <asm/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/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
new file mode 100644
index 000000000000..46980fc663ac
--- /dev/null
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
@@ -0,0 +1,246 @@
1/*
2 * intel_pt_insn_decoder.c: Intel Processor Trace support
3 * Copyright (c) 2013-2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <stdio.h>
17#include <string.h>
18#include <endian.h>
19#include <byteswap.h>
20
21#include "event.h"
22
23#include <asm/insn.h>
24
25#include "inat.c"
26#include "insn.c"
27
28#include "intel-pt-insn-decoder.h"
29
30/* Based on branch_type() from perf_event_intel_lbr.c */
31static void intel_pt_insn_decoder(struct insn *insn,
32 struct intel_pt_insn *intel_pt_insn)
33{
34 enum intel_pt_insn_op op = INTEL_PT_OP_OTHER;
35 enum intel_pt_insn_branch branch = INTEL_PT_BR_NO_BRANCH;
36 int ext;
37
38 if (insn_is_avx(insn)) {
39 intel_pt_insn->op = INTEL_PT_OP_OTHER;
40 intel_pt_insn->branch = INTEL_PT_BR_NO_BRANCH;
41 intel_pt_insn->length = insn->length;
42 return;
43 }
44
45 switch (insn->opcode.bytes[0]) {
46 case 0xf:
47 switch (insn->opcode.bytes[1]) {
48 case 0x05: /* syscall */
49 case 0x34: /* sysenter */
50 op = INTEL_PT_OP_SYSCALL;
51 branch = INTEL_PT_BR_INDIRECT;
52 break;
53 case 0x07: /* sysret */
54 case 0x35: /* sysexit */
55 op = INTEL_PT_OP_SYSRET;
56 branch = INTEL_PT_BR_INDIRECT;
57 break;
58 case 0x80 ... 0x8f: /* jcc */
59 op = INTEL_PT_OP_JCC;
60 branch = INTEL_PT_BR_CONDITIONAL;
61 break;
62 default:
63 break;
64 }
65 break;
66 case 0x70 ... 0x7f: /* jcc */
67 op = INTEL_PT_OP_JCC;
68 branch = INTEL_PT_BR_CONDITIONAL;
69 break;
70 case 0xc2: /* near ret */
71 case 0xc3: /* near ret */
72 case 0xca: /* far ret */
73 case 0xcb: /* far ret */
74 op = INTEL_PT_OP_RET;
75 branch = INTEL_PT_BR_INDIRECT;
76 break;
77 case 0xcf: /* iret */
78 op = INTEL_PT_OP_IRET;
79 branch = INTEL_PT_BR_INDIRECT;
80 break;
81 case 0xcc ... 0xce: /* int */
82 op = INTEL_PT_OP_INT;
83 branch = INTEL_PT_BR_INDIRECT;
84 break;
85 case 0xe8: /* call near rel */
86 op = INTEL_PT_OP_CALL;
87 branch = INTEL_PT_BR_UNCONDITIONAL;
88 break;
89 case 0x9a: /* call far absolute */
90 op = INTEL_PT_OP_CALL;
91 branch = INTEL_PT_BR_INDIRECT;
92 break;
93 case 0xe0 ... 0xe2: /* loop */
94 op = INTEL_PT_OP_LOOP;
95 branch = INTEL_PT_BR_CONDITIONAL;
96 break;
97 case 0xe3: /* jcc */
98 op = INTEL_PT_OP_JCC;
99 branch = INTEL_PT_BR_CONDITIONAL;
100 break;
101 case 0xe9: /* jmp */
102 case 0xeb: /* jmp */
103 op = INTEL_PT_OP_JMP;
104 branch = INTEL_PT_BR_UNCONDITIONAL;
105 break;
106 case 0xea: /* far jmp */
107 op = INTEL_PT_OP_JMP;
108 branch = INTEL_PT_BR_INDIRECT;
109 break;
110 case 0xff: /* call near absolute, call far absolute ind */
111 ext = (insn->modrm.bytes[0] >> 3) & 0x7;
112 switch (ext) {
113 case 2: /* near ind call */
114 case 3: /* far ind call */
115 op = INTEL_PT_OP_CALL;
116 branch = INTEL_PT_BR_INDIRECT;
117 break;
118 case 4:
119 case 5:
120 op = INTEL_PT_OP_JMP;
121 branch = INTEL_PT_BR_INDIRECT;
122 break;
123 default:
124 break;
125 }
126 break;
127 default:
128 break;
129 }
130
131 intel_pt_insn->op = op;
132 intel_pt_insn->branch = branch;
133 intel_pt_insn->length = insn->length;
134
135 if (branch == INTEL_PT_BR_CONDITIONAL ||
136 branch == INTEL_PT_BR_UNCONDITIONAL) {
137#if __BYTE_ORDER == __BIG_ENDIAN
138 switch (insn->immediate.nbytes) {
139 case 1:
140 intel_pt_insn->rel = insn->immediate.value;
141 break;
142 case 2:
143 intel_pt_insn->rel =
144 bswap_16((short)insn->immediate.value);
145 break;
146 case 4:
147 intel_pt_insn->rel = bswap_32(insn->immediate.value);
148 break;
149 }
150#else
151 intel_pt_insn->rel = insn->immediate.value;
152#endif
153 }
154}
155
156int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
157 struct intel_pt_insn *intel_pt_insn)
158{
159 struct insn insn;
160
161 insn_init(&insn, buf, len, x86_64);
162 insn_get_length(&insn);
163 if (!insn_complete(&insn) || insn.length > len)
164 return -1;
165 intel_pt_insn_decoder(&insn, intel_pt_insn);
166 if (insn.length < INTEL_PT_INSN_DBG_BUF_SZ)
167 memcpy(intel_pt_insn->buf, buf, insn.length);
168 else
169 memcpy(intel_pt_insn->buf, buf, INTEL_PT_INSN_DBG_BUF_SZ);
170 return 0;
171}
172
173const char *branch_name[] = {
174 [INTEL_PT_OP_OTHER] = "Other",
175 [INTEL_PT_OP_CALL] = "Call",
176 [INTEL_PT_OP_RET] = "Ret",
177 [INTEL_PT_OP_JCC] = "Jcc",
178 [INTEL_PT_OP_JMP] = "Jmp",
179 [INTEL_PT_OP_LOOP] = "Loop",
180 [INTEL_PT_OP_IRET] = "IRet",
181 [INTEL_PT_OP_INT] = "Int",
182 [INTEL_PT_OP_SYSCALL] = "Syscall",
183 [INTEL_PT_OP_SYSRET] = "Sysret",
184};
185
186const char *intel_pt_insn_name(enum intel_pt_insn_op op)
187{
188 return branch_name[op];
189}
190
191int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf,
192 size_t buf_len)
193{
194 switch (intel_pt_insn->branch) {
195 case INTEL_PT_BR_CONDITIONAL:
196 case INTEL_PT_BR_UNCONDITIONAL:
197 return snprintf(buf, buf_len, "%s %s%d",
198 intel_pt_insn_name(intel_pt_insn->op),
199 intel_pt_insn->rel > 0 ? "+" : "",
200 intel_pt_insn->rel);
201 case INTEL_PT_BR_NO_BRANCH:
202 case INTEL_PT_BR_INDIRECT:
203 return snprintf(buf, buf_len, "%s",
204 intel_pt_insn_name(intel_pt_insn->op));
205 default:
206 break;
207 }
208 return 0;
209}
210
211size_t intel_pt_insn_max_size(void)
212{
213 return MAX_INSN_SIZE;
214}
215
216int intel_pt_insn_type(enum intel_pt_insn_op op)
217{
218 switch (op) {
219 case INTEL_PT_OP_OTHER:
220 return 0;
221 case INTEL_PT_OP_CALL:
222 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL;
223 case INTEL_PT_OP_RET:
224 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN;
225 case INTEL_PT_OP_JCC:
226 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL;
227 case INTEL_PT_OP_JMP:
228 return PERF_IP_FLAG_BRANCH;
229 case INTEL_PT_OP_LOOP:
230 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL;
231 case INTEL_PT_OP_IRET:
232 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN |
233 PERF_IP_FLAG_INTERRUPT;
234 case INTEL_PT_OP_INT:
235 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
236 PERF_IP_FLAG_INTERRUPT;
237 case INTEL_PT_OP_SYSCALL:
238 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
239 PERF_IP_FLAG_SYSCALLRET;
240 case INTEL_PT_OP_SYSRET:
241 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN |
242 PERF_IP_FLAG_SYSCALLRET;
243 default:
244 return 0;
245 }
246}
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
new file mode 100644
index 000000000000..b0adbf37323e
--- /dev/null
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
@@ -0,0 +1,65 @@
1/*
2 * intel_pt_insn_decoder.h: Intel Processor Trace support
3 * Copyright (c) 2013-2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#ifndef INCLUDE__INTEL_PT_INSN_DECODER_H__
17#define INCLUDE__INTEL_PT_INSN_DECODER_H__
18
19#include <stddef.h>
20#include <stdint.h>
21
22#define INTEL_PT_INSN_DESC_MAX 32
23#define INTEL_PT_INSN_DBG_BUF_SZ 16
24
25enum intel_pt_insn_op {
26 INTEL_PT_OP_OTHER,
27 INTEL_PT_OP_CALL,
28 INTEL_PT_OP_RET,
29 INTEL_PT_OP_JCC,
30 INTEL_PT_OP_JMP,
31 INTEL_PT_OP_LOOP,
32 INTEL_PT_OP_IRET,
33 INTEL_PT_OP_INT,
34 INTEL_PT_OP_SYSCALL,
35 INTEL_PT_OP_SYSRET,
36};
37
38enum intel_pt_insn_branch {
39 INTEL_PT_BR_NO_BRANCH,
40 INTEL_PT_BR_INDIRECT,
41 INTEL_PT_BR_CONDITIONAL,
42 INTEL_PT_BR_UNCONDITIONAL,
43};
44
45struct intel_pt_insn {
46 enum intel_pt_insn_op op;
47 enum intel_pt_insn_branch branch;
48 int length;
49 int32_t rel;
50 unsigned char buf[INTEL_PT_INSN_DBG_BUF_SZ];
51};
52
53int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
54 struct intel_pt_insn *intel_pt_insn);
55
56const char *intel_pt_insn_name(enum intel_pt_insn_op op);
57
58int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf,
59 size_t buf_len);
60
61size_t intel_pt_insn_max_size(void);
62
63int intel_pt_insn_type(enum intel_pt_insn_op op);
64
65#endif
diff --git a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
new file mode 100644
index 000000000000..816488c0b97e
--- /dev/null
+++ b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
@@ -0,0 +1,970 @@
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:
3561a: BNDCL Ev,Gv | BNDCU Ev,Gv | BNDMOV Gv,Ev | BNDLDX Gv,Ev,Gv
3571b: BNDCN Ev,Gv | BNDMOV Ev,Gv | BNDMK Gv,Ev | BNDSTX Ev,GV,Gv
3581c:
3591d:
3601e:
3611f: NOP Ev
362# 0x0f 0x20-0x2f
36320: MOV Rd,Cd
36421: MOV Rd,Dd
36522: MOV Cd,Rd
36623: MOV Dd,Rd
36724:
36825:
36926:
37027:
37128: vmovaps Vps,Wps | vmovapd Vpd,Wpd (66)
37229: vmovaps Wps,Vps | vmovapd Wpd,Vpd (66)
3732a: cvtpi2ps Vps,Qpi | cvtpi2pd Vpd,Qpi (66) | vcvtsi2ss Vss,Hss,Ey (F3),(v1) | vcvtsi2sd Vsd,Hsd,Ey (F2),(v1)
3742b: vmovntps Mps,Vps | vmovntpd Mpd,Vpd (66)
3752c: cvttps2pi Ppi,Wps | cvttpd2pi Ppi,Wpd (66) | vcvttss2si Gy,Wss (F3),(v1) | vcvttsd2si Gy,Wsd (F2),(v1)
3762d: cvtps2pi Ppi,Wps | cvtpd2pi Qpi,Wpd (66) | vcvtss2si Gy,Wss (F3),(v1) | vcvtsd2si Gy,Wsd (F2),(v1)
3772e: vucomiss Vss,Wss (v1) | vucomisd Vsd,Wsd (66),(v1)
3782f: vcomiss Vss,Wss (v1) | vcomisd Vsd,Wsd (66),(v1)
379# 0x0f 0x30-0x3f
38030: WRMSR
38131: RDTSC
38232: RDMSR
38333: RDPMC
38434: SYSENTER
38535: SYSEXIT
38636:
38737: GETSEC
38838: escape # 3-byte escape 1
38939:
3903a: escape # 3-byte escape 2
3913b:
3923c:
3933d:
3943e:
3953f:
396# 0x0f 0x40-0x4f
39740: CMOVO Gv,Ev
39841: CMOVNO Gv,Ev
39942: CMOVB/C/NAE Gv,Ev
40043: CMOVAE/NB/NC Gv,Ev
40144: CMOVE/Z Gv,Ev
40245: CMOVNE/NZ Gv,Ev
40346: CMOVBE/NA Gv,Ev
40447: CMOVA/NBE Gv,Ev
40548: CMOVS Gv,Ev
40649: CMOVNS Gv,Ev
4074a: CMOVP/PE Gv,Ev
4084b: CMOVNP/PO Gv,Ev
4094c: CMOVL/NGE Gv,Ev
4104d: CMOVNL/GE Gv,Ev
4114e: CMOVLE/NG Gv,Ev
4124f: CMOVNLE/G Gv,Ev
413# 0x0f 0x50-0x5f
41450: vmovmskps Gy,Ups | vmovmskpd Gy,Upd (66)
41551: vsqrtps Vps,Wps | vsqrtpd Vpd,Wpd (66) | vsqrtss Vss,Hss,Wss (F3),(v1) | vsqrtsd Vsd,Hsd,Wsd (F2),(v1)
41652: vrsqrtps Vps,Wps | vrsqrtss Vss,Hss,Wss (F3),(v1)
41753: vrcpps Vps,Wps | vrcpss Vss,Hss,Wss (F3),(v1)
41854: vandps Vps,Hps,Wps | vandpd Vpd,Hpd,Wpd (66)
41955: vandnps Vps,Hps,Wps | vandnpd Vpd,Hpd,Wpd (66)
42056: vorps Vps,Hps,Wps | vorpd Vpd,Hpd,Wpd (66)
42157: vxorps Vps,Hps,Wps | vxorpd Vpd,Hpd,Wpd (66)
42258: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1)
42359: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1)
4245a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1)
4255b: vcvtdq2ps Vps,Wdq | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3)
4265c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1)
4275d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1)
4285e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1)
4295f: vmaxps Vps,Hps,Wps | vmaxpd Vpd,Hpd,Wpd (66) | vmaxss Vss,Hss,Wss (F3),(v1) | vmaxsd Vsd,Hsd,Wsd (F2),(v1)
430# 0x0f 0x60-0x6f
43160: punpcklbw Pq,Qd | vpunpcklbw Vx,Hx,Wx (66),(v1)
43261: punpcklwd Pq,Qd | vpunpcklwd Vx,Hx,Wx (66),(v1)
43362: punpckldq Pq,Qd | vpunpckldq Vx,Hx,Wx (66),(v1)
43463: packsswb Pq,Qq | vpacksswb Vx,Hx,Wx (66),(v1)
43564: pcmpgtb Pq,Qq | vpcmpgtb Vx,Hx,Wx (66),(v1)
43665: pcmpgtw Pq,Qq | vpcmpgtw Vx,Hx,Wx (66),(v1)
43766: pcmpgtd Pq,Qq | vpcmpgtd Vx,Hx,Wx (66),(v1)
43867: packuswb Pq,Qq | vpackuswb Vx,Hx,Wx (66),(v1)
43968: punpckhbw Pq,Qd | vpunpckhbw Vx,Hx,Wx (66),(v1)
44069: punpckhwd Pq,Qd | vpunpckhwd Vx,Hx,Wx (66),(v1)
4416a: punpckhdq Pq,Qd | vpunpckhdq Vx,Hx,Wx (66),(v1)
4426b: packssdw Pq,Qd | vpackssdw Vx,Hx,Wx (66),(v1)
4436c: vpunpcklqdq Vx,Hx,Wx (66),(v1)
4446d: vpunpckhqdq Vx,Hx,Wx (66),(v1)
4456e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1)
4466f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqu Vx,Wx (F3)
447# 0x0f 0x70-0x7f
44870: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1)
44971: Grp12 (1A)
45072: Grp13 (1A)
45173: Grp14 (1A)
45274: pcmpeqb Pq,Qq | vpcmpeqb Vx,Hx,Wx (66),(v1)
45375: pcmpeqw Pq,Qq | vpcmpeqw Vx,Hx,Wx (66),(v1)
45476: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1)
455# Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX.
45677: emms | vzeroupper | vzeroall
45778: VMREAD Ey,Gy
45879: VMWRITE Gy,Ey
4597a:
4607b:
4617c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2)
4627d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2)
4637e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1)
4647f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqu Wx,Vx (F3)
465# 0x0f 0x80-0x8f
466# Note: "forced64" is Intel CPU behavior (see comment about CALL insn).
46780: JO Jz (f64)
46881: JNO Jz (f64)
46982: JB/JC/JNAE Jz (f64)
47083: JAE/JNB/JNC Jz (f64)
47184: JE/JZ Jz (f64)
47285: JNE/JNZ Jz (f64)
47386: JBE/JNA Jz (f64)
47487: JA/JNBE Jz (f64)
47588: JS Jz (f64)
47689: JNS Jz (f64)
4778a: JP/JPE Jz (f64)
4788b: JNP/JPO Jz (f64)
4798c: JL/JNGE Jz (f64)
4808d: JNL/JGE Jz (f64)
4818e: JLE/JNG Jz (f64)
4828f: JNLE/JG Jz (f64)
483# 0x0f 0x90-0x9f
48490: SETO Eb
48591: SETNO Eb
48692: SETB/C/NAE Eb
48793: SETAE/NB/NC Eb
48894: SETE/Z Eb
48995: SETNE/NZ Eb
49096: SETBE/NA Eb
49197: SETA/NBE Eb
49298: SETS Eb
49399: SETNS Eb
4949a: SETP/PE Eb
4959b: SETNP/PO Eb
4969c: SETL/NGE Eb
4979d: SETNL/GE Eb
4989e: SETLE/NG Eb
4999f: SETNLE/G Eb
500# 0x0f 0xa0-0xaf
501a0: PUSH FS (d64)
502a1: POP FS (d64)
503a2: CPUID
504a3: BT Ev,Gv
505a4: SHLD Ev,Gv,Ib
506a5: SHLD Ev,Gv,CL
507a6: GrpPDLK
508a7: GrpRNG
509a8: PUSH GS (d64)
510a9: POP GS (d64)
511aa: RSM
512ab: BTS Ev,Gv
513ac: SHRD Ev,Gv,Ib
514ad: SHRD Ev,Gv,CL
515ae: Grp15 (1A),(1C)
516af: IMUL Gv,Ev
517# 0x0f 0xb0-0xbf
518b0: CMPXCHG Eb,Gb
519b1: CMPXCHG Ev,Gv
520b2: LSS Gv,Mp
521b3: BTR Ev,Gv
522b4: LFS Gv,Mp
523b5: LGS Gv,Mp
524b6: MOVZX Gv,Eb
525b7: MOVZX Gv,Ew
526b8: JMPE (!F3) | POPCNT Gv,Ev (F3)
527b9: Grp10 (1A)
528ba: Grp8 Ev,Ib (1A)
529bb: BTC Ev,Gv
530bc: BSF Gv,Ev (!F3) | TZCNT Gv,Ev (F3)
531bd: BSR Gv,Ev (!F3) | LZCNT Gv,Ev (F3)
532be: MOVSX Gv,Eb
533bf: MOVSX Gv,Ew
534# 0x0f 0xc0-0xcf
535c0: XADD Eb,Gb
536c1: XADD Ev,Gv
537c2: 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)
538c3: movnti My,Gy
539c4: pinsrw Pq,Ry/Mw,Ib | vpinsrw Vdq,Hdq,Ry/Mw,Ib (66),(v1)
540c5: pextrw Gd,Nq,Ib | vpextrw Gd,Udq,Ib (66),(v1)
541c6: vshufps Vps,Hps,Wps,Ib | vshufpd Vpd,Hpd,Wpd,Ib (66)
542c7: Grp9 (1A)
543c8: BSWAP RAX/EAX/R8/R8D
544c9: BSWAP RCX/ECX/R9/R9D
545ca: BSWAP RDX/EDX/R10/R10D
546cb: BSWAP RBX/EBX/R11/R11D
547cc: BSWAP RSP/ESP/R12/R12D
548cd: BSWAP RBP/EBP/R13/R13D
549ce: BSWAP RSI/ESI/R14/R14D
550cf: BSWAP RDI/EDI/R15/R15D
551# 0x0f 0xd0-0xdf
552d0: vaddsubpd Vpd,Hpd,Wpd (66) | vaddsubps Vps,Hps,Wps (F2)
553d1: psrlw Pq,Qq | vpsrlw Vx,Hx,Wx (66),(v1)
554d2: psrld Pq,Qq | vpsrld Vx,Hx,Wx (66),(v1)
555d3: psrlq Pq,Qq | vpsrlq Vx,Hx,Wx (66),(v1)
556d4: paddq Pq,Qq | vpaddq Vx,Hx,Wx (66),(v1)
557d5: pmullw Pq,Qq | vpmullw Vx,Hx,Wx (66),(v1)
558d6: vmovq Wq,Vq (66),(v1) | movq2dq Vdq,Nq (F3) | movdq2q Pq,Uq (F2)
559d7: pmovmskb Gd,Nq | vpmovmskb Gd,Ux (66),(v1)
560d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1)
561d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1)
562da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1)
563db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1)
564dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1)
565dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1)
566de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1)
567df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1)
568# 0x0f 0xe0-0xef
569e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1)
570e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1)
571e2: psrad Pq,Qq | vpsrad Vx,Hx,Wx (66),(v1)
572e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1)
573e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1)
574e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1)
575e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtpd2dq Vx,Wpd (F2)
576e7: movntq Mq,Pq | vmovntdq Mx,Vx (66)
577e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1)
578e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1)
579ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1)
580eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1)
581ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1)
582ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1)
583ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1)
584ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1)
585# 0x0f 0xf0-0xff
586f0: vlddqu Vx,Mx (F2)
587f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1)
588f2: pslld Pq,Qq | vpslld Vx,Hx,Wx (66),(v1)
589f3: psllq Pq,Qq | vpsllq Vx,Hx,Wx (66),(v1)
590f4: pmuludq Pq,Qq | vpmuludq Vx,Hx,Wx (66),(v1)
591f5: pmaddwd Pq,Qq | vpmaddwd Vx,Hx,Wx (66),(v1)
592f6: psadbw Pq,Qq | vpsadbw Vx,Hx,Wx (66),(v1)
593f7: maskmovq Pq,Nq | vmaskmovdqu Vx,Ux (66),(v1)
594f8: psubb Pq,Qq | vpsubb Vx,Hx,Wx (66),(v1)
595f9: psubw Pq,Qq | vpsubw Vx,Hx,Wx (66),(v1)
596fa: psubd Pq,Qq | vpsubd Vx,Hx,Wx (66),(v1)
597fb: psubq Pq,Qq | vpsubq Vx,Hx,Wx (66),(v1)
598fc: paddb Pq,Qq | vpaddb Vx,Hx,Wx (66),(v1)
599fd: paddw Pq,Qq | vpaddw Vx,Hx,Wx (66),(v1)
600fe: paddd Pq,Qq | vpaddd Vx,Hx,Wx (66),(v1)
601ff:
602EndTable
603
604Table: 3-byte opcode 1 (0x0f 0x38)
605Referrer: 3-byte escape 1
606AVXcode: 2
607# 0x0f 0x38 0x00-0x0f
60800: pshufb Pq,Qq | vpshufb Vx,Hx,Wx (66),(v1)
60901: phaddw Pq,Qq | vphaddw Vx,Hx,Wx (66),(v1)
61002: phaddd Pq,Qq | vphaddd Vx,Hx,Wx (66),(v1)
61103: phaddsw Pq,Qq | vphaddsw Vx,Hx,Wx (66),(v1)
61204: pmaddubsw Pq,Qq | vpmaddubsw Vx,Hx,Wx (66),(v1)
61305: phsubw Pq,Qq | vphsubw Vx,Hx,Wx (66),(v1)
61406: phsubd Pq,Qq | vphsubd Vx,Hx,Wx (66),(v1)
61507: phsubsw Pq,Qq | vphsubsw Vx,Hx,Wx (66),(v1)
61608: psignb Pq,Qq | vpsignb Vx,Hx,Wx (66),(v1)
61709: psignw Pq,Qq | vpsignw Vx,Hx,Wx (66),(v1)
6180a: psignd Pq,Qq | vpsignd Vx,Hx,Wx (66),(v1)
6190b: pmulhrsw Pq,Qq | vpmulhrsw Vx,Hx,Wx (66),(v1)
6200c: vpermilps Vx,Hx,Wx (66),(v)
6210d: vpermilpd Vx,Hx,Wx (66),(v)
6220e: vtestps Vx,Wx (66),(v)
6230f: vtestpd Vx,Wx (66),(v)
624# 0x0f 0x38 0x10-0x1f
62510: pblendvb Vdq,Wdq (66)
62611:
62712:
62813: vcvtph2ps Vx,Wx,Ib (66),(v)
62914: blendvps Vdq,Wdq (66)
63015: blendvpd Vdq,Wdq (66)
63116: vpermps Vqq,Hqq,Wqq (66),(v)
63217: vptest Vx,Wx (66)
63318: vbroadcastss Vx,Wd (66),(v)
63419: vbroadcastsd Vqq,Wq (66),(v)
6351a: vbroadcastf128 Vqq,Mdq (66),(v)
6361b:
6371c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1)
6381d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1)
6391e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1)
6401f:
641# 0x0f 0x38 0x20-0x2f
64220: vpmovsxbw Vx,Ux/Mq (66),(v1)
64321: vpmovsxbd Vx,Ux/Md (66),(v1)
64422: vpmovsxbq Vx,Ux/Mw (66),(v1)
64523: vpmovsxwd Vx,Ux/Mq (66),(v1)
64624: vpmovsxwq Vx,Ux/Md (66),(v1)
64725: vpmovsxdq Vx,Ux/Mq (66),(v1)
64826:
64927:
65028: vpmuldq Vx,Hx,Wx (66),(v1)
65129: vpcmpeqq Vx,Hx,Wx (66),(v1)
6522a: vmovntdqa Vx,Mx (66),(v1)
6532b: vpackusdw Vx,Hx,Wx (66),(v1)
6542c: vmaskmovps Vx,Hx,Mx (66),(v)
6552d: vmaskmovpd Vx,Hx,Mx (66),(v)
6562e: vmaskmovps Mx,Hx,Vx (66),(v)
6572f: vmaskmovpd Mx,Hx,Vx (66),(v)
658# 0x0f 0x38 0x30-0x3f
65930: vpmovzxbw Vx,Ux/Mq (66),(v1)
66031: vpmovzxbd Vx,Ux/Md (66),(v1)
66132: vpmovzxbq Vx,Ux/Mw (66),(v1)
66233: vpmovzxwd Vx,Ux/Mq (66),(v1)
66334: vpmovzxwq Vx,Ux/Md (66),(v1)
66435: vpmovzxdq Vx,Ux/Mq (66),(v1)
66536: vpermd Vqq,Hqq,Wqq (66),(v)
66637: vpcmpgtq Vx,Hx,Wx (66),(v1)
66738: vpminsb Vx,Hx,Wx (66),(v1)
66839: vpminsd Vx,Hx,Wx (66),(v1)
6693a: vpminuw Vx,Hx,Wx (66),(v1)
6703b: vpminud Vx,Hx,Wx (66),(v1)
6713c: vpmaxsb Vx,Hx,Wx (66),(v1)
6723d: vpmaxsd Vx,Hx,Wx (66),(v1)
6733e: vpmaxuw Vx,Hx,Wx (66),(v1)
6743f: vpmaxud Vx,Hx,Wx (66),(v1)
675# 0x0f 0x38 0x40-0x8f
67640: vpmulld Vx,Hx,Wx (66),(v1)
67741: vphminposuw Vdq,Wdq (66),(v1)
67842:
67943:
68044:
68145: vpsrlvd/q Vx,Hx,Wx (66),(v)
68246: vpsravd Vx,Hx,Wx (66),(v)
68347: vpsllvd/q Vx,Hx,Wx (66),(v)
684# Skip 0x48-0x57
68558: vpbroadcastd Vx,Wx (66),(v)
68659: vpbroadcastq Vx,Wx (66),(v)
6875a: vbroadcasti128 Vqq,Mdq (66),(v)
688# Skip 0x5b-0x77
68978: vpbroadcastb Vx,Wx (66),(v)
69079: vpbroadcastw Vx,Wx (66),(v)
691# Skip 0x7a-0x7f
69280: INVEPT Gy,Mdq (66)
69381: INVPID Gy,Mdq (66)
69482: INVPCID Gy,Mdq (66)
6958c: vpmaskmovd/q Vx,Hx,Mx (66),(v)
6968e: vpmaskmovd/q Mx,Vx,Hx (66),(v)
697# 0x0f 0x38 0x90-0xbf (FMA)
69890: vgatherdd/q Vx,Hx,Wx (66),(v)
69991: vgatherqd/q Vx,Hx,Wx (66),(v)
70092: vgatherdps/d Vx,Hx,Wx (66),(v)
70193: vgatherqps/d Vx,Hx,Wx (66),(v)
70294:
70395:
70496: vfmaddsub132ps/d Vx,Hx,Wx (66),(v)
70597: vfmsubadd132ps/d Vx,Hx,Wx (66),(v)
70698: vfmadd132ps/d Vx,Hx,Wx (66),(v)
70799: vfmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
7089a: vfmsub132ps/d Vx,Hx,Wx (66),(v)
7099b: vfmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
7109c: vfnmadd132ps/d Vx,Hx,Wx (66),(v)
7119d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
7129e: vfnmsub132ps/d Vx,Hx,Wx (66),(v)
7139f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
714a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v)
715a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v)
716a8: vfmadd213ps/d Vx,Hx,Wx (66),(v)
717a9: vfmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
718aa: vfmsub213ps/d Vx,Hx,Wx (66),(v)
719ab: vfmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
720ac: vfnmadd213ps/d Vx,Hx,Wx (66),(v)
721ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
722ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v)
723af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
724b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v)
725b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v)
726b8: vfmadd231ps/d Vx,Hx,Wx (66),(v)
727b9: vfmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
728ba: vfmsub231ps/d Vx,Hx,Wx (66),(v)
729bb: vfmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
730bc: vfnmadd231ps/d Vx,Hx,Wx (66),(v)
731bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
732be: vfnmsub231ps/d Vx,Hx,Wx (66),(v)
733bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
734# 0x0f 0x38 0xc0-0xff
735db: VAESIMC Vdq,Wdq (66),(v1)
736dc: VAESENC Vdq,Hdq,Wdq (66),(v1)
737dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1)
738de: VAESDEC Vdq,Hdq,Wdq (66),(v1)
739df: VAESDECLAST Vdq,Hdq,Wdq (66),(v1)
740f0: MOVBE Gy,My | MOVBE Gw,Mw (66) | CRC32 Gd,Eb (F2) | CRC32 Gd,Eb (66&F2)
741f1: MOVBE My,Gy | MOVBE Mw,Gw (66) | CRC32 Gd,Ey (F2) | CRC32 Gd,Ew (66&F2)
742f2: ANDN Gy,By,Ey (v)
743f3: Grp17 (1A)
744f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v)
745f6: ADCX Gy,Ey (66) | ADOX Gy,Ey (F3) | MULX By,Gy,rDX,Ey (F2),(v)
746f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v)
747EndTable
748
749Table: 3-byte opcode 2 (0x0f 0x3a)
750Referrer: 3-byte escape 2
751AVXcode: 3
752# 0x0f 0x3a 0x00-0xff
75300: vpermq Vqq,Wqq,Ib (66),(v)
75401: vpermpd Vqq,Wqq,Ib (66),(v)
75502: vpblendd Vx,Hx,Wx,Ib (66),(v)
75603:
75704: vpermilps Vx,Wx,Ib (66),(v)
75805: vpermilpd Vx,Wx,Ib (66),(v)
75906: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v)
76007:
76108: vroundps Vx,Wx,Ib (66)
76209: vroundpd Vx,Wx,Ib (66)
7630a: vroundss Vss,Wss,Ib (66),(v1)
7640b: vroundsd Vsd,Wsd,Ib (66),(v1)
7650c: vblendps Vx,Hx,Wx,Ib (66)
7660d: vblendpd Vx,Hx,Wx,Ib (66)
7670e: vpblendw Vx,Hx,Wx,Ib (66),(v1)
7680f: palignr Pq,Qq,Ib | vpalignr Vx,Hx,Wx,Ib (66),(v1)
76914: vpextrb Rd/Mb,Vdq,Ib (66),(v1)
77015: vpextrw Rd/Mw,Vdq,Ib (66),(v1)
77116: vpextrd/q Ey,Vdq,Ib (66),(v1)
77217: vextractps Ed,Vdq,Ib (66),(v1)
77318: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v)
77419: vextractf128 Wdq,Vqq,Ib (66),(v)
7751d: vcvtps2ph Wx,Vx,Ib (66),(v)
77620: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1)
77721: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1)
77822: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1)
77938: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v)
78039: vextracti128 Wdq,Vqq,Ib (66),(v)
78140: vdpps Vx,Hx,Wx,Ib (66)
78241: vdppd Vdq,Hdq,Wdq,Ib (66),(v1)
78342: vmpsadbw Vx,Hx,Wx,Ib (66),(v1)
78444: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1)
78546: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v)
7864a: vblendvps Vx,Hx,Wx,Lx (66),(v)
7874b: vblendvpd Vx,Hx,Wx,Lx (66),(v)
7884c: vpblendvb Vx,Hx,Wx,Lx (66),(v1)
78960: vpcmpestrm Vdq,Wdq,Ib (66),(v1)
79061: vpcmpestri Vdq,Wdq,Ib (66),(v1)
79162: vpcmpistrm Vdq,Wdq,Ib (66),(v1)
79263: vpcmpistri Vdq,Wdq,Ib (66),(v1)
793df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1)
794f0: RORX Gy,Ey,Ib (F2),(v)
795EndTable
796
797GrpTable: Grp1
7980: ADD
7991: OR
8002: ADC
8013: SBB
8024: AND
8035: SUB
8046: XOR
8057: CMP
806EndTable
807
808GrpTable: Grp1A
8090: POP
810EndTable
811
812GrpTable: Grp2
8130: ROL
8141: ROR
8152: RCL
8163: RCR
8174: SHL/SAL
8185: SHR
8196:
8207: SAR
821EndTable
822
823GrpTable: Grp3_1
8240: TEST Eb,Ib
8251:
8262: NOT Eb
8273: NEG Eb
8284: MUL AL,Eb
8295: IMUL AL,Eb
8306: DIV AL,Eb
8317: IDIV AL,Eb
832EndTable
833
834GrpTable: Grp3_2
8350: TEST Ev,Iz
8361:
8372: NOT Ev
8383: NEG Ev
8394: MUL rAX,Ev
8405: IMUL rAX,Ev
8416: DIV rAX,Ev
8427: IDIV rAX,Ev
843EndTable
844
845GrpTable: Grp4
8460: INC Eb
8471: DEC Eb
848EndTable
849
850GrpTable: Grp5
8510: INC Ev
8521: DEC Ev
853# Note: "forced64" is Intel CPU behavior (see comment about CALL insn).
8542: CALLN Ev (f64)
8553: CALLF Ep
8564: JMPN Ev (f64)
8575: JMPF Mp
8586: PUSH Ev (d64)
8597:
860EndTable
861
862GrpTable: Grp6
8630: SLDT Rv/Mw
8641: STR Rv/Mw
8652: LLDT Ew
8663: LTR Ew
8674: VERR Ew
8685: VERW Ew
869EndTable
870
871GrpTable: Grp7
8720: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B)
8731: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B)
8742: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B)
8753: LIDT Ms
8764: SMSW Mw/Rv
8775:
8786: LMSW Ew
8797: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B)
880EndTable
881
882GrpTable: Grp8
8834: BT
8845: BTS
8856: BTR
8867: BTC
887EndTable
888
889GrpTable: Grp9
8901: CMPXCHG8B/16B Mq/Mdq
8916: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B)
8927: VMPTRST Mq | VMPTRST Mq (F3) | RDSEED Rv (11B)
893EndTable
894
895GrpTable: Grp10
896EndTable
897
898# Grp11A and Grp11B are expressed as Grp11 in Intel SDM
899GrpTable: Grp11A
9000: MOV Eb,Ib
9017: XABORT Ib (000),(11B)
902EndTable
903
904GrpTable: Grp11B
9050: MOV Eb,Iz
9067: XBEGIN Jz (000),(11B)
907EndTable
908
909GrpTable: Grp12
9102: psrlw Nq,Ib (11B) | vpsrlw Hx,Ux,Ib (66),(11B),(v1)
9114: psraw Nq,Ib (11B) | vpsraw Hx,Ux,Ib (66),(11B),(v1)
9126: psllw Nq,Ib (11B) | vpsllw Hx,Ux,Ib (66),(11B),(v1)
913EndTable
914
915GrpTable: Grp13
9162: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1)
9174: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1)
9186: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1)
919EndTable
920
921GrpTable: Grp14
9222: psrlq Nq,Ib (11B) | vpsrlq Hx,Ux,Ib (66),(11B),(v1)
9233: vpsrldq Hx,Ux,Ib (66),(11B),(v1)
9246: psllq Nq,Ib (11B) | vpsllq Hx,Ux,Ib (66),(11B),(v1)
9257: vpslldq Hx,Ux,Ib (66),(11B),(v1)
926EndTable
927
928GrpTable: Grp15
9290: fxsave | RDFSBASE Ry (F3),(11B)
9301: fxstor | RDGSBASE Ry (F3),(11B)
9312: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B)
9323: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B)
9334: XSAVE
9345: XRSTOR | lfence (11B)
9356: XSAVEOPT | mfence (11B)
9367: clflush | sfence (11B)
937EndTable
938
939GrpTable: Grp16
9400: prefetch NTA
9411: prefetch T0
9422: prefetch T1
9433: prefetch T2
944EndTable
945
946GrpTable: Grp17
9471: BLSR By,Ey (v)
9482: BLSMSK By,Ey (v)
9493: BLSI By,Ey (v)
950EndTable
951
952# AMD's Prefetch Group
953GrpTable: GrpP
9540: PREFETCH
9551: PREFETCHW
956EndTable
957
958GrpTable: GrpPDLK
9590: MONTMUL
9601: XSHA1
9612: XSHA2
962EndTable
963
964GrpTable: GrpRNG
9650: xstore-rng
9661: xcrypt-ecb
9672: xcrypt-cbc
9684: xcrypt-cfb
9695: xcrypt-ofb
970EndTable