Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Adrian Hunter and committed by
Arnaldo Carvalho de Melo
237fae79 a4e92590

+2803 -3
+2
tools/build/Makefile.build
··· 57 57 quiet_cmd_cc_s_c = AS $@ 58 58 cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $< 59 59 60 + quiet_cmd_gen = GEN $@ 61 + 60 62 # Link agregate command 61 63 # If there's nothing to link, create empty $@ object. 62 64 quiet_cmd_ld_multi = LD $@
+1
tools/perf/.gitignore
··· 29 29 *.pyc 30 30 *.pyo 31 31 .config-detected 32 + util/intel-pt-decoder/inat-tables.c
+10 -2
tools/perf/Makefile.perf
··· 76 76 # 77 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 80 + unexport LC_ALL 81 + LC_COLLATE=C 82 + LC_NUMERIC=C 83 + export LC_COLLATE LC_NUMERIC 84 + 79 85 ifeq ($(srctree),) 80 86 srctree := $(patsubst %/,%,$(dir $(shell pwd))) 81 87 srctree := $(patsubst %/,%,$(dir $(srctree))) ··· 141 135 FLEX = flex 142 136 BISON = bison 143 137 STRIP = strip 138 + AWK = awk 144 139 145 140 LIB_DIR = $(srctree)/tools/lib/api/ 146 141 TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ ··· 296 289 297 290 PERF_IN := $(OUTPUT)perf-in.o 298 291 299 - export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX 292 + export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK 300 293 build := -f $(srctree)/tools/build/Makefile.build dir=. obj 301 294 302 295 $(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE ··· 572 565 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 573 566 $(Q)$(RM) $(OUTPUT).config-detected 574 567 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 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* 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* \ 569 + $(OUTPUT)util/intel-pt-decoder/inat-tables.c 576 570 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 577 571 $(python-clean) 578 572
+11 -1
tools/perf/util/intel-pt-decoder/Build
··· 1 - libperf-$(CONFIG_AUXTRACE) += intel-pt-pkt-decoder.o 1 + libperf-$(CONFIG_AUXTRACE) += intel-pt-pkt-decoder.o intel-pt-insn-decoder.o 2 + 3 + inat_tables_script = util/intel-pt-decoder/gen-insn-attr-x86.awk 4 + inat_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 + 11 + CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder -Wno-override-init
+386
tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk
··· 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 8 + function 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 15 + function 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 + 26 + BEGIN { 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 + 102 + function semantic_error(msg) { 103 + print "Semantic error at " NR ": " msg > "/dev/stderr" 104 + exit 1 105 + } 106 + 107 + function debug(msg) { 108 + print "DEBUG: " msg 109 + } 110 + 111 + function 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 + 156 + function 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 + 225 + function 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. 235 + function 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 + 356 + END { 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 + }
+96
tools/perf/util/intel-pt-decoder/inat.c
··· 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 */ 27 + insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode) 28 + { 29 + return inat_primary_table[opcode]; 30 + } 31 + 32 + int 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 + 40 + insn_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 + 59 + insn_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 + 79 + insn_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 + }
+221
tools/perf/util/intel-pt-decoder/inat.h
··· 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 */ 99 + extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode); 100 + extern int inat_get_last_prefix_id(insn_byte_t last_pfx); 101 + extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, 102 + int lpfx_id, 103 + insn_attr_t esc_attr); 104 + extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm, 105 + int lpfx_id, 106 + insn_attr_t esc_attr); 107 + extern 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 */ 112 + static 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 + 118 + static inline int inat_is_address_size_prefix(insn_attr_t attr) 119 + { 120 + return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ; 121 + } 122 + 123 + static inline int inat_is_operand_size_prefix(insn_attr_t attr) 124 + { 125 + return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ; 126 + } 127 + 128 + static inline int inat_is_rex_prefix(insn_attr_t attr) 129 + { 130 + return (attr & INAT_PFX_MASK) == INAT_PFX_REX; 131 + } 132 + 133 + static 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 + 141 + static 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 + 147 + static inline int inat_is_vex3_prefix(insn_attr_t attr) 148 + { 149 + return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3; 150 + } 151 + 152 + static inline int inat_is_escape(insn_attr_t attr) 153 + { 154 + return attr & INAT_ESC_MASK; 155 + } 156 + 157 + static inline int inat_escape_id(insn_attr_t attr) 158 + { 159 + return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS; 160 + } 161 + 162 + static inline int inat_is_group(insn_attr_t attr) 163 + { 164 + return attr & INAT_GRP_MASK; 165 + } 166 + 167 + static inline int inat_group_id(insn_attr_t attr) 168 + { 169 + return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS; 170 + } 171 + 172 + static inline int inat_group_common_attribute(insn_attr_t attr) 173 + { 174 + return attr & ~INAT_GRP_MASK; 175 + } 176 + 177 + static inline int inat_has_immediate(insn_attr_t attr) 178 + { 179 + return attr & INAT_IMM_MASK; 180 + } 181 + 182 + static inline int inat_immediate_size(insn_attr_t attr) 183 + { 184 + return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS; 185 + } 186 + 187 + static inline int inat_has_modrm(insn_attr_t attr) 188 + { 189 + return attr & INAT_MODRM; 190 + } 191 + 192 + static inline int inat_is_force64(insn_attr_t attr) 193 + { 194 + return attr & INAT_FORCE64; 195 + } 196 + 197 + static inline int inat_has_second_immediate(insn_attr_t attr) 198 + { 199 + return attr & INAT_SCNDIMM; 200 + } 201 + 202 + static inline int inat_has_moffset(insn_attr_t attr) 203 + { 204 + return attr & INAT_MOFFSET; 205 + } 206 + 207 + static inline int inat_has_variant(insn_attr_t attr) 208 + { 209 + return attr & INAT_VARIANT; 210 + } 211 + 212 + static inline int inat_accept_vex(insn_attr_t attr) 213 + { 214 + return attr & INAT_VEXOK; 215 + } 216 + 217 + static inline int inat_must_vex(insn_attr_t attr) 218 + { 219 + return attr & INAT_VEXONLY; 220 + } 221 + #endif
+594
tools/perf/util/intel-pt-decoder/insn.c
··· 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 + */ 53 + void 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 + */ 82 + void 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 + } 115 + found: 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 + } 184 + vex_end: 185 + insn->vex_prefix.got = 1; 186 + 187 + prefixes->got = 1; 188 + 189 + err_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 + */ 203 + void 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 */ 239 + end: 240 + opcode->got = 1; 241 + 242 + err_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 + */ 254 + void 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 + 280 + err_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 + */ 292 + int 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 + */ 314 + void 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 + 332 + err_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 + */ 345 + void 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 + } 393 + out: 394 + insn->displacement.got = 1; 395 + 396 + err_out: 397 + return; 398 + } 399 + 400 + /* Decode moffset16/32/64. Return 0 if failed */ 401 + static 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 + 425 + err_out: 426 + return 0; 427 + } 428 + 429 + /* Decode imm v32(Iz). Return 0 if failed */ 430 + static 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 + 448 + err_out: 449 + return 0; 450 + } 451 + 452 + /* Decode imm v64(Iv/Ov), Return 0 if failed */ 453 + static 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; 476 + err_out: 477 + return 0; 478 + } 479 + 480 + /* Decode ptr16:16/32(Ap) */ 481 + static 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; 503 + err_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 + */ 516 + void 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 + } 572 + done: 573 + insn->immediate.got = 1; 574 + 575 + err_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 + */ 586 + void 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 + }
+201
tools/perf/util/intel-pt-decoder/insn.h
··· 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 + 26 + struct 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 + 36 + struct 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 + 100 + extern void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64); 101 + extern void insn_get_prefixes(struct insn *insn); 102 + extern void insn_get_opcode(struct insn *insn); 103 + extern void insn_get_modrm(struct insn *insn); 104 + extern void insn_get_sib(struct insn *insn); 105 + extern void insn_get_displacement(struct insn *insn); 106 + extern void insn_get_immediate(struct insn *insn); 107 + extern void insn_get_length(struct insn *insn); 108 + 109 + /* Attribute will be determined after getting ModRM (for opcode groups) */ 110 + static inline void insn_get_attribute(struct insn *insn) 111 + { 112 + insn_get_modrm(insn); 113 + } 114 + 115 + /* Instruction uses RIP-relative addressing */ 116 + extern int insn_rip_relative(struct insn *insn); 117 + 118 + /* Init insn for kernel text */ 119 + static 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 + 129 + static 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 */ 137 + static 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 + 143 + static 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 + 151 + static 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 */ 160 + static 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 */ 172 + static inline int insn_offset_rex_prefix(struct insn *insn) 173 + { 174 + return insn->prefixes.nbytes; 175 + } 176 + static inline int insn_offset_vex_prefix(struct insn *insn) 177 + { 178 + return insn_offset_rex_prefix(insn) + insn->rex_prefix.nbytes; 179 + } 180 + static inline int insn_offset_opcode(struct insn *insn) 181 + { 182 + return insn_offset_vex_prefix(insn) + insn->vex_prefix.nbytes; 183 + } 184 + static inline int insn_offset_modrm(struct insn *insn) 185 + { 186 + return insn_offset_opcode(insn) + insn->opcode.nbytes; 187 + } 188 + static inline int insn_offset_sib(struct insn *insn) 189 + { 190 + return insn_offset_modrm(insn) + insn->modrm.nbytes; 191 + } 192 + static inline int insn_offset_displacement(struct insn *insn) 193 + { 194 + return insn_offset_sib(insn) + insn->sib.nbytes; 195 + } 196 + static 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 */
+246
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
··· 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 */ 31 + static 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 + 156 + int 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 + 173 + const 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 + 186 + const char *intel_pt_insn_name(enum intel_pt_insn_op op) 187 + { 188 + return branch_name[op]; 189 + } 190 + 191 + int 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 + 211 + size_t intel_pt_insn_max_size(void) 212 + { 213 + return MAX_INSN_SIZE; 214 + } 215 + 216 + int 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 + }
+65
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.h
··· 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 + 25 + enum 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 + 38 + enum 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 + 45 + struct 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 + 53 + int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64, 54 + struct intel_pt_insn *intel_pt_insn); 55 + 56 + const char *intel_pt_insn_name(enum intel_pt_insn_op op); 57 + 58 + int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf, 59 + size_t buf_len); 60 + 61 + size_t intel_pt_insn_max_size(void); 62 + 63 + int intel_pt_insn_type(enum intel_pt_insn_op op); 64 + 65 + #endif
+970
tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
··· 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 + 32 + Table: one byte opcode 33 + Referrer: 34 + AVXcode: 35 + # 0x00 - 0x0f 36 + 00: ADD Eb,Gb 37 + 01: ADD Ev,Gv 38 + 02: ADD Gb,Eb 39 + 03: ADD Gv,Ev 40 + 04: ADD AL,Ib 41 + 05: ADD rAX,Iz 42 + 06: PUSH ES (i64) 43 + 07: POP ES (i64) 44 + 08: OR Eb,Gb 45 + 09: OR Ev,Gv 46 + 0a: OR Gb,Eb 47 + 0b: OR Gv,Ev 48 + 0c: OR AL,Ib 49 + 0d: OR rAX,Iz 50 + 0e: PUSH CS (i64) 51 + 0f: escape # 2-byte escape 52 + # 0x10 - 0x1f 53 + 10: ADC Eb,Gb 54 + 11: ADC Ev,Gv 55 + 12: ADC Gb,Eb 56 + 13: ADC Gv,Ev 57 + 14: ADC AL,Ib 58 + 15: ADC rAX,Iz 59 + 16: PUSH SS (i64) 60 + 17: POP SS (i64) 61 + 18: SBB Eb,Gb 62 + 19: SBB Ev,Gv 63 + 1a: SBB Gb,Eb 64 + 1b: SBB Gv,Ev 65 + 1c: SBB AL,Ib 66 + 1d: SBB rAX,Iz 67 + 1e: PUSH DS (i64) 68 + 1f: POP DS (i64) 69 + # 0x20 - 0x2f 70 + 20: AND Eb,Gb 71 + 21: AND Ev,Gv 72 + 22: AND Gb,Eb 73 + 23: AND Gv,Ev 74 + 24: AND AL,Ib 75 + 25: AND rAx,Iz 76 + 26: SEG=ES (Prefix) 77 + 27: DAA (i64) 78 + 28: SUB Eb,Gb 79 + 29: SUB Ev,Gv 80 + 2a: SUB Gb,Eb 81 + 2b: SUB Gv,Ev 82 + 2c: SUB AL,Ib 83 + 2d: SUB rAX,Iz 84 + 2e: SEG=CS (Prefix) 85 + 2f: DAS (i64) 86 + # 0x30 - 0x3f 87 + 30: XOR Eb,Gb 88 + 31: XOR Ev,Gv 89 + 32: XOR Gb,Eb 90 + 33: XOR Gv,Ev 91 + 34: XOR AL,Ib 92 + 35: XOR rAX,Iz 93 + 36: SEG=SS (Prefix) 94 + 37: AAA (i64) 95 + 38: CMP Eb,Gb 96 + 39: CMP Ev,Gv 97 + 3a: CMP Gb,Eb 98 + 3b: CMP Gv,Ev 99 + 3c: CMP AL,Ib 100 + 3d: CMP rAX,Iz 101 + 3e: SEG=DS (Prefix) 102 + 3f: AAS (i64) 103 + # 0x40 - 0x4f 104 + 40: INC eAX (i64) | REX (o64) 105 + 41: INC eCX (i64) | REX.B (o64) 106 + 42: INC eDX (i64) | REX.X (o64) 107 + 43: INC eBX (i64) | REX.XB (o64) 108 + 44: INC eSP (i64) | REX.R (o64) 109 + 45: INC eBP (i64) | REX.RB (o64) 110 + 46: INC eSI (i64) | REX.RX (o64) 111 + 47: INC eDI (i64) | REX.RXB (o64) 112 + 48: DEC eAX (i64) | REX.W (o64) 113 + 49: DEC eCX (i64) | REX.WB (o64) 114 + 4a: DEC eDX (i64) | REX.WX (o64) 115 + 4b: DEC eBX (i64) | REX.WXB (o64) 116 + 4c: DEC eSP (i64) | REX.WR (o64) 117 + 4d: DEC eBP (i64) | REX.WRB (o64) 118 + 4e: DEC eSI (i64) | REX.WRX (o64) 119 + 4f: DEC eDI (i64) | REX.WRXB (o64) 120 + # 0x50 - 0x5f 121 + 50: PUSH rAX/r8 (d64) 122 + 51: PUSH rCX/r9 (d64) 123 + 52: PUSH rDX/r10 (d64) 124 + 53: PUSH rBX/r11 (d64) 125 + 54: PUSH rSP/r12 (d64) 126 + 55: PUSH rBP/r13 (d64) 127 + 56: PUSH rSI/r14 (d64) 128 + 57: PUSH rDI/r15 (d64) 129 + 58: POP rAX/r8 (d64) 130 + 59: POP rCX/r9 (d64) 131 + 5a: POP rDX/r10 (d64) 132 + 5b: POP rBX/r11 (d64) 133 + 5c: POP rSP/r12 (d64) 134 + 5d: POP rBP/r13 (d64) 135 + 5e: POP rSI/r14 (d64) 136 + 5f: POP rDI/r15 (d64) 137 + # 0x60 - 0x6f 138 + 60: PUSHA/PUSHAD (i64) 139 + 61: POPA/POPAD (i64) 140 + 62: BOUND Gv,Ma (i64) 141 + 63: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64) 142 + 64: SEG=FS (Prefix) 143 + 65: SEG=GS (Prefix) 144 + 66: Operand-Size (Prefix) 145 + 67: Address-Size (Prefix) 146 + 68: PUSH Iz (d64) 147 + 69: IMUL Gv,Ev,Iz 148 + 6a: PUSH Ib (d64) 149 + 6b: IMUL Gv,Ev,Ib 150 + 6c: INS/INSB Yb,DX 151 + 6d: INS/INSW/INSD Yz,DX 152 + 6e: OUTS/OUTSB DX,Xb 153 + 6f: OUTS/OUTSW/OUTSD DX,Xz 154 + # 0x70 - 0x7f 155 + 70: JO Jb 156 + 71: JNO Jb 157 + 72: JB/JNAE/JC Jb 158 + 73: JNB/JAE/JNC Jb 159 + 74: JZ/JE Jb 160 + 75: JNZ/JNE Jb 161 + 76: JBE/JNA Jb 162 + 77: JNBE/JA Jb 163 + 78: JS Jb 164 + 79: JNS Jb 165 + 7a: JP/JPE Jb 166 + 7b: JNP/JPO Jb 167 + 7c: JL/JNGE Jb 168 + 7d: JNL/JGE Jb 169 + 7e: JLE/JNG Jb 170 + 7f: JNLE/JG Jb 171 + # 0x80 - 0x8f 172 + 80: Grp1 Eb,Ib (1A) 173 + 81: Grp1 Ev,Iz (1A) 174 + 82: Grp1 Eb,Ib (1A),(i64) 175 + 83: Grp1 Ev,Ib (1A) 176 + 84: TEST Eb,Gb 177 + 85: TEST Ev,Gv 178 + 86: XCHG Eb,Gb 179 + 87: XCHG Ev,Gv 180 + 88: MOV Eb,Gb 181 + 89: MOV Ev,Gv 182 + 8a: MOV Gb,Eb 183 + 8b: MOV Gv,Ev 184 + 8c: MOV Ev,Sw 185 + 8d: LEA Gv,M 186 + 8e: MOV Sw,Ew 187 + 8f: Grp1A (1A) | POP Ev (d64) 188 + # 0x90 - 0x9f 189 + 90: NOP | PAUSE (F3) | XCHG r8,rAX 190 + 91: XCHG rCX/r9,rAX 191 + 92: XCHG rDX/r10,rAX 192 + 93: XCHG rBX/r11,rAX 193 + 94: XCHG rSP/r12,rAX 194 + 95: XCHG rBP/r13,rAX 195 + 96: XCHG rSI/r14,rAX 196 + 97: XCHG rDI/r15,rAX 197 + 98: CBW/CWDE/CDQE 198 + 99: CWD/CDQ/CQO 199 + 9a: CALLF Ap (i64) 200 + 9b: FWAIT/WAIT 201 + 9c: PUSHF/D/Q Fv (d64) 202 + 9d: POPF/D/Q Fv (d64) 203 + 9e: SAHF 204 + 9f: LAHF 205 + # 0xa0 - 0xaf 206 + a0: MOV AL,Ob 207 + a1: MOV rAX,Ov 208 + a2: MOV Ob,AL 209 + a3: MOV Ov,rAX 210 + a4: MOVS/B Yb,Xb 211 + a5: MOVS/W/D/Q Yv,Xv 212 + a6: CMPS/B Xb,Yb 213 + a7: CMPS/W/D Xv,Yv 214 + a8: TEST AL,Ib 215 + a9: TEST rAX,Iz 216 + aa: STOS/B Yb,AL 217 + ab: STOS/W/D/Q Yv,rAX 218 + ac: LODS/B AL,Xb 219 + ad: LODS/W/D/Q rAX,Xv 220 + ae: 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 223 + af: SCAS/W/D/Q rAX,Yv 224 + # 0xb0 - 0xbf 225 + b0: MOV AL/R8L,Ib 226 + b1: MOV CL/R9L,Ib 227 + b2: MOV DL/R10L,Ib 228 + b3: MOV BL/R11L,Ib 229 + b4: MOV AH/R12L,Ib 230 + b5: MOV CH/R13L,Ib 231 + b6: MOV DH/R14L,Ib 232 + b7: MOV BH/R15L,Ib 233 + b8: MOV rAX/r8,Iv 234 + b9: MOV rCX/r9,Iv 235 + ba: MOV rDX/r10,Iv 236 + bb: MOV rBX/r11,Iv 237 + bc: MOV rSP/r12,Iv 238 + bd: MOV rBP/r13,Iv 239 + be: MOV rSI/r14,Iv 240 + bf: MOV rDI/r15,Iv 241 + # 0xc0 - 0xcf 242 + c0: Grp2 Eb,Ib (1A) 243 + c1: Grp2 Ev,Ib (1A) 244 + c2: RETN Iw (f64) 245 + c3: RETN 246 + c4: LES Gz,Mp (i64) | VEX+2byte (Prefix) 247 + c5: LDS Gz,Mp (i64) | VEX+1byte (Prefix) 248 + c6: Grp11A Eb,Ib (1A) 249 + c7: Grp11B Ev,Iz (1A) 250 + c8: ENTER Iw,Ib 251 + c9: LEAVE (d64) 252 + ca: RETF Iw 253 + cb: RETF 254 + cc: INT3 255 + cd: INT Ib 256 + ce: INTO (i64) 257 + cf: IRET/D/Q 258 + # 0xd0 - 0xdf 259 + d0: Grp2 Eb,1 (1A) 260 + d1: Grp2 Ev,1 (1A) 261 + d2: Grp2 Eb,CL (1A) 262 + d3: Grp2 Ev,CL (1A) 263 + d4: AAM Ib (i64) 264 + d5: AAD Ib (i64) 265 + d6: 266 + d7: XLAT/XLATB 267 + d8: ESC 268 + d9: ESC 269 + da: ESC 270 + db: ESC 271 + dc: ESC 272 + dd: ESC 273 + de: ESC 274 + df: 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. 279 + e0: LOOPNE/LOOPNZ Jb (f64) 280 + e1: LOOPE/LOOPZ Jb (f64) 281 + e2: LOOP Jb (f64) 282 + e3: JrCXZ Jb (f64) 283 + e4: IN AL,Ib 284 + e5: IN eAX,Ib 285 + e6: OUT Ib,AL 286 + e7: 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. 291 + e8: CALL Jz (f64) 292 + e9: JMP-near Jz (f64) 293 + ea: JMP-far Ap (i64) 294 + eb: JMP-short Jb (f64) 295 + ec: IN AL,DX 296 + ed: IN eAX,DX 297 + ee: OUT DX,AL 298 + ef: OUT DX,eAX 299 + # 0xf0 - 0xff 300 + f0: LOCK (Prefix) 301 + f1: 302 + f2: REPNE (Prefix) | XACQUIRE (Prefix) 303 + f3: REP/REPE (Prefix) | XRELEASE (Prefix) 304 + f4: HLT 305 + f5: CMC 306 + f6: Grp3_1 Eb (1A) 307 + f7: Grp3_2 Ev (1A) 308 + f8: CLC 309 + f9: STC 310 + fa: CLI 311 + fb: STI 312 + fc: CLD 313 + fd: STD 314 + fe: Grp4 (1A) 315 + ff: Grp5 (1A) 316 + EndTable 317 + 318 + Table: 2-byte opcode (0x0f) 319 + Referrer: 2-byte escape 320 + AVXcode: 1 321 + # 0x0f 0x00-0x0f 322 + 00: Grp6 (1A) 323 + 01: Grp7 (1A) 324 + 02: LAR Gv,Ew 325 + 03: LSL Gv,Ew 326 + 04: 327 + 05: SYSCALL (o64) 328 + 06: CLTS 329 + 07: SYSRET (o64) 330 + 08: INVD 331 + 09: WBINVD 332 + 0a: 333 + 0b: UD2 (1B) 334 + 0c: 335 + # AMD's prefetch group. Intel supports prefetchw(/1) only. 336 + 0d: GrpP 337 + 0e: FEMMS 338 + # 3DNow! uses the last imm byte as opcode extension. 339 + 0f: 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 346 + 10: vmovups Vps,Wps | vmovupd Vpd,Wpd (66) | vmovss Vx,Hx,Wss (F3),(v1) | vmovsd Vx,Hx,Wsd (F2),(v1) 347 + 11: vmovups Wps,Vps | vmovupd Wpd,Vpd (66) | vmovss Wss,Hx,Vss (F3),(v1) | vmovsd Wsd,Hx,Vsd (F2),(v1) 348 + 12: vmovlps Vq,Hq,Mq (v1) | vmovhlps Vq,Hq,Uq (v1) | vmovlpd Vq,Hq,Mq (66),(v1) | vmovsldup Vx,Wx (F3) | vmovddup Vx,Wx (F2) 349 + 13: vmovlps Mq,Vq (v1) | vmovlpd Mq,Vq (66),(v1) 350 + 14: vunpcklps Vx,Hx,Wx | vunpcklpd Vx,Hx,Wx (66) 351 + 15: vunpckhps Vx,Hx,Wx | vunpckhpd Vx,Hx,Wx (66) 352 + 16: vmovhps Vdq,Hq,Mq (v1) | vmovlhps Vdq,Hq,Uq (v1) | vmovhpd Vdq,Hq,Mq (66),(v1) | vmovshdup Vx,Wx (F3) 353 + 17: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1) 354 + 18: Grp16 (1A) 355 + 19: 356 + 1a: BNDCL Ev,Gv | BNDCU Ev,Gv | BNDMOV Gv,Ev | BNDLDX Gv,Ev,Gv 357 + 1b: BNDCN Ev,Gv | BNDMOV Ev,Gv | BNDMK Gv,Ev | BNDSTX Ev,GV,Gv 358 + 1c: 359 + 1d: 360 + 1e: 361 + 1f: NOP Ev 362 + # 0x0f 0x20-0x2f 363 + 20: MOV Rd,Cd 364 + 21: MOV Rd,Dd 365 + 22: MOV Cd,Rd 366 + 23: MOV Dd,Rd 367 + 24: 368 + 25: 369 + 26: 370 + 27: 371 + 28: vmovaps Vps,Wps | vmovapd Vpd,Wpd (66) 372 + 29: vmovaps Wps,Vps | vmovapd Wpd,Vpd (66) 373 + 2a: cvtpi2ps Vps,Qpi | cvtpi2pd Vpd,Qpi (66) | vcvtsi2ss Vss,Hss,Ey (F3),(v1) | vcvtsi2sd Vsd,Hsd,Ey (F2),(v1) 374 + 2b: vmovntps Mps,Vps | vmovntpd Mpd,Vpd (66) 375 + 2c: cvttps2pi Ppi,Wps | cvttpd2pi Ppi,Wpd (66) | vcvttss2si Gy,Wss (F3),(v1) | vcvttsd2si Gy,Wsd (F2),(v1) 376 + 2d: cvtps2pi Ppi,Wps | cvtpd2pi Qpi,Wpd (66) | vcvtss2si Gy,Wss (F3),(v1) | vcvtsd2si Gy,Wsd (F2),(v1) 377 + 2e: vucomiss Vss,Wss (v1) | vucomisd Vsd,Wsd (66),(v1) 378 + 2f: vcomiss Vss,Wss (v1) | vcomisd Vsd,Wsd (66),(v1) 379 + # 0x0f 0x30-0x3f 380 + 30: WRMSR 381 + 31: RDTSC 382 + 32: RDMSR 383 + 33: RDPMC 384 + 34: SYSENTER 385 + 35: SYSEXIT 386 + 36: 387 + 37: GETSEC 388 + 38: escape # 3-byte escape 1 389 + 39: 390 + 3a: escape # 3-byte escape 2 391 + 3b: 392 + 3c: 393 + 3d: 394 + 3e: 395 + 3f: 396 + # 0x0f 0x40-0x4f 397 + 40: CMOVO Gv,Ev 398 + 41: CMOVNO Gv,Ev 399 + 42: CMOVB/C/NAE Gv,Ev 400 + 43: CMOVAE/NB/NC Gv,Ev 401 + 44: CMOVE/Z Gv,Ev 402 + 45: CMOVNE/NZ Gv,Ev 403 + 46: CMOVBE/NA Gv,Ev 404 + 47: CMOVA/NBE Gv,Ev 405 + 48: CMOVS Gv,Ev 406 + 49: CMOVNS Gv,Ev 407 + 4a: CMOVP/PE Gv,Ev 408 + 4b: CMOVNP/PO Gv,Ev 409 + 4c: CMOVL/NGE Gv,Ev 410 + 4d: CMOVNL/GE Gv,Ev 411 + 4e: CMOVLE/NG Gv,Ev 412 + 4f: CMOVNLE/G Gv,Ev 413 + # 0x0f 0x50-0x5f 414 + 50: vmovmskps Gy,Ups | vmovmskpd Gy,Upd (66) 415 + 51: vsqrtps Vps,Wps | vsqrtpd Vpd,Wpd (66) | vsqrtss Vss,Hss,Wss (F3),(v1) | vsqrtsd Vsd,Hsd,Wsd (F2),(v1) 416 + 52: vrsqrtps Vps,Wps | vrsqrtss Vss,Hss,Wss (F3),(v1) 417 + 53: vrcpps Vps,Wps | vrcpss Vss,Hss,Wss (F3),(v1) 418 + 54: vandps Vps,Hps,Wps | vandpd Vpd,Hpd,Wpd (66) 419 + 55: vandnps Vps,Hps,Wps | vandnpd Vpd,Hpd,Wpd (66) 420 + 56: vorps Vps,Hps,Wps | vorpd Vpd,Hpd,Wpd (66) 421 + 57: vxorps Vps,Hps,Wps | vxorpd Vpd,Hpd,Wpd (66) 422 + 58: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1) 423 + 59: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1) 424 + 5a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1) 425 + 5b: vcvtdq2ps Vps,Wdq | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3) 426 + 5c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1) 427 + 5d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1) 428 + 5e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1) 429 + 5f: 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 431 + 60: punpcklbw Pq,Qd | vpunpcklbw Vx,Hx,Wx (66),(v1) 432 + 61: punpcklwd Pq,Qd | vpunpcklwd Vx,Hx,Wx (66),(v1) 433 + 62: punpckldq Pq,Qd | vpunpckldq Vx,Hx,Wx (66),(v1) 434 + 63: packsswb Pq,Qq | vpacksswb Vx,Hx,Wx (66),(v1) 435 + 64: pcmpgtb Pq,Qq | vpcmpgtb Vx,Hx,Wx (66),(v1) 436 + 65: pcmpgtw Pq,Qq | vpcmpgtw Vx,Hx,Wx (66),(v1) 437 + 66: pcmpgtd Pq,Qq | vpcmpgtd Vx,Hx,Wx (66),(v1) 438 + 67: packuswb Pq,Qq | vpackuswb Vx,Hx,Wx (66),(v1) 439 + 68: punpckhbw Pq,Qd | vpunpckhbw Vx,Hx,Wx (66),(v1) 440 + 69: punpckhwd Pq,Qd | vpunpckhwd Vx,Hx,Wx (66),(v1) 441 + 6a: punpckhdq Pq,Qd | vpunpckhdq Vx,Hx,Wx (66),(v1) 442 + 6b: packssdw Pq,Qd | vpackssdw Vx,Hx,Wx (66),(v1) 443 + 6c: vpunpcklqdq Vx,Hx,Wx (66),(v1) 444 + 6d: vpunpckhqdq Vx,Hx,Wx (66),(v1) 445 + 6e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1) 446 + 6f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqu Vx,Wx (F3) 447 + # 0x0f 0x70-0x7f 448 + 70: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1) 449 + 71: Grp12 (1A) 450 + 72: Grp13 (1A) 451 + 73: Grp14 (1A) 452 + 74: pcmpeqb Pq,Qq | vpcmpeqb Vx,Hx,Wx (66),(v1) 453 + 75: pcmpeqw Pq,Qq | vpcmpeqw Vx,Hx,Wx (66),(v1) 454 + 76: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1) 455 + # Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX. 456 + 77: emms | vzeroupper | vzeroall 457 + 78: VMREAD Ey,Gy 458 + 79: VMWRITE Gy,Ey 459 + 7a: 460 + 7b: 461 + 7c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2) 462 + 7d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2) 463 + 7e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1) 464 + 7f: 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). 467 + 80: JO Jz (f64) 468 + 81: JNO Jz (f64) 469 + 82: JB/JC/JNAE Jz (f64) 470 + 83: JAE/JNB/JNC Jz (f64) 471 + 84: JE/JZ Jz (f64) 472 + 85: JNE/JNZ Jz (f64) 473 + 86: JBE/JNA Jz (f64) 474 + 87: JA/JNBE Jz (f64) 475 + 88: JS Jz (f64) 476 + 89: JNS Jz (f64) 477 + 8a: JP/JPE Jz (f64) 478 + 8b: JNP/JPO Jz (f64) 479 + 8c: JL/JNGE Jz (f64) 480 + 8d: JNL/JGE Jz (f64) 481 + 8e: JLE/JNG Jz (f64) 482 + 8f: JNLE/JG Jz (f64) 483 + # 0x0f 0x90-0x9f 484 + 90: SETO Eb 485 + 91: SETNO Eb 486 + 92: SETB/C/NAE Eb 487 + 93: SETAE/NB/NC Eb 488 + 94: SETE/Z Eb 489 + 95: SETNE/NZ Eb 490 + 96: SETBE/NA Eb 491 + 97: SETA/NBE Eb 492 + 98: SETS Eb 493 + 99: SETNS Eb 494 + 9a: SETP/PE Eb 495 + 9b: SETNP/PO Eb 496 + 9c: SETL/NGE Eb 497 + 9d: SETNL/GE Eb 498 + 9e: SETLE/NG Eb 499 + 9f: SETNLE/G Eb 500 + # 0x0f 0xa0-0xaf 501 + a0: PUSH FS (d64) 502 + a1: POP FS (d64) 503 + a2: CPUID 504 + a3: BT Ev,Gv 505 + a4: SHLD Ev,Gv,Ib 506 + a5: SHLD Ev,Gv,CL 507 + a6: GrpPDLK 508 + a7: GrpRNG 509 + a8: PUSH GS (d64) 510 + a9: POP GS (d64) 511 + aa: RSM 512 + ab: BTS Ev,Gv 513 + ac: SHRD Ev,Gv,Ib 514 + ad: SHRD Ev,Gv,CL 515 + ae: Grp15 (1A),(1C) 516 + af: IMUL Gv,Ev 517 + # 0x0f 0xb0-0xbf 518 + b0: CMPXCHG Eb,Gb 519 + b1: CMPXCHG Ev,Gv 520 + b2: LSS Gv,Mp 521 + b3: BTR Ev,Gv 522 + b4: LFS Gv,Mp 523 + b5: LGS Gv,Mp 524 + b6: MOVZX Gv,Eb 525 + b7: MOVZX Gv,Ew 526 + b8: JMPE (!F3) | POPCNT Gv,Ev (F3) 527 + b9: Grp10 (1A) 528 + ba: Grp8 Ev,Ib (1A) 529 + bb: BTC Ev,Gv 530 + bc: BSF Gv,Ev (!F3) | TZCNT Gv,Ev (F3) 531 + bd: BSR Gv,Ev (!F3) | LZCNT Gv,Ev (F3) 532 + be: MOVSX Gv,Eb 533 + bf: MOVSX Gv,Ew 534 + # 0x0f 0xc0-0xcf 535 + c0: XADD Eb,Gb 536 + c1: XADD Ev,Gv 537 + c2: 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) 538 + c3: movnti My,Gy 539 + c4: pinsrw Pq,Ry/Mw,Ib | vpinsrw Vdq,Hdq,Ry/Mw,Ib (66),(v1) 540 + c5: pextrw Gd,Nq,Ib | vpextrw Gd,Udq,Ib (66),(v1) 541 + c6: vshufps Vps,Hps,Wps,Ib | vshufpd Vpd,Hpd,Wpd,Ib (66) 542 + c7: Grp9 (1A) 543 + c8: BSWAP RAX/EAX/R8/R8D 544 + c9: BSWAP RCX/ECX/R9/R9D 545 + ca: BSWAP RDX/EDX/R10/R10D 546 + cb: BSWAP RBX/EBX/R11/R11D 547 + cc: BSWAP RSP/ESP/R12/R12D 548 + cd: BSWAP RBP/EBP/R13/R13D 549 + ce: BSWAP RSI/ESI/R14/R14D 550 + cf: BSWAP RDI/EDI/R15/R15D 551 + # 0x0f 0xd0-0xdf 552 + d0: vaddsubpd Vpd,Hpd,Wpd (66) | vaddsubps Vps,Hps,Wps (F2) 553 + d1: psrlw Pq,Qq | vpsrlw Vx,Hx,Wx (66),(v1) 554 + d2: psrld Pq,Qq | vpsrld Vx,Hx,Wx (66),(v1) 555 + d3: psrlq Pq,Qq | vpsrlq Vx,Hx,Wx (66),(v1) 556 + d4: paddq Pq,Qq | vpaddq Vx,Hx,Wx (66),(v1) 557 + d5: pmullw Pq,Qq | vpmullw Vx,Hx,Wx (66),(v1) 558 + d6: vmovq Wq,Vq (66),(v1) | movq2dq Vdq,Nq (F3) | movdq2q Pq,Uq (F2) 559 + d7: pmovmskb Gd,Nq | vpmovmskb Gd,Ux (66),(v1) 560 + d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1) 561 + d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1) 562 + da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1) 563 + db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1) 564 + dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1) 565 + dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1) 566 + de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1) 567 + df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1) 568 + # 0x0f 0xe0-0xef 569 + e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1) 570 + e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1) 571 + e2: psrad Pq,Qq | vpsrad Vx,Hx,Wx (66),(v1) 572 + e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1) 573 + e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1) 574 + e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1) 575 + e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtpd2dq Vx,Wpd (F2) 576 + e7: movntq Mq,Pq | vmovntdq Mx,Vx (66) 577 + e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1) 578 + e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1) 579 + ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1) 580 + eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1) 581 + ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1) 582 + ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1) 583 + ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1) 584 + ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1) 585 + # 0x0f 0xf0-0xff 586 + f0: vlddqu Vx,Mx (F2) 587 + f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1) 588 + f2: pslld Pq,Qq | vpslld Vx,Hx,Wx (66),(v1) 589 + f3: psllq Pq,Qq | vpsllq Vx,Hx,Wx (66),(v1) 590 + f4: pmuludq Pq,Qq | vpmuludq Vx,Hx,Wx (66),(v1) 591 + f5: pmaddwd Pq,Qq | vpmaddwd Vx,Hx,Wx (66),(v1) 592 + f6: psadbw Pq,Qq | vpsadbw Vx,Hx,Wx (66),(v1) 593 + f7: maskmovq Pq,Nq | vmaskmovdqu Vx,Ux (66),(v1) 594 + f8: psubb Pq,Qq | vpsubb Vx,Hx,Wx (66),(v1) 595 + f9: psubw Pq,Qq | vpsubw Vx,Hx,Wx (66),(v1) 596 + fa: psubd Pq,Qq | vpsubd Vx,Hx,Wx (66),(v1) 597 + fb: psubq Pq,Qq | vpsubq Vx,Hx,Wx (66),(v1) 598 + fc: paddb Pq,Qq | vpaddb Vx,Hx,Wx (66),(v1) 599 + fd: paddw Pq,Qq | vpaddw Vx,Hx,Wx (66),(v1) 600 + fe: paddd Pq,Qq | vpaddd Vx,Hx,Wx (66),(v1) 601 + ff: 602 + EndTable 603 + 604 + Table: 3-byte opcode 1 (0x0f 0x38) 605 + Referrer: 3-byte escape 1 606 + AVXcode: 2 607 + # 0x0f 0x38 0x00-0x0f 608 + 00: pshufb Pq,Qq | vpshufb Vx,Hx,Wx (66),(v1) 609 + 01: phaddw Pq,Qq | vphaddw Vx,Hx,Wx (66),(v1) 610 + 02: phaddd Pq,Qq | vphaddd Vx,Hx,Wx (66),(v1) 611 + 03: phaddsw Pq,Qq | vphaddsw Vx,Hx,Wx (66),(v1) 612 + 04: pmaddubsw Pq,Qq | vpmaddubsw Vx,Hx,Wx (66),(v1) 613 + 05: phsubw Pq,Qq | vphsubw Vx,Hx,Wx (66),(v1) 614 + 06: phsubd Pq,Qq | vphsubd Vx,Hx,Wx (66),(v1) 615 + 07: phsubsw Pq,Qq | vphsubsw Vx,Hx,Wx (66),(v1) 616 + 08: psignb Pq,Qq | vpsignb Vx,Hx,Wx (66),(v1) 617 + 09: psignw Pq,Qq | vpsignw Vx,Hx,Wx (66),(v1) 618 + 0a: psignd Pq,Qq | vpsignd Vx,Hx,Wx (66),(v1) 619 + 0b: pmulhrsw Pq,Qq | vpmulhrsw Vx,Hx,Wx (66),(v1) 620 + 0c: vpermilps Vx,Hx,Wx (66),(v) 621 + 0d: vpermilpd Vx,Hx,Wx (66),(v) 622 + 0e: vtestps Vx,Wx (66),(v) 623 + 0f: vtestpd Vx,Wx (66),(v) 624 + # 0x0f 0x38 0x10-0x1f 625 + 10: pblendvb Vdq,Wdq (66) 626 + 11: 627 + 12: 628 + 13: vcvtph2ps Vx,Wx,Ib (66),(v) 629 + 14: blendvps Vdq,Wdq (66) 630 + 15: blendvpd Vdq,Wdq (66) 631 + 16: vpermps Vqq,Hqq,Wqq (66),(v) 632 + 17: vptest Vx,Wx (66) 633 + 18: vbroadcastss Vx,Wd (66),(v) 634 + 19: vbroadcastsd Vqq,Wq (66),(v) 635 + 1a: vbroadcastf128 Vqq,Mdq (66),(v) 636 + 1b: 637 + 1c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1) 638 + 1d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1) 639 + 1e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1) 640 + 1f: 641 + # 0x0f 0x38 0x20-0x2f 642 + 20: vpmovsxbw Vx,Ux/Mq (66),(v1) 643 + 21: vpmovsxbd Vx,Ux/Md (66),(v1) 644 + 22: vpmovsxbq Vx,Ux/Mw (66),(v1) 645 + 23: vpmovsxwd Vx,Ux/Mq (66),(v1) 646 + 24: vpmovsxwq Vx,Ux/Md (66),(v1) 647 + 25: vpmovsxdq Vx,Ux/Mq (66),(v1) 648 + 26: 649 + 27: 650 + 28: vpmuldq Vx,Hx,Wx (66),(v1) 651 + 29: vpcmpeqq Vx,Hx,Wx (66),(v1) 652 + 2a: vmovntdqa Vx,Mx (66),(v1) 653 + 2b: vpackusdw Vx,Hx,Wx (66),(v1) 654 + 2c: vmaskmovps Vx,Hx,Mx (66),(v) 655 + 2d: vmaskmovpd Vx,Hx,Mx (66),(v) 656 + 2e: vmaskmovps Mx,Hx,Vx (66),(v) 657 + 2f: vmaskmovpd Mx,Hx,Vx (66),(v) 658 + # 0x0f 0x38 0x30-0x3f 659 + 30: vpmovzxbw Vx,Ux/Mq (66),(v1) 660 + 31: vpmovzxbd Vx,Ux/Md (66),(v1) 661 + 32: vpmovzxbq Vx,Ux/Mw (66),(v1) 662 + 33: vpmovzxwd Vx,Ux/Mq (66),(v1) 663 + 34: vpmovzxwq Vx,Ux/Md (66),(v1) 664 + 35: vpmovzxdq Vx,Ux/Mq (66),(v1) 665 + 36: vpermd Vqq,Hqq,Wqq (66),(v) 666 + 37: vpcmpgtq Vx,Hx,Wx (66),(v1) 667 + 38: vpminsb Vx,Hx,Wx (66),(v1) 668 + 39: vpminsd Vx,Hx,Wx (66),(v1) 669 + 3a: vpminuw Vx,Hx,Wx (66),(v1) 670 + 3b: vpminud Vx,Hx,Wx (66),(v1) 671 + 3c: vpmaxsb Vx,Hx,Wx (66),(v1) 672 + 3d: vpmaxsd Vx,Hx,Wx (66),(v1) 673 + 3e: vpmaxuw Vx,Hx,Wx (66),(v1) 674 + 3f: vpmaxud Vx,Hx,Wx (66),(v1) 675 + # 0x0f 0x38 0x40-0x8f 676 + 40: vpmulld Vx,Hx,Wx (66),(v1) 677 + 41: vphminposuw Vdq,Wdq (66),(v1) 678 + 42: 679 + 43: 680 + 44: 681 + 45: vpsrlvd/q Vx,Hx,Wx (66),(v) 682 + 46: vpsravd Vx,Hx,Wx (66),(v) 683 + 47: vpsllvd/q Vx,Hx,Wx (66),(v) 684 + # Skip 0x48-0x57 685 + 58: vpbroadcastd Vx,Wx (66),(v) 686 + 59: vpbroadcastq Vx,Wx (66),(v) 687 + 5a: vbroadcasti128 Vqq,Mdq (66),(v) 688 + # Skip 0x5b-0x77 689 + 78: vpbroadcastb Vx,Wx (66),(v) 690 + 79: vpbroadcastw Vx,Wx (66),(v) 691 + # Skip 0x7a-0x7f 692 + 80: INVEPT Gy,Mdq (66) 693 + 81: INVPID Gy,Mdq (66) 694 + 82: INVPCID Gy,Mdq (66) 695 + 8c: vpmaskmovd/q Vx,Hx,Mx (66),(v) 696 + 8e: vpmaskmovd/q Mx,Vx,Hx (66),(v) 697 + # 0x0f 0x38 0x90-0xbf (FMA) 698 + 90: vgatherdd/q Vx,Hx,Wx (66),(v) 699 + 91: vgatherqd/q Vx,Hx,Wx (66),(v) 700 + 92: vgatherdps/d Vx,Hx,Wx (66),(v) 701 + 93: vgatherqps/d Vx,Hx,Wx (66),(v) 702 + 94: 703 + 95: 704 + 96: vfmaddsub132ps/d Vx,Hx,Wx (66),(v) 705 + 97: vfmsubadd132ps/d Vx,Hx,Wx (66),(v) 706 + 98: vfmadd132ps/d Vx,Hx,Wx (66),(v) 707 + 99: vfmadd132ss/d Vx,Hx,Wx (66),(v),(v1) 708 + 9a: vfmsub132ps/d Vx,Hx,Wx (66),(v) 709 + 9b: vfmsub132ss/d Vx,Hx,Wx (66),(v),(v1) 710 + 9c: vfnmadd132ps/d Vx,Hx,Wx (66),(v) 711 + 9d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1) 712 + 9e: vfnmsub132ps/d Vx,Hx,Wx (66),(v) 713 + 9f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1) 714 + a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v) 715 + a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v) 716 + a8: vfmadd213ps/d Vx,Hx,Wx (66),(v) 717 + a9: vfmadd213ss/d Vx,Hx,Wx (66),(v),(v1) 718 + aa: vfmsub213ps/d Vx,Hx,Wx (66),(v) 719 + ab: vfmsub213ss/d Vx,Hx,Wx (66),(v),(v1) 720 + ac: vfnmadd213ps/d Vx,Hx,Wx (66),(v) 721 + ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1) 722 + ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v) 723 + af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1) 724 + b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v) 725 + b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v) 726 + b8: vfmadd231ps/d Vx,Hx,Wx (66),(v) 727 + b9: vfmadd231ss/d Vx,Hx,Wx (66),(v),(v1) 728 + ba: vfmsub231ps/d Vx,Hx,Wx (66),(v) 729 + bb: vfmsub231ss/d Vx,Hx,Wx (66),(v),(v1) 730 + bc: vfnmadd231ps/d Vx,Hx,Wx (66),(v) 731 + bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1) 732 + be: vfnmsub231ps/d Vx,Hx,Wx (66),(v) 733 + bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1) 734 + # 0x0f 0x38 0xc0-0xff 735 + db: VAESIMC Vdq,Wdq (66),(v1) 736 + dc: VAESENC Vdq,Hdq,Wdq (66),(v1) 737 + dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1) 738 + de: VAESDEC Vdq,Hdq,Wdq (66),(v1) 739 + df: VAESDECLAST Vdq,Hdq,Wdq (66),(v1) 740 + f0: MOVBE Gy,My | MOVBE Gw,Mw (66) | CRC32 Gd,Eb (F2) | CRC32 Gd,Eb (66&F2) 741 + f1: MOVBE My,Gy | MOVBE Mw,Gw (66) | CRC32 Gd,Ey (F2) | CRC32 Gd,Ew (66&F2) 742 + f2: ANDN Gy,By,Ey (v) 743 + f3: Grp17 (1A) 744 + f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v) 745 + f6: ADCX Gy,Ey (66) | ADOX Gy,Ey (F3) | MULX By,Gy,rDX,Ey (F2),(v) 746 + f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v) 747 + EndTable 748 + 749 + Table: 3-byte opcode 2 (0x0f 0x3a) 750 + Referrer: 3-byte escape 2 751 + AVXcode: 3 752 + # 0x0f 0x3a 0x00-0xff 753 + 00: vpermq Vqq,Wqq,Ib (66),(v) 754 + 01: vpermpd Vqq,Wqq,Ib (66),(v) 755 + 02: vpblendd Vx,Hx,Wx,Ib (66),(v) 756 + 03: 757 + 04: vpermilps Vx,Wx,Ib (66),(v) 758 + 05: vpermilpd Vx,Wx,Ib (66),(v) 759 + 06: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v) 760 + 07: 761 + 08: vroundps Vx,Wx,Ib (66) 762 + 09: vroundpd Vx,Wx,Ib (66) 763 + 0a: vroundss Vss,Wss,Ib (66),(v1) 764 + 0b: vroundsd Vsd,Wsd,Ib (66),(v1) 765 + 0c: vblendps Vx,Hx,Wx,Ib (66) 766 + 0d: vblendpd Vx,Hx,Wx,Ib (66) 767 + 0e: vpblendw Vx,Hx,Wx,Ib (66),(v1) 768 + 0f: palignr Pq,Qq,Ib | vpalignr Vx,Hx,Wx,Ib (66),(v1) 769 + 14: vpextrb Rd/Mb,Vdq,Ib (66),(v1) 770 + 15: vpextrw Rd/Mw,Vdq,Ib (66),(v1) 771 + 16: vpextrd/q Ey,Vdq,Ib (66),(v1) 772 + 17: vextractps Ed,Vdq,Ib (66),(v1) 773 + 18: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v) 774 + 19: vextractf128 Wdq,Vqq,Ib (66),(v) 775 + 1d: vcvtps2ph Wx,Vx,Ib (66),(v) 776 + 20: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1) 777 + 21: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1) 778 + 22: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1) 779 + 38: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v) 780 + 39: vextracti128 Wdq,Vqq,Ib (66),(v) 781 + 40: vdpps Vx,Hx,Wx,Ib (66) 782 + 41: vdppd Vdq,Hdq,Wdq,Ib (66),(v1) 783 + 42: vmpsadbw Vx,Hx,Wx,Ib (66),(v1) 784 + 44: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1) 785 + 46: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v) 786 + 4a: vblendvps Vx,Hx,Wx,Lx (66),(v) 787 + 4b: vblendvpd Vx,Hx,Wx,Lx (66),(v) 788 + 4c: vpblendvb Vx,Hx,Wx,Lx (66),(v1) 789 + 60: vpcmpestrm Vdq,Wdq,Ib (66),(v1) 790 + 61: vpcmpestri Vdq,Wdq,Ib (66),(v1) 791 + 62: vpcmpistrm Vdq,Wdq,Ib (66),(v1) 792 + 63: vpcmpistri Vdq,Wdq,Ib (66),(v1) 793 + df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1) 794 + f0: RORX Gy,Ey,Ib (F2),(v) 795 + EndTable 796 + 797 + GrpTable: Grp1 798 + 0: ADD 799 + 1: OR 800 + 2: ADC 801 + 3: SBB 802 + 4: AND 803 + 5: SUB 804 + 6: XOR 805 + 7: CMP 806 + EndTable 807 + 808 + GrpTable: Grp1A 809 + 0: POP 810 + EndTable 811 + 812 + GrpTable: Grp2 813 + 0: ROL 814 + 1: ROR 815 + 2: RCL 816 + 3: RCR 817 + 4: SHL/SAL 818 + 5: SHR 819 + 6: 820 + 7: SAR 821 + EndTable 822 + 823 + GrpTable: Grp3_1 824 + 0: TEST Eb,Ib 825 + 1: 826 + 2: NOT Eb 827 + 3: NEG Eb 828 + 4: MUL AL,Eb 829 + 5: IMUL AL,Eb 830 + 6: DIV AL,Eb 831 + 7: IDIV AL,Eb 832 + EndTable 833 + 834 + GrpTable: Grp3_2 835 + 0: TEST Ev,Iz 836 + 1: 837 + 2: NOT Ev 838 + 3: NEG Ev 839 + 4: MUL rAX,Ev 840 + 5: IMUL rAX,Ev 841 + 6: DIV rAX,Ev 842 + 7: IDIV rAX,Ev 843 + EndTable 844 + 845 + GrpTable: Grp4 846 + 0: INC Eb 847 + 1: DEC Eb 848 + EndTable 849 + 850 + GrpTable: Grp5 851 + 0: INC Ev 852 + 1: DEC Ev 853 + # Note: "forced64" is Intel CPU behavior (see comment about CALL insn). 854 + 2: CALLN Ev (f64) 855 + 3: CALLF Ep 856 + 4: JMPN Ev (f64) 857 + 5: JMPF Mp 858 + 6: PUSH Ev (d64) 859 + 7: 860 + EndTable 861 + 862 + GrpTable: Grp6 863 + 0: SLDT Rv/Mw 864 + 1: STR Rv/Mw 865 + 2: LLDT Ew 866 + 3: LTR Ew 867 + 4: VERR Ew 868 + 5: VERW Ew 869 + EndTable 870 + 871 + GrpTable: Grp7 872 + 0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B) 873 + 1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B) 874 + 2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B) 875 + 3: LIDT Ms 876 + 4: SMSW Mw/Rv 877 + 5: 878 + 6: LMSW Ew 879 + 7: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B) 880 + EndTable 881 + 882 + GrpTable: Grp8 883 + 4: BT 884 + 5: BTS 885 + 6: BTR 886 + 7: BTC 887 + EndTable 888 + 889 + GrpTable: Grp9 890 + 1: CMPXCHG8B/16B Mq/Mdq 891 + 6: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B) 892 + 7: VMPTRST Mq | VMPTRST Mq (F3) | RDSEED Rv (11B) 893 + EndTable 894 + 895 + GrpTable: Grp10 896 + EndTable 897 + 898 + # Grp11A and Grp11B are expressed as Grp11 in Intel SDM 899 + GrpTable: Grp11A 900 + 0: MOV Eb,Ib 901 + 7: XABORT Ib (000),(11B) 902 + EndTable 903 + 904 + GrpTable: Grp11B 905 + 0: MOV Eb,Iz 906 + 7: XBEGIN Jz (000),(11B) 907 + EndTable 908 + 909 + GrpTable: Grp12 910 + 2: psrlw Nq,Ib (11B) | vpsrlw Hx,Ux,Ib (66),(11B),(v1) 911 + 4: psraw Nq,Ib (11B) | vpsraw Hx,Ux,Ib (66),(11B),(v1) 912 + 6: psllw Nq,Ib (11B) | vpsllw Hx,Ux,Ib (66),(11B),(v1) 913 + EndTable 914 + 915 + GrpTable: Grp13 916 + 2: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1) 917 + 4: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1) 918 + 6: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1) 919 + EndTable 920 + 921 + GrpTable: Grp14 922 + 2: psrlq Nq,Ib (11B) | vpsrlq Hx,Ux,Ib (66),(11B),(v1) 923 + 3: vpsrldq Hx,Ux,Ib (66),(11B),(v1) 924 + 6: psllq Nq,Ib (11B) | vpsllq Hx,Ux,Ib (66),(11B),(v1) 925 + 7: vpslldq Hx,Ux,Ib (66),(11B),(v1) 926 + EndTable 927 + 928 + GrpTable: Grp15 929 + 0: fxsave | RDFSBASE Ry (F3),(11B) 930 + 1: fxstor | RDGSBASE Ry (F3),(11B) 931 + 2: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B) 932 + 3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B) 933 + 4: XSAVE 934 + 5: XRSTOR | lfence (11B) 935 + 6: XSAVEOPT | mfence (11B) 936 + 7: clflush | sfence (11B) 937 + EndTable 938 + 939 + GrpTable: Grp16 940 + 0: prefetch NTA 941 + 1: prefetch T0 942 + 2: prefetch T1 943 + 3: prefetch T2 944 + EndTable 945 + 946 + GrpTable: Grp17 947 + 1: BLSR By,Ey (v) 948 + 2: BLSMSK By,Ey (v) 949 + 3: BLSI By,Ey (v) 950 + EndTable 951 + 952 + # AMD's Prefetch Group 953 + GrpTable: GrpP 954 + 0: PREFETCH 955 + 1: PREFETCHW 956 + EndTable 957 + 958 + GrpTable: GrpPDLK 959 + 0: MONTMUL 960 + 1: XSHA1 961 + 2: XSHA2 962 + EndTable 963 + 964 + GrpTable: GrpRNG 965 + 0: xstore-rng 966 + 1: xcrypt-ecb 967 + 2: xcrypt-cbc 968 + 4: xcrypt-cfb 969 + 5: xcrypt-ofb 970 + EndTable