1179237Sjb/* 2253772Savg * 3179237Sjb * CDDL HEADER START 4179237Sjb * 5179237Sjb * The contents of this file are subject to the terms of the 6179237Sjb * Common Development and Distribution License (the "License"). 7179237Sjb * You may not use this file except in compliance with the License. 8179237Sjb * 9179237Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10179237Sjb * or http://www.opensolaris.org/os/licensing. 11179237Sjb * See the License for the specific language governing permissions 12179237Sjb * and limitations under the License. 13179237Sjb * 14179237Sjb * When distributing Covered Code, include this CDDL HEADER in each 15179237Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16179237Sjb * If applicable, add the following below this CDDL HEADER, with the 17179237Sjb * fields enclosed by brackets "[]" replaced with your own identifying 18179237Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 19179237Sjb * 20179237Sjb * CDDL HEADER END 21179237Sjb */ 22179237Sjb/* 23253772Savg * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 24179237Sjb */ 25179237Sjb 26253772Savg/* 27253772Savg * Copyright (c) 2010, Intel Corporation. 28253772Savg * All rights reserved. 29253772Savg */ 30253772Savg 31179237Sjb/* Copyright (c) 1988 AT&T */ 32179237Sjb/* All Rights Reserved */ 33179237Sjb 34253772Savg/* 35253772Savg * $FreeBSD$ 36253772Savg */ 37179237Sjb 38179237Sjb#include "dis_tables.h" 39179237Sjb 40179237Sjb/* BEGIN CSTYLED */ 41179237Sjb 42179237Sjb/* 43179237Sjb * Disassembly begins in dis_distable, which is equivalent to the One-byte 44179237Sjb * Opcode Map in the Intel IA32 ISA Reference (page A-6 in my copy). The 45179237Sjb * decoding loops then traverse out through the other tables as necessary to 46179237Sjb * decode a given instruction. 47179237Sjb * 48179237Sjb * The behavior of this file can be controlled by one of the following flags: 49179237Sjb * 50179237Sjb * DIS_TEXT Include text for disassembly 51179237Sjb * DIS_MEM Include memory-size calculations 52179237Sjb * 53179237Sjb * Either or both of these can be defined. 54179237Sjb * 55179237Sjb * This file is not, and will never be, cstyled. If anything, the tables should 56179237Sjb * be taken out another tab stop or two so nothing overlaps. 57179237Sjb */ 58179237Sjb 59179237Sjb/* 60179237Sjb * These functions must be provided for the consumer to do disassembly. 61179237Sjb */ 62179237Sjb#ifdef DIS_TEXT 63179237Sjbextern char *strncpy(char *, const char *, size_t); 64179237Sjbextern size_t strlen(const char *); 65179237Sjbextern int strcmp(const char *, const char *); 66179237Sjbextern int strncmp(const char *, const char *, size_t); 67179237Sjbextern size_t strlcat(char *, const char *, size_t); 68179237Sjb#endif 69179237Sjb 70179237Sjb 71253772Savg#define TERM 0 /* used to indicate that the 'indirect' */ 72179237Sjb /* field terminates - no pointer. */ 73179237Sjb 74179237Sjb/* Used to decode instructions. */ 75179237Sjbtypedef struct instable { 76253772Savg struct instable *it_indirect; /* for decode op codes */ 77179237Sjb uchar_t it_adrmode; 78179237Sjb#ifdef DIS_TEXT 79179237Sjb char it_name[NCPS]; 80253772Savg uint_t it_suffix:1; /* mnem + "w", "l", or "d" */ 81179237Sjb#endif 82179237Sjb#ifdef DIS_MEM 83179237Sjb uint_t it_size:16; 84179237Sjb#endif 85179237Sjb uint_t it_invalid64:1; /* opcode invalid in amd64 */ 86179237Sjb uint_t it_always64:1; /* 64 bit when in 64 bit mode */ 87179237Sjb uint_t it_invalid32:1; /* invalid in IA32 */ 88179237Sjb uint_t it_stackop:1; /* push/pop stack operation */ 89179237Sjb} instable_t; 90179237Sjb 91179237Sjb/* 92179237Sjb * Instruction formats. 93179237Sjb */ 94179237Sjbenum { 95179237Sjb UNKNOWN, 96179237Sjb MRw, 97179237Sjb IMlw, 98179237Sjb IMw, 99179237Sjb IR, 100179237Sjb OA, 101179237Sjb AO, 102179237Sjb MS, 103179237Sjb SM, 104179237Sjb Mv, 105179237Sjb Mw, 106179237Sjb M, /* register or memory */ 107179237Sjb Mb, /* register or memory, always byte sized */ 108179237Sjb MO, /* memory only (no registers) */ 109179237Sjb PREF, 110179237Sjb SWAPGS, 111253772Savg MONITOR_MWAIT, 112179237Sjb R, 113179237Sjb RA, 114179237Sjb SEG, 115179237Sjb MR, 116179237Sjb RM, 117179237Sjb IA, 118179237Sjb MA, 119179237Sjb SD, 120179237Sjb AD, 121179237Sjb SA, 122179237Sjb D, 123179237Sjb INM, 124179237Sjb SO, 125179237Sjb BD, 126179237Sjb I, 127179237Sjb P, 128179237Sjb V, 129179237Sjb DSHIFT, /* for double shift that has an 8-bit immediate */ 130179237Sjb U, 131179237Sjb OVERRIDE, 132179237Sjb NORM, /* instructions w/o ModR/M byte, no memory access */ 133179237Sjb IMPLMEM, /* instructions w/o ModR/M byte, implicit mem access */ 134179237Sjb O, /* for call */ 135179237Sjb JTAB, /* jump table */ 136179237Sjb IMUL, /* for 186 iimul instr */ 137179237Sjb CBW, /* so data16 can be evaluated for cbw and variants */ 138179237Sjb MvI, /* for 186 logicals */ 139179237Sjb ENTER, /* for 186 enter instr */ 140179237Sjb RMw, /* for 286 arpl instr */ 141179237Sjb Ib, /* for push immediate byte */ 142179237Sjb F, /* for 287 instructions */ 143179237Sjb FF, /* for 287 instructions */ 144179237Sjb FFC, /* for 287 instructions */ 145179237Sjb DM, /* 16-bit data */ 146179237Sjb AM, /* 16-bit addr */ 147179237Sjb LSEG, /* for 3-bit seg reg encoding */ 148179237Sjb MIb, /* for 386 logicals */ 149179237Sjb SREG, /* for 386 special registers */ 150179237Sjb PREFIX, /* a REP instruction prefix */ 151179237Sjb LOCK, /* a LOCK instruction prefix */ 152179237Sjb INT3, /* The int 3 instruction, which has a fake operand */ 153179237Sjb INTx, /* The normal int instruction, with explicit int num */ 154179237Sjb DSHIFTcl, /* for double shift that implicitly uses %cl */ 155179237Sjb CWD, /* so data16 can be evaluated for cwd and variants */ 156179237Sjb RET, /* single immediate 16-bit operand */ 157179237Sjb MOVZ, /* for movs and movz, with different size operands */ 158253772Savg CRC32, /* for crc32, with different size operands */ 159179237Sjb XADDB, /* for xaddb */ 160179237Sjb MOVSXZ, /* AMD64 mov sign extend 32 to 64 bit instruction */ 161253772Savg MOVBE, /* movbe instruction */ 162179237Sjb 163179237Sjb/* 164179237Sjb * MMX/SIMD addressing modes. 165179237Sjb */ 166179237Sjb 167179237Sjb MMO, /* Prefixable MMX/SIMD-Int mm/mem -> mm */ 168179237Sjb MMOIMPL, /* Prefixable MMX/SIMD-Int mm -> mm (mem) */ 169179237Sjb MMO3P, /* Prefixable MMX/SIMD-Int mm -> r32,imm8 */ 170179237Sjb MMOM3, /* Prefixable MMX/SIMD-Int mm -> r32 */ 171179237Sjb MMOS, /* Prefixable MMX/SIMD-Int mm -> mm/mem */ 172179237Sjb MMOMS, /* Prefixable MMX/SIMD-Int mm -> mem */ 173179237Sjb MMOPM, /* MMX/SIMD-Int mm/mem -> mm,imm8 */ 174253772Savg MMOPM_66o, /* MMX/SIMD-Int 0x66 optional mm/mem -> mm,imm8 */ 175179237Sjb MMOPRM, /* Prefixable MMX/SIMD-Int r32/mem -> mm,imm8 */ 176179237Sjb MMOSH, /* Prefixable MMX mm,imm8 */ 177179237Sjb MM, /* MMX/SIMD-Int mm/mem -> mm */ 178179237Sjb MMS, /* MMX/SIMD-Int mm -> mm/mem */ 179179237Sjb MMSH, /* MMX mm,imm8 */ 180179237Sjb XMMO, /* Prefixable SIMD xmm/mem -> xmm */ 181179237Sjb XMMOS, /* Prefixable SIMD xmm -> xmm/mem */ 182179237Sjb XMMOPM, /* Prefixable SIMD xmm/mem w/to xmm,imm8 */ 183179237Sjb XMMOMX, /* Prefixable SIMD mm/mem -> xmm */ 184179237Sjb XMMOX3, /* Prefixable SIMD xmm -> r32 */ 185179237Sjb XMMOXMM, /* Prefixable SIMD xmm/mem -> mm */ 186179237Sjb XMMOM, /* Prefixable SIMD xmm -> mem */ 187179237Sjb XMMOMS, /* Prefixable SIMD mem -> xmm */ 188179237Sjb XMM, /* SIMD xmm/mem -> xmm */ 189253772Savg XMM_66r, /* SIMD 0x66 prefix required xmm/mem -> xmm */ 190253772Savg XMM_66o, /* SIMD 0x66 prefix optional xmm/mem -> xmm */ 191179237Sjb XMMXIMPL, /* SIMD xmm -> xmm (mem) */ 192179237Sjb XMM3P, /* SIMD xmm -> r32,imm8 */ 193253772Savg XMM3PM_66r, /* SIMD 0x66 prefix required xmm -> r32/mem,imm8 */ 194179237Sjb XMMP, /* SIMD xmm/mem w/to xmm,imm8 */ 195253772Savg XMMP_66o, /* SIMD 0x66 prefix optional xmm/mem w/to xmm,imm8 */ 196253772Savg XMMP_66r, /* SIMD 0x66 prefix required xmm/mem w/to xmm,imm8 */ 197179237Sjb XMMPRM, /* SIMD r32/mem -> xmm,imm8 */ 198253772Savg XMMPRM_66r, /* SIMD 0x66 prefix required r32/mem -> xmm,imm8 */ 199179237Sjb XMMS, /* SIMD xmm -> xmm/mem */ 200179237Sjb XMMM, /* SIMD mem -> xmm */ 201253772Savg XMMM_66r, /* SIMD 0x66 prefix required mem -> xmm */ 202179237Sjb XMMMS, /* SIMD xmm -> mem */ 203179237Sjb XMM3MX, /* SIMD r32/mem -> xmm */ 204179237Sjb XMM3MXS, /* SIMD xmm -> r32/mem */ 205179237Sjb XMMSH, /* SIMD xmm,imm8 */ 206179237Sjb XMMXM3, /* SIMD xmm/mem -> r32 */ 207179237Sjb XMMX3, /* SIMD xmm -> r32 */ 208179237Sjb XMMXMM, /* SIMD xmm/mem -> mm */ 209179237Sjb XMMMX, /* SIMD mm -> xmm */ 210179237Sjb XMMXM, /* SIMD xmm -> mm */ 211253772Savg XMMX2I, /* SIMD xmm -> xmm, imm, imm */ 212253772Savg XMM2I, /* SIMD xmm, imm, imm */ 213179237Sjb XMMFENCE, /* SIMD lfence or mfence */ 214253772Savg XMMSFNC, /* SIMD sfence (none or mem) */ 215253772Savg XGETBV_XSETBV, 216253772Savg VEX_NONE, /* VEX no operand */ 217253772Savg VEX_MO, /* VEX mod_rm -> implicit reg */ 218253772Savg VEX_RMrX, /* VEX VEX.vvvv, mod_rm -> mod_reg */ 219253772Savg VEX_RRX, /* VEX VEX.vvvv, mod_reg -> mod_rm */ 220253772Savg VEX_RMRX, /* VEX VEX.vvvv, mod_rm, imm8[7:4] -> mod_reg */ 221253772Savg VEX_MX, /* VEX mod_rm -> mod_reg */ 222253772Savg VEX_MXI, /* VEX mod_rm, imm8 -> mod_reg */ 223253772Savg VEX_XXI, /* VEX mod_rm, imm8 -> VEX.vvvv */ 224253772Savg VEX_MR, /* VEX mod_rm -> mod_reg */ 225253772Savg VEX_RRI, /* VEX mod_reg, mod_rm -> implicit(eflags/r32) */ 226253772Savg VEX_RX, /* VEX mod_reg -> mod_rm */ 227253772Savg VEX_RR, /* VEX mod_rm -> mod_reg */ 228253772Savg VEX_RRi, /* VEX mod_rm, imm8 -> mod_reg */ 229253772Savg VEX_RM, /* VEX mod_reg -> mod_rm */ 230253772Savg VEX_RRM, /* VEX VEX.vvvv, mod_reg -> mod_rm */ 231253772Savg VEX_RMX /* VEX VEX.vvvv, mod_rm -> mod_reg */ 232179237Sjb}; 233179237Sjb 234253772Savg/* 235253772Savg * VEX prefixes 236253772Savg */ 237253772Savg#define VEX_2bytes 0xC5 /* the first byte of two-byte form */ 238253772Savg#define VEX_3bytes 0xC4 /* the first byte of three-byte form */ 239253772Savg 240179237Sjb#define FILL 0x90 /* Fill byte used for alignment (nop) */ 241179237Sjb 242179237Sjb/* 243179237Sjb** Register numbers for the i386 244179237Sjb*/ 245179237Sjb#define EAX_REGNO 0 246179237Sjb#define ECX_REGNO 1 247179237Sjb#define EDX_REGNO 2 248179237Sjb#define EBX_REGNO 3 249179237Sjb#define ESP_REGNO 4 250179237Sjb#define EBP_REGNO 5 251179237Sjb#define ESI_REGNO 6 252179237Sjb#define EDI_REGNO 7 253179237Sjb 254179237Sjb/* 255179237Sjb * modes for immediate values 256179237Sjb */ 257179237Sjb#define MODE_NONE 0 258179237Sjb#define MODE_IPREL 1 /* signed IP relative value */ 259179237Sjb#define MODE_SIGNED 2 /* sign extended immediate */ 260179237Sjb#define MODE_IMPLIED 3 /* constant value implied from opcode */ 261179237Sjb#define MODE_OFFSET 4 /* offset part of an address */ 262253772Savg#define MODE_RIPREL 5 /* like IPREL, but from %rip (amd64) */ 263179237Sjb 264179237Sjb/* 265179237Sjb * The letters used in these macros are: 266179237Sjb * IND - indirect to another to another table 267179237Sjb * "T" - means to Terminate indirections (this is the final opcode) 268179237Sjb * "S" - means "operand length suffix required" 269179237Sjb * "NS" - means "no suffix" which is the operand length suffix of the opcode 270179237Sjb * "Z" - means instruction size arg required 271179237Sjb * "u" - means the opcode is invalid in IA32 but valid in amd64 272179237Sjb * "x" - means the opcode is invalid in amd64, but not IA32 273179237Sjb * "y" - means the operand size is always 64 bits in 64 bit mode 274179237Sjb * "p" - means push/pop stack operation 275179237Sjb */ 276179237Sjb 277179237Sjb#if defined(DIS_TEXT) && defined(DIS_MEM) 278253772Savg#define IND(table) {(instable_t *)table, 0, "", 0, 0, 0, 0, 0, 0} 279253772Savg#define INDx(table) {(instable_t *)table, 0, "", 0, 0, 1, 0, 0, 0} 280179237Sjb#define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0, 0} 281179237Sjb#define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 0, 1, 0} 282179237Sjb#define TNSx(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0, 0} 283179237Sjb#define TNSy(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 0} 284179237Sjb#define TNSyp(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 1} 285179237Sjb#define TNSZ(name, amode, sz) {TERM, amode, name, 0, sz, 0, 0, 0, 0} 286179237Sjb#define TNSZy(name, amode, sz) {TERM, amode, name, 0, sz, 0, 1, 0, 0} 287179237Sjb#define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 0} 288179237Sjb#define TSx(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0, 0} 289179237Sjb#define TSy(name, amode) {TERM, amode, name, 1, 0, 0, 1, 0, 0} 290179237Sjb#define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 1} 291179237Sjb#define TSZ(name, amode, sz) {TERM, amode, name, 1, sz, 0, 0, 0, 0} 292179237Sjb#define TSZx(name, amode, sz) {TERM, amode, name, 1, sz, 1, 0, 0, 0} 293179237Sjb#define TSZy(name, amode, sz) {TERM, amode, name, 1, sz, 0, 1, 0, 0} 294179237Sjb#define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0} 295179237Sjb#elif defined(DIS_TEXT) 296253772Savg#define IND(table) {(instable_t *)table, 0, "", 0, 0, 0, 0, 0} 297253772Savg#define INDx(table) {(instable_t *)table, 0, "", 0, 1, 0, 0, 0} 298179237Sjb#define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0} 299179237Sjb#define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0} 300179237Sjb#define TNSx(name, amode) {TERM, amode, name, 0, 1, 0, 0, 0} 301179237Sjb#define TNSy(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0} 302179237Sjb#define TNSyp(name, amode) {TERM, amode, name, 0, 0, 1, 0, 1} 303179237Sjb#define TNSZ(name, amode, sz) {TERM, amode, name, 0, 0, 0, 0, 0} 304179237Sjb#define TNSZy(name, amode, sz) {TERM, amode, name, 0, 0, 1, 0, 0} 305179237Sjb#define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0} 306179237Sjb#define TSx(name, amode) {TERM, amode, name, 1, 1, 0, 0, 0} 307179237Sjb#define TSy(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0} 308179237Sjb#define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 1} 309179237Sjb#define TSZ(name, amode, sz) {TERM, amode, name, 1, 0, 0, 0, 0} 310179237Sjb#define TSZx(name, amode, sz) {TERM, amode, name, 1, 1, 0, 0, 0} 311179237Sjb#define TSZy(name, amode, sz) {TERM, amode, name, 1, 0, 1, 0, 0} 312179237Sjb#define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0} 313179237Sjb#elif defined(DIS_MEM) 314253772Savg#define IND(table) {(instable_t *)table, 0, 0, 0, 0, 0, 0} 315253772Savg#define INDx(table) {(instable_t *)table, 0, 0, 1, 0, 0, 0} 316179237Sjb#define TNS(name, amode) {TERM, amode, 0, 0, 0, 0, 0} 317179237Sjb#define TNSu(name, amode) {TERM, amode, 0, 0, 0, 1, 0} 318179237Sjb#define TNSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0} 319179237Sjb#define TNSyp(name, amode) {TERM, amode, 0, 0, 1, 0, 1} 320179237Sjb#define TNSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0} 321179237Sjb#define TNSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0} 322179237Sjb#define TNSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0} 323179237Sjb#define TS(name, amode) {TERM, amode, 0, 0, 0, 0, 0} 324179237Sjb#define TSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0} 325179237Sjb#define TSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0} 326179237Sjb#define TSp(name, amode) {TERM, amode, 0, 0, 0, 0, 1} 327179237Sjb#define TSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0} 328179237Sjb#define TSZx(name, amode, sz) {TERM, amode, sz, 1, 0, 0, 0} 329179237Sjb#define TSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0} 330179237Sjb#define INVALID {TERM, UNKNOWN, 0, 0, 0, 0, 0} 331179237Sjb#else 332253772Savg#define IND(table) {(instable_t *)table, 0, 0, 0, 0, 0} 333253772Savg#define INDx(table) {(instable_t *)table, 0, 1, 0, 0, 0} 334179237Sjb#define TNS(name, amode) {TERM, amode, 0, 0, 0, 0} 335179237Sjb#define TNSu(name, amode) {TERM, amode, 0, 0, 1, 0} 336179237Sjb#define TNSy(name, amode) {TERM, amode, 0, 1, 0, 0} 337179237Sjb#define TNSyp(name, amode) {TERM, amode, 0, 1, 0, 1} 338179237Sjb#define TNSx(name, amode) {TERM, amode, 1, 0, 0, 0} 339179237Sjb#define TNSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0} 340179237Sjb#define TNSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0} 341179237Sjb#define TS(name, amode) {TERM, amode, 0, 0, 0, 0} 342179237Sjb#define TSx(name, amode) {TERM, amode, 1, 0, 0, 0} 343179237Sjb#define TSy(name, amode) {TERM, amode, 0, 1, 0, 0} 344179237Sjb#define TSp(name, amode) {TERM, amode, 0, 0, 0, 1} 345179237Sjb#define TSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0} 346179237Sjb#define TSZx(name, amode, sz) {TERM, amode, 1, 0, 0, 0} 347179237Sjb#define TSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0} 348179237Sjb#define INVALID {TERM, UNKNOWN, 0, 0, 0, 0} 349179237Sjb#endif 350179237Sjb 351179237Sjb#ifdef DIS_TEXT 352179237Sjb/* 353179237Sjb * this decodes the r_m field for mode's 0, 1, 2 in 16 bit mode 354179237Sjb */ 355179237Sjbconst char *const dis_addr16[3][8] = { 356179237Sjb"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "", 357179237Sjb "(%bx)", 358179237Sjb"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di", "(%bp)", 359179237Sjb "(%bx)", 360179237Sjb"(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "(%bp)", 361179237Sjb "(%bx)", 362179237Sjb}; 363179237Sjb 364179237Sjb 365179237Sjb/* 366179237Sjb * This decodes 32 bit addressing mode r_m field for modes 0, 1, 2 367179237Sjb */ 368179237Sjbconst char *const dis_addr32_mode0[16] = { 369179237Sjb "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "", "(%esi)", "(%edi)", 370179237Sjb "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "", "(%r14d)", "(%r15d)" 371179237Sjb}; 372179237Sjb 373179237Sjbconst char *const dis_addr32_mode12[16] = { 374179237Sjb "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "(%ebp)", "(%esi)", "(%edi)", 375179237Sjb "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "(%r13d)", "(%r14d)", "(%r15d)" 376179237Sjb}; 377179237Sjb 378179237Sjb/* 379179237Sjb * This decodes 64 bit addressing mode r_m field for modes 0, 1, 2 380179237Sjb */ 381179237Sjbconst char *const dis_addr64_mode0[16] = { 382179237Sjb "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rip)", "(%rsi)", "(%rdi)", 383179237Sjb "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%rip)", "(%r14)", "(%r15)" 384179237Sjb}; 385179237Sjbconst char *const dis_addr64_mode12[16] = { 386179237Sjb "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rbp)", "(%rsi)", "(%rdi)", 387179237Sjb "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%r13)", "(%r14)", "(%r15)" 388179237Sjb}; 389179237Sjb 390179237Sjb/* 391179237Sjb * decode for scale from SIB byte 392179237Sjb */ 393179237Sjbconst char *const dis_scale_factor[4] = { ")", ",2)", ",4)", ",8)" }; 394179237Sjb 395179237Sjb/* 396179237Sjb * register decoding for normal references to registers (ie. not addressing) 397179237Sjb */ 398179237Sjbconst char *const dis_REG8[16] = { 399179237Sjb "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", 400179237Sjb "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" 401179237Sjb}; 402179237Sjb 403179237Sjbconst char *const dis_REG8_REX[16] = { 404179237Sjb "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", 405179237Sjb "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" 406179237Sjb}; 407179237Sjb 408179237Sjbconst char *const dis_REG16[16] = { 409179237Sjb "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", 410179237Sjb "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" 411179237Sjb}; 412179237Sjb 413179237Sjbconst char *const dis_REG32[16] = { 414179237Sjb "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", 415179237Sjb "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" 416179237Sjb}; 417179237Sjb 418179237Sjbconst char *const dis_REG64[16] = { 419179237Sjb "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", 420179237Sjb "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" 421179237Sjb}; 422179237Sjb 423179237Sjbconst char *const dis_DEBUGREG[16] = { 424179237Sjb "%db0", "%db1", "%db2", "%db3", "%db4", "%db5", "%db6", "%db7", 425179237Sjb "%db8", "%db9", "%db10", "%db11", "%db12", "%db13", "%db14", "%db15" 426179237Sjb}; 427179237Sjb 428179237Sjbconst char *const dis_CONTROLREG[16] = { 429179237Sjb "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5?", "%cr6?", "%cr7?", 430179237Sjb "%cr8", "%cr9?", "%cr10?", "%cr11?", "%cr12?", "%cr13?", "%cr14?", "%cr15?" 431179237Sjb}; 432179237Sjb 433179237Sjbconst char *const dis_TESTREG[16] = { 434179237Sjb "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7", 435179237Sjb "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7" 436179237Sjb}; 437179237Sjb 438179237Sjbconst char *const dis_MMREG[16] = { 439179237Sjb "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", 440179237Sjb "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" 441179237Sjb}; 442179237Sjb 443179237Sjbconst char *const dis_XMMREG[16] = { 444179237Sjb "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", 445179237Sjb "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" 446179237Sjb}; 447179237Sjb 448253772Savgconst char *const dis_YMMREG[16] = { 449253772Savg "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6", "%ymm7", 450253772Savg "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13", "%ymm14", "%ymm15" 451253772Savg}; 452253772Savg 453179237Sjbconst char *const dis_SEGREG[16] = { 454179237Sjb "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>", 455179237Sjb "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>" 456179237Sjb}; 457179237Sjb 458179237Sjb/* 459179237Sjb * SIMD predicate suffixes 460179237Sjb */ 461179237Sjbconst char *const dis_PREDSUFFIX[8] = { 462179237Sjb "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord" 463179237Sjb}; 464179237Sjb 465253772Savgconst char *const dis_AVXvgrp7[3][8] = { 466253772Savg /*0 1 2 3 4 5 6 7*/ 467253772Savg/*71*/ {"", "", "vpsrlw", "", "vpsraw", "", "vpsllw", ""}, 468253772Savg/*72*/ {"", "", "vpsrld", "", "vpsrad", "", "vpslld", ""}, 469253772Savg/*73*/ {"", "", "vpsrlq", "vpsrldq", "", "", "vpsllq", "vpslldq"} 470253772Savg}; 471179237Sjb 472179237Sjb#endif /* DIS_TEXT */ 473179237Sjb 474179237Sjb/* 475179237Sjb * "decode table" for 64 bit mode MOVSXD instruction (opcode 0x63) 476179237Sjb */ 477179237Sjbconst instable_t dis_opMOVSLD = TNS("movslq",MOVSXZ); 478179237Sjb 479179237Sjb/* 480179237Sjb * "decode table" for pause and clflush instructions 481179237Sjb */ 482179237Sjbconst instable_t dis_opPause = TNS("pause", NORM); 483179237Sjb 484179237Sjb/* 485179237Sjb * Decode table for 0x0F00 opcodes 486179237Sjb */ 487179237Sjbconst instable_t dis_op0F00[8] = { 488179237Sjb 489179237Sjb/* [0] */ TNS("sldt",M), TNS("str",M), TNSy("lldt",M), TNSy("ltr",M), 490179237Sjb/* [4] */ TNSZ("verr",M,2), TNSZ("verw",M,2), INVALID, INVALID, 491179237Sjb}; 492179237Sjb 493179237Sjb 494179237Sjb/* 495179237Sjb * Decode table for 0x0F01 opcodes 496179237Sjb */ 497179237Sjbconst instable_t dis_op0F01[8] = { 498179237Sjb 499253772Savg/* [0] */ TNSZ("sgdt",MO,6), TNSZ("sidt",MONITOR_MWAIT,6), TNSZ("lgdt",XGETBV_XSETBV,6), TNSZ("lidt",MO,6), 500179237Sjb/* [4] */ TNSZ("smsw",M,2), INVALID, TNSZ("lmsw",M,2), TNS("invlpg",SWAPGS), 501179237Sjb}; 502179237Sjb 503179237Sjb/* 504179237Sjb * Decode table for 0x0F18 opcodes -- SIMD prefetch 505179237Sjb */ 506179237Sjbconst instable_t dis_op0F18[8] = { 507179237Sjb 508179237Sjb/* [0] */ TNS("prefetchnta",PREF),TNS("prefetcht0",PREF), TNS("prefetcht1",PREF), TNS("prefetcht2",PREF), 509179237Sjb/* [4] */ INVALID, INVALID, INVALID, INVALID, 510179237Sjb}; 511179237Sjb 512179237Sjb/* 513179237Sjb * Decode table for 0x0FAE opcodes -- SIMD state save/restore 514179237Sjb */ 515179237Sjbconst instable_t dis_op0FAE[8] = { 516179237Sjb/* [0] */ TNSZ("fxsave",M,512), TNSZ("fxrstor",M,512), TNS("ldmxcsr",M), TNS("stmxcsr",M), 517253772Savg/* [4] */ TNSZ("xsave",M,512), TNS("lfence",XMMFENCE), TNS("mfence",XMMFENCE), TNS("sfence",XMMSFNC), 518179237Sjb}; 519179237Sjb 520179237Sjb/* 521179237Sjb * Decode table for 0x0FBA opcodes 522179237Sjb */ 523179237Sjb 524179237Sjbconst instable_t dis_op0FBA[8] = { 525179237Sjb 526179237Sjb/* [0] */ INVALID, INVALID, INVALID, INVALID, 527179237Sjb/* [4] */ TS("bt",MIb), TS("bts",MIb), TS("btr",MIb), TS("btc",MIb), 528179237Sjb}; 529179237Sjb 530179237Sjb/* 531179237Sjb * Decode table for 0x0FC7 opcode 532179237Sjb */ 533179237Sjb 534179237Sjbconst instable_t dis_op0FC7[8] = { 535179237Sjb 536179237Sjb/* [0] */ INVALID, TNS("cmpxchg8b",M), INVALID, INVALID, 537179237Sjb/* [4] */ INVALID, INVALID, INVALID, INVALID, 538179237Sjb}; 539179237Sjb 540179237Sjb 541179237Sjb/* 542179237Sjb * Decode table for 0x0FC8 opcode -- 486 bswap instruction 543179237Sjb * 544179237Sjb *bit pattern: 0000 1111 1100 1reg 545179237Sjb */ 546179237Sjbconst instable_t dis_op0FC8[4] = { 547179237Sjb/* [0] */ TNS("bswap",R), INVALID, INVALID, INVALID, 548179237Sjb}; 549179237Sjb 550179237Sjb/* 551179237Sjb * Decode table for 0x0F71, 0x0F72, and 0x0F73 opcodes -- MMX instructions 552179237Sjb */ 553179237Sjbconst instable_t dis_op0F7123[4][8] = { 554179237Sjb{ 555179237Sjb/* [70].0 */ INVALID, INVALID, INVALID, INVALID, 556179237Sjb/* .4 */ INVALID, INVALID, INVALID, INVALID, 557179237Sjb}, { 558179237Sjb/* [71].0 */ INVALID, INVALID, TNS("psrlw",MMOSH), INVALID, 559179237Sjb/* .4 */ TNS("psraw",MMOSH), INVALID, TNS("psllw",MMOSH), INVALID, 560179237Sjb}, { 561179237Sjb/* [72].0 */ INVALID, INVALID, TNS("psrld",MMOSH), INVALID, 562179237Sjb/* .4 */ TNS("psrad",MMOSH), INVALID, TNS("pslld",MMOSH), INVALID, 563179237Sjb}, { 564179237Sjb/* [73].0 */ INVALID, INVALID, TNS("psrlq",MMOSH), TNS("INVALID",MMOSH), 565179237Sjb/* .4 */ INVALID, INVALID, TNS("psllq",MMOSH), TNS("INVALID",MMOSH), 566179237Sjb} }; 567179237Sjb 568179237Sjb/* 569179237Sjb * Decode table for SIMD extensions to above 0x0F71-0x0F73 opcodes. 570179237Sjb */ 571179237Sjbconst instable_t dis_opSIMD7123[32] = { 572179237Sjb/* [70].0 */ INVALID, INVALID, INVALID, INVALID, 573179237Sjb/* .4 */ INVALID, INVALID, INVALID, INVALID, 574179237Sjb 575179237Sjb/* [71].0 */ INVALID, INVALID, TNS("psrlw",XMMSH), INVALID, 576179237Sjb/* .4 */ TNS("psraw",XMMSH), INVALID, TNS("psllw",XMMSH), INVALID, 577179237Sjb 578179237Sjb/* [72].0 */ INVALID, INVALID, TNS("psrld",XMMSH), INVALID, 579179237Sjb/* .4 */ TNS("psrad",XMMSH), INVALID, TNS("pslld",XMMSH), INVALID, 580179237Sjb 581179237Sjb/* [73].0 */ INVALID, INVALID, TNS("psrlq",XMMSH), TNS("psrldq",XMMSH), 582179237Sjb/* .4 */ INVALID, INVALID, TNS("psllq",XMMSH), TNS("pslldq",XMMSH), 583179237Sjb}; 584179237Sjb 585179237Sjb/* 586179237Sjb * SIMD instructions have been wedged into the existing IA32 instruction 587179237Sjb * set through the use of prefixes. That is, while 0xf0 0x58 may be 588179237Sjb * addps, 0xf3 0xf0 0x58 (literally, repz addps) is a completely different 589179237Sjb * instruction - addss. At present, three prefixes have been coopted in 590179237Sjb * this manner - address size (0x66), repnz (0xf2) and repz (0xf3). The 591179237Sjb * following tables are used to provide the prefixed instruction names. 592179237Sjb * The arrays are sparse, but they're fast. 593179237Sjb */ 594179237Sjb 595179237Sjb/* 596179237Sjb * Decode table for SIMD instructions with the address size (0x66) prefix. 597179237Sjb */ 598179237Sjbconst instable_t dis_opSIMDdata16[256] = { 599179237Sjb/* [00] */ INVALID, INVALID, INVALID, INVALID, 600179237Sjb/* [04] */ INVALID, INVALID, INVALID, INVALID, 601179237Sjb/* [08] */ INVALID, INVALID, INVALID, INVALID, 602179237Sjb/* [0C] */ INVALID, INVALID, INVALID, INVALID, 603179237Sjb 604179237Sjb/* [10] */ TNSZ("movupd",XMM,16), TNSZ("movupd",XMMS,16), TNSZ("movlpd",XMMM,8), TNSZ("movlpd",XMMMS,8), 605179237Sjb/* [14] */ TNSZ("unpcklpd",XMM,16),TNSZ("unpckhpd",XMM,16),TNSZ("movhpd",XMMM,8), TNSZ("movhpd",XMMMS,8), 606179237Sjb/* [18] */ INVALID, INVALID, INVALID, INVALID, 607179237Sjb/* [1C] */ INVALID, INVALID, INVALID, INVALID, 608179237Sjb 609179237Sjb/* [20] */ INVALID, INVALID, INVALID, INVALID, 610179237Sjb/* [24] */ INVALID, INVALID, INVALID, INVALID, 611179237Sjb/* [28] */ TNSZ("movapd",XMM,16), TNSZ("movapd",XMMS,16), TNSZ("cvtpi2pd",XMMOMX,8),TNSZ("movntpd",XMMOMS,16), 612179237Sjb/* [2C] */ TNSZ("cvttpd2pi",XMMXMM,16),TNSZ("cvtpd2pi",XMMXMM,16),TNSZ("ucomisd",XMM,8),TNSZ("comisd",XMM,8), 613179237Sjb 614179237Sjb/* [30] */ INVALID, INVALID, INVALID, INVALID, 615179237Sjb/* [34] */ INVALID, INVALID, INVALID, INVALID, 616179237Sjb/* [38] */ INVALID, INVALID, INVALID, INVALID, 617179237Sjb/* [3C] */ INVALID, INVALID, INVALID, INVALID, 618179237Sjb 619179237Sjb/* [40] */ INVALID, INVALID, INVALID, INVALID, 620179237Sjb/* [44] */ INVALID, INVALID, INVALID, INVALID, 621179237Sjb/* [48] */ INVALID, INVALID, INVALID, INVALID, 622179237Sjb/* [4C] */ INVALID, INVALID, INVALID, INVALID, 623179237Sjb 624179237Sjb/* [50] */ TNS("movmskpd",XMMOX3), TNSZ("sqrtpd",XMM,16), INVALID, INVALID, 625179237Sjb/* [54] */ TNSZ("andpd",XMM,16), TNSZ("andnpd",XMM,16), TNSZ("orpd",XMM,16), TNSZ("xorpd",XMM,16), 626179237Sjb/* [58] */ TNSZ("addpd",XMM,16), TNSZ("mulpd",XMM,16), TNSZ("cvtpd2ps",XMM,16),TNSZ("cvtps2dq",XMM,16), 627179237Sjb/* [5C] */ TNSZ("subpd",XMM,16), TNSZ("minpd",XMM,16), TNSZ("divpd",XMM,16), TNSZ("maxpd",XMM,16), 628179237Sjb 629179237Sjb/* [60] */ TNSZ("punpcklbw",XMM,16),TNSZ("punpcklwd",XMM,16),TNSZ("punpckldq",XMM,16),TNSZ("packsswb",XMM,16), 630179237Sjb/* [64] */ TNSZ("pcmpgtb",XMM,16), TNSZ("pcmpgtw",XMM,16), TNSZ("pcmpgtd",XMM,16), TNSZ("packuswb",XMM,16), 631179237Sjb/* [68] */ TNSZ("punpckhbw",XMM,16),TNSZ("punpckhwd",XMM,16),TNSZ("punpckhdq",XMM,16),TNSZ("packssdw",XMM,16), 632179237Sjb/* [6C] */ TNSZ("punpcklqdq",XMM,16),TNSZ("punpckhqdq",XMM,16),TNSZ("movd",XMM3MX,4),TNSZ("movdqa",XMM,16), 633179237Sjb 634179237Sjb/* [70] */ TNSZ("pshufd",XMMP,16), INVALID, INVALID, INVALID, 635179237Sjb/* [74] */ TNSZ("pcmpeqb",XMM,16), TNSZ("pcmpeqw",XMM,16), TNSZ("pcmpeqd",XMM,16), INVALID, 636253772Savg/* [78] */ TNSZ("extrq",XMM2I,16), TNSZ("extrq",XMM,16), INVALID, INVALID, 637179237Sjb/* [7C] */ INVALID, INVALID, TNSZ("movd",XMM3MXS,4), TNSZ("movdqa",XMMS,16), 638179237Sjb 639179237Sjb/* [80] */ INVALID, INVALID, INVALID, INVALID, 640179237Sjb/* [84] */ INVALID, INVALID, INVALID, INVALID, 641179237Sjb/* [88] */ INVALID, INVALID, INVALID, INVALID, 642179237Sjb/* [8C] */ INVALID, INVALID, INVALID, INVALID, 643179237Sjb 644179237Sjb/* [90] */ INVALID, INVALID, INVALID, INVALID, 645179237Sjb/* [94] */ INVALID, INVALID, INVALID, INVALID, 646179237Sjb/* [98] */ INVALID, INVALID, INVALID, INVALID, 647179237Sjb/* [9C] */ INVALID, INVALID, INVALID, INVALID, 648179237Sjb 649179237Sjb/* [A0] */ INVALID, INVALID, INVALID, INVALID, 650179237Sjb/* [A4] */ INVALID, INVALID, INVALID, INVALID, 651179237Sjb/* [A8] */ INVALID, INVALID, INVALID, INVALID, 652179237Sjb/* [AC] */ INVALID, INVALID, INVALID, INVALID, 653179237Sjb 654179237Sjb/* [B0] */ INVALID, INVALID, INVALID, INVALID, 655179237Sjb/* [B4] */ INVALID, INVALID, INVALID, INVALID, 656179237Sjb/* [B8] */ INVALID, INVALID, INVALID, INVALID, 657179237Sjb/* [BC] */ INVALID, INVALID, INVALID, INVALID, 658179237Sjb 659179237Sjb/* [C0] */ INVALID, INVALID, TNSZ("cmppd",XMMP,16), INVALID, 660179237Sjb/* [C4] */ TNSZ("pinsrw",XMMPRM,2),TNS("pextrw",XMM3P), TNSZ("shufpd",XMMP,16), INVALID, 661179237Sjb/* [C8] */ INVALID, INVALID, INVALID, INVALID, 662179237Sjb/* [CC] */ INVALID, INVALID, INVALID, INVALID, 663179237Sjb 664179237Sjb/* [D0] */ INVALID, TNSZ("psrlw",XMM,16), TNSZ("psrld",XMM,16), TNSZ("psrlq",XMM,16), 665179237Sjb/* [D4] */ TNSZ("paddq",XMM,16), TNSZ("pmullw",XMM,16), TNSZ("movq",XMMS,8), TNS("pmovmskb",XMMX3), 666179237Sjb/* [D8] */ TNSZ("psubusb",XMM,16), TNSZ("psubusw",XMM,16), TNSZ("pminub",XMM,16), TNSZ("pand",XMM,16), 667179237Sjb/* [DC] */ TNSZ("paddusb",XMM,16), TNSZ("paddusw",XMM,16), TNSZ("pmaxub",XMM,16), TNSZ("pandn",XMM,16), 668179237Sjb 669179237Sjb/* [E0] */ TNSZ("pavgb",XMM,16), TNSZ("psraw",XMM,16), TNSZ("psrad",XMM,16), TNSZ("pavgw",XMM,16), 670179237Sjb/* [E4] */ TNSZ("pmulhuw",XMM,16), TNSZ("pmulhw",XMM,16), TNSZ("cvttpd2dq",XMM,16),TNSZ("movntdq",XMMS,16), 671179237Sjb/* [E8] */ TNSZ("psubsb",XMM,16), TNSZ("psubsw",XMM,16), TNSZ("pminsw",XMM,16), TNSZ("por",XMM,16), 672179237Sjb/* [EC] */ TNSZ("paddsb",XMM,16), TNSZ("paddsw",XMM,16), TNSZ("pmaxsw",XMM,16), TNSZ("pxor",XMM,16), 673179237Sjb 674179237Sjb/* [F0] */ INVALID, TNSZ("psllw",XMM,16), TNSZ("pslld",XMM,16), TNSZ("psllq",XMM,16), 675179237Sjb/* [F4] */ TNSZ("pmuludq",XMM,16), TNSZ("pmaddwd",XMM,16), TNSZ("psadbw",XMM,16), TNSZ("maskmovdqu", XMMXIMPL,16), 676179237Sjb/* [F8] */ TNSZ("psubb",XMM,16), TNSZ("psubw",XMM,16), TNSZ("psubd",XMM,16), TNSZ("psubq",XMM,16), 677179237Sjb/* [FC] */ TNSZ("paddb",XMM,16), TNSZ("paddw",XMM,16), TNSZ("paddd",XMM,16), INVALID, 678179237Sjb}; 679179237Sjb 680253772Savgconst instable_t dis_opAVX660F[256] = { 681253772Savg/* [00] */ INVALID, INVALID, INVALID, INVALID, 682253772Savg/* [04] */ INVALID, INVALID, INVALID, INVALID, 683253772Savg/* [08] */ INVALID, INVALID, INVALID, INVALID, 684253772Savg/* [0C] */ INVALID, INVALID, INVALID, INVALID, 685253772Savg 686253772Savg/* [10] */ TNSZ("vmovupd",VEX_MX,16), TNSZ("vmovupd",VEX_RX,16), TNSZ("vmovlpd",VEX_RMrX,8), TNSZ("vmovlpd",VEX_RM,8), 687253772Savg/* [14] */ TNSZ("vunpcklpd",VEX_RMrX,16),TNSZ("vunpckhpd",VEX_RMrX,16),TNSZ("vmovhpd",VEX_RMrX,8), TNSZ("vmovhpd",VEX_RM,8), 688253772Savg/* [18] */ INVALID, INVALID, INVALID, INVALID, 689253772Savg/* [1C] */ INVALID, INVALID, INVALID, INVALID, 690253772Savg 691253772Savg/* [20] */ INVALID, INVALID, INVALID, INVALID, 692253772Savg/* [24] */ INVALID, INVALID, INVALID, INVALID, 693253772Savg/* [28] */ TNSZ("vmovapd",VEX_MX,16), TNSZ("vmovapd",VEX_RX,16), INVALID, TNSZ("vmovntpd",VEX_RM,16), 694253772Savg/* [2C] */ INVALID, INVALID, TNSZ("vucomisd",VEX_MX,8),TNSZ("vcomisd",VEX_MX,8), 695253772Savg 696253772Savg/* [30] */ INVALID, INVALID, INVALID, INVALID, 697253772Savg/* [34] */ INVALID, INVALID, INVALID, INVALID, 698253772Savg/* [38] */ INVALID, INVALID, INVALID, INVALID, 699253772Savg/* [3C] */ INVALID, INVALID, INVALID, INVALID, 700253772Savg 701253772Savg/* [40] */ INVALID, INVALID, INVALID, INVALID, 702253772Savg/* [44] */ INVALID, INVALID, INVALID, INVALID, 703253772Savg/* [48] */ INVALID, INVALID, INVALID, INVALID, 704253772Savg/* [4C] */ INVALID, INVALID, INVALID, INVALID, 705253772Savg 706253772Savg/* [50] */ TNS("vmovmskpd",VEX_MR), TNSZ("vsqrtpd",VEX_MX,16), INVALID, INVALID, 707253772Savg/* [54] */ TNSZ("vandpd",VEX_RMrX,16), TNSZ("vandnpd",VEX_RMrX,16), TNSZ("vorpd",VEX_RMrX,16), TNSZ("vxorpd",VEX_RMrX,16), 708253772Savg/* [58] */ TNSZ("vaddpd",VEX_RMrX,16), TNSZ("vmulpd",VEX_RMrX,16), TNSZ("vcvtpd2ps",VEX_MX,16),TNSZ("vcvtps2dq",VEX_MX,16), 709253772Savg/* [5C] */ TNSZ("vsubpd",VEX_RMrX,16), TNSZ("vminpd",VEX_RMrX,16), TNSZ("vdivpd",VEX_RMrX,16), TNSZ("vmaxpd",VEX_RMrX,16), 710253772Savg 711253772Savg/* [60] */ TNSZ("vpunpcklbw",VEX_RMrX,16),TNSZ("vpunpcklwd",VEX_RMrX,16),TNSZ("vpunpckldq",VEX_RMrX,16),TNSZ("vpacksswb",VEX_RMrX,16), 712253772Savg/* [64] */ TNSZ("vpcmpgtb",VEX_RMrX,16), TNSZ("vpcmpgtw",VEX_RMrX,16), TNSZ("vpcmpgtd",VEX_RMrX,16), TNSZ("vpackuswb",VEX_RMrX,16), 713253772Savg/* [68] */ TNSZ("vpunpckhbw",VEX_RMrX,16),TNSZ("vpunpckhwd",VEX_RMrX,16),TNSZ("vpunpckhdq",VEX_RMrX,16),TNSZ("vpackssdw",VEX_RMrX,16), 714253772Savg/* [6C] */ TNSZ("vpunpcklqdq",VEX_RMrX,16),TNSZ("vpunpckhqdq",VEX_RMrX,16),TNSZ("vmovd",VEX_MX,4),TNSZ("vmovdqa",VEX_MX,16), 715253772Savg 716253772Savg/* [70] */ TNSZ("vpshufd",VEX_MXI,16), TNSZ("vgrp71",VEX_XXI,16), TNSZ("vgrp72",VEX_XXI,16), TNSZ("vgrp73",VEX_XXI,16), 717253772Savg/* [74] */ TNSZ("vpcmpeqb",VEX_RMrX,16), TNSZ("vpcmpeqw",VEX_RMrX,16), TNSZ("vpcmpeqd",VEX_RMrX,16), INVALID, 718253772Savg/* [78] */ INVALID, INVALID, INVALID, INVALID, 719253772Savg/* [7C] */ TNSZ("vhaddpd",VEX_RMrX,16), TNSZ("vhsubpd",VEX_RMrX,16), TNSZ("vmovd",VEX_RR,4), TNSZ("vmovdqa",VEX_RX,16), 720253772Savg 721253772Savg/* [80] */ INVALID, INVALID, INVALID, INVALID, 722253772Savg/* [84] */ INVALID, INVALID, INVALID, INVALID, 723253772Savg/* [88] */ INVALID, INVALID, INVALID, INVALID, 724253772Savg/* [8C] */ INVALID, INVALID, INVALID, INVALID, 725253772Savg 726253772Savg/* [90] */ INVALID, INVALID, INVALID, INVALID, 727253772Savg/* [94] */ INVALID, INVALID, INVALID, INVALID, 728253772Savg/* [98] */ INVALID, INVALID, INVALID, INVALID, 729253772Savg/* [9C] */ INVALID, INVALID, INVALID, INVALID, 730253772Savg 731253772Savg/* [A0] */ INVALID, INVALID, INVALID, INVALID, 732253772Savg/* [A4] */ INVALID, INVALID, INVALID, INVALID, 733253772Savg/* [A8] */ INVALID, INVALID, INVALID, INVALID, 734253772Savg/* [AC] */ INVALID, INVALID, INVALID, INVALID, 735253772Savg 736253772Savg/* [B0] */ INVALID, INVALID, INVALID, INVALID, 737253772Savg/* [B4] */ INVALID, INVALID, INVALID, INVALID, 738253772Savg/* [B8] */ INVALID, INVALID, INVALID, INVALID, 739253772Savg/* [BC] */ INVALID, INVALID, INVALID, INVALID, 740253772Savg 741253772Savg/* [C0] */ INVALID, INVALID, TNSZ("vcmppd",VEX_RMRX,16), INVALID, 742253772Savg/* [C4] */ TNSZ("vpinsrw",VEX_RMRX,2),TNS("vpextrw",VEX_MR), TNSZ("vshufpd",VEX_RMRX,16), INVALID, 743253772Savg/* [C8] */ INVALID, INVALID, INVALID, INVALID, 744253772Savg/* [CC] */ INVALID, INVALID, INVALID, INVALID, 745253772Savg 746253772Savg/* [D0] */ TNSZ("vaddsubpd",VEX_RMrX,16),TNSZ("vpsrlw",VEX_RMrX,16), TNSZ("vpsrld",VEX_RMrX,16), TNSZ("vpsrlq",VEX_RMrX,16), 747253772Savg/* [D4] */ TNSZ("vpaddq",VEX_RMrX,16), TNSZ("vpmullw",VEX_RMrX,16), TNSZ("vmovq",VEX_RX,8), TNS("vpmovmskb",VEX_MR), 748253772Savg/* [D8] */ TNSZ("vpsubusb",VEX_RMrX,16), TNSZ("vpsubusw",VEX_RMrX,16), TNSZ("vpminub",VEX_RMrX,16), TNSZ("vpand",VEX_RMrX,16), 749253772Savg/* [DC] */ TNSZ("vpaddusb",VEX_RMrX,16), TNSZ("vpaddusw",VEX_RMrX,16), TNSZ("vpmaxub",VEX_RMrX,16), TNSZ("vpandn",VEX_RMrX,16), 750253772Savg 751253772Savg/* [E0] */ TNSZ("vpavgb",VEX_RMrX,16), TNSZ("vpsraw",VEX_RMrX,16), TNSZ("vpsrad",VEX_RMrX,16), TNSZ("vpavgw",VEX_RMrX,16), 752253772Savg/* [E4] */ TNSZ("vpmulhuw",VEX_RMrX,16), TNSZ("vpmulhw",VEX_RMrX,16), TNSZ("vcvttpd2dq",VEX_MX,16),TNSZ("vmovntdq",VEX_RM,16), 753253772Savg/* [E8] */ TNSZ("vpsubsb",VEX_RMrX,16), TNSZ("vpsubsw",VEX_RMrX,16), TNSZ("vpminsw",VEX_RMrX,16), TNSZ("vpor",VEX_RMrX,16), 754253772Savg/* [EC] */ TNSZ("vpaddsb",VEX_RMrX,16), TNSZ("vpaddsw",VEX_RMrX,16), TNSZ("vpmaxsw",VEX_RMrX,16), TNSZ("vpxor",VEX_RMrX,16), 755253772Savg 756253772Savg/* [F0] */ INVALID, TNSZ("vpsllw",VEX_RMrX,16), TNSZ("vpslld",VEX_RMrX,16), TNSZ("vpsllq",VEX_RMrX,16), 757253772Savg/* [F4] */ TNSZ("vpmuludq",VEX_RMrX,16), TNSZ("vpmaddwd",VEX_RMrX,16), TNSZ("vpsadbw",VEX_RMrX,16), TNS("vmaskmovdqu",VEX_MX), 758253772Savg/* [F8] */ TNSZ("vpsubb",VEX_RMrX,16), TNSZ("vpsubw",VEX_RMrX,16), TNSZ("vpsubd",VEX_RMrX,16), TNSZ("vpsubq",VEX_RMrX,16), 759253772Savg/* [FC] */ TNSZ("vpaddb",VEX_RMrX,16), TNSZ("vpaddw",VEX_RMrX,16), TNSZ("vpaddd",VEX_RMrX,16), INVALID, 760253772Savg}; 761253772Savg 762179237Sjb/* 763179237Sjb * Decode table for SIMD instructions with the repnz (0xf2) prefix. 764179237Sjb */ 765179237Sjbconst instable_t dis_opSIMDrepnz[256] = { 766179237Sjb/* [00] */ INVALID, INVALID, INVALID, INVALID, 767179237Sjb/* [04] */ INVALID, INVALID, INVALID, INVALID, 768179237Sjb/* [08] */ INVALID, INVALID, INVALID, INVALID, 769179237Sjb/* [0C] */ INVALID, INVALID, INVALID, INVALID, 770179237Sjb 771179237Sjb/* [10] */ TNSZ("movsd",XMM,8), TNSZ("movsd",XMMS,8), INVALID, INVALID, 772179237Sjb/* [14] */ INVALID, INVALID, INVALID, INVALID, 773179237Sjb/* [18] */ INVALID, INVALID, INVALID, INVALID, 774179237Sjb/* [1C] */ INVALID, INVALID, INVALID, INVALID, 775179237Sjb 776179237Sjb/* [20] */ INVALID, INVALID, INVALID, INVALID, 777179237Sjb/* [24] */ INVALID, INVALID, INVALID, INVALID, 778253772Savg/* [28] */ INVALID, INVALID, TNSZ("cvtsi2sd",XMM3MX,4),TNSZ("movntsd",XMMMS,8), 779179237Sjb/* [2C] */ TNSZ("cvttsd2si",XMMXM3,8),TNSZ("cvtsd2si",XMMXM3,8),INVALID, INVALID, 780179237Sjb 781179237Sjb/* [30] */ INVALID, INVALID, INVALID, INVALID, 782179237Sjb/* [34] */ INVALID, INVALID, INVALID, INVALID, 783179237Sjb/* [38] */ INVALID, INVALID, INVALID, INVALID, 784179237Sjb/* [3C] */ INVALID, INVALID, INVALID, INVALID, 785179237Sjb 786179237Sjb/* [40] */ INVALID, INVALID, INVALID, INVALID, 787179237Sjb/* [44] */ INVALID, INVALID, INVALID, INVALID, 788179237Sjb/* [48] */ INVALID, INVALID, INVALID, INVALID, 789179237Sjb/* [4C] */ INVALID, INVALID, INVALID, INVALID, 790179237Sjb 791179237Sjb/* [50] */ INVALID, TNSZ("sqrtsd",XMM,8), INVALID, INVALID, 792179237Sjb/* [54] */ INVALID, INVALID, INVALID, INVALID, 793179237Sjb/* [58] */ TNSZ("addsd",XMM,8), TNSZ("mulsd",XMM,8), TNSZ("cvtsd2ss",XMM,8), INVALID, 794179237Sjb/* [5C] */ TNSZ("subsd",XMM,8), TNSZ("minsd",XMM,8), TNSZ("divsd",XMM,8), TNSZ("maxsd",XMM,8), 795179237Sjb 796179237Sjb/* [60] */ INVALID, INVALID, INVALID, INVALID, 797179237Sjb/* [64] */ INVALID, INVALID, INVALID, INVALID, 798179237Sjb/* [68] */ INVALID, INVALID, INVALID, INVALID, 799179237Sjb/* [6C] */ INVALID, INVALID, INVALID, INVALID, 800179237Sjb 801179237Sjb/* [70] */ TNSZ("pshuflw",XMMP,16),INVALID, INVALID, INVALID, 802179237Sjb/* [74] */ INVALID, INVALID, INVALID, INVALID, 803253772Savg/* [78] */ TNSZ("insertq",XMMX2I,16),TNSZ("insertq",XMM,8),INVALID, INVALID, 804179237Sjb/* [7C] */ INVALID, INVALID, INVALID, INVALID, 805179237Sjb 806179237Sjb/* [80] */ INVALID, INVALID, INVALID, INVALID, 807179237Sjb/* [84] */ INVALID, INVALID, INVALID, INVALID, 808179237Sjb/* [88] */ INVALID, INVALID, INVALID, INVALID, 809179237Sjb/* [0C] */ INVALID, INVALID, INVALID, INVALID, 810179237Sjb 811179237Sjb/* [90] */ INVALID, INVALID, INVALID, INVALID, 812179237Sjb/* [94] */ INVALID, INVALID, INVALID, INVALID, 813179237Sjb/* [98] */ INVALID, INVALID, INVALID, INVALID, 814179237Sjb/* [9C] */ INVALID, INVALID, INVALID, INVALID, 815179237Sjb 816179237Sjb/* [A0] */ INVALID, INVALID, INVALID, INVALID, 817179237Sjb/* [A4] */ INVALID, INVALID, INVALID, INVALID, 818179237Sjb/* [A8] */ INVALID, INVALID, INVALID, INVALID, 819179237Sjb/* [AC] */ INVALID, INVALID, INVALID, INVALID, 820179237Sjb 821179237Sjb/* [B0] */ INVALID, INVALID, INVALID, INVALID, 822179237Sjb/* [B4] */ INVALID, INVALID, INVALID, INVALID, 823179237Sjb/* [B8] */ INVALID, INVALID, INVALID, INVALID, 824179237Sjb/* [BC] */ INVALID, INVALID, INVALID, INVALID, 825179237Sjb 826179237Sjb/* [C0] */ INVALID, INVALID, TNSZ("cmpsd",XMMP,8), INVALID, 827179237Sjb/* [C4] */ INVALID, INVALID, INVALID, INVALID, 828179237Sjb/* [C8] */ INVALID, INVALID, INVALID, INVALID, 829179237Sjb/* [CC] */ INVALID, INVALID, INVALID, INVALID, 830179237Sjb 831179237Sjb/* [D0] */ INVALID, INVALID, INVALID, INVALID, 832179237Sjb/* [D4] */ INVALID, INVALID, TNS("movdq2q",XMMXM), INVALID, 833179237Sjb/* [D8] */ INVALID, INVALID, INVALID, INVALID, 834179237Sjb/* [DC] */ INVALID, INVALID, INVALID, INVALID, 835179237Sjb 836179237Sjb/* [E0] */ INVALID, INVALID, INVALID, INVALID, 837179237Sjb/* [E4] */ INVALID, INVALID, TNSZ("cvtpd2dq",XMM,16),INVALID, 838179237Sjb/* [E8] */ INVALID, INVALID, INVALID, INVALID, 839179237Sjb/* [EC] */ INVALID, INVALID, INVALID, INVALID, 840179237Sjb 841179237Sjb/* [F0] */ INVALID, INVALID, INVALID, INVALID, 842179237Sjb/* [F4] */ INVALID, INVALID, INVALID, INVALID, 843179237Sjb/* [F8] */ INVALID, INVALID, INVALID, INVALID, 844179237Sjb/* [FC] */ INVALID, INVALID, INVALID, INVALID, 845179237Sjb}; 846179237Sjb 847253772Savgconst instable_t dis_opAVXF20F[256] = { 848253772Savg/* [00] */ INVALID, INVALID, INVALID, INVALID, 849253772Savg/* [04] */ INVALID, INVALID, INVALID, INVALID, 850253772Savg/* [08] */ INVALID, INVALID, INVALID, INVALID, 851253772Savg/* [0C] */ INVALID, INVALID, INVALID, INVALID, 852253772Savg 853253772Savg/* [10] */ TNSZ("vmovsd",VEX_RMrX,8), TNSZ("vmovsd",VEX_RRX,8), TNSZ("vmovddup",VEX_MX,8), INVALID, 854253772Savg/* [14] */ INVALID, INVALID, INVALID, INVALID, 855253772Savg/* [18] */ INVALID, INVALID, INVALID, INVALID, 856253772Savg/* [1C] */ INVALID, INVALID, INVALID, INVALID, 857253772Savg 858253772Savg/* [20] */ INVALID, INVALID, INVALID, INVALID, 859253772Savg/* [24] */ INVALID, INVALID, INVALID, INVALID, 860253772Savg/* [28] */ INVALID, INVALID, TNSZ("vcvtsi2sd",VEX_RMrX,4),INVALID, 861253772Savg/* [2C] */ TNSZ("vcvttsd2si",VEX_MR,8),TNSZ("vcvtsd2si",VEX_MR,8),INVALID, INVALID, 862253772Savg 863253772Savg/* [30] */ INVALID, INVALID, INVALID, INVALID, 864253772Savg/* [34] */ INVALID, INVALID, INVALID, INVALID, 865253772Savg/* [38] */ INVALID, INVALID, INVALID, INVALID, 866253772Savg/* [3C] */ INVALID, INVALID, INVALID, INVALID, 867253772Savg 868253772Savg/* [40] */ INVALID, INVALID, INVALID, INVALID, 869253772Savg/* [44] */ INVALID, INVALID, INVALID, INVALID, 870253772Savg/* [48] */ INVALID, INVALID, INVALID, INVALID, 871253772Savg/* [4C] */ INVALID, INVALID, INVALID, INVALID, 872253772Savg 873253772Savg/* [50] */ INVALID, TNSZ("vsqrtsd",VEX_RMrX,8), INVALID, INVALID, 874253772Savg/* [54] */ INVALID, INVALID, INVALID, INVALID, 875253772Savg/* [58] */ TNSZ("vaddsd",VEX_RMrX,8), TNSZ("vmulsd",VEX_RMrX,8), TNSZ("vcvtsd2ss",VEX_RMrX,8), INVALID, 876253772Savg/* [5C] */ TNSZ("vsubsd",VEX_RMrX,8), TNSZ("vminsd",VEX_RMrX,8), TNSZ("vdivsd",VEX_RMrX,8), TNSZ("vmaxsd",VEX_RMrX,8), 877253772Savg 878253772Savg/* [60] */ INVALID, INVALID, INVALID, INVALID, 879253772Savg/* [64] */ INVALID, INVALID, INVALID, INVALID, 880253772Savg/* [68] */ INVALID, INVALID, INVALID, INVALID, 881253772Savg/* [6C] */ INVALID, INVALID, INVALID, INVALID, 882253772Savg 883253772Savg/* [70] */ TNSZ("vpshuflw",VEX_MXI,16),INVALID, INVALID, INVALID, 884253772Savg/* [74] */ INVALID, INVALID, INVALID, INVALID, 885253772Savg/* [78] */ INVALID, INVALID, INVALID, INVALID, 886253772Savg/* [7C] */ TNSZ("vhaddps",VEX_RMrX,8), TNSZ("vhsubps",VEX_RMrX,8), INVALID, INVALID, 887253772Savg 888253772Savg/* [80] */ INVALID, INVALID, INVALID, INVALID, 889253772Savg/* [84] */ INVALID, INVALID, INVALID, INVALID, 890253772Savg/* [88] */ INVALID, INVALID, INVALID, INVALID, 891253772Savg/* [0C] */ INVALID, INVALID, INVALID, INVALID, 892253772Savg 893253772Savg/* [90] */ INVALID, INVALID, INVALID, INVALID, 894253772Savg/* [94] */ INVALID, INVALID, INVALID, INVALID, 895253772Savg/* [98] */ INVALID, INVALID, INVALID, INVALID, 896253772Savg/* [9C] */ INVALID, INVALID, INVALID, INVALID, 897253772Savg 898253772Savg/* [A0] */ INVALID, INVALID, INVALID, INVALID, 899253772Savg/* [A4] */ INVALID, INVALID, INVALID, INVALID, 900253772Savg/* [A8] */ INVALID, INVALID, INVALID, INVALID, 901253772Savg/* [AC] */ INVALID, INVALID, INVALID, INVALID, 902253772Savg 903253772Savg/* [B0] */ INVALID, INVALID, INVALID, INVALID, 904253772Savg/* [B4] */ INVALID, INVALID, INVALID, INVALID, 905253772Savg/* [B8] */ INVALID, INVALID, INVALID, INVALID, 906253772Savg/* [BC] */ INVALID, INVALID, INVALID, INVALID, 907253772Savg 908253772Savg/* [C0] */ INVALID, INVALID, TNSZ("vcmpsd",VEX_RMRX,8), INVALID, 909253772Savg/* [C4] */ INVALID, INVALID, INVALID, INVALID, 910253772Savg/* [C8] */ INVALID, INVALID, INVALID, INVALID, 911253772Savg/* [CC] */ INVALID, INVALID, INVALID, INVALID, 912253772Savg 913253772Savg/* [D0] */ TNSZ("vaddsubps",VEX_RMrX,8), INVALID, INVALID, INVALID, 914253772Savg/* [D4] */ INVALID, INVALID, INVALID, INVALID, 915253772Savg/* [D8] */ INVALID, INVALID, INVALID, INVALID, 916253772Savg/* [DC] */ INVALID, INVALID, INVALID, INVALID, 917253772Savg 918253772Savg/* [E0] */ INVALID, INVALID, INVALID, INVALID, 919253772Savg/* [E4] */ INVALID, INVALID, TNSZ("vcvtpd2dq",VEX_MX,16),INVALID, 920253772Savg/* [E8] */ INVALID, INVALID, INVALID, INVALID, 921253772Savg/* [EC] */ INVALID, INVALID, INVALID, INVALID, 922253772Savg 923253772Savg/* [F0] */ TNSZ("vlddqu",VEX_MX,16), INVALID, INVALID, INVALID, 924253772Savg/* [F4] */ INVALID, INVALID, INVALID, INVALID, 925253772Savg/* [F8] */ INVALID, INVALID, INVALID, INVALID, 926253772Savg/* [FC] */ INVALID, INVALID, INVALID, INVALID, 927253772Savg}; 928253772Savg 929179237Sjb/* 930179237Sjb * Decode table for SIMD instructions with the repz (0xf3) prefix. 931179237Sjb */ 932179237Sjbconst instable_t dis_opSIMDrepz[256] = { 933179237Sjb/* [00] */ INVALID, INVALID, INVALID, INVALID, 934179237Sjb/* [04] */ INVALID, INVALID, INVALID, INVALID, 935179237Sjb/* [08] */ INVALID, INVALID, INVALID, INVALID, 936179237Sjb/* [0C] */ INVALID, INVALID, INVALID, INVALID, 937179237Sjb 938179237Sjb/* [10] */ TNSZ("movss",XMM,4), TNSZ("movss",XMMS,4), INVALID, INVALID, 939179237Sjb/* [14] */ INVALID, INVALID, INVALID, INVALID, 940179237Sjb/* [18] */ INVALID, INVALID, INVALID, INVALID, 941179237Sjb/* [1C] */ INVALID, INVALID, INVALID, INVALID, 942179237Sjb 943179237Sjb/* [20] */ INVALID, INVALID, INVALID, INVALID, 944179237Sjb/* [24] */ INVALID, INVALID, INVALID, INVALID, 945253772Savg/* [28] */ INVALID, INVALID, TNSZ("cvtsi2ss",XMM3MX,4),TNSZ("movntss",XMMMS,4), 946179237Sjb/* [2C] */ TNSZ("cvttss2si",XMMXM3,4),TNSZ("cvtss2si",XMMXM3,4),INVALID, INVALID, 947179237Sjb 948179237Sjb/* [30] */ INVALID, INVALID, INVALID, INVALID, 949179237Sjb/* [34] */ INVALID, INVALID, INVALID, INVALID, 950179237Sjb/* [38] */ INVALID, INVALID, INVALID, INVALID, 951179237Sjb/* [3C] */ INVALID, INVALID, INVALID, INVALID, 952179237Sjb 953179237Sjb/* [40] */ INVALID, INVALID, INVALID, INVALID, 954179237Sjb/* [44] */ INVALID, INVALID, INVALID, INVALID, 955179237Sjb/* [48] */ INVALID, INVALID, INVALID, INVALID, 956179237Sjb/* [4C] */ INVALID, INVALID, INVALID, INVALID, 957179237Sjb 958179237Sjb/* [50] */ INVALID, TNSZ("sqrtss",XMM,4), TNSZ("rsqrtss",XMM,4), TNSZ("rcpss",XMM,4), 959179237Sjb/* [54] */ INVALID, INVALID, INVALID, INVALID, 960179237Sjb/* [58] */ TNSZ("addss",XMM,4), TNSZ("mulss",XMM,4), TNSZ("cvtss2sd",XMM,4), TNSZ("cvttps2dq",XMM,16), 961179237Sjb/* [5C] */ TNSZ("subss",XMM,4), TNSZ("minss",XMM,4), TNSZ("divss",XMM,4), TNSZ("maxss",XMM,4), 962179237Sjb 963179237Sjb/* [60] */ INVALID, INVALID, INVALID, INVALID, 964179237Sjb/* [64] */ INVALID, INVALID, INVALID, INVALID, 965179237Sjb/* [68] */ INVALID, INVALID, INVALID, INVALID, 966179237Sjb/* [6C] */ INVALID, INVALID, INVALID, TNSZ("movdqu",XMM,16), 967179237Sjb 968179237Sjb/* [70] */ TNSZ("pshufhw",XMMP,16),INVALID, INVALID, INVALID, 969179237Sjb/* [74] */ INVALID, INVALID, INVALID, INVALID, 970179237Sjb/* [78] */ INVALID, INVALID, INVALID, INVALID, 971179237Sjb/* [7C] */ INVALID, INVALID, TNSZ("movq",XMM,8), TNSZ("movdqu",XMMS,16), 972179237Sjb 973179237Sjb/* [80] */ INVALID, INVALID, INVALID, INVALID, 974179237Sjb/* [84] */ INVALID, INVALID, INVALID, INVALID, 975179237Sjb/* [88] */ INVALID, INVALID, INVALID, INVALID, 976179237Sjb/* [0C] */ INVALID, INVALID, INVALID, INVALID, 977179237Sjb 978179237Sjb/* [90] */ INVALID, INVALID, INVALID, INVALID, 979179237Sjb/* [94] */ INVALID, INVALID, INVALID, INVALID, 980179237Sjb/* [98] */ INVALID, INVALID, INVALID, INVALID, 981179237Sjb/* [9C] */ INVALID, INVALID, INVALID, INVALID, 982179237Sjb 983179237Sjb/* [A0] */ INVALID, INVALID, INVALID, INVALID, 984179237Sjb/* [A4] */ INVALID, INVALID, INVALID, INVALID, 985179237Sjb/* [A8] */ INVALID, INVALID, INVALID, INVALID, 986179237Sjb/* [AC] */ INVALID, INVALID, INVALID, INVALID, 987179237Sjb 988179237Sjb/* [B0] */ INVALID, INVALID, INVALID, INVALID, 989179237Sjb/* [B4] */ INVALID, INVALID, INVALID, INVALID, 990253772Savg/* [B8] */ TS("popcnt",MRw), INVALID, INVALID, INVALID, 991253772Savg/* [BC] */ INVALID, TS("lzcnt",MRw), INVALID, INVALID, 992179237Sjb 993179237Sjb/* [C0] */ INVALID, INVALID, TNSZ("cmpss",XMMP,4), INVALID, 994179237Sjb/* [C4] */ INVALID, INVALID, INVALID, INVALID, 995179237Sjb/* [C8] */ INVALID, INVALID, INVALID, INVALID, 996179237Sjb/* [CC] */ INVALID, INVALID, INVALID, INVALID, 997179237Sjb 998179237Sjb/* [D0] */ INVALID, INVALID, INVALID, INVALID, 999179237Sjb/* [D4] */ INVALID, INVALID, TNS("movq2dq",XMMMX), INVALID, 1000179237Sjb/* [D8] */ INVALID, INVALID, INVALID, INVALID, 1001179237Sjb/* [DC] */ INVALID, INVALID, INVALID, INVALID, 1002179237Sjb 1003179237Sjb/* [E0] */ INVALID, INVALID, INVALID, INVALID, 1004179237Sjb/* [E4] */ INVALID, INVALID, TNSZ("cvtdq2pd",XMM,8), INVALID, 1005179237Sjb/* [E8] */ INVALID, INVALID, INVALID, INVALID, 1006179237Sjb/* [EC] */ INVALID, INVALID, INVALID, INVALID, 1007179237Sjb 1008179237Sjb/* [F0] */ INVALID, INVALID, INVALID, INVALID, 1009179237Sjb/* [F4] */ INVALID, INVALID, INVALID, INVALID, 1010179237Sjb/* [F8] */ INVALID, INVALID, INVALID, INVALID, 1011179237Sjb/* [FC] */ INVALID, INVALID, INVALID, INVALID, 1012179237Sjb}; 1013179237Sjb 1014253772Savgconst instable_t dis_opAVXF30F[256] = { 1015253772Savg/* [00] */ INVALID, INVALID, INVALID, INVALID, 1016253772Savg/* [04] */ INVALID, INVALID, INVALID, INVALID, 1017253772Savg/* [08] */ INVALID, INVALID, INVALID, INVALID, 1018253772Savg/* [0C] */ INVALID, INVALID, INVALID, INVALID, 1019253772Savg 1020253772Savg/* [10] */ TNSZ("vmovss",VEX_RMrX,4), TNSZ("vmovss",VEX_RRX,4), TNSZ("vmovsldup",VEX_MX,4), INVALID, 1021253772Savg/* [14] */ INVALID, INVALID, TNSZ("vmovshdup",VEX_MX,4), INVALID, 1022253772Savg/* [18] */ INVALID, INVALID, INVALID, INVALID, 1023253772Savg/* [1C] */ INVALID, INVALID, INVALID, INVALID, 1024253772Savg 1025253772Savg/* [20] */ INVALID, INVALID, INVALID, INVALID, 1026253772Savg/* [24] */ INVALID, INVALID, INVALID, INVALID, 1027253772Savg/* [28] */ INVALID, INVALID, TNSZ("vcvtsi2ss",VEX_RMrX,4),INVALID, 1028253772Savg/* [2C] */ TNSZ("vcvttss2si",VEX_MR,4),TNSZ("vcvtss2si",VEX_MR,4),INVALID, INVALID, 1029253772Savg 1030253772Savg/* [30] */ INVALID, INVALID, INVALID, INVALID, 1031253772Savg/* [34] */ INVALID, INVALID, INVALID, INVALID, 1032253772Savg/* [38] */ INVALID, INVALID, INVALID, INVALID, 1033253772Savg/* [3C] */ INVALID, INVALID, INVALID, INVALID, 1034253772Savg 1035253772Savg/* [40] */ INVALID, INVALID, INVALID, INVALID, 1036253772Savg/* [44] */ INVALID, INVALID, INVALID, INVALID, 1037253772Savg/* [48] */ INVALID, INVALID, INVALID, INVALID, 1038253772Savg/* [4C] */ INVALID, INVALID, INVALID, INVALID, 1039253772Savg 1040253772Savg/* [50] */ INVALID, TNSZ("vsqrtss",VEX_RMrX,4), TNSZ("vrsqrtss",VEX_RMrX,4), TNSZ("vrcpss",VEX_RMrX,4), 1041253772Savg/* [54] */ INVALID, INVALID, INVALID, INVALID, 1042253772Savg/* [58] */ TNSZ("vaddss",VEX_RMrX,4), TNSZ("vmulss",VEX_RMrX,4), TNSZ("vcvtss2sd",VEX_RMrX,4), TNSZ("vcvttps2dq",VEX_MX,16), 1043253772Savg/* [5C] */ TNSZ("vsubss",VEX_RMrX,4), TNSZ("vminss",VEX_RMrX,4), TNSZ("vdivss",VEX_RMrX,4), TNSZ("vmaxss",VEX_RMrX,4), 1044253772Savg 1045253772Savg/* [60] */ INVALID, INVALID, INVALID, INVALID, 1046253772Savg/* [64] */ INVALID, INVALID, INVALID, INVALID, 1047253772Savg/* [68] */ INVALID, INVALID, INVALID, INVALID, 1048253772Savg/* [6C] */ INVALID, INVALID, INVALID, TNSZ("vmovdqu",VEX_MX,16), 1049253772Savg 1050253772Savg/* [70] */ TNSZ("vpshufhw",VEX_MXI,16),INVALID, INVALID, INVALID, 1051253772Savg/* [74] */ INVALID, INVALID, INVALID, INVALID, 1052253772Savg/* [78] */ INVALID, INVALID, INVALID, INVALID, 1053253772Savg/* [7C] */ INVALID, INVALID, TNSZ("vmovq",VEX_MX,8), TNSZ("vmovdqu",VEX_RX,16), 1054253772Savg 1055253772Savg/* [80] */ INVALID, INVALID, INVALID, INVALID, 1056253772Savg/* [84] */ INVALID, INVALID, INVALID, INVALID, 1057253772Savg/* [88] */ INVALID, INVALID, INVALID, INVALID, 1058253772Savg/* [0C] */ INVALID, INVALID, INVALID, INVALID, 1059253772Savg 1060253772Savg/* [90] */ INVALID, INVALID, INVALID, INVALID, 1061253772Savg/* [94] */ INVALID, INVALID, INVALID, INVALID, 1062253772Savg/* [98] */ INVALID, INVALID, INVALID, INVALID, 1063253772Savg/* [9C] */ INVALID, INVALID, INVALID, INVALID, 1064253772Savg 1065253772Savg/* [A0] */ INVALID, INVALID, INVALID, INVALID, 1066253772Savg/* [A4] */ INVALID, INVALID, INVALID, INVALID, 1067253772Savg/* [A8] */ INVALID, INVALID, INVALID, INVALID, 1068253772Savg/* [AC] */ INVALID, INVALID, INVALID, INVALID, 1069253772Savg 1070253772Savg/* [B0] */ INVALID, INVALID, INVALID, INVALID, 1071253772Savg/* [B4] */ INVALID, INVALID, INVALID, INVALID, 1072253772Savg/* [B8] */ INVALID, INVALID, INVALID, INVALID, 1073253772Savg/* [BC] */ INVALID, INVALID, INVALID, INVALID, 1074253772Savg 1075253772Savg/* [C0] */ INVALID, INVALID, TNSZ("vcmpss",VEX_RMRX,4), INVALID, 1076253772Savg/* [C4] */ INVALID, INVALID, INVALID, INVALID, 1077253772Savg/* [C8] */ INVALID, INVALID, INVALID, INVALID, 1078253772Savg/* [CC] */ INVALID, INVALID, INVALID, INVALID, 1079253772Savg 1080253772Savg/* [D0] */ INVALID, INVALID, INVALID, INVALID, 1081253772Savg/* [D4] */ INVALID, INVALID, INVALID, INVALID, 1082253772Savg/* [D8] */ INVALID, INVALID, INVALID, INVALID, 1083253772Savg/* [DC] */ INVALID, INVALID, INVALID, INVALID, 1084253772Savg 1085253772Savg/* [E0] */ INVALID, INVALID, INVALID, INVALID, 1086253772Savg/* [E4] */ INVALID, INVALID, TNSZ("vcvtdq2pd",VEX_MX,8), INVALID, 1087253772Savg/* [E8] */ INVALID, INVALID, INVALID, INVALID, 1088253772Savg/* [EC] */ INVALID, INVALID, INVALID, INVALID, 1089253772Savg 1090253772Savg/* [F0] */ INVALID, INVALID, INVALID, INVALID, 1091253772Savg/* [F4] */ INVALID, INVALID, INVALID, INVALID, 1092253772Savg/* [F8] */ INVALID, INVALID, INVALID, INVALID, 1093253772Savg/* [FC] */ INVALID, INVALID, INVALID, INVALID, 1094253772Savg}; 1095179237Sjb/* 1096253772Savg * The following two tables are used to encode crc32 and movbe 1097253772Savg * since they share the same opcodes. 1098253772Savg */ 1099253772Savgconst instable_t dis_op0F38F0[2] = { 1100253772Savg/* [00] */ TNS("crc32b",CRC32), 1101253772Savg TS("movbe",MOVBE), 1102253772Savg}; 1103253772Savg 1104253772Savgconst instable_t dis_op0F38F1[2] = { 1105253772Savg/* [00] */ TS("crc32",CRC32), 1106253772Savg TS("movbe",MOVBE), 1107253772Savg}; 1108253772Savg 1109253772Savgconst instable_t dis_op0F38[256] = { 1110253772Savg/* [00] */ TNSZ("pshufb",XMM_66o,16),TNSZ("phaddw",XMM_66o,16),TNSZ("phaddd",XMM_66o,16),TNSZ("phaddsw",XMM_66o,16), 1111253772Savg/* [04] */ TNSZ("pmaddubsw",XMM_66o,16),TNSZ("phsubw",XMM_66o,16), TNSZ("phsubd",XMM_66o,16),TNSZ("phsubsw",XMM_66o,16), 1112253772Savg/* [08] */ TNSZ("psignb",XMM_66o,16),TNSZ("psignw",XMM_66o,16),TNSZ("psignd",XMM_66o,16),TNSZ("pmulhrsw",XMM_66o,16), 1113253772Savg/* [0C] */ INVALID, INVALID, INVALID, INVALID, 1114253772Savg 1115253772Savg/* [10] */ TNSZ("pblendvb",XMM_66r,16),INVALID, INVALID, INVALID, 1116253772Savg/* [14] */ TNSZ("blendvps",XMM_66r,16),TNSZ("blendvpd",XMM_66r,16),INVALID, TNSZ("ptest",XMM_66r,16), 1117253772Savg/* [18] */ INVALID, INVALID, INVALID, INVALID, 1118253772Savg/* [1C] */ TNSZ("pabsb",XMM_66o,16),TNSZ("pabsw",XMM_66o,16),TNSZ("pabsd",XMM_66o,16),INVALID, 1119253772Savg 1120253772Savg/* [20] */ TNSZ("pmovsxbw",XMM_66r,16),TNSZ("pmovsxbd",XMM_66r,16),TNSZ("pmovsxbq",XMM_66r,16),TNSZ("pmovsxwd",XMM_66r,16), 1121253772Savg/* [24] */ TNSZ("pmovsxwq",XMM_66r,16),TNSZ("pmovsxdq",XMM_66r,16),INVALID, INVALID, 1122253772Savg/* [28] */ TNSZ("pmuldq",XMM_66r,16),TNSZ("pcmpeqq",XMM_66r,16),TNSZ("movntdqa",XMMM_66r,16),TNSZ("packusdw",XMM_66r,16), 1123253772Savg/* [2C] */ INVALID, INVALID, INVALID, INVALID, 1124253772Savg 1125253772Savg/* [30] */ TNSZ("pmovzxbw",XMM_66r,16),TNSZ("pmovzxbd",XMM_66r,16),TNSZ("pmovzxbq",XMM_66r,16),TNSZ("pmovzxwd",XMM_66r,16), 1126253772Savg/* [34] */ TNSZ("pmovzxwq",XMM_66r,16),TNSZ("pmovzxdq",XMM_66r,16),INVALID, TNSZ("pcmpgtq",XMM_66r,16), 1127253772Savg/* [38] */ TNSZ("pminsb",XMM_66r,16),TNSZ("pminsd",XMM_66r,16),TNSZ("pminuw",XMM_66r,16),TNSZ("pminud",XMM_66r,16), 1128253772Savg/* [3C] */ TNSZ("pmaxsb",XMM_66r,16),TNSZ("pmaxsd",XMM_66r,16),TNSZ("pmaxuw",XMM_66r,16),TNSZ("pmaxud",XMM_66r,16), 1129253772Savg 1130253772Savg/* [40] */ TNSZ("pmulld",XMM_66r,16),TNSZ("phminposuw",XMM_66r,16),INVALID, INVALID, 1131253772Savg/* [44] */ INVALID, INVALID, INVALID, INVALID, 1132253772Savg/* [48] */ INVALID, INVALID, INVALID, INVALID, 1133253772Savg/* [4C] */ INVALID, INVALID, INVALID, INVALID, 1134253772Savg 1135253772Savg/* [50] */ INVALID, INVALID, INVALID, INVALID, 1136253772Savg/* [54] */ INVALID, INVALID, INVALID, INVALID, 1137253772Savg/* [58] */ INVALID, INVALID, INVALID, INVALID, 1138253772Savg/* [5C] */ INVALID, INVALID, INVALID, INVALID, 1139253772Savg 1140253772Savg/* [60] */ INVALID, INVALID, INVALID, INVALID, 1141253772Savg/* [64] */ INVALID, INVALID, INVALID, INVALID, 1142253772Savg/* [68] */ INVALID, INVALID, INVALID, INVALID, 1143253772Savg/* [6C] */ INVALID, INVALID, INVALID, INVALID, 1144253772Savg 1145253772Savg/* [70] */ INVALID, INVALID, INVALID, INVALID, 1146253772Savg/* [74] */ INVALID, INVALID, INVALID, INVALID, 1147253772Savg/* [78] */ INVALID, INVALID, INVALID, INVALID, 1148253772Savg/* [7C] */ INVALID, INVALID, INVALID, INVALID, 1149253772Savg 1150253772Savg/* [80] */ INVALID, INVALID, INVALID, INVALID, 1151253772Savg/* [84] */ INVALID, INVALID, INVALID, INVALID, 1152253772Savg/* [88] */ INVALID, INVALID, INVALID, INVALID, 1153253772Savg/* [8C] */ INVALID, INVALID, INVALID, INVALID, 1154253772Savg 1155253772Savg/* [90] */ INVALID, INVALID, INVALID, INVALID, 1156253772Savg/* [94] */ INVALID, INVALID, INVALID, INVALID, 1157253772Savg/* [98] */ INVALID, INVALID, INVALID, INVALID, 1158253772Savg/* [9C] */ INVALID, INVALID, INVALID, INVALID, 1159253772Savg 1160253772Savg/* [A0] */ INVALID, INVALID, INVALID, INVALID, 1161253772Savg/* [A4] */ INVALID, INVALID, INVALID, INVALID, 1162253772Savg/* [A8] */ INVALID, INVALID, INVALID, INVALID, 1163253772Savg/* [AC] */ INVALID, INVALID, INVALID, INVALID, 1164253772Savg 1165253772Savg/* [B0] */ INVALID, INVALID, INVALID, INVALID, 1166253772Savg/* [B4] */ INVALID, INVALID, INVALID, INVALID, 1167253772Savg/* [B8] */ INVALID, INVALID, INVALID, INVALID, 1168253772Savg/* [BC] */ INVALID, INVALID, INVALID, INVALID, 1169253772Savg 1170253772Savg/* [C0] */ INVALID, INVALID, INVALID, INVALID, 1171253772Savg/* [C4] */ INVALID, INVALID, INVALID, INVALID, 1172253772Savg/* [C8] */ INVALID, INVALID, INVALID, INVALID, 1173253772Savg/* [CC] */ INVALID, INVALID, INVALID, INVALID, 1174253772Savg 1175253772Savg/* [D0] */ INVALID, INVALID, INVALID, INVALID, 1176253772Savg/* [D4] */ INVALID, INVALID, INVALID, INVALID, 1177253772Savg/* [D8] */ INVALID, INVALID, INVALID, TNSZ("aesimc",XMM_66r,16), 1178253772Savg/* [DC] */ TNSZ("aesenc",XMM_66r,16),TNSZ("aesenclast",XMM_66r,16),TNSZ("aesdec",XMM_66r,16),TNSZ("aesdeclast",XMM_66r,16), 1179253772Savg 1180253772Savg/* [E0] */ INVALID, INVALID, INVALID, INVALID, 1181253772Savg/* [E4] */ INVALID, INVALID, INVALID, INVALID, 1182253772Savg/* [E8] */ INVALID, INVALID, INVALID, INVALID, 1183253772Savg/* [EC] */ INVALID, INVALID, INVALID, INVALID, 1184253772Savg/* [F0] */ IND(dis_op0F38F0), IND(dis_op0F38F1), INVALID, INVALID, 1185253772Savg/* [F4] */ INVALID, INVALID, INVALID, INVALID, 1186253772Savg/* [F8] */ INVALID, INVALID, INVALID, INVALID, 1187253772Savg/* [FC] */ INVALID, INVALID, INVALID, INVALID, 1188253772Savg}; 1189253772Savg 1190253772Savgconst instable_t dis_opAVX660F38[256] = { 1191253772Savg/* [00] */ TNSZ("vpshufb",VEX_RMrX,16),TNSZ("vphaddw",VEX_RMrX,16),TNSZ("vphaddd",VEX_RMrX,16),TNSZ("vphaddsw",VEX_RMrX,16), 1192253772Savg/* [04] */ TNSZ("vpmaddubsw",VEX_RMrX,16),TNSZ("vphsubw",VEX_RMrX,16), TNSZ("vphsubd",VEX_RMrX,16),TNSZ("vphsubsw",VEX_RMrX,16), 1193253772Savg/* [08] */ TNSZ("vpsignb",VEX_RMrX,16),TNSZ("vpsignw",VEX_RMrX,16),TNSZ("vpsignd",VEX_RMrX,16),TNSZ("vpmulhrsw",VEX_RMrX,16), 1194253772Savg/* [0C] */ TNSZ("vpermilps",VEX_RMrX,8),TNSZ("vpermilpd",VEX_RMrX,16),TNSZ("vtestps",VEX_RRI,8), TNSZ("vtestpd",VEX_RRI,16), 1195253772Savg 1196253772Savg/* [10] */ INVALID, INVALID, INVALID, INVALID, 1197253772Savg/* [14] */ INVALID, INVALID, INVALID, TNSZ("vptest",VEX_RRI,16), 1198253772Savg/* [18] */ TNSZ("vbroadcastss",VEX_MX,4),TNSZ("vbroadcastsd",VEX_MX,8),TNSZ("vbroadcastf128",VEX_MX,16),INVALID, 1199253772Savg/* [1C] */ TNSZ("vpabsb",VEX_MX,16),TNSZ("vpabsw",VEX_MX,16),TNSZ("vpabsd",VEX_MX,16),INVALID, 1200253772Savg 1201253772Savg/* [20] */ TNSZ("vpmovsxbw",VEX_MX,16),TNSZ("vpmovsxbd",VEX_MX,16),TNSZ("vpmovsxbq",VEX_MX,16),TNSZ("vpmovsxwd",VEX_MX,16), 1202253772Savg/* [24] */ TNSZ("vpmovsxwq",VEX_MX,16),TNSZ("vpmovsxdq",VEX_MX,16),INVALID, INVALID, 1203253772Savg/* [28] */ TNSZ("vpmuldq",VEX_RMrX,16),TNSZ("vpcmpeqq",VEX_RMrX,16),TNSZ("vmovntdqa",VEX_MX,16),TNSZ("vpackusdw",VEX_RMrX,16), 1204253772Savg/* [2C] */ TNSZ("vmaskmovps",VEX_RMrX,8),TNSZ("vmaskmovpd",VEX_RMrX,16),TNSZ("vmaskmovps",VEX_RRM,8),TNSZ("vmaskmovpd",VEX_RRM,16), 1205253772Savg 1206253772Savg/* [30] */ TNSZ("vpmovzxbw",VEX_MX,16),TNSZ("vpmovzxbd",VEX_MX,16),TNSZ("vpmovzxbq",VEX_MX,16),TNSZ("vpmovzxwd",VEX_MX,16), 1207253772Savg/* [34] */ TNSZ("vpmovzxwq",VEX_MX,16),TNSZ("vpmovzxdq",VEX_MX,16),INVALID, TNSZ("vpcmpgtq",VEX_RMrX,16), 1208253772Savg/* [38] */ TNSZ("vpminsb",VEX_RMrX,16),TNSZ("vpminsd",VEX_RMrX,16),TNSZ("vpminuw",VEX_RMrX,16),TNSZ("vpminud",VEX_RMrX,16), 1209253772Savg/* [3C] */ TNSZ("vpmaxsb",VEX_RMrX,16),TNSZ("vpmaxsd",VEX_RMrX,16),TNSZ("vpmaxuw",VEX_RMrX,16),TNSZ("vpmaxud",VEX_RMrX,16), 1210253772Savg 1211253772Savg/* [40] */ TNSZ("vpmulld",VEX_RMrX,16),TNSZ("vphminposuw",VEX_MX,16),INVALID, INVALID, 1212253772Savg/* [44] */ INVALID, INVALID, INVALID, INVALID, 1213253772Savg/* [48] */ INVALID, INVALID, INVALID, INVALID, 1214253772Savg/* [4C] */ INVALID, INVALID, INVALID, INVALID, 1215253772Savg 1216253772Savg/* [50] */ INVALID, INVALID, INVALID, INVALID, 1217253772Savg/* [54] */ INVALID, INVALID, INVALID, INVALID, 1218253772Savg/* [58] */ INVALID, INVALID, INVALID, INVALID, 1219253772Savg/* [5C] */ INVALID, INVALID, INVALID, INVALID, 1220253772Savg 1221253772Savg/* [60] */ INVALID, INVALID, INVALID, INVALID, 1222253772Savg/* [64] */ INVALID, INVALID, INVALID, INVALID, 1223253772Savg/* [68] */ INVALID, INVALID, INVALID, INVALID, 1224253772Savg/* [6C] */ INVALID, INVALID, INVALID, INVALID, 1225253772Savg 1226253772Savg/* [70] */ INVALID, INVALID, INVALID, INVALID, 1227253772Savg/* [74] */ INVALID, INVALID, INVALID, INVALID, 1228253772Savg/* [78] */ INVALID, INVALID, INVALID, INVALID, 1229253772Savg/* [7C] */ INVALID, INVALID, INVALID, INVALID, 1230253772Savg 1231253772Savg/* [80] */ INVALID, INVALID, INVALID, INVALID, 1232253772Savg/* [84] */ INVALID, INVALID, INVALID, INVALID, 1233253772Savg/* [88] */ INVALID, INVALID, INVALID, INVALID, 1234253772Savg/* [8C] */ INVALID, INVALID, INVALID, INVALID, 1235253772Savg 1236253772Savg/* [90] */ INVALID, INVALID, INVALID, INVALID, 1237253772Savg/* [94] */ INVALID, INVALID, INVALID, INVALID, 1238253772Savg/* [98] */ INVALID, INVALID, INVALID, INVALID, 1239253772Savg/* [9C] */ INVALID, INVALID, INVALID, INVALID, 1240253772Savg 1241253772Savg/* [A0] */ INVALID, INVALID, INVALID, INVALID, 1242253772Savg/* [A4] */ INVALID, INVALID, INVALID, INVALID, 1243253772Savg/* [A8] */ INVALID, INVALID, INVALID, INVALID, 1244253772Savg/* [AC] */ INVALID, INVALID, INVALID, INVALID, 1245253772Savg 1246253772Savg/* [B0] */ INVALID, INVALID, INVALID, INVALID, 1247253772Savg/* [B4] */ INVALID, INVALID, INVALID, INVALID, 1248253772Savg/* [B8] */ INVALID, INVALID, INVALID, INVALID, 1249253772Savg/* [BC] */ INVALID, INVALID, INVALID, INVALID, 1250253772Savg 1251253772Savg/* [C0] */ INVALID, INVALID, INVALID, INVALID, 1252253772Savg/* [C4] */ INVALID, INVALID, INVALID, INVALID, 1253253772Savg/* [C8] */ INVALID, INVALID, INVALID, INVALID, 1254253772Savg/* [CC] */ INVALID, INVALID, INVALID, INVALID, 1255253772Savg 1256253772Savg/* [D0] */ INVALID, INVALID, INVALID, INVALID, 1257253772Savg/* [D4] */ INVALID, INVALID, INVALID, INVALID, 1258253772Savg/* [D8] */ INVALID, INVALID, INVALID, TNSZ("vaesimc",VEX_MX,16), 1259253772Savg/* [DC] */ TNSZ("vaesenc",VEX_RMrX,16),TNSZ("vaesenclast",VEX_RMrX,16),TNSZ("vaesdec",VEX_RMrX,16),TNSZ("vaesdeclast",VEX_RMrX,16), 1260253772Savg 1261253772Savg/* [E0] */ INVALID, INVALID, INVALID, INVALID, 1262253772Savg/* [E4] */ INVALID, INVALID, INVALID, INVALID, 1263253772Savg/* [E8] */ INVALID, INVALID, INVALID, INVALID, 1264253772Savg/* [EC] */ INVALID, INVALID, INVALID, INVALID, 1265253772Savg/* [F0] */ IND(dis_op0F38F0), IND(dis_op0F38F1), INVALID, INVALID, 1266253772Savg/* [F4] */ INVALID, INVALID, INVALID, INVALID, 1267253772Savg/* [F8] */ INVALID, INVALID, INVALID, INVALID, 1268253772Savg/* [FC] */ INVALID, INVALID, INVALID, INVALID, 1269253772Savg}; 1270253772Savg 1271253772Savgconst instable_t dis_op0F3A[256] = { 1272253772Savg/* [00] */ INVALID, INVALID, INVALID, INVALID, 1273253772Savg/* [04] */ INVALID, INVALID, INVALID, INVALID, 1274253772Savg/* [08] */ TNSZ("roundps",XMMP_66r,16),TNSZ("roundpd",XMMP_66r,16),TNSZ("roundss",XMMP_66r,16),TNSZ("roundsd",XMMP_66r,16), 1275253772Savg/* [0C] */ TNSZ("blendps",XMMP_66r,16),TNSZ("blendpd",XMMP_66r,16),TNSZ("pblendw",XMMP_66r,16),TNSZ("palignr",XMMP_66o,16), 1276253772Savg 1277253772Savg/* [10] */ INVALID, INVALID, INVALID, INVALID, 1278253772Savg/* [14] */ TNSZ("pextrb",XMM3PM_66r,8),TNSZ("pextrw",XMM3PM_66r,16),TSZ("pextr",XMM3PM_66r,16),TNSZ("extractps",XMM3PM_66r,16), 1279253772Savg/* [18] */ INVALID, INVALID, INVALID, INVALID, 1280253772Savg/* [1C] */ INVALID, INVALID, INVALID, INVALID, 1281253772Savg 1282253772Savg/* [20] */ TNSZ("pinsrb",XMMPRM_66r,8),TNSZ("insertps",XMMP_66r,16),TSZ("pinsr",XMMPRM_66r,16),INVALID, 1283253772Savg/* [24] */ INVALID, INVALID, INVALID, INVALID, 1284253772Savg/* [28] */ INVALID, INVALID, INVALID, INVALID, 1285253772Savg/* [2C] */ INVALID, INVALID, INVALID, INVALID, 1286253772Savg 1287253772Savg/* [30] */ INVALID, INVALID, INVALID, INVALID, 1288253772Savg/* [34] */ INVALID, INVALID, INVALID, INVALID, 1289253772Savg/* [38] */ INVALID, INVALID, INVALID, INVALID, 1290253772Savg/* [3C] */ INVALID, INVALID, INVALID, INVALID, 1291253772Savg 1292253772Savg/* [40] */ TNSZ("dpps",XMMP_66r,16),TNSZ("dppd",XMMP_66r,16),TNSZ("mpsadbw",XMMP_66r,16),INVALID, 1293253772Savg/* [44] */ TNSZ("pclmulqdq",XMMP_66r,16),INVALID, INVALID, INVALID, 1294253772Savg/* [48] */ INVALID, INVALID, INVALID, INVALID, 1295253772Savg/* [4C] */ INVALID, INVALID, INVALID, INVALID, 1296253772Savg 1297253772Savg/* [50] */ INVALID, INVALID, INVALID, INVALID, 1298253772Savg/* [54] */ INVALID, INVALID, INVALID, INVALID, 1299253772Savg/* [58] */ INVALID, INVALID, INVALID, INVALID, 1300253772Savg/* [5C] */ INVALID, INVALID, INVALID, INVALID, 1301253772Savg 1302253772Savg/* [60] */ TNSZ("pcmpestrm",XMMP_66r,16),TNSZ("pcmpestri",XMMP_66r,16),TNSZ("pcmpistrm",XMMP_66r,16),TNSZ("pcmpistri",XMMP_66r,16), 1303253772Savg/* [64] */ INVALID, INVALID, INVALID, INVALID, 1304253772Savg/* [68] */ INVALID, INVALID, INVALID, INVALID, 1305253772Savg/* [6C] */ INVALID, INVALID, INVALID, INVALID, 1306253772Savg 1307253772Savg/* [70] */ INVALID, INVALID, INVALID, INVALID, 1308253772Savg/* [74] */ INVALID, INVALID, INVALID, INVALID, 1309253772Savg/* [78] */ INVALID, INVALID, INVALID, INVALID, 1310253772Savg/* [7C] */ INVALID, INVALID, INVALID, INVALID, 1311253772Savg 1312253772Savg/* [80] */ INVALID, INVALID, INVALID, INVALID, 1313253772Savg/* [84] */ INVALID, INVALID, INVALID, INVALID, 1314253772Savg/* [88] */ INVALID, INVALID, INVALID, INVALID, 1315253772Savg/* [8C] */ INVALID, INVALID, INVALID, INVALID, 1316253772Savg 1317253772Savg/* [90] */ INVALID, INVALID, INVALID, INVALID, 1318253772Savg/* [94] */ INVALID, INVALID, INVALID, INVALID, 1319253772Savg/* [98] */ INVALID, INVALID, INVALID, INVALID, 1320253772Savg/* [9C] */ INVALID, INVALID, INVALID, INVALID, 1321253772Savg 1322253772Savg/* [A0] */ INVALID, INVALID, INVALID, INVALID, 1323253772Savg/* [A4] */ INVALID, INVALID, INVALID, INVALID, 1324253772Savg/* [A8] */ INVALID, INVALID, INVALID, INVALID, 1325253772Savg/* [AC] */ INVALID, INVALID, INVALID, INVALID, 1326253772Savg 1327253772Savg/* [B0] */ INVALID, INVALID, INVALID, INVALID, 1328253772Savg/* [B4] */ INVALID, INVALID, INVALID, INVALID, 1329253772Savg/* [B8] */ INVALID, INVALID, INVALID, INVALID, 1330253772Savg/* [BC] */ INVALID, INVALID, INVALID, INVALID, 1331253772Savg 1332253772Savg/* [C0] */ INVALID, INVALID, INVALID, INVALID, 1333253772Savg/* [C4] */ INVALID, INVALID, INVALID, INVALID, 1334253772Savg/* [C8] */ INVALID, INVALID, INVALID, INVALID, 1335253772Savg/* [CC] */ INVALID, INVALID, INVALID, INVALID, 1336253772Savg 1337253772Savg/* [D0] */ INVALID, INVALID, INVALID, INVALID, 1338253772Savg/* [D4] */ INVALID, INVALID, INVALID, INVALID, 1339253772Savg/* [D8] */ INVALID, INVALID, INVALID, INVALID, 1340253772Savg/* [DC] */ INVALID, INVALID, INVALID, TNSZ("aeskeygenassist",XMMP_66r,16), 1341253772Savg 1342253772Savg/* [E0] */ INVALID, INVALID, INVALID, INVALID, 1343253772Savg/* [E4] */ INVALID, INVALID, INVALID, INVALID, 1344253772Savg/* [E8] */ INVALID, INVALID, INVALID, INVALID, 1345253772Savg/* [EC] */ INVALID, INVALID, INVALID, INVALID, 1346253772Savg 1347253772Savg/* [F0] */ INVALID, INVALID, INVALID, INVALID, 1348253772Savg/* [F4] */ INVALID, INVALID, INVALID, INVALID, 1349253772Savg/* [F8] */ INVALID, INVALID, INVALID, INVALID, 1350253772Savg/* [FC] */ INVALID, INVALID, INVALID, INVALID, 1351253772Savg}; 1352253772Savg 1353253772Savgconst instable_t dis_opAVX660F3A[256] = { 1354253772Savg/* [00] */ INVALID, INVALID, INVALID, INVALID, 1355253772Savg/* [04] */ TNSZ("vpermilps",VEX_MXI,8),TNSZ("vpermilpd",VEX_MXI,16),TNSZ("vperm2f128",VEX_RMRX,16),INVALID, 1356253772Savg/* [08] */ TNSZ("vroundps",VEX_MXI,16),TNSZ("vroundpd",VEX_MXI,16),TNSZ("vroundss",VEX_RMRX,16),TNSZ("vroundsd",VEX_RMRX,16), 1357253772Savg/* [0C] */ TNSZ("vblendps",VEX_RMRX,16),TNSZ("vblendpd",VEX_RMRX,16),TNSZ("vpblendw",VEX_RMRX,16),TNSZ("vpalignr",VEX_RMRX,16), 1358253772Savg 1359253772Savg/* [10] */ INVALID, INVALID, INVALID, INVALID, 1360253772Savg/* [14] */ TNSZ("vpextrb",VEX_RRi,8),TNSZ("vpextrw",VEX_RRi,16),TNSZ("vpextrd",VEX_RRi,16),TNSZ("vextractps",VEX_RM,16), 1361253772Savg/* [18] */ TNSZ("vinsertf128",VEX_RMRX,16),TNSZ("vextractf128",VEX_RX,16),INVALID, INVALID, 1362253772Savg/* [1C] */ INVALID, INVALID, INVALID, INVALID, 1363253772Savg 1364253772Savg/* [20] */ TNSZ("vpinsrb",VEX_RMRX,8),TNSZ("vinsertps",VEX_RMRX,16),TNSZ("vpinsrd",VEX_RMRX,16),INVALID, 1365253772Savg/* [24] */ INVALID, INVALID, INVALID, INVALID, 1366253772Savg/* [28] */ INVALID, INVALID, INVALID, INVALID, 1367253772Savg/* [2C] */ INVALID, INVALID, INVALID, INVALID, 1368253772Savg 1369253772Savg/* [30] */ INVALID, INVALID, INVALID, INVALID, 1370253772Savg/* [34] */ INVALID, INVALID, INVALID, INVALID, 1371253772Savg/* [38] */ INVALID, INVALID, INVALID, INVALID, 1372253772Savg/* [3C] */ INVALID, INVALID, INVALID, INVALID, 1373253772Savg 1374253772Savg/* [40] */ TNSZ("vdpps",VEX_RMRX,16),TNSZ("vdppd",VEX_RMRX,16),TNSZ("vmpsadbw",VEX_RMRX,16),INVALID, 1375253772Savg/* [44] */ TNSZ("vpclmulqdq",VEX_RMRX,16),INVALID, INVALID, INVALID, 1376253772Savg/* [48] */ INVALID, INVALID, TNSZ("vblendvps",VEX_RMRX,8), TNSZ("vblendvpd",VEX_RMRX,16), 1377253772Savg/* [4C] */ TNSZ("vpblendvb",VEX_RMRX,16),INVALID, INVALID, INVALID, 1378253772Savg 1379253772Savg/* [50] */ INVALID, INVALID, INVALID, INVALID, 1380253772Savg/* [54] */ INVALID, INVALID, INVALID, INVALID, 1381253772Savg/* [58] */ INVALID, INVALID, INVALID, INVALID, 1382253772Savg/* [5C] */ INVALID, INVALID, INVALID, INVALID, 1383253772Savg 1384253772Savg/* [60] */ TNSZ("vpcmpestrm",VEX_MXI,16),TNSZ("vpcmpestri",VEX_MXI,16),TNSZ("vpcmpistrm",VEX_MXI,16),TNSZ("vpcmpistri",VEX_MXI,16), 1385253772Savg/* [64] */ INVALID, INVALID, INVALID, INVALID, 1386253772Savg/* [68] */ INVALID, INVALID, INVALID, INVALID, 1387253772Savg/* [6C] */ INVALID, INVALID, INVALID, INVALID, 1388253772Savg 1389253772Savg/* [70] */ INVALID, INVALID, INVALID, INVALID, 1390253772Savg/* [74] */ INVALID, INVALID, INVALID, INVALID, 1391253772Savg/* [78] */ INVALID, INVALID, INVALID, INVALID, 1392253772Savg/* [7C] */ INVALID, INVALID, INVALID, INVALID, 1393253772Savg 1394253772Savg/* [80] */ INVALID, INVALID, INVALID, INVALID, 1395253772Savg/* [84] */ INVALID, INVALID, INVALID, INVALID, 1396253772Savg/* [88] */ INVALID, INVALID, INVALID, INVALID, 1397253772Savg/* [8C] */ INVALID, INVALID, INVALID, INVALID, 1398253772Savg 1399253772Savg/* [90] */ INVALID, INVALID, INVALID, INVALID, 1400253772Savg/* [94] */ INVALID, INVALID, INVALID, INVALID, 1401253772Savg/* [98] */ INVALID, INVALID, INVALID, INVALID, 1402253772Savg/* [9C] */ INVALID, INVALID, INVALID, INVALID, 1403253772Savg 1404253772Savg/* [A0] */ INVALID, INVALID, INVALID, INVALID, 1405253772Savg/* [A4] */ INVALID, INVALID, INVALID, INVALID, 1406253772Savg/* [A8] */ INVALID, INVALID, INVALID, INVALID, 1407253772Savg/* [AC] */ INVALID, INVALID, INVALID, INVALID, 1408253772Savg 1409253772Savg/* [B0] */ INVALID, INVALID, INVALID, INVALID, 1410253772Savg/* [B4] */ INVALID, INVALID, INVALID, INVALID, 1411253772Savg/* [B8] */ INVALID, INVALID, INVALID, INVALID, 1412253772Savg/* [BC] */ INVALID, INVALID, INVALID, INVALID, 1413253772Savg 1414253772Savg/* [C0] */ INVALID, INVALID, INVALID, INVALID, 1415253772Savg/* [C4] */ INVALID, INVALID, INVALID, INVALID, 1416253772Savg/* [C8] */ INVALID, INVALID, INVALID, INVALID, 1417253772Savg/* [CC] */ INVALID, INVALID, INVALID, INVALID, 1418253772Savg 1419253772Savg/* [D0] */ INVALID, INVALID, INVALID, INVALID, 1420253772Savg/* [D4] */ INVALID, INVALID, INVALID, INVALID, 1421253772Savg/* [D8] */ INVALID, INVALID, INVALID, INVALID, 1422253772Savg/* [DC] */ INVALID, INVALID, INVALID, TNSZ("vaeskeygenassist",VEX_MXI,16), 1423253772Savg 1424253772Savg/* [E0] */ INVALID, INVALID, INVALID, INVALID, 1425253772Savg/* [E4] */ INVALID, INVALID, INVALID, INVALID, 1426253772Savg/* [E8] */ INVALID, INVALID, INVALID, INVALID, 1427253772Savg/* [EC] */ INVALID, INVALID, INVALID, INVALID, 1428253772Savg 1429253772Savg/* [F0] */ INVALID, INVALID, INVALID, INVALID, 1430253772Savg/* [F4] */ INVALID, INVALID, INVALID, INVALID, 1431253772Savg/* [F8] */ INVALID, INVALID, INVALID, INVALID, 1432253772Savg/* [FC] */ INVALID, INVALID, INVALID, INVALID, 1433253772Savg}; 1434253772Savg 1435253772Savg/* 1436179237Sjb * Decode table for 0x0F opcodes 1437179237Sjb */ 1438179237Sjb 1439179237Sjbconst instable_t dis_op0F[16][16] = { 1440179237Sjb{ 1441179237Sjb/* [00] */ IND(dis_op0F00), IND(dis_op0F01), TNS("lar",MR), TNS("lsl",MR), 1442179237Sjb/* [04] */ INVALID, TNS("syscall",NORM), TNS("clts",NORM), TNS("sysret",NORM), 1443179237Sjb/* [08] */ TNS("invd",NORM), TNS("wbinvd",NORM), INVALID, TNS("ud2",NORM), 1444179237Sjb/* [0C] */ INVALID, INVALID, INVALID, INVALID, 1445179237Sjb}, { 1446179237Sjb/* [10] */ TNSZ("movups",XMMO,16), TNSZ("movups",XMMOS,16),TNSZ("movlps",XMMO,8), TNSZ("movlps",XMMOS,8), 1447179237Sjb/* [14] */ TNSZ("unpcklps",XMMO,16),TNSZ("unpckhps",XMMO,16),TNSZ("movhps",XMMOM,8),TNSZ("movhps",XMMOMS,8), 1448179237Sjb/* [18] */ IND(dis_op0F18), INVALID, INVALID, INVALID, 1449238169Savg/* [1C] */ INVALID, INVALID, INVALID, TS("nopw", Mw), 1450179237Sjb}, { 1451179237Sjb/* [20] */ TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG), 1452179237Sjb/* [24] */ TSx("mov",SREG), INVALID, TSx("mov",SREG), INVALID, 1453179237Sjb/* [28] */ TNSZ("movaps",XMMO,16), TNSZ("movaps",XMMOS,16),TNSZ("cvtpi2ps",XMMOMX,8),TNSZ("movntps",XMMOS,16), 1454179237Sjb/* [2C] */ TNSZ("cvttps2pi",XMMOXMM,8),TNSZ("cvtps2pi",XMMOXMM,8),TNSZ("ucomiss",XMMO,4),TNSZ("comiss",XMMO,4), 1455179237Sjb}, { 1456179237Sjb/* [30] */ TNS("wrmsr",NORM), TNS("rdtsc",NORM), TNS("rdmsr",NORM), TNS("rdpmc",NORM), 1457179237Sjb/* [34] */ TNSx("sysenter",NORM), TNSx("sysexit",NORM), INVALID, INVALID, 1458179237Sjb/* [38] */ INVALID, INVALID, INVALID, INVALID, 1459179237Sjb/* [3C] */ INVALID, INVALID, INVALID, INVALID, 1460179237Sjb}, { 1461179237Sjb/* [40] */ TS("cmovx.o",MR), TS("cmovx.no",MR), TS("cmovx.b",MR), TS("cmovx.ae",MR), 1462179237Sjb/* [44] */ TS("cmovx.e",MR), TS("cmovx.ne",MR), TS("cmovx.be",MR), TS("cmovx.a",MR), 1463179237Sjb/* [48] */ TS("cmovx.s",MR), TS("cmovx.ns",MR), TS("cmovx.pe",MR), TS("cmovx.po",MR), 1464179237Sjb/* [4C] */ TS("cmovx.l",MR), TS("cmovx.ge",MR), TS("cmovx.le",MR), TS("cmovx.g",MR), 1465179237Sjb}, { 1466179237Sjb/* [50] */ TNS("movmskps",XMMOX3), TNSZ("sqrtps",XMMO,16), TNSZ("rsqrtps",XMMO,16),TNSZ("rcpps",XMMO,16), 1467179237Sjb/* [54] */ TNSZ("andps",XMMO,16), TNSZ("andnps",XMMO,16), TNSZ("orps",XMMO,16), TNSZ("xorps",XMMO,16), 1468179237Sjb/* [58] */ TNSZ("addps",XMMO,16), TNSZ("mulps",XMMO,16), TNSZ("cvtps2pd",XMMO,8),TNSZ("cvtdq2ps",XMMO,16), 1469179237Sjb/* [5C] */ TNSZ("subps",XMMO,16), TNSZ("minps",XMMO,16), TNSZ("divps",XMMO,16), TNSZ("maxps",XMMO,16), 1470179237Sjb}, { 1471179237Sjb/* [60] */ TNSZ("punpcklbw",MMO,4),TNSZ("punpcklwd",MMO,4),TNSZ("punpckldq",MMO,4),TNSZ("packsswb",MMO,8), 1472179237Sjb/* [64] */ TNSZ("pcmpgtb",MMO,8), TNSZ("pcmpgtw",MMO,8), TNSZ("pcmpgtd",MMO,8), TNSZ("packuswb",MMO,8), 1473179237Sjb/* [68] */ TNSZ("punpckhbw",MMO,8),TNSZ("punpckhwd",MMO,8),TNSZ("punpckhdq",MMO,8),TNSZ("packssdw",MMO,8), 1474179237Sjb/* [6C] */ TNSZ("INVALID",MMO,0), TNSZ("INVALID",MMO,0), TNSZ("movd",MMO,4), TNSZ("movq",MMO,8), 1475179237Sjb}, { 1476179237Sjb/* [70] */ TNSZ("pshufw",MMOPM,8), TNS("psrXXX",MR), TNS("psrXXX",MR), TNS("psrXXX",MR), 1477179237Sjb/* [74] */ TNSZ("pcmpeqb",MMO,8), TNSZ("pcmpeqw",MMO,8), TNSZ("pcmpeqd",MMO,8), TNS("emms",NORM), 1478253772Savg/* [78] */ TNS("INVALID",XMMO), TNS("INVALID",XMMO), INVALID, INVALID, 1479179237Sjb/* [7C] */ INVALID, INVALID, TNSZ("movd",MMOS,4), TNSZ("movq",MMOS,8), 1480179237Sjb}, { 1481179237Sjb/* [80] */ TNS("jo",D), TNS("jno",D), TNS("jb",D), TNS("jae",D), 1482179237Sjb/* [84] */ TNS("je",D), TNS("jne",D), TNS("jbe",D), TNS("ja",D), 1483179237Sjb/* [88] */ TNS("js",D), TNS("jns",D), TNS("jp",D), TNS("jnp",D), 1484179237Sjb/* [8C] */ TNS("jl",D), TNS("jge",D), TNS("jle",D), TNS("jg",D), 1485179237Sjb}, { 1486179237Sjb/* [90] */ TNS("seto",Mb), TNS("setno",Mb), TNS("setb",Mb), TNS("setae",Mb), 1487179237Sjb/* [94] */ TNS("sete",Mb), TNS("setne",Mb), TNS("setbe",Mb), TNS("seta",Mb), 1488179237Sjb/* [98] */ TNS("sets",Mb), TNS("setns",Mb), TNS("setp",Mb), TNS("setnp",Mb), 1489179237Sjb/* [9C] */ TNS("setl",Mb), TNS("setge",Mb), TNS("setle",Mb), TNS("setg",Mb), 1490179237Sjb}, { 1491179237Sjb/* [A0] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("cpuid",NORM), TS("bt",RMw), 1492179237Sjb/* [A4] */ TS("shld",DSHIFT), TS("shld",DSHIFTcl), INVALID, INVALID, 1493179237Sjb/* [A8] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("rsm",NORM), TS("bts",RMw), 1494179237Sjb/* [AC] */ TS("shrd",DSHIFT), TS("shrd",DSHIFTcl), IND(dis_op0FAE), TS("imul",MRw), 1495179237Sjb}, { 1496179237Sjb/* [B0] */ TNS("cmpxchgb",RMw), TS("cmpxchg",RMw), TS("lss",MR), TS("btr",RMw), 1497179237Sjb/* [B4] */ TS("lfs",MR), TS("lgs",MR), TS("movzb",MOVZ), TNS("movzwl",MOVZ), 1498253772Savg/* [B8] */ TNS("INVALID",MRw), INVALID, IND(dis_op0FBA), TS("btc",RMw), 1499179237Sjb/* [BC] */ TS("bsf",MRw), TS("bsr",MRw), TS("movsb",MOVZ), TNS("movswl",MOVZ), 1500179237Sjb}, { 1501179237Sjb/* [C0] */ TNS("xaddb",XADDB), TS("xadd",RMw), TNSZ("cmpps",XMMOPM,16),TNS("movnti",RM), 1502179237Sjb/* [C4] */ TNSZ("pinsrw",MMOPRM,2),TNS("pextrw",MMO3P), TNSZ("shufps",XMMOPM,16),IND(dis_op0FC7), 1503179237Sjb/* [C8] */ INVALID, INVALID, INVALID, INVALID, 1504179237Sjb/* [CC] */ INVALID, INVALID, INVALID, INVALID, 1505179237Sjb}, { 1506179237Sjb/* [D0] */ INVALID, TNSZ("psrlw",MMO,8), TNSZ("psrld",MMO,8), TNSZ("psrlq",MMO,8), 1507179237Sjb/* [D4] */ TNSZ("paddq",MMO,8), TNSZ("pmullw",MMO,8), TNSZ("INVALID",MMO,0), TNS("pmovmskb",MMOM3), 1508179237Sjb/* [D8] */ TNSZ("psubusb",MMO,8), TNSZ("psubusw",MMO,8), TNSZ("pminub",MMO,8), TNSZ("pand",MMO,8), 1509179237Sjb/* [DC] */ TNSZ("paddusb",MMO,8), TNSZ("paddusw",MMO,8), TNSZ("pmaxub",MMO,8), TNSZ("pandn",MMO,8), 1510179237Sjb}, { 1511179237Sjb/* [E0] */ TNSZ("pavgb",MMO,8), TNSZ("psraw",MMO,8), TNSZ("psrad",MMO,8), TNSZ("pavgw",MMO,8), 1512179237Sjb/* [E4] */ TNSZ("pmulhuw",MMO,8), TNSZ("pmulhw",MMO,8), TNS("INVALID",XMMO), TNSZ("movntq",MMOMS,8), 1513179237Sjb/* [E8] */ TNSZ("psubsb",MMO,8), TNSZ("psubsw",MMO,8), TNSZ("pminsw",MMO,8), TNSZ("por",MMO,8), 1514179237Sjb/* [EC] */ TNSZ("paddsb",MMO,8), TNSZ("paddsw",MMO,8), TNSZ("pmaxsw",MMO,8), TNSZ("pxor",MMO,8), 1515179237Sjb}, { 1516179237Sjb/* [F0] */ INVALID, TNSZ("psllw",MMO,8), TNSZ("pslld",MMO,8), TNSZ("psllq",MMO,8), 1517179237Sjb/* [F4] */ TNSZ("pmuludq",MMO,8), TNSZ("pmaddwd",MMO,8), TNSZ("psadbw",MMO,8), TNSZ("maskmovq",MMOIMPL,8), 1518179237Sjb/* [F8] */ TNSZ("psubb",MMO,8), TNSZ("psubw",MMO,8), TNSZ("psubd",MMO,8), TNSZ("psubq",MMO,8), 1519179237Sjb/* [FC] */ TNSZ("paddb",MMO,8), TNSZ("paddw",MMO,8), TNSZ("paddd",MMO,8), INVALID, 1520179237Sjb} }; 1521179237Sjb 1522253772Savgconst instable_t dis_opAVX0F[16][16] = { 1523253772Savg{ 1524253772Savg/* [00] */ INVALID, INVALID, INVALID, INVALID, 1525253772Savg/* [04] */ INVALID, INVALID, INVALID, INVALID, 1526253772Savg/* [08] */ INVALID, INVALID, INVALID, INVALID, 1527253772Savg/* [0C] */ INVALID, INVALID, INVALID, INVALID, 1528253772Savg}, { 1529253772Savg/* [10] */ TNSZ("vmovups",VEX_MX,16), TNSZ("vmovups",VEX_RM,16),TNSZ("vmovlps",VEX_RMrX,8), TNSZ("vmovlps",VEX_RM,8), 1530253772Savg/* [14] */ TNSZ("vunpcklps",VEX_RMrX,16),TNSZ("vunpckhps",VEX_RMrX,16),TNSZ("vmovhps",VEX_RMrX,8),TNSZ("vmovhps",VEX_RM,8), 1531253772Savg/* [18] */ INVALID, INVALID, INVALID, INVALID, 1532253772Savg/* [1C] */ INVALID, INVALID, INVALID, INVALID, 1533253772Savg}, { 1534253772Savg/* [20] */ INVALID, INVALID, INVALID, INVALID, 1535253772Savg/* [24] */ INVALID, INVALID, INVALID, INVALID, 1536253772Savg/* [28] */ TNSZ("vmovaps",VEX_MX,16), TNSZ("vmovaps",VEX_RX,16),INVALID, TNSZ("vmovntps",VEX_RM,16), 1537253772Savg/* [2C] */ INVALID, INVALID, TNSZ("vucomiss",VEX_MX,4),TNSZ("vcomiss",VEX_MX,4), 1538253772Savg}, { 1539253772Savg/* [30] */ INVALID, INVALID, INVALID, INVALID, 1540253772Savg/* [34] */ INVALID, INVALID, INVALID, INVALID, 1541253772Savg/* [38] */ INVALID, INVALID, INVALID, INVALID, 1542253772Savg/* [3C] */ INVALID, INVALID, INVALID, INVALID, 1543253772Savg}, { 1544253772Savg/* [40] */ INVALID, INVALID, INVALID, INVALID, 1545253772Savg/* [44] */ INVALID, INVALID, INVALID, INVALID, 1546253772Savg/* [48] */ INVALID, INVALID, INVALID, INVALID, 1547253772Savg/* [4C] */ INVALID, INVALID, INVALID, INVALID, 1548253772Savg}, { 1549253772Savg/* [50] */ TNS("vmovmskps",VEX_MR), TNSZ("vsqrtps",VEX_MX,16), TNSZ("vrsqrtps",VEX_MX,16),TNSZ("vrcpps",VEX_MX,16), 1550253772Savg/* [54] */ TNSZ("vandps",VEX_RMrX,16), TNSZ("vandnps",VEX_RMrX,16), TNSZ("vorps",VEX_RMrX,16), TNSZ("vxorps",VEX_RMrX,16), 1551253772Savg/* [58] */ TNSZ("vaddps",VEX_RMrX,16), TNSZ("vmulps",VEX_RMrX,16), TNSZ("vcvtps2pd",VEX_MX,8),TNSZ("vcvtdq2ps",VEX_MX,16), 1552253772Savg/* [5C] */ TNSZ("vsubps",VEX_RMrX,16), TNSZ("vminps",VEX_RMrX,16), TNSZ("vdivps",VEX_RMrX,16), TNSZ("vmaxps",VEX_RMrX,16), 1553253772Savg}, { 1554253772Savg/* [60] */ INVALID, INVALID, INVALID, INVALID, 1555253772Savg/* [64] */ INVALID, INVALID, INVALID, INVALID, 1556253772Savg/* [68] */ INVALID, INVALID, INVALID, INVALID, 1557253772Savg/* [6C] */ INVALID, INVALID, INVALID, INVALID, 1558253772Savg}, { 1559253772Savg/* [70] */ INVALID, INVALID, INVALID, INVALID, 1560253772Savg/* [74] */ INVALID, INVALID, INVALID, TNS("vzeroupper", VEX_NONE), 1561253772Savg/* [78] */ INVALID, INVALID, INVALID, INVALID, 1562253772Savg/* [7C] */ INVALID, INVALID, INVALID, INVALID, 1563253772Savg}, { 1564253772Savg/* [80] */ INVALID, INVALID, INVALID, INVALID, 1565253772Savg/* [84] */ INVALID, INVALID, INVALID, INVALID, 1566253772Savg/* [88] */ INVALID, INVALID, INVALID, INVALID, 1567253772Savg/* [8C] */ INVALID, INVALID, INVALID, INVALID, 1568253772Savg}, { 1569253772Savg/* [90] */ INVALID, INVALID, INVALID, INVALID, 1570253772Savg/* [94] */ INVALID, INVALID, INVALID, INVALID, 1571253772Savg/* [98] */ INVALID, INVALID, INVALID, INVALID, 1572253772Savg/* [9C] */ INVALID, INVALID, INVALID, INVALID, 1573253772Savg}, { 1574253772Savg/* [A0] */ INVALID, INVALID, INVALID, INVALID, 1575253772Savg/* [A4] */ INVALID, INVALID, INVALID, INVALID, 1576253772Savg/* [A8] */ INVALID, INVALID, INVALID, INVALID, 1577253772Savg/* [AC] */ INVALID, INVALID, TNSZ("vldmxcsr",VEX_MO,2), INVALID, 1578253772Savg}, { 1579253772Savg/* [B0] */ INVALID, INVALID, INVALID, INVALID, 1580253772Savg/* [B4] */ INVALID, INVALID, INVALID, INVALID, 1581253772Savg/* [B8] */ INVALID, INVALID, INVALID, INVALID, 1582253772Savg/* [BC] */ INVALID, INVALID, INVALID, INVALID, 1583253772Savg}, { 1584253772Savg/* [C0] */ INVALID, INVALID, TNSZ("vcmpps",VEX_RMRX,16),INVALID, 1585253772Savg/* [C4] */ INVALID, INVALID, TNSZ("vshufps",VEX_RMRX,16),INVALID, 1586253772Savg/* [C8] */ INVALID, INVALID, INVALID, INVALID, 1587253772Savg/* [CC] */ INVALID, INVALID, INVALID, INVALID, 1588253772Savg}, { 1589253772Savg/* [D0] */ INVALID, INVALID, INVALID, INVALID, 1590253772Savg/* [D4] */ INVALID, INVALID, INVALID, INVALID, 1591253772Savg/* [D8] */ INVALID, INVALID, INVALID, INVALID, 1592253772Savg/* [DC] */ INVALID, INVALID, INVALID, INVALID, 1593253772Savg}, { 1594253772Savg/* [E0] */ INVALID, INVALID, INVALID, INVALID, 1595253772Savg/* [E4] */ INVALID, INVALID, INVALID, INVALID, 1596253772Savg/* [E8] */ INVALID, INVALID, INVALID, INVALID, 1597253772Savg/* [EC] */ INVALID, INVALID, INVALID, INVALID, 1598253772Savg}, { 1599253772Savg/* [F0] */ INVALID, INVALID, INVALID, INVALID, 1600253772Savg/* [F4] */ INVALID, INVALID, INVALID, INVALID, 1601253772Savg/* [F8] */ INVALID, INVALID, INVALID, INVALID, 1602253772Savg/* [FC] */ INVALID, INVALID, INVALID, INVALID, 1603253772Savg} }; 1604179237Sjb 1605179237Sjb/* 1606179237Sjb * Decode table for 0x80 opcodes 1607179237Sjb */ 1608179237Sjb 1609179237Sjbconst instable_t dis_op80[8] = { 1610179237Sjb 1611179237Sjb/* [0] */ TNS("addb",IMlw), TNS("orb",IMw), TNS("adcb",IMlw), TNS("sbbb",IMlw), 1612179237Sjb/* [4] */ TNS("andb",IMw), TNS("subb",IMlw), TNS("xorb",IMw), TNS("cmpb",IMlw), 1613179237Sjb}; 1614179237Sjb 1615179237Sjb 1616179237Sjb/* 1617179237Sjb * Decode table for 0x81 opcodes. 1618179237Sjb */ 1619179237Sjb 1620179237Sjbconst instable_t dis_op81[8] = { 1621179237Sjb 1622179237Sjb/* [0] */ TS("add",IMlw), TS("or",IMw), TS("adc",IMlw), TS("sbb",IMlw), 1623179237Sjb/* [4] */ TS("and",IMw), TS("sub",IMlw), TS("xor",IMw), TS("cmp",IMlw), 1624179237Sjb}; 1625179237Sjb 1626179237Sjb 1627179237Sjb/* 1628179237Sjb * Decode table for 0x82 opcodes. 1629179237Sjb */ 1630179237Sjb 1631179237Sjbconst instable_t dis_op82[8] = { 1632179237Sjb 1633179237Sjb/* [0] */ TNSx("addb",IMlw), TNSx("orb",IMlw), TNSx("adcb",IMlw), TNSx("sbbb",IMlw), 1634179237Sjb/* [4] */ TNSx("andb",IMlw), TNSx("subb",IMlw), TNSx("xorb",IMlw), TNSx("cmpb",IMlw), 1635179237Sjb}; 1636179237Sjb/* 1637179237Sjb * Decode table for 0x83 opcodes. 1638179237Sjb */ 1639179237Sjb 1640179237Sjbconst instable_t dis_op83[8] = { 1641179237Sjb 1642179237Sjb/* [0] */ TS("add",IMlw), TS("or",IMlw), TS("adc",IMlw), TS("sbb",IMlw), 1643179237Sjb/* [4] */ TS("and",IMlw), TS("sub",IMlw), TS("xor",IMlw), TS("cmp",IMlw), 1644179237Sjb}; 1645179237Sjb 1646179237Sjb/* 1647179237Sjb * Decode table for 0xC0 opcodes. 1648179237Sjb */ 1649179237Sjb 1650179237Sjbconst instable_t dis_opC0[8] = { 1651179237Sjb 1652179237Sjb/* [0] */ TNS("rolb",MvI), TNS("rorb",MvI), TNS("rclb",MvI), TNS("rcrb",MvI), 1653179237Sjb/* [4] */ TNS("shlb",MvI), TNS("shrb",MvI), INVALID, TNS("sarb",MvI), 1654179237Sjb}; 1655179237Sjb 1656179237Sjb/* 1657179237Sjb * Decode table for 0xD0 opcodes. 1658179237Sjb */ 1659179237Sjb 1660179237Sjbconst instable_t dis_opD0[8] = { 1661179237Sjb 1662179237Sjb/* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv), 1663179237Sjb/* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv), 1664179237Sjb}; 1665179237Sjb 1666179237Sjb/* 1667179237Sjb * Decode table for 0xC1 opcodes. 1668179237Sjb * 186 instruction set 1669179237Sjb */ 1670179237Sjb 1671179237Sjbconst instable_t dis_opC1[8] = { 1672179237Sjb 1673179237Sjb/* [0] */ TS("rol",MvI), TS("ror",MvI), TS("rcl",MvI), TS("rcr",MvI), 1674179237Sjb/* [4] */ TS("shl",MvI), TS("shr",MvI), TS("sal",MvI), TS("sar",MvI), 1675179237Sjb}; 1676179237Sjb 1677179237Sjb/* 1678179237Sjb * Decode table for 0xD1 opcodes. 1679179237Sjb */ 1680179237Sjb 1681179237Sjbconst instable_t dis_opD1[8] = { 1682179237Sjb 1683179237Sjb/* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv), 1684179237Sjb/* [4] */ TS("shl",Mv), TS("shr",Mv), TS("sal",Mv), TS("sar",Mv), 1685179237Sjb}; 1686179237Sjb 1687179237Sjb 1688179237Sjb/* 1689179237Sjb * Decode table for 0xD2 opcodes. 1690179237Sjb */ 1691179237Sjb 1692179237Sjbconst instable_t dis_opD2[8] = { 1693179237Sjb 1694179237Sjb/* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv), 1695179237Sjb/* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv), 1696179237Sjb}; 1697179237Sjb/* 1698179237Sjb * Decode table for 0xD3 opcodes. 1699179237Sjb */ 1700179237Sjb 1701179237Sjbconst instable_t dis_opD3[8] = { 1702179237Sjb 1703179237Sjb/* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv), 1704179237Sjb/* [4] */ TS("shl",Mv), TS("shr",Mv), TS("salb",Mv), TS("sar",Mv), 1705179237Sjb}; 1706179237Sjb 1707179237Sjb 1708179237Sjb/* 1709179237Sjb * Decode table for 0xF6 opcodes. 1710179237Sjb */ 1711179237Sjb 1712179237Sjbconst instable_t dis_opF6[8] = { 1713179237Sjb 1714179237Sjb/* [0] */ TNS("testb",IMw), TNS("testb",IMw), TNS("notb",Mw), TNS("negb",Mw), 1715179237Sjb/* [4] */ TNS("mulb",MA), TNS("imulb",MA), TNS("divb",MA), TNS("idivb",MA), 1716179237Sjb}; 1717179237Sjb 1718179237Sjb 1719179237Sjb/* 1720179237Sjb * Decode table for 0xF7 opcodes. 1721179237Sjb */ 1722179237Sjb 1723179237Sjbconst instable_t dis_opF7[8] = { 1724179237Sjb 1725179237Sjb/* [0] */ TS("test",IMw), TS("test",IMw), TS("not",Mw), TS("neg",Mw), 1726179237Sjb/* [4] */ TS("mul",MA), TS("imul",MA), TS("div",MA), TS("idiv",MA), 1727179237Sjb}; 1728179237Sjb 1729179237Sjb 1730179237Sjb/* 1731179237Sjb * Decode table for 0xFE opcodes. 1732179237Sjb */ 1733179237Sjb 1734179237Sjbconst instable_t dis_opFE[8] = { 1735179237Sjb 1736179237Sjb/* [0] */ TNS("incb",Mw), TNS("decb",Mw), INVALID, INVALID, 1737179237Sjb/* [4] */ INVALID, INVALID, INVALID, INVALID, 1738179237Sjb}; 1739179237Sjb/* 1740179237Sjb * Decode table for 0xFF opcodes. 1741179237Sjb */ 1742179237Sjb 1743179237Sjbconst instable_t dis_opFF[8] = { 1744179237Sjb 1745179237Sjb/* [0] */ TS("inc",Mw), TS("dec",Mw), TNSyp("call",INM), TNS("lcall",INM), 1746179237Sjb/* [4] */ TNSy("jmp",INM), TNS("ljmp",INM), TSp("push",M), INVALID, 1747179237Sjb}; 1748179237Sjb 1749179237Sjb/* for 287 instructions, which are a mess to decode */ 1750179237Sjb 1751179237Sjbconst instable_t dis_opFP1n2[8][8] = { 1752179237Sjb{ 1753179237Sjb/* bit pattern: 1101 1xxx MODxx xR/M */ 1754179237Sjb/* [0,0] */ TNS("fadds",M), TNS("fmuls",M), TNS("fcoms",M), TNS("fcomps",M), 1755179237Sjb/* [0,4] */ TNS("fsubs",M), TNS("fsubrs",M), TNS("fdivs",M), TNS("fdivrs",M), 1756179237Sjb}, { 1757179237Sjb/* [1,0] */ TNS("flds",M), INVALID, TNS("fsts",M), TNS("fstps",M), 1758179237Sjb/* [1,4] */ TNSZ("fldenv",M,28), TNSZ("fldcw",M,2), TNSZ("fnstenv",M,28), TNSZ("fnstcw",M,2), 1759179237Sjb}, { 1760179237Sjb/* [2,0] */ TNS("fiaddl",M), TNS("fimull",M), TNS("ficoml",M), TNS("ficompl",M), 1761179237Sjb/* [2,4] */ TNS("fisubl",M), TNS("fisubrl",M), TNS("fidivl",M), TNS("fidivrl",M), 1762179237Sjb}, { 1763179237Sjb/* [3,0] */ TNS("fildl",M), INVALID, TNS("fistl",M), TNS("fistpl",M), 1764179237Sjb/* [3,4] */ INVALID, TNSZ("fldt",M,10), INVALID, TNSZ("fstpt",M,10), 1765179237Sjb}, { 1766179237Sjb/* [4,0] */ TNSZ("faddl",M,8), TNSZ("fmull",M,8), TNSZ("fcoml",M,8), TNSZ("fcompl",M,8), 1767179237Sjb/* [4,1] */ TNSZ("fsubl",M,8), TNSZ("fsubrl",M,8), TNSZ("fdivl",M,8), TNSZ("fdivrl",M,8), 1768179237Sjb}, { 1769179237Sjb/* [5,0] */ TNSZ("fldl",M,8), INVALID, TNSZ("fstl",M,8), TNSZ("fstpl",M,8), 1770179237Sjb/* [5,4] */ TNSZ("frstor",M,108), INVALID, TNSZ("fnsave",M,108), TNSZ("fnstsw",M,2), 1771179237Sjb}, { 1772179237Sjb/* [6,0] */ TNSZ("fiadd",M,2), TNSZ("fimul",M,2), TNSZ("ficom",M,2), TNSZ("ficomp",M,2), 1773179237Sjb/* [6,4] */ TNSZ("fisub",M,2), TNSZ("fisubr",M,2), TNSZ("fidiv",M,2), TNSZ("fidivr",M,2), 1774179237Sjb}, { 1775179237Sjb/* [7,0] */ TNSZ("fild",M,2), INVALID, TNSZ("fist",M,2), TNSZ("fistp",M,2), 1776179237Sjb/* [7,4] */ TNSZ("fbld",M,10), TNSZ("fildll",M,8), TNSZ("fbstp",M,10), TNSZ("fistpll",M,8), 1777179237Sjb} }; 1778179237Sjb 1779179237Sjbconst instable_t dis_opFP3[8][8] = { 1780179237Sjb{ 1781179237Sjb/* bit pattern: 1101 1xxx 11xx xREG */ 1782179237Sjb/* [0,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F), 1783179237Sjb/* [0,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF), 1784179237Sjb}, { 1785179237Sjb/* [1,0] */ TNS("fld",F), TNS("fxch",F), TNS("fnop",NORM), TNS("fstp",F), 1786179237Sjb/* [1,4] */ INVALID, INVALID, INVALID, INVALID, 1787179237Sjb}, { 1788179237Sjb/* [2,0] */ INVALID, INVALID, INVALID, INVALID, 1789179237Sjb/* [2,4] */ INVALID, TNS("fucompp",NORM), INVALID, INVALID, 1790179237Sjb}, { 1791179237Sjb/* [3,0] */ INVALID, INVALID, INVALID, INVALID, 1792179237Sjb/* [3,4] */ INVALID, INVALID, INVALID, INVALID, 1793179237Sjb}, { 1794179237Sjb/* [4,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F), 1795179237Sjb/* [4,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF), 1796179237Sjb}, { 1797179237Sjb/* [5,0] */ TNS("ffree",F), TNS("fxch",F), TNS("fst",F), TNS("fstp",F), 1798179237Sjb/* [5,4] */ TNS("fucom",F), TNS("fucomp",F), INVALID, INVALID, 1799179237Sjb}, { 1800179237Sjb/* [6,0] */ TNS("faddp",FF), TNS("fmulp",FF), TNS("fcomp",F), TNS("fcompp",NORM), 1801179237Sjb/* [6,4] */ TNS("fsubp",FF), TNS("fsubrp",FF), TNS("fdivp",FF), TNS("fdivrp",FF), 1802179237Sjb}, { 1803253772Savg/* [7,0] */ TNS("ffreep",F), TNS("fxch",F), TNS("fstp",F), TNS("fstp",F), 1804179237Sjb/* [7,4] */ TNS("fnstsw",M), TNS("fucomip",FFC), TNS("fcomip",FFC), INVALID, 1805179237Sjb} }; 1806179237Sjb 1807179237Sjbconst instable_t dis_opFP4[4][8] = { 1808179237Sjb{ 1809179237Sjb/* bit pattern: 1101 1001 111x xxxx */ 1810179237Sjb/* [0,0] */ TNS("fchs",NORM), TNS("fabs",NORM), INVALID, INVALID, 1811179237Sjb/* [0,4] */ TNS("ftst",NORM), TNS("fxam",NORM), TNS("ftstp",NORM), INVALID, 1812179237Sjb}, { 1813179237Sjb/* [1,0] */ TNS("fld1",NORM), TNS("fldl2t",NORM), TNS("fldl2e",NORM), TNS("fldpi",NORM), 1814179237Sjb/* [1,4] */ TNS("fldlg2",NORM), TNS("fldln2",NORM), TNS("fldz",NORM), INVALID, 1815179237Sjb}, { 1816179237Sjb/* [2,0] */ TNS("f2xm1",NORM), TNS("fyl2x",NORM), TNS("fptan",NORM), TNS("fpatan",NORM), 1817179237Sjb/* [2,4] */ TNS("fxtract",NORM), TNS("fprem1",NORM), TNS("fdecstp",NORM), TNS("fincstp",NORM), 1818179237Sjb}, { 1819179237Sjb/* [3,0] */ TNS("fprem",NORM), TNS("fyl2xp1",NORM), TNS("fsqrt",NORM), TNS("fsincos",NORM), 1820179237Sjb/* [3,4] */ TNS("frndint",NORM), TNS("fscale",NORM), TNS("fsin",NORM), TNS("fcos",NORM), 1821179237Sjb} }; 1822179237Sjb 1823179237Sjbconst instable_t dis_opFP5[8] = { 1824179237Sjb/* bit pattern: 1101 1011 111x xxxx */ 1825179237Sjb/* [0] */ TNS("feni",NORM), TNS("fdisi",NORM), TNS("fnclex",NORM), TNS("fninit",NORM), 1826179237Sjb/* [4] */ TNS("fsetpm",NORM), TNS("frstpm",NORM), INVALID, INVALID, 1827179237Sjb}; 1828179237Sjb 1829179237Sjbconst instable_t dis_opFP6[8] = { 1830179237Sjb/* bit pattern: 1101 1011 11yy yxxx */ 1831179237Sjb/* [00] */ TNS("fcmov.nb",FF), TNS("fcmov.ne",FF), TNS("fcmov.nbe",FF), TNS("fcmov.nu",FF), 1832179237Sjb/* [04] */ INVALID, TNS("fucomi",F), TNS("fcomi",F), INVALID, 1833179237Sjb}; 1834179237Sjb 1835179237Sjbconst instable_t dis_opFP7[8] = { 1836179237Sjb/* bit pattern: 1101 1010 11yy yxxx */ 1837179237Sjb/* [00] */ TNS("fcmov.b",FF), TNS("fcmov.e",FF), TNS("fcmov.be",FF), TNS("fcmov.u",FF), 1838179237Sjb/* [04] */ INVALID, INVALID, INVALID, INVALID, 1839179237Sjb}; 1840179237Sjb 1841179237Sjb/* 1842179237Sjb * Main decode table for the op codes. The first two nibbles 1843179237Sjb * will be used as an index into the table. If there is a 1844179237Sjb * a need to further decode an instruction, the array to be 1845179237Sjb * referenced is indicated with the other two entries being 1846179237Sjb * empty. 1847179237Sjb */ 1848179237Sjb 1849179237Sjbconst instable_t dis_distable[16][16] = { 1850179237Sjb{ 1851179237Sjb/* [0,0] */ TNS("addb",RMw), TS("add",RMw), TNS("addb",MRw), TS("add",MRw), 1852179237Sjb/* [0,4] */ TNS("addb",IA), TS("add",IA), TSx("push",SEG), TSx("pop",SEG), 1853179237Sjb/* [0,8] */ TNS("orb",RMw), TS("or",RMw), TNS("orb",MRw), TS("or",MRw), 1854253772Savg/* [0,C] */ TNS("orb",IA), TS("or",IA), TSx("push",SEG), IND(dis_op0F), 1855179237Sjb}, { 1856179237Sjb/* [1,0] */ TNS("adcb",RMw), TS("adc",RMw), TNS("adcb",MRw), TS("adc",MRw), 1857179237Sjb/* [1,4] */ TNS("adcb",IA), TS("adc",IA), TSx("push",SEG), TSx("pop",SEG), 1858179237Sjb/* [1,8] */ TNS("sbbb",RMw), TS("sbb",RMw), TNS("sbbb",MRw), TS("sbb",MRw), 1859179237Sjb/* [1,C] */ TNS("sbbb",IA), TS("sbb",IA), TSx("push",SEG), TSx("pop",SEG), 1860179237Sjb}, { 1861179237Sjb/* [2,0] */ TNS("andb",RMw), TS("and",RMw), TNS("andb",MRw), TS("and",MRw), 1862238168Savg/* [2,4] */ TNS("andb",IA), TS("and",IA), TNS("%es:",OVERRIDE), TNSx("daa",NORM), 1863179237Sjb/* [2,8] */ TNS("subb",RMw), TS("sub",RMw), TNS("subb",MRw), TS("sub",MRw), 1864238168Savg/* [2,C] */ TNS("subb",IA), TS("sub",IA), TNS("%cs:",OVERRIDE), TNSx("das",NORM), 1865179237Sjb}, { 1866179237Sjb/* [3,0] */ TNS("xorb",RMw), TS("xor",RMw), TNS("xorb",MRw), TS("xor",MRw), 1867238168Savg/* [3,4] */ TNS("xorb",IA), TS("xor",IA), TNS("%ss:",OVERRIDE), TNSx("aaa",NORM), 1868179237Sjb/* [3,8] */ TNS("cmpb",RMw), TS("cmp",RMw), TNS("cmpb",MRw), TS("cmp",MRw), 1869238168Savg/* [3,C] */ TNS("cmpb",IA), TS("cmp",IA), TNS("%ds:",OVERRIDE), TNSx("aas",NORM), 1870179237Sjb}, { 1871179237Sjb/* [4,0] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R), 1872179237Sjb/* [4,4] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R), 1873179237Sjb/* [4,8] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R), 1874179237Sjb/* [4,C] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R), 1875179237Sjb}, { 1876179237Sjb/* [5,0] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R), 1877179237Sjb/* [5,4] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R), 1878179237Sjb/* [5,8] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R), 1879179237Sjb/* [5,C] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R), 1880179237Sjb}, { 1881179237Sjb/* [6,0] */ TSZx("pusha",IMPLMEM,28),TSZx("popa",IMPLMEM,28), TSx("bound",MR), TNS("arpl",RMw), 1882179237Sjb/* [6,4] */ TNS("%fs:",OVERRIDE), TNS("%gs:",OVERRIDE), TNS("data16",DM), TNS("addr16",AM), 1883179237Sjb/* [6,8] */ TSp("push",I), TS("imul",IMUL), TSp("push",Ib), TS("imul",IMUL), 1884179237Sjb/* [6,C] */ TNSZ("insb",IMPLMEM,1), TSZ("ins",IMPLMEM,4), TNSZ("outsb",IMPLMEM,1),TSZ("outs",IMPLMEM,4), 1885179237Sjb}, { 1886179237Sjb/* [7,0] */ TNSy("jo",BD), TNSy("jno",BD), TNSy("jb",BD), TNSy("jae",BD), 1887179237Sjb/* [7,4] */ TNSy("je",BD), TNSy("jne",BD), TNSy("jbe",BD), TNSy("ja",BD), 1888179237Sjb/* [7,8] */ TNSy("js",BD), TNSy("jns",BD), TNSy("jp",BD), TNSy("jnp",BD), 1889179237Sjb/* [7,C] */ TNSy("jl",BD), TNSy("jge",BD), TNSy("jle",BD), TNSy("jg",BD), 1890179237Sjb}, { 1891179237Sjb/* [8,0] */ IND(dis_op80), IND(dis_op81), INDx(dis_op82), IND(dis_op83), 1892179237Sjb/* [8,4] */ TNS("testb",RMw), TS("test",RMw), TNS("xchgb",RMw), TS("xchg",RMw), 1893179237Sjb/* [8,8] */ TNS("movb",RMw), TS("mov",RMw), TNS("movb",MRw), TS("mov",MRw), 1894179237Sjb/* [8,C] */ TNS("movw",SM), TS("lea",MR), TNS("movw",MS), TSp("pop",M), 1895179237Sjb}, { 1896179237Sjb/* [9,0] */ TNS("nop",NORM), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), 1897179237Sjb/* [9,4] */ TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), 1898179237Sjb/* [9,8] */ TNS("cXtX",CBW), TNS("cXtX",CWD), TNSx("lcall",SO), TNS("fwait",NORM), 1899179237Sjb/* [9,C] */ TSZy("pushf",IMPLMEM,4),TSZy("popf",IMPLMEM,4), TNSx("sahf",NORM), TNSx("lahf",NORM), 1900179237Sjb}, { 1901179237Sjb/* [A,0] */ TNS("movb",OA), TS("mov",OA), TNS("movb",AO), TS("mov",AO), 1902179237Sjb/* [A,4] */ TNSZ("movsb",SD,1), TS("movs",SD), TNSZ("cmpsb",SD,1), TS("cmps",SD), 1903179237Sjb/* [A,8] */ TNS("testb",IA), TS("test",IA), TNS("stosb",AD), TS("stos",AD), 1904179237Sjb/* [A,C] */ TNS("lodsb",SA), TS("lods",SA), TNS("scasb",AD), TS("scas",AD), 1905179237Sjb}, { 1906179237Sjb/* [B,0] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), 1907179237Sjb/* [B,4] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), 1908179237Sjb/* [B,8] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR), 1909179237Sjb/* [B,C] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR), 1910179237Sjb}, { 1911179237Sjb/* [C,0] */ IND(dis_opC0), IND(dis_opC1), TNSyp("ret",RET), TNSyp("ret",NORM), 1912179237Sjb/* [C,4] */ TNSx("les",MR), TNSx("lds",MR), TNS("movb",IMw), TS("mov",IMw), 1913179237Sjb/* [C,8] */ TNSyp("enter",ENTER), TNSyp("leave",NORM), TNS("lret",RET), TNS("lret",NORM), 1914179237Sjb/* [C,C] */ TNS("int",INT3), TNS("int",INTx), TNSx("into",NORM), TNS("iret",NORM), 1915179237Sjb}, { 1916179237Sjb/* [D,0] */ IND(dis_opD0), IND(dis_opD1), IND(dis_opD2), IND(dis_opD3), 1917179237Sjb/* [D,4] */ TNSx("aam",U), TNSx("aad",U), TNSx("falc",NORM), TNSZ("xlat",IMPLMEM,1), 1918179237Sjb 1919179237Sjb/* 287 instructions. Note that although the indirect field */ 1920179237Sjb/* indicates opFP1n2 for further decoding, this is not necessarily */ 1921179237Sjb/* the case since the opFP arrays are not partitioned according to key1 */ 1922179237Sjb/* and key2. opFP1n2 is given only to indicate that we haven't */ 1923179237Sjb/* finished decoding the instruction. */ 1924253772Savg/* [D,8] */ IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), 1925253772Savg/* [D,C] */ IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), 1926179237Sjb}, { 1927179237Sjb/* [E,0] */ TNSy("loopnz",BD), TNSy("loopz",BD), TNSy("loop",BD), TNSy("jcxz",BD), 1928179237Sjb/* [E,4] */ TNS("inb",P), TS("in",P), TNS("outb",P), TS("out",P), 1929179237Sjb/* [E,8] */ TNSyp("call",D), TNSy("jmp",D), TNSx("ljmp",SO), TNSy("jmp",BD), 1930179237Sjb/* [E,C] */ TNS("inb",V), TS("in",V), TNS("outb",V), TS("out",V), 1931179237Sjb}, { 1932179237Sjb/* [F,0] */ TNS("lock",LOCK), TNS("icebp", NORM), TNS("repnz",PREFIX), TNS("repz",PREFIX), 1933179237Sjb/* [F,4] */ TNS("hlt",NORM), TNS("cmc",NORM), IND(dis_opF6), IND(dis_opF7), 1934179237Sjb/* [F,8] */ TNS("clc",NORM), TNS("stc",NORM), TNS("cli",NORM), TNS("sti",NORM), 1935179237Sjb/* [F,C] */ TNS("cld",NORM), TNS("std",NORM), IND(dis_opFE), IND(dis_opFF), 1936179237Sjb} }; 1937179237Sjb 1938179237Sjb/* END CSTYLED */ 1939179237Sjb 1940179237Sjb/* 1941179237Sjb * common functions to decode and disassemble an x86 or amd64 instruction 1942179237Sjb */ 1943179237Sjb 1944179237Sjb/* 1945179237Sjb * These are the individual fields of a REX prefix. Note that a REX 1946179237Sjb * prefix with none of these set is still needed to: 1947179237Sjb * - use the MOVSXD (sign extend 32 to 64 bits) instruction 1948179237Sjb * - access the %sil, %dil, %bpl, %spl registers 1949179237Sjb */ 1950179237Sjb#define REX_W 0x08 /* 64 bit operand size when set */ 1951179237Sjb#define REX_R 0x04 /* high order bit extension of ModRM reg field */ 1952179237Sjb#define REX_X 0x02 /* high order bit extension of SIB index field */ 1953179237Sjb#define REX_B 0x01 /* extends ModRM r_m, SIB base, or opcode reg */ 1954179237Sjb 1955253772Savg/* 1956253772Savg * These are the individual fields of a VEX prefix. 1957253772Savg */ 1958253772Savg#define VEX_R 0x08 /* REX.R in 1's complement form */ 1959253772Savg#define VEX_X 0x04 /* REX.X in 1's complement form */ 1960253772Savg#define VEX_B 0x02 /* REX.B in 1's complement form */ 1961253772Savg/* Vector Length, 0: scalar or 128-bit vector, 1: 256-bit vector */ 1962253772Savg#define VEX_L 0x04 1963253772Savg#define VEX_W 0x08 /* opcode specific, use like REX.W */ 1964253772Savg#define VEX_m 0x1F /* VEX m-mmmm field */ 1965253772Savg#define VEX_v 0x78 /* VEX register specifier */ 1966253772Savg#define VEX_p 0x03 /* VEX pp field, opcode extension */ 1967179237Sjb 1968253772Savg/* VEX m-mmmm field, only used by three bytes prefix */ 1969253772Savg#define VEX_m_0F 0x01 /* implied 0F leading opcode byte */ 1970253772Savg#define VEX_m_0F38 0x02 /* implied 0F 38 leading opcode byte */ 1971253772Savg#define VEX_m_0F3A 0x03 /* implied 0F 3A leading opcode byte */ 1972253772Savg 1973253772Savg/* VEX pp field, providing equivalent functionality of a SIMD prefix */ 1974253772Savg#define VEX_p_66 0x01 1975253772Savg#define VEX_p_F3 0x02 1976253772Savg#define VEX_p_F2 0x03 1977253772Savg 1978179237Sjb/* 1979179237Sjb * Even in 64 bit mode, usually only 4 byte immediate operands are supported. 1980179237Sjb */ 1981179237Sjbstatic int isize[] = {1, 2, 4, 4}; 1982179237Sjbstatic int isize64[] = {1, 2, 4, 8}; 1983179237Sjb 1984179237Sjb/* 1985179237Sjb * Just a bunch of useful macros. 1986179237Sjb */ 1987179237Sjb#define WBIT(x) (x & 0x1) /* to get w bit */ 1988179237Sjb#define REGNO(x) (x & 0x7) /* to get 3 bit register */ 1989179237Sjb#define VBIT(x) ((x)>>1 & 0x1) /* to get 'v' bit */ 1990179237Sjb#define OPSIZE(osize, wbit) ((wbit) ? isize[osize] : 1) 1991179237Sjb#define OPSIZE64(osize, wbit) ((wbit) ? isize64[osize] : 1) 1992179237Sjb 1993179237Sjb#define REG_ONLY 3 /* mode to indicate a register operand (not memory) */ 1994179237Sjb 1995179237Sjb#define BYTE_OPND 0 /* w-bit value indicating byte register */ 1996179237Sjb#define LONG_OPND 1 /* w-bit value indicating opnd_size register */ 1997179237Sjb#define MM_OPND 2 /* "value" used to indicate a mmx reg */ 1998179237Sjb#define XMM_OPND 3 /* "value" used to indicate a xmm reg */ 1999179237Sjb#define SEG_OPND 4 /* "value" used to indicate a segment reg */ 2000179237Sjb#define CONTROL_OPND 5 /* "value" used to indicate a control reg */ 2001179237Sjb#define DEBUG_OPND 6 /* "value" used to indicate a debug reg */ 2002179237Sjb#define TEST_OPND 7 /* "value" used to indicate a test reg */ 2003179237Sjb#define WORD_OPND 8 /* w-bit value indicating word size reg */ 2004253772Savg#define YMM_OPND 9 /* "value" used to indicate a ymm reg */ 2005179237Sjb 2006179237Sjb/* 2007179237Sjb * Get the next byte and separate the op code into the high and low nibbles. 2008179237Sjb */ 2009179237Sjbstatic int 2010179237Sjbdtrace_get_opcode(dis86_t *x, uint_t *high, uint_t *low) 2011179237Sjb{ 2012179237Sjb int byte; 2013179237Sjb 2014179237Sjb /* 2015179237Sjb * x86 instructions have a maximum length of 15 bytes. Bail out if 2016179237Sjb * we try to read more. 2017179237Sjb */ 2018179237Sjb if (x->d86_len >= 15) 2019179237Sjb return (x->d86_error = 1); 2020179237Sjb 2021179237Sjb if (x->d86_error) 2022179237Sjb return (1); 2023179237Sjb byte = x->d86_get_byte(x->d86_data); 2024179237Sjb if (byte < 0) 2025179237Sjb return (x->d86_error = 1); 2026179237Sjb x->d86_bytes[x->d86_len++] = byte; 2027179237Sjb *low = byte & 0xf; /* ----xxxx low 4 bits */ 2028179237Sjb *high = byte >> 4 & 0xf; /* xxxx---- bits 7 to 4 */ 2029179237Sjb return (0); 2030179237Sjb} 2031179237Sjb 2032179237Sjb/* 2033179237Sjb * Get and decode an SIB (scaled index base) byte 2034179237Sjb */ 2035179237Sjbstatic void 2036179237Sjbdtrace_get_SIB(dis86_t *x, uint_t *ss, uint_t *index, uint_t *base) 2037179237Sjb{ 2038179237Sjb int byte; 2039179237Sjb 2040179237Sjb if (x->d86_error) 2041179237Sjb return; 2042179237Sjb 2043179237Sjb byte = x->d86_get_byte(x->d86_data); 2044179237Sjb if (byte < 0) { 2045179237Sjb x->d86_error = 1; 2046179237Sjb return; 2047179237Sjb } 2048179237Sjb x->d86_bytes[x->d86_len++] = byte; 2049179237Sjb 2050179237Sjb *base = byte & 0x7; 2051179237Sjb *index = (byte >> 3) & 0x7; 2052179237Sjb *ss = (byte >> 6) & 0x3; 2053179237Sjb} 2054179237Sjb 2055179237Sjb/* 2056179237Sjb * Get the byte following the op code and separate it into the 2057179237Sjb * mode, register, and r/m fields. 2058179237Sjb */ 2059179237Sjbstatic void 2060179237Sjbdtrace_get_modrm(dis86_t *x, uint_t *mode, uint_t *reg, uint_t *r_m) 2061179237Sjb{ 2062179237Sjb if (x->d86_got_modrm == 0) { 2063179237Sjb if (x->d86_rmindex == -1) 2064179237Sjb x->d86_rmindex = x->d86_len; 2065179237Sjb dtrace_get_SIB(x, mode, reg, r_m); 2066179237Sjb x->d86_got_modrm = 1; 2067179237Sjb } 2068179237Sjb} 2069179237Sjb 2070179237Sjb/* 2071179237Sjb * Adjust register selection based on any REX prefix bits present. 2072179237Sjb */ 2073179237Sjb/*ARGSUSED*/ 2074179237Sjbstatic void 2075179237Sjbdtrace_rex_adjust(uint_t rex_prefix, uint_t mode, uint_t *reg, uint_t *r_m) 2076179237Sjb{ 2077179237Sjb if (reg != NULL && r_m == NULL) { 2078179237Sjb if (rex_prefix & REX_B) 2079179237Sjb *reg += 8; 2080179237Sjb } else { 2081179237Sjb if (reg != NULL && (REX_R & rex_prefix) != 0) 2082179237Sjb *reg += 8; 2083179237Sjb if (r_m != NULL && (REX_B & rex_prefix) != 0) 2084179237Sjb *r_m += 8; 2085179237Sjb } 2086179237Sjb} 2087179237Sjb 2088179237Sjb/* 2089253772Savg * Adjust register selection based on any VEX prefix bits present. 2090253772Savg * Notes: VEX.R, VEX.X and VEX.B use the inverted form compared with REX prefix 2091253772Savg */ 2092253772Savg/*ARGSUSED*/ 2093253772Savgstatic void 2094253772Savgdtrace_vex_adjust(uint_t vex_byte1, uint_t mode, uint_t *reg, uint_t *r_m) 2095253772Savg{ 2096253772Savg if (reg != NULL && r_m == NULL) { 2097253772Savg if (!(vex_byte1 & VEX_B)) 2098253772Savg *reg += 8; 2099253772Savg } else { 2100253772Savg if (reg != NULL && ((VEX_R & vex_byte1) == 0)) 2101253772Savg *reg += 8; 2102253772Savg if (r_m != NULL && ((VEX_B & vex_byte1) == 0)) 2103253772Savg *r_m += 8; 2104253772Savg } 2105253772Savg} 2106253772Savg 2107253772Savg/* 2108179237Sjb * Get an immediate operand of the given size, with sign extension. 2109179237Sjb */ 2110179237Sjbstatic void 2111179237Sjbdtrace_imm_opnd(dis86_t *x, int wbit, int size, int opindex) 2112179237Sjb{ 2113179237Sjb int i; 2114179237Sjb int byte; 2115253772Savg int valsize; 2116179237Sjb 2117179237Sjb if (x->d86_numopnds < opindex + 1) 2118179237Sjb x->d86_numopnds = opindex + 1; 2119179237Sjb 2120179237Sjb switch (wbit) { 2121179237Sjb case BYTE_OPND: 2122179237Sjb valsize = 1; 2123179237Sjb break; 2124179237Sjb case LONG_OPND: 2125179237Sjb if (x->d86_opnd_size == SIZE16) 2126179237Sjb valsize = 2; 2127179237Sjb else if (x->d86_opnd_size == SIZE32) 2128179237Sjb valsize = 4; 2129179237Sjb else 2130179237Sjb valsize = 8; 2131179237Sjb break; 2132179237Sjb case MM_OPND: 2133179237Sjb case XMM_OPND: 2134253772Savg case YMM_OPND: 2135179237Sjb case SEG_OPND: 2136179237Sjb case CONTROL_OPND: 2137179237Sjb case DEBUG_OPND: 2138179237Sjb case TEST_OPND: 2139179237Sjb valsize = size; 2140179237Sjb break; 2141179237Sjb case WORD_OPND: 2142179237Sjb valsize = 2; 2143179237Sjb break; 2144179237Sjb } 2145179237Sjb if (valsize < size) 2146179237Sjb valsize = size; 2147179237Sjb 2148179237Sjb if (x->d86_error) 2149179237Sjb return; 2150179237Sjb x->d86_opnd[opindex].d86_value = 0; 2151179237Sjb for (i = 0; i < size; ++i) { 2152179237Sjb byte = x->d86_get_byte(x->d86_data); 2153179237Sjb if (byte < 0) { 2154179237Sjb x->d86_error = 1; 2155179237Sjb return; 2156179237Sjb } 2157179237Sjb x->d86_bytes[x->d86_len++] = byte; 2158179237Sjb x->d86_opnd[opindex].d86_value |= (uint64_t)byte << (i * 8); 2159179237Sjb } 2160179237Sjb /* Do sign extension */ 2161179237Sjb if (x->d86_bytes[x->d86_len - 1] & 0x80) { 2162253772Savg for (; i < sizeof (uint64_t); i++) 2163179237Sjb x->d86_opnd[opindex].d86_value |= 2164253772Savg (uint64_t)0xff << (i * 8); 2165179237Sjb } 2166179237Sjb#ifdef DIS_TEXT 2167179237Sjb x->d86_opnd[opindex].d86_mode = MODE_SIGNED; 2168179237Sjb x->d86_opnd[opindex].d86_value_size = valsize; 2169179237Sjb x->d86_imm_bytes += size; 2170179237Sjb#endif 2171179237Sjb} 2172179237Sjb 2173179237Sjb/* 2174179237Sjb * Get an ip relative operand of the given size, with sign extension. 2175179237Sjb */ 2176179237Sjbstatic void 2177179237Sjbdtrace_disp_opnd(dis86_t *x, int wbit, int size, int opindex) 2178179237Sjb{ 2179179237Sjb dtrace_imm_opnd(x, wbit, size, opindex); 2180179237Sjb#ifdef DIS_TEXT 2181179237Sjb x->d86_opnd[opindex].d86_mode = MODE_IPREL; 2182179237Sjb#endif 2183179237Sjb} 2184179237Sjb 2185179237Sjb/* 2186179237Sjb * Check to see if there is a segment override prefix pending. 2187179237Sjb * If so, print it in the current 'operand' location and set 2188179237Sjb * the override flag back to false. 2189179237Sjb */ 2190179237Sjb/*ARGSUSED*/ 2191179237Sjbstatic void 2192179237Sjbdtrace_check_override(dis86_t *x, int opindex) 2193179237Sjb{ 2194179237Sjb#ifdef DIS_TEXT 2195179237Sjb if (x->d86_seg_prefix) { 2196179237Sjb (void) strlcat(x->d86_opnd[opindex].d86_prefix, 2197179237Sjb x->d86_seg_prefix, PFIXLEN); 2198179237Sjb } 2199179237Sjb#endif 2200179237Sjb x->d86_seg_prefix = NULL; 2201179237Sjb} 2202179237Sjb 2203179237Sjb 2204179237Sjb/* 2205179237Sjb * Process a single instruction Register or Memory operand. 2206179237Sjb * 2207179237Sjb * mode = addressing mode from ModRM byte 2208179237Sjb * r_m = r_m (or reg if mode == 3) field from ModRM byte 2209179237Sjb * wbit = indicates which register (8bit, 16bit, ... MMX, etc.) set to use. 2210179237Sjb * o = index of operand that we are processing (0, 1 or 2) 2211179237Sjb * 2212179237Sjb * the value of reg or r_m must have already been adjusted for any REX prefix. 2213179237Sjb */ 2214179237Sjb/*ARGSUSED*/ 2215179237Sjbstatic void 2216179237Sjbdtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex) 2217179237Sjb{ 2218179237Sjb int have_SIB = 0; /* flag presence of scale-index-byte */ 2219179237Sjb uint_t ss; /* scale-factor from opcode */ 2220179237Sjb uint_t index; /* index register number */ 2221179237Sjb uint_t base; /* base register number */ 2222179237Sjb int dispsize; /* size of displacement in bytes */ 2223179237Sjb#ifdef DIS_TEXT 2224179237Sjb char *opnd = x->d86_opnd[opindex].d86_opnd; 2225179237Sjb#endif 2226179237Sjb 2227179237Sjb if (x->d86_numopnds < opindex + 1) 2228179237Sjb x->d86_numopnds = opindex + 1; 2229179237Sjb 2230179237Sjb if (x->d86_error) 2231179237Sjb return; 2232179237Sjb 2233179237Sjb /* 2234179237Sjb * first handle a simple register 2235179237Sjb */ 2236179237Sjb if (mode == REG_ONLY) { 2237179237Sjb#ifdef DIS_TEXT 2238179237Sjb switch (wbit) { 2239179237Sjb case MM_OPND: 2240179237Sjb (void) strlcat(opnd, dis_MMREG[r_m], OPLEN); 2241179237Sjb break; 2242179237Sjb case XMM_OPND: 2243179237Sjb (void) strlcat(opnd, dis_XMMREG[r_m], OPLEN); 2244179237Sjb break; 2245253772Savg case YMM_OPND: 2246253772Savg (void) strlcat(opnd, dis_YMMREG[r_m], OPLEN); 2247253772Savg break; 2248179237Sjb case SEG_OPND: 2249179237Sjb (void) strlcat(opnd, dis_SEGREG[r_m], OPLEN); 2250179237Sjb break; 2251179237Sjb case CONTROL_OPND: 2252179237Sjb (void) strlcat(opnd, dis_CONTROLREG[r_m], OPLEN); 2253179237Sjb break; 2254179237Sjb case DEBUG_OPND: 2255179237Sjb (void) strlcat(opnd, dis_DEBUGREG[r_m], OPLEN); 2256179237Sjb break; 2257179237Sjb case TEST_OPND: 2258179237Sjb (void) strlcat(opnd, dis_TESTREG[r_m], OPLEN); 2259179237Sjb break; 2260179237Sjb case BYTE_OPND: 2261179237Sjb if (x->d86_rex_prefix == 0) 2262179237Sjb (void) strlcat(opnd, dis_REG8[r_m], OPLEN); 2263179237Sjb else 2264179237Sjb (void) strlcat(opnd, dis_REG8_REX[r_m], OPLEN); 2265179237Sjb break; 2266179237Sjb case WORD_OPND: 2267179237Sjb (void) strlcat(opnd, dis_REG16[r_m], OPLEN); 2268179237Sjb break; 2269179237Sjb case LONG_OPND: 2270179237Sjb if (x->d86_opnd_size == SIZE16) 2271179237Sjb (void) strlcat(opnd, dis_REG16[r_m], OPLEN); 2272179237Sjb else if (x->d86_opnd_size == SIZE32) 2273179237Sjb (void) strlcat(opnd, dis_REG32[r_m], OPLEN); 2274179237Sjb else 2275179237Sjb (void) strlcat(opnd, dis_REG64[r_m], OPLEN); 2276179237Sjb break; 2277179237Sjb } 2278179237Sjb#endif /* DIS_TEXT */ 2279179237Sjb return; 2280179237Sjb } 2281179237Sjb 2282179237Sjb /* 2283179237Sjb * if symbolic representation, skip override prefix, if any 2284179237Sjb */ 2285179237Sjb dtrace_check_override(x, opindex); 2286179237Sjb 2287179237Sjb /* 2288179237Sjb * Handle 16 bit memory references first, since they decode 2289179237Sjb * the mode values more simply. 2290179237Sjb * mode 1 is r_m + 8 bit displacement 2291179237Sjb * mode 2 is r_m + 16 bit displacement 2292179237Sjb * mode 0 is just r_m, unless r_m is 6 which is 16 bit disp 2293179237Sjb */ 2294179237Sjb if (x->d86_addr_size == SIZE16) { 2295179237Sjb if ((mode == 0 && r_m == 6) || mode == 2) 2296179237Sjb dtrace_imm_opnd(x, WORD_OPND, 2, opindex); 2297179237Sjb else if (mode == 1) 2298179237Sjb dtrace_imm_opnd(x, BYTE_OPND, 1, opindex); 2299179237Sjb#ifdef DIS_TEXT 2300179237Sjb if (mode == 0 && r_m == 6) 2301179237Sjb x->d86_opnd[opindex].d86_mode = MODE_SIGNED; 2302179237Sjb else if (mode == 0) 2303179237Sjb x->d86_opnd[opindex].d86_mode = MODE_NONE; 2304179237Sjb else 2305179237Sjb x->d86_opnd[opindex].d86_mode = MODE_OFFSET; 2306179237Sjb (void) strlcat(opnd, dis_addr16[mode][r_m], OPLEN); 2307179237Sjb#endif 2308179237Sjb return; 2309179237Sjb } 2310179237Sjb 2311179237Sjb /* 2312179237Sjb * 32 and 64 bit addressing modes are more complex since they 2313179237Sjb * can involve an SIB (scaled index and base) byte to decode. 2314179237Sjb */ 2315179237Sjb if (r_m == ESP_REGNO || r_m == ESP_REGNO + 8) { 2316179237Sjb have_SIB = 1; 2317179237Sjb dtrace_get_SIB(x, &ss, &index, &base); 2318179237Sjb if (x->d86_error) 2319179237Sjb return; 2320179237Sjb if (base != 5 || mode != 0) 2321179237Sjb if (x->d86_rex_prefix & REX_B) 2322179237Sjb base += 8; 2323179237Sjb if (x->d86_rex_prefix & REX_X) 2324179237Sjb index += 8; 2325179237Sjb } else { 2326179237Sjb base = r_m; 2327179237Sjb } 2328179237Sjb 2329179237Sjb /* 2330179237Sjb * Compute the displacement size and get its bytes 2331179237Sjb */ 2332179237Sjb dispsize = 0; 2333179237Sjb 2334179237Sjb if (mode == 1) 2335179237Sjb dispsize = 1; 2336179237Sjb else if (mode == 2) 2337179237Sjb dispsize = 4; 2338179237Sjb else if ((r_m & 7) == EBP_REGNO || 2339179237Sjb (have_SIB && (base & 7) == EBP_REGNO)) 2340179237Sjb dispsize = 4; 2341179237Sjb 2342179237Sjb if (dispsize > 0) { 2343179237Sjb dtrace_imm_opnd(x, dispsize == 4 ? LONG_OPND : BYTE_OPND, 2344179237Sjb dispsize, opindex); 2345179237Sjb if (x->d86_error) 2346179237Sjb return; 2347179237Sjb } 2348179237Sjb 2349179237Sjb#ifdef DIS_TEXT 2350179237Sjb if (dispsize > 0) 2351179237Sjb x->d86_opnd[opindex].d86_mode = MODE_OFFSET; 2352179237Sjb 2353179237Sjb if (have_SIB == 0) { 2354179237Sjb if (x->d86_mode == SIZE32) { 2355179237Sjb if (mode == 0) 2356179237Sjb (void) strlcat(opnd, dis_addr32_mode0[r_m], 2357179237Sjb OPLEN); 2358179237Sjb else 2359179237Sjb (void) strlcat(opnd, dis_addr32_mode12[r_m], 2360179237Sjb OPLEN); 2361179237Sjb } else { 2362253772Savg if (mode == 0) { 2363179237Sjb (void) strlcat(opnd, dis_addr64_mode0[r_m], 2364179237Sjb OPLEN); 2365253772Savg if (r_m == 5) { 2366253772Savg x->d86_opnd[opindex].d86_mode = 2367253772Savg MODE_RIPREL; 2368253772Savg } 2369253772Savg } else { 2370179237Sjb (void) strlcat(opnd, dis_addr64_mode12[r_m], 2371179237Sjb OPLEN); 2372253772Savg } 2373179237Sjb } 2374179237Sjb } else { 2375179237Sjb uint_t need_paren = 0; 2376179237Sjb char **regs; 2377179237Sjb if (x->d86_mode == SIZE32) /* NOTE this is not addr_size! */ 2378179237Sjb regs = (char **)dis_REG32; 2379179237Sjb else 2380179237Sjb regs = (char **)dis_REG64; 2381179237Sjb 2382179237Sjb /* 2383179237Sjb * print the base (if any) 2384179237Sjb */ 2385179237Sjb if (base == EBP_REGNO && mode == 0) { 2386179237Sjb if (index != ESP_REGNO) { 2387179237Sjb (void) strlcat(opnd, "(", OPLEN); 2388179237Sjb need_paren = 1; 2389179237Sjb } 2390179237Sjb } else { 2391179237Sjb (void) strlcat(opnd, "(", OPLEN); 2392179237Sjb (void) strlcat(opnd, regs[base], OPLEN); 2393179237Sjb need_paren = 1; 2394179237Sjb } 2395179237Sjb 2396179237Sjb /* 2397179237Sjb * print the index (if any) 2398179237Sjb */ 2399179237Sjb if (index != ESP_REGNO) { 2400179237Sjb (void) strlcat(opnd, ",", OPLEN); 2401179237Sjb (void) strlcat(opnd, regs[index], OPLEN); 2402179237Sjb (void) strlcat(opnd, dis_scale_factor[ss], OPLEN); 2403179237Sjb } else 2404179237Sjb if (need_paren) 2405179237Sjb (void) strlcat(opnd, ")", OPLEN); 2406179237Sjb } 2407179237Sjb#endif 2408179237Sjb} 2409179237Sjb 2410179237Sjb/* 2411179237Sjb * Operand sequence for standard instruction involving one register 2412179237Sjb * and one register/memory operand. 2413179237Sjb * wbit indicates a byte(0) or opnd_size(1) operation 2414179237Sjb * vbit indicates direction (0 for "opcode r,r_m") or (1 for "opcode r_m, r") 2415179237Sjb */ 2416179237Sjb#define STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, vbit) { \ 2417179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); \ 2418179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 2419179237Sjb dtrace_get_operand(x, mode, r_m, wbit, vbit); \ 2420179237Sjb dtrace_get_operand(x, REG_ONLY, reg, wbit, 1 - vbit); \ 2421179237Sjb} 2422179237Sjb 2423179237Sjb/* 2424179237Sjb * Similar to above, but allows for the two operands to be of different 2425179237Sjb * classes (ie. wbit). 2426179237Sjb * wbit is for the r_m operand 2427179237Sjb * w2 is for the reg operand 2428179237Sjb */ 2429179237Sjb#define MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, w2, vbit) { \ 2430179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); \ 2431179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 2432179237Sjb dtrace_get_operand(x, mode, r_m, wbit, vbit); \ 2433179237Sjb dtrace_get_operand(x, REG_ONLY, reg, w2, 1 - vbit); \ 2434179237Sjb} 2435179237Sjb 2436179237Sjb/* 2437179237Sjb * Similar, but for 2 operands plus an immediate. 2438253772Savg * vbit indicates direction 2439253772Savg * 0 for "opcode imm, r, r_m" or 2440253772Savg * 1 for "opcode imm, r_m, r" 2441179237Sjb */ 2442253772Savg#define THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize, vbit) { \ 2443179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); \ 2444179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 2445253772Savg dtrace_get_operand(x, mode, r_m, wbit, 2-vbit); \ 2446253772Savg dtrace_get_operand(x, REG_ONLY, reg, w2, 1+vbit); \ 2447179237Sjb dtrace_imm_opnd(x, wbit, immsize, 0); \ 2448179237Sjb} 2449179237Sjb 2450179237Sjb/* 2451253772Savg * Similar, but for 2 operands plus two immediates. 2452253772Savg */ 2453253772Savg#define FOUROPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize) { \ 2454253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); \ 2455253772Savg dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 2456253772Savg dtrace_get_operand(x, mode, r_m, wbit, 2); \ 2457253772Savg dtrace_get_operand(x, REG_ONLY, reg, w2, 3); \ 2458253772Savg dtrace_imm_opnd(x, wbit, immsize, 1); \ 2459253772Savg dtrace_imm_opnd(x, wbit, immsize, 0); \ 2460253772Savg} 2461253772Savg 2462253772Savg/* 2463253772Savg * 1 operands plus two immediates. 2464253772Savg */ 2465253772Savg#define ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, wbit, immsize) { \ 2466253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); \ 2467253772Savg dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 2468253772Savg dtrace_get_operand(x, mode, r_m, wbit, 2); \ 2469253772Savg dtrace_imm_opnd(x, wbit, immsize, 1); \ 2470253772Savg dtrace_imm_opnd(x, wbit, immsize, 0); \ 2471253772Savg} 2472253772Savg 2473253772Savg/* 2474179237Sjb * Dissassemble a single x86 or amd64 instruction. 2475179237Sjb * 2476179237Sjb * Mode determines the default operating mode (SIZE16, SIZE32 or SIZE64) 2477179237Sjb * for interpreting instructions. 2478179237Sjb * 2479179237Sjb * returns non-zero for bad opcode 2480179237Sjb */ 2481179237Sjbint 2482179237Sjbdtrace_disx86(dis86_t *x, uint_t cpu_mode) 2483179237Sjb{ 2484253772Savg instable_t *dp; /* decode table being used */ 2485179237Sjb#ifdef DIS_TEXT 2486179237Sjb uint_t i; 2487179237Sjb#endif 2488179237Sjb#ifdef DIS_MEM 2489179237Sjb uint_t nomem = 0; 2490179237Sjb#define NOMEM (nomem = 1) 2491179237Sjb#else 2492179237Sjb#define NOMEM /* nothing */ 2493179237Sjb#endif 2494253772Savg uint_t opnd_size; /* SIZE16, SIZE32 or SIZE64 */ 2495253772Savg uint_t addr_size; /* SIZE16, SIZE32 or SIZE64 */ 2496253772Savg uint_t wbit; /* opcode wbit, 0 is 8 bit, !0 for opnd_size */ 2497179237Sjb uint_t w2; /* wbit value for second operand */ 2498179237Sjb uint_t vbit; 2499179237Sjb uint_t mode = 0; /* mode value from ModRM byte */ 2500179237Sjb uint_t reg; /* reg value from ModRM byte */ 2501179237Sjb uint_t r_m; /* r_m value from ModRM byte */ 2502179237Sjb 2503179237Sjb uint_t opcode1; /* high nibble of 1st byte */ 2504179237Sjb uint_t opcode2; /* low nibble of 1st byte */ 2505179237Sjb uint_t opcode3; /* extra opcode bits usually from ModRM byte */ 2506179237Sjb uint_t opcode4; /* high nibble of 2nd byte */ 2507253772Savg uint_t opcode5; /* low nibble of 2nd byte */ 2508179237Sjb uint_t opcode6; /* high nibble of 3rd byte */ 2509179237Sjb uint_t opcode7; /* low nibble of 3rd byte */ 2510179237Sjb uint_t opcode_bytes = 1; 2511179237Sjb 2512179237Sjb /* 2513179237Sjb * legacy prefixes come in 5 flavors, you should have only one of each 2514179237Sjb */ 2515179237Sjb uint_t opnd_size_prefix = 0; 2516179237Sjb uint_t addr_size_prefix = 0; 2517179237Sjb uint_t segment_prefix = 0; 2518179237Sjb uint_t lock_prefix = 0; 2519179237Sjb uint_t rep_prefix = 0; 2520179237Sjb uint_t rex_prefix = 0; /* amd64 register extension prefix */ 2521253772Savg 2522253772Savg /* 2523253772Savg * Intel VEX instruction encoding prefix and fields 2524253772Savg */ 2525253772Savg 2526253772Savg /* 0xC4 means 3 bytes prefix, 0xC5 means 2 bytes prefix */ 2527253772Savg uint_t vex_prefix = 0; 2528253772Savg 2529253772Savg /* 2530253772Savg * VEX prefix byte 1, includes vex.r, vex.x and vex.b 2531253772Savg * (for 3 bytes prefix) 2532253772Savg */ 2533253772Savg uint_t vex_byte1 = 0; 2534253772Savg 2535253772Savg /* 2536253772Savg * For 32-bit mode, it should prefetch the next byte to 2537253772Savg * distinguish between AVX and les/lds 2538253772Savg */ 2539253772Savg uint_t vex_prefetch = 0; 2540253772Savg 2541253772Savg uint_t vex_m = 0; 2542253772Savg uint_t vex_v = 0; 2543253772Savg uint_t vex_p = 0; 2544253772Savg uint_t vex_R = 1; 2545253772Savg uint_t vex_X = 1; 2546253772Savg uint_t vex_B = 1; 2547253772Savg uint_t vex_W = 0; 2548253772Savg uint_t vex_L; 2549253772Savg 2550253772Savg 2551179237Sjb size_t off; 2552179237Sjb 2553253772Savg instable_t dp_mmx; 2554253772Savg 2555179237Sjb x->d86_len = 0; 2556179237Sjb x->d86_rmindex = -1; 2557179237Sjb x->d86_error = 0; 2558179237Sjb#ifdef DIS_TEXT 2559179237Sjb x->d86_numopnds = 0; 2560179237Sjb x->d86_seg_prefix = NULL; 2561253772Savg x->d86_mnem[0] = 0; 2562253772Savg for (i = 0; i < 4; ++i) { 2563179237Sjb x->d86_opnd[i].d86_opnd[0] = 0; 2564179237Sjb x->d86_opnd[i].d86_prefix[0] = 0; 2565179237Sjb x->d86_opnd[i].d86_value_size = 0; 2566179237Sjb x->d86_opnd[i].d86_value = 0; 2567179237Sjb x->d86_opnd[i].d86_mode = MODE_NONE; 2568179237Sjb } 2569179237Sjb#endif 2570253772Savg x->d86_rex_prefix = 0; 2571253772Savg x->d86_got_modrm = 0; 2572179237Sjb x->d86_memsize = 0; 2573179237Sjb 2574179237Sjb if (cpu_mode == SIZE16) { 2575179237Sjb opnd_size = SIZE16; 2576179237Sjb addr_size = SIZE16; 2577179237Sjb } else if (cpu_mode == SIZE32) { 2578179237Sjb opnd_size = SIZE32; 2579179237Sjb addr_size = SIZE32; 2580179237Sjb } else { 2581179237Sjb opnd_size = SIZE32; 2582179237Sjb addr_size = SIZE64; 2583179237Sjb } 2584179237Sjb 2585179237Sjb /* 2586179237Sjb * Get one opcode byte and check for zero padding that follows 2587179237Sjb * jump tables. 2588179237Sjb */ 2589179237Sjb if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 2590179237Sjb goto error; 2591179237Sjb 2592179237Sjb if (opcode1 == 0 && opcode2 == 0 && 2593179237Sjb x->d86_check_func != NULL && x->d86_check_func(x->d86_data)) { 2594179237Sjb#ifdef DIS_TEXT 2595253772Savg (void) strncpy(x->d86_mnem, ".byte\t0", OPLEN); 2596179237Sjb#endif 2597179237Sjb goto done; 2598179237Sjb } 2599179237Sjb 2600179237Sjb /* 2601179237Sjb * Gather up legacy x86 prefix bytes. 2602179237Sjb */ 2603179237Sjb for (;;) { 2604179237Sjb uint_t *which_prefix = NULL; 2605179237Sjb 2606253772Savg dp = (instable_t *)&dis_distable[opcode1][opcode2]; 2607179237Sjb 2608179237Sjb switch (dp->it_adrmode) { 2609179237Sjb case PREFIX: 2610179237Sjb which_prefix = &rep_prefix; 2611179237Sjb break; 2612179237Sjb case LOCK: 2613179237Sjb which_prefix = &lock_prefix; 2614179237Sjb break; 2615179237Sjb case OVERRIDE: 2616179237Sjb which_prefix = &segment_prefix; 2617179237Sjb#ifdef DIS_TEXT 2618179237Sjb x->d86_seg_prefix = (char *)dp->it_name; 2619179237Sjb#endif 2620179237Sjb if (dp->it_invalid64 && cpu_mode == SIZE64) 2621179237Sjb goto error; 2622179237Sjb break; 2623179237Sjb case AM: 2624179237Sjb which_prefix = &addr_size_prefix; 2625179237Sjb break; 2626179237Sjb case DM: 2627179237Sjb which_prefix = &opnd_size_prefix; 2628179237Sjb break; 2629179237Sjb } 2630179237Sjb if (which_prefix == NULL) 2631179237Sjb break; 2632179237Sjb *which_prefix = (opcode1 << 4) | opcode2; 2633179237Sjb if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 2634179237Sjb goto error; 2635179237Sjb } 2636179237Sjb 2637179237Sjb /* 2638179237Sjb * Handle amd64 mode PREFIX values. 2639179237Sjb * Some of the segment prefixes are no-ops. (only FS/GS actually work) 2640179237Sjb * We might have a REX prefix (opcodes 0x40-0x4f) 2641179237Sjb */ 2642179237Sjb if (cpu_mode == SIZE64) { 2643179237Sjb if (segment_prefix != 0x64 && segment_prefix != 0x65) 2644179237Sjb segment_prefix = 0; 2645179237Sjb 2646179237Sjb if (opcode1 == 0x4) { 2647179237Sjb rex_prefix = (opcode1 << 4) | opcode2; 2648179237Sjb if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 2649179237Sjb goto error; 2650253772Savg dp = (instable_t *)&dis_distable[opcode1][opcode2]; 2651253772Savg } else if (opcode1 == 0xC && 2652253772Savg (opcode2 == 0x4 || opcode2 == 0x5)) { 2653253772Savg /* AVX instructions */ 2654253772Savg vex_prefix = (opcode1 << 4) | opcode2; 2655253772Savg x->d86_rex_prefix = 0x40; 2656179237Sjb } 2657253772Savg } else if (opcode1 == 0xC && (opcode2 == 0x4 || opcode2 == 0x5)) { 2658253772Savg /* LDS, LES or AVX */ 2659253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 2660253772Savg vex_prefetch = 1; 2661253772Savg 2662253772Savg if (mode == REG_ONLY) { 2663253772Savg /* AVX */ 2664253772Savg vex_prefix = (opcode1 << 4) | opcode2; 2665253772Savg x->d86_rex_prefix = 0x40; 2666253772Savg opcode3 = (((mode << 3) | reg)>>1) & 0x0F; 2667253772Savg opcode4 = ((reg << 3) | r_m) & 0x0F; 2668253772Savg } 2669179237Sjb } 2670179237Sjb 2671253772Savg if (vex_prefix == VEX_2bytes) { 2672253772Savg if (!vex_prefetch) { 2673253772Savg if (dtrace_get_opcode(x, &opcode3, &opcode4) != 0) 2674253772Savg goto error; 2675253772Savg } 2676253772Savg vex_R = ((opcode3 & VEX_R) & 0x0F) >> 3; 2677253772Savg vex_L = ((opcode4 & VEX_L) & 0x0F) >> 2; 2678253772Savg vex_v = (((opcode3 << 4) | opcode4) & VEX_v) >> 3; 2679253772Savg vex_p = opcode4 & VEX_p; 2680253772Savg /* 2681253772Savg * The vex.x and vex.b bits are not defined in two bytes 2682253772Savg * mode vex prefix, their default values are 1 2683253772Savg */ 2684253772Savg vex_byte1 = (opcode3 & VEX_R) | VEX_X | VEX_B; 2685253772Savg 2686253772Savg if (vex_R == 0) 2687253772Savg x->d86_rex_prefix |= REX_R; 2688253772Savg 2689253772Savg if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 2690253772Savg goto error; 2691253772Savg 2692253772Savg switch (vex_p) { 2693253772Savg case VEX_p_66: 2694253772Savg dp = (instable_t *) 2695253772Savg &dis_opAVX660F[(opcode1 << 4) | opcode2]; 2696253772Savg break; 2697253772Savg case VEX_p_F3: 2698253772Savg dp = (instable_t *) 2699253772Savg &dis_opAVXF30F[(opcode1 << 4) | opcode2]; 2700253772Savg break; 2701253772Savg case VEX_p_F2: 2702253772Savg dp = (instable_t *) 2703253772Savg &dis_opAVXF20F [(opcode1 << 4) | opcode2]; 2704253772Savg break; 2705253772Savg default: 2706253772Savg dp = (instable_t *) 2707253772Savg &dis_opAVX0F[opcode1][opcode2]; 2708253772Savg 2709253772Savg } 2710253772Savg 2711253772Savg } else if (vex_prefix == VEX_3bytes) { 2712253772Savg if (!vex_prefetch) { 2713253772Savg if (dtrace_get_opcode(x, &opcode3, &opcode4) != 0) 2714253772Savg goto error; 2715253772Savg } 2716253772Savg vex_R = (opcode3 & VEX_R) >> 3; 2717253772Savg vex_X = (opcode3 & VEX_X) >> 2; 2718253772Savg vex_B = (opcode3 & VEX_B) >> 1; 2719253772Savg vex_m = (((opcode3 << 4) | opcode4) & VEX_m); 2720253772Savg vex_byte1 = opcode3 & (VEX_R | VEX_X | VEX_B); 2721253772Savg 2722253772Savg if (vex_R == 0) 2723253772Savg x->d86_rex_prefix |= REX_R; 2724253772Savg if (vex_X == 0) 2725253772Savg x->d86_rex_prefix |= REX_X; 2726253772Savg if (vex_B == 0) 2727253772Savg x->d86_rex_prefix |= REX_B; 2728253772Savg 2729253772Savg if (dtrace_get_opcode(x, &opcode5, &opcode6) != 0) 2730253772Savg goto error; 2731253772Savg vex_W = (opcode5 & VEX_W) >> 3; 2732253772Savg vex_L = (opcode6 & VEX_L) >> 2; 2733253772Savg vex_v = (((opcode5 << 4) | opcode6) & VEX_v) >> 3; 2734253772Savg vex_p = opcode6 & VEX_p; 2735253772Savg 2736253772Savg if (vex_W) 2737253772Savg x->d86_rex_prefix |= REX_W; 2738253772Savg 2739253772Savg /* Only these three vex_m values valid; others are reserved */ 2740253772Savg if ((vex_m != VEX_m_0F) && (vex_m != VEX_m_0F38) && 2741253772Savg (vex_m != VEX_m_0F3A)) 2742253772Savg goto error; 2743253772Savg 2744253772Savg if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 2745253772Savg goto error; 2746253772Savg 2747253772Savg switch (vex_p) { 2748253772Savg case VEX_p_66: 2749253772Savg if (vex_m == VEX_m_0F) { 2750253772Savg dp = (instable_t *) 2751253772Savg &dis_opAVX660F 2752253772Savg [(opcode1 << 4) | opcode2]; 2753253772Savg } else if (vex_m == VEX_m_0F38) { 2754253772Savg dp = (instable_t *) 2755253772Savg &dis_opAVX660F38 2756253772Savg [(opcode1 << 4) | opcode2]; 2757253772Savg } else if (vex_m == VEX_m_0F3A) { 2758253772Savg dp = (instable_t *) 2759253772Savg &dis_opAVX660F3A 2760253772Savg [(opcode1 << 4) | opcode2]; 2761253772Savg } else { 2762253772Savg goto error; 2763253772Savg } 2764253772Savg break; 2765253772Savg case VEX_p_F3: 2766253772Savg if (vex_m == VEX_m_0F) { 2767253772Savg dp = (instable_t *) 2768253772Savg &dis_opAVXF30F 2769253772Savg [(opcode1 << 4) | opcode2]; 2770253772Savg } else { 2771253772Savg goto error; 2772253772Savg } 2773253772Savg break; 2774253772Savg case VEX_p_F2: 2775253772Savg if (vex_m == VEX_m_0F) { 2776253772Savg dp = (instable_t *) 2777253772Savg &dis_opAVXF20F 2778253772Savg [(opcode1 << 4) | opcode2]; 2779253772Savg } else { 2780253772Savg goto error; 2781253772Savg } 2782253772Savg break; 2783253772Savg default: 2784253772Savg dp = (instable_t *) 2785253772Savg &dis_opAVX0F[opcode1][opcode2]; 2786253772Savg 2787253772Savg } 2788253772Savg } 2789253772Savg if (vex_prefix) { 2790253772Savg if (vex_L) 2791253772Savg wbit = YMM_OPND; 2792253772Savg else 2793253772Savg wbit = XMM_OPND; 2794253772Savg } 2795253772Savg 2796179237Sjb /* 2797179237Sjb * Deal with selection of operand and address size now. 2798179237Sjb * Note that the REX.W bit being set causes opnd_size_prefix to be 2799179237Sjb * ignored. 2800179237Sjb */ 2801179237Sjb if (cpu_mode == SIZE64) { 2802253772Savg if ((rex_prefix & REX_W) || vex_W) 2803179237Sjb opnd_size = SIZE64; 2804179237Sjb else if (opnd_size_prefix) 2805179237Sjb opnd_size = SIZE16; 2806179237Sjb 2807179237Sjb if (addr_size_prefix) 2808179237Sjb addr_size = SIZE32; 2809179237Sjb } else if (cpu_mode == SIZE32) { 2810179237Sjb if (opnd_size_prefix) 2811179237Sjb opnd_size = SIZE16; 2812179237Sjb if (addr_size_prefix) 2813179237Sjb addr_size = SIZE16; 2814179237Sjb } else { 2815179237Sjb if (opnd_size_prefix) 2816179237Sjb opnd_size = SIZE32; 2817179237Sjb if (addr_size_prefix) 2818179237Sjb addr_size = SIZE32; 2819179237Sjb } 2820179237Sjb /* 2821179237Sjb * The pause instruction - a repz'd nop. This doesn't fit 2822179237Sjb * with any of the other prefix goop added for SSE, so we'll 2823179237Sjb * special-case it here. 2824179237Sjb */ 2825179237Sjb if (rep_prefix == 0xf3 && opcode1 == 0x9 && opcode2 == 0x0) { 2826179237Sjb rep_prefix = 0; 2827253772Savg dp = (instable_t *)&dis_opPause; 2828179237Sjb } 2829179237Sjb 2830179237Sjb /* 2831179237Sjb * Some 386 instructions have 2 bytes of opcode before the mod_r/m 2832179237Sjb * byte so we may need to perform a table indirection. 2833179237Sjb */ 2834253772Savg if (dp->it_indirect == (instable_t *)dis_op0F) { 2835179237Sjb if (dtrace_get_opcode(x, &opcode4, &opcode5) != 0) 2836179237Sjb goto error; 2837179237Sjb opcode_bytes = 2; 2838179237Sjb if (opcode4 == 0x7 && opcode5 >= 0x1 && opcode5 <= 0x3) { 2839179237Sjb uint_t subcode; 2840179237Sjb 2841179237Sjb if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 2842179237Sjb goto error; 2843179237Sjb opcode_bytes = 3; 2844179237Sjb subcode = ((opcode6 & 0x3) << 1) | 2845179237Sjb ((opcode7 & 0x8) >> 3); 2846253772Savg dp = (instable_t *)&dis_op0F7123[opcode5][subcode]; 2847179237Sjb } else if ((opcode4 == 0xc) && (opcode5 >= 0x8)) { 2848253772Savg dp = (instable_t *)&dis_op0FC8[0]; 2849253772Savg } else if ((opcode4 == 0x3) && (opcode5 == 0xA)) { 2850253772Savg opcode_bytes = 3; 2851253772Savg if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 2852253772Savg goto error; 2853253772Savg if (opnd_size == SIZE16) 2854253772Savg opnd_size = SIZE32; 2855253772Savg 2856253772Savg dp = (instable_t *)&dis_op0F3A[(opcode6<<4)|opcode7]; 2857253772Savg#ifdef DIS_TEXT 2858253772Savg if (strcmp(dp->it_name, "INVALID") == 0) 2859253772Savg goto error; 2860253772Savg#endif 2861253772Savg switch (dp->it_adrmode) { 2862253772Savg case XMMP_66r: 2863253772Savg case XMMPRM_66r: 2864253772Savg case XMM3PM_66r: 2865253772Savg if (opnd_size_prefix == 0) { 2866253772Savg goto error; 2867253772Savg } 2868253772Savg break; 2869253772Savg case XMMP_66o: 2870253772Savg if (opnd_size_prefix == 0) { 2871253772Savg /* SSSE3 MMX instructions */ 2872253772Savg dp_mmx = *dp; 2873253772Savg dp = &dp_mmx; 2874253772Savg dp->it_adrmode = MMOPM_66o; 2875253772Savg#ifdef DIS_MEM 2876253772Savg dp->it_size = 8; 2877253772Savg#endif 2878253772Savg } 2879253772Savg break; 2880253772Savg default: 2881253772Savg goto error; 2882253772Savg } 2883253772Savg } else if ((opcode4 == 0x3) && (opcode5 == 0x8)) { 2884253772Savg opcode_bytes = 3; 2885253772Savg if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 2886253772Savg goto error; 2887253772Savg dp = (instable_t *)&dis_op0F38[(opcode6<<4)|opcode7]; 2888253772Savg 2889253772Savg /* 2890253772Savg * Both crc32 and movbe have the same 3rd opcode 2891253772Savg * byte of either 0xF0 or 0xF1, so we use another 2892253772Savg * indirection to distinguish between the two. 2893253772Savg */ 2894253772Savg if (dp->it_indirect == (instable_t *)dis_op0F38F0 || 2895253772Savg dp->it_indirect == (instable_t *)dis_op0F38F1) { 2896253772Savg 2897253772Savg dp = dp->it_indirect; 2898253772Savg if (rep_prefix != 0xF2) { 2899253772Savg /* It is movbe */ 2900253772Savg dp++; 2901253772Savg } 2902253772Savg } 2903253772Savg#ifdef DIS_TEXT 2904253772Savg if (strcmp(dp->it_name, "INVALID") == 0) 2905253772Savg goto error; 2906253772Savg#endif 2907253772Savg switch (dp->it_adrmode) { 2908253772Savg case XMM_66r: 2909253772Savg case XMMM_66r: 2910253772Savg if (opnd_size_prefix == 0) { 2911253772Savg goto error; 2912253772Savg } 2913253772Savg break; 2914253772Savg case XMM_66o: 2915253772Savg if (opnd_size_prefix == 0) { 2916253772Savg /* SSSE3 MMX instructions */ 2917253772Savg dp_mmx = *dp; 2918253772Savg dp = &dp_mmx; 2919253772Savg dp->it_adrmode = MM; 2920253772Savg#ifdef DIS_MEM 2921253772Savg dp->it_size = 8; 2922253772Savg#endif 2923253772Savg } 2924253772Savg break; 2925253772Savg case CRC32: 2926253772Savg if (rep_prefix != 0xF2) { 2927253772Savg goto error; 2928253772Savg } 2929253772Savg rep_prefix = 0; 2930253772Savg break; 2931253772Savg case MOVBE: 2932253772Savg if (rep_prefix != 0x0) { 2933253772Savg goto error; 2934253772Savg } 2935253772Savg break; 2936253772Savg default: 2937253772Savg goto error; 2938253772Savg } 2939179237Sjb } else { 2940253772Savg dp = (instable_t *)&dis_op0F[opcode4][opcode5]; 2941179237Sjb } 2942179237Sjb } 2943179237Sjb 2944179237Sjb /* 2945179237Sjb * If still not at a TERM decode entry, then a ModRM byte 2946179237Sjb * exists and its fields further decode the instruction. 2947179237Sjb */ 2948179237Sjb x->d86_got_modrm = 0; 2949179237Sjb if (dp->it_indirect != TERM) { 2950179237Sjb dtrace_get_modrm(x, &mode, &opcode3, &r_m); 2951179237Sjb if (x->d86_error) 2952179237Sjb goto error; 2953179237Sjb reg = opcode3; 2954179237Sjb 2955179237Sjb /* 2956179237Sjb * decode 287 instructions (D8-DF) from opcodeN 2957179237Sjb */ 2958179237Sjb if (opcode1 == 0xD && opcode2 >= 0x8) { 2959179237Sjb if (opcode2 == 0xB && mode == 0x3 && opcode3 == 4) 2960253772Savg dp = (instable_t *)&dis_opFP5[r_m]; 2961179237Sjb else if (opcode2 == 0xA && mode == 0x3 && opcode3 < 4) 2962253772Savg dp = (instable_t *)&dis_opFP7[opcode3]; 2963179237Sjb else if (opcode2 == 0xB && mode == 0x3) 2964253772Savg dp = (instable_t *)&dis_opFP6[opcode3]; 2965179237Sjb else if (opcode2 == 0x9 && mode == 0x3 && opcode3 >= 4) 2966253772Savg dp = (instable_t *)&dis_opFP4[opcode3 - 4][r_m]; 2967179237Sjb else if (mode == 0x3) 2968253772Savg dp = (instable_t *) 2969253772Savg &dis_opFP3[opcode2 - 8][opcode3]; 2970179237Sjb else 2971253772Savg dp = (instable_t *) 2972253772Savg &dis_opFP1n2[opcode2 - 8][opcode3]; 2973179237Sjb } else { 2974253772Savg dp = (instable_t *)dp->it_indirect + opcode3; 2975179237Sjb } 2976179237Sjb } 2977179237Sjb 2978179237Sjb /* 2979179237Sjb * In amd64 bit mode, ARPL opcode is changed to MOVSXD 2980179237Sjb * (sign extend 32bit to 64 bit) 2981179237Sjb */ 2982253772Savg if ((vex_prefix == 0) && cpu_mode == SIZE64 && 2983253772Savg opcode1 == 0x6 && opcode2 == 0x3) 2984253772Savg dp = (instable_t *)&dis_opMOVSLD; 2985179237Sjb 2986179237Sjb /* 2987179237Sjb * at this point we should have a correct (or invalid) opcode 2988179237Sjb */ 2989253772Savg if (cpu_mode == SIZE64 && dp->it_invalid64 || 2990253772Savg cpu_mode != SIZE64 && dp->it_invalid32) 2991179237Sjb goto error; 2992179237Sjb if (dp->it_indirect != TERM) 2993179237Sjb goto error; 2994179237Sjb 2995179237Sjb /* 2996179237Sjb * deal with MMX/SSE opcodes which are changed by prefixes 2997179237Sjb */ 2998179237Sjb switch (dp->it_adrmode) { 2999179237Sjb case MMO: 3000179237Sjb case MMOIMPL: 3001179237Sjb case MMO3P: 3002179237Sjb case MMOM3: 3003179237Sjb case MMOMS: 3004179237Sjb case MMOPM: 3005179237Sjb case MMOPRM: 3006179237Sjb case MMOS: 3007179237Sjb case XMMO: 3008179237Sjb case XMMOM: 3009179237Sjb case XMMOMS: 3010179237Sjb case XMMOPM: 3011179237Sjb case XMMOS: 3012179237Sjb case XMMOMX: 3013179237Sjb case XMMOX3: 3014179237Sjb case XMMOXMM: 3015179237Sjb /* 3016179237Sjb * This is horrible. Some SIMD instructions take the 3017179237Sjb * form 0x0F 0x?? ..., which is easily decoded using the 3018179237Sjb * existing tables. Other SIMD instructions use various 3019179237Sjb * prefix bytes to overload existing instructions. For 3020179237Sjb * Example, addps is F0, 58, whereas addss is F3 (repz), 3021179237Sjb * F0, 58. Presumably someone got a raise for this. 3022179237Sjb * 3023179237Sjb * If we see one of the instructions which can be 3024179237Sjb * modified in this way (if we've got one of the SIMDO* 3025179237Sjb * address modes), we'll check to see if the last prefix 3026179237Sjb * was a repz. If it was, we strip the prefix from the 3027179237Sjb * mnemonic, and we indirect using the dis_opSIMDrepz 3028179237Sjb * table. 3029179237Sjb */ 3030179237Sjb 3031179237Sjb /* 3032179237Sjb * Calculate our offset in dis_op0F 3033179237Sjb */ 3034179237Sjb if ((uintptr_t)dp - (uintptr_t)dis_op0F > sizeof (dis_op0F)) 3035179237Sjb goto error; 3036179237Sjb 3037179237Sjb off = ((uintptr_t)dp - (uintptr_t)dis_op0F) / 3038179237Sjb sizeof (instable_t); 3039179237Sjb 3040179237Sjb /* 3041179237Sjb * Rewrite if this instruction used one of the magic prefixes. 3042179237Sjb */ 3043179237Sjb if (rep_prefix) { 3044179237Sjb if (rep_prefix == 0xf2) 3045253772Savg dp = (instable_t *)&dis_opSIMDrepnz[off]; 3046179237Sjb else 3047253772Savg dp = (instable_t *)&dis_opSIMDrepz[off]; 3048179237Sjb rep_prefix = 0; 3049179237Sjb } else if (opnd_size_prefix) { 3050253772Savg dp = (instable_t *)&dis_opSIMDdata16[off]; 3051179237Sjb opnd_size_prefix = 0; 3052179237Sjb if (opnd_size == SIZE16) 3053179237Sjb opnd_size = SIZE32; 3054179237Sjb } 3055179237Sjb break; 3056179237Sjb 3057179237Sjb case MMOSH: 3058179237Sjb /* 3059179237Sjb * As with the "normal" SIMD instructions, the MMX 3060179237Sjb * shuffle instructions are overloaded. These 3061179237Sjb * instructions, however, are special in that they use 3062179237Sjb * an extra byte, and thus an extra table. As of this 3063179237Sjb * writing, they only use the opnd_size prefix. 3064179237Sjb */ 3065179237Sjb 3066179237Sjb /* 3067179237Sjb * Calculate our offset in dis_op0F7123 3068179237Sjb */ 3069179237Sjb if ((uintptr_t)dp - (uintptr_t)dis_op0F7123 > 3070179237Sjb sizeof (dis_op0F7123)) 3071179237Sjb goto error; 3072179237Sjb 3073179237Sjb if (opnd_size_prefix) { 3074179237Sjb off = ((uintptr_t)dp - (uintptr_t)dis_op0F7123) / 3075179237Sjb sizeof (instable_t); 3076253772Savg dp = (instable_t *)&dis_opSIMD7123[off]; 3077179237Sjb opnd_size_prefix = 0; 3078179237Sjb if (opnd_size == SIZE16) 3079179237Sjb opnd_size = SIZE32; 3080179237Sjb } 3081179237Sjb break; 3082253772Savg case MRw: 3083253772Savg if (rep_prefix) { 3084253772Savg if (rep_prefix == 0xf3) { 3085253772Savg 3086253772Savg /* 3087253772Savg * Calculate our offset in dis_op0F 3088253772Savg */ 3089253772Savg if ((uintptr_t)dp - (uintptr_t)dis_op0F 3090253772Savg > sizeof (dis_op0F)) 3091253772Savg goto error; 3092253772Savg 3093253772Savg off = ((uintptr_t)dp - (uintptr_t)dis_op0F) / 3094253772Savg sizeof (instable_t); 3095253772Savg 3096253772Savg dp = (instable_t *)&dis_opSIMDrepz[off]; 3097253772Savg rep_prefix = 0; 3098253772Savg } else { 3099253772Savg goto error; 3100253772Savg } 3101253772Savg } 3102253772Savg break; 3103179237Sjb } 3104179237Sjb 3105179237Sjb /* 3106179237Sjb * In 64 bit mode, some opcodes automatically use opnd_size == SIZE64. 3107179237Sjb */ 3108179237Sjb if (cpu_mode == SIZE64) 3109179237Sjb if (dp->it_always64 || (opnd_size == SIZE32 && dp->it_stackop)) 3110179237Sjb opnd_size = SIZE64; 3111179237Sjb 3112179237Sjb#ifdef DIS_TEXT 3113179237Sjb /* 3114179237Sjb * At this point most instructions can format the opcode mnemonic 3115179237Sjb * including the prefixes. 3116179237Sjb */ 3117179237Sjb if (lock_prefix) 3118253772Savg (void) strlcat(x->d86_mnem, "lock ", OPLEN); 3119179237Sjb 3120179237Sjb if (rep_prefix == 0xf2) 3121253772Savg (void) strlcat(x->d86_mnem, "repnz ", OPLEN); 3122179237Sjb else if (rep_prefix == 0xf3) 3123253772Savg (void) strlcat(x->d86_mnem, "repz ", OPLEN); 3124179237Sjb 3125179237Sjb if (cpu_mode == SIZE64 && addr_size_prefix) 3126253772Savg (void) strlcat(x->d86_mnem, "addr32 ", OPLEN); 3127179237Sjb 3128179237Sjb if (dp->it_adrmode != CBW && 3129179237Sjb dp->it_adrmode != CWD && 3130179237Sjb dp->it_adrmode != XMMSFNC) { 3131179237Sjb if (strcmp(dp->it_name, "INVALID") == 0) 3132179237Sjb goto error; 3133253772Savg (void) strlcat(x->d86_mnem, dp->it_name, OPLEN); 3134179237Sjb if (dp->it_suffix) { 3135179237Sjb char *types[] = {"", "w", "l", "q"}; 3136179237Sjb if (opcode_bytes == 2 && opcode4 == 4) { 3137179237Sjb /* It's a cmovx.yy. Replace the suffix x */ 3138179237Sjb for (i = 5; i < OPLEN; i++) { 3139253772Savg if (x->d86_mnem[i] == '.') 3140179237Sjb break; 3141179237Sjb } 3142253772Savg x->d86_mnem[i - 1] = *types[opnd_size]; 3143253772Savg } else if ((opnd_size == 2) && (opcode_bytes == 3) && 3144253772Savg ((opcode6 == 1 && opcode7 == 6) || 3145253772Savg (opcode6 == 2 && opcode7 == 2))) { 3146253772Savg /* 3147253772Savg * To handle PINSRD and PEXTRD 3148253772Savg */ 3149253772Savg (void) strlcat(x->d86_mnem, "d", OPLEN); 3150179237Sjb } else { 3151253772Savg (void) strlcat(x->d86_mnem, types[opnd_size], 3152179237Sjb OPLEN); 3153179237Sjb } 3154179237Sjb } 3155179237Sjb } 3156179237Sjb#endif 3157179237Sjb 3158179237Sjb /* 3159179237Sjb * Process operands based on the addressing modes. 3160179237Sjb */ 3161179237Sjb x->d86_mode = cpu_mode; 3162253772Savg /* 3163253772Savg * In vex mode the rex_prefix has no meaning 3164253772Savg */ 3165253772Savg if (!vex_prefix) 3166253772Savg x->d86_rex_prefix = rex_prefix; 3167179237Sjb x->d86_opnd_size = opnd_size; 3168179237Sjb x->d86_addr_size = addr_size; 3169179237Sjb vbit = 0; /* initialize for mem/reg -> reg */ 3170179237Sjb switch (dp->it_adrmode) { 3171179237Sjb /* 3172179237Sjb * amd64 instruction to sign extend 32 bit reg/mem operands 3173179237Sjb * into 64 bit register values 3174179237Sjb */ 3175179237Sjb case MOVSXZ: 3176179237Sjb#ifdef DIS_TEXT 3177179237Sjb if (rex_prefix == 0) 3178253772Savg (void) strncpy(x->d86_mnem, "movzld", OPLEN); 3179179237Sjb#endif 3180179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3181179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 3182179237Sjb x->d86_opnd_size = SIZE64; 3183179237Sjb dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 3184179237Sjb x->d86_opnd_size = opnd_size = SIZE32; 3185179237Sjb wbit = LONG_OPND; 3186179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 0); 3187179237Sjb break; 3188179237Sjb 3189179237Sjb /* 3190179237Sjb * movsbl movsbw movsbq (0x0FBE) or movswl movswq (0x0FBF) 3191253772Savg * movzbl movzbw movzbq (0x0FB6) or movzwl movzwq (0x0FB7) 3192179237Sjb * wbit lives in 2nd byte, note that operands 3193179237Sjb * are different sized 3194179237Sjb */ 3195179237Sjb case MOVZ: 3196179237Sjb if (rex_prefix & REX_W) { 3197179237Sjb /* target register size = 64 bit */ 3198253772Savg x->d86_mnem[5] = 'q'; 3199179237Sjb } 3200179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3201179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 3202179237Sjb dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 3203179237Sjb x->d86_opnd_size = opnd_size = SIZE16; 3204179237Sjb wbit = WBIT(opcode5); 3205179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 0); 3206179237Sjb break; 3207253772Savg case CRC32: 3208253772Savg opnd_size = SIZE32; 3209253772Savg if (rex_prefix & REX_W) 3210253772Savg opnd_size = SIZE64; 3211253772Savg x->d86_opnd_size = opnd_size; 3212179237Sjb 3213253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 3214253772Savg dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 3215253772Savg dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 3216253772Savg wbit = WBIT(opcode7); 3217253772Savg if (opnd_size_prefix) 3218253772Savg x->d86_opnd_size = opnd_size = SIZE16; 3219253772Savg dtrace_get_operand(x, mode, r_m, wbit, 0); 3220253772Savg break; 3221253772Savg case MOVBE: 3222253772Savg opnd_size = SIZE32; 3223253772Savg if (rex_prefix & REX_W) 3224253772Savg opnd_size = SIZE64; 3225253772Savg x->d86_opnd_size = opnd_size; 3226253772Savg 3227253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 3228253772Savg dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 3229253772Savg wbit = WBIT(opcode7); 3230253772Savg if (opnd_size_prefix) 3231253772Savg x->d86_opnd_size = opnd_size = SIZE16; 3232253772Savg if (wbit) { 3233253772Savg /* reg -> mem */ 3234253772Savg dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 3235253772Savg dtrace_get_operand(x, mode, r_m, wbit, 1); 3236253772Savg } else { 3237253772Savg /* mem -> reg */ 3238253772Savg dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 3239253772Savg dtrace_get_operand(x, mode, r_m, wbit, 0); 3240253772Savg } 3241253772Savg break; 3242253772Savg 3243179237Sjb /* 3244179237Sjb * imul instruction, with either 8-bit or longer immediate 3245179237Sjb * opcode 0x6B for byte, sign-extended displacement, 0x69 for word(s) 3246179237Sjb */ 3247179237Sjb case IMUL: 3248179237Sjb wbit = LONG_OPND; 3249179237Sjb THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 3250253772Savg OPSIZE(opnd_size, opcode2 == 0x9), 1); 3251179237Sjb break; 3252179237Sjb 3253179237Sjb /* memory or register operand to register, with 'w' bit */ 3254179237Sjb case MRw: 3255179237Sjb wbit = WBIT(opcode2); 3256179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 3257179237Sjb break; 3258179237Sjb 3259179237Sjb /* register to memory or register operand, with 'w' bit */ 3260179237Sjb /* arpl happens to fit here also because it is odd */ 3261179237Sjb case RMw: 3262179237Sjb if (opcode_bytes == 2) 3263179237Sjb wbit = WBIT(opcode5); 3264179237Sjb else 3265179237Sjb wbit = WBIT(opcode2); 3266179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 3267179237Sjb break; 3268179237Sjb 3269179237Sjb /* xaddb instruction */ 3270179237Sjb case XADDB: 3271179237Sjb wbit = 0; 3272179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 3273179237Sjb break; 3274179237Sjb 3275179237Sjb /* MMX register to memory or register operand */ 3276179237Sjb case MMS: 3277179237Sjb case MMOS: 3278179237Sjb#ifdef DIS_TEXT 3279179237Sjb wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 3280179237Sjb#else 3281179237Sjb wbit = LONG_OPND; 3282179237Sjb#endif 3283179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1); 3284179237Sjb break; 3285179237Sjb 3286179237Sjb /* MMX register to memory */ 3287179237Sjb case MMOMS: 3288179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3289179237Sjb if (mode == REG_ONLY) 3290179237Sjb goto error; 3291179237Sjb wbit = MM_OPND; 3292179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1); 3293179237Sjb break; 3294179237Sjb 3295179237Sjb /* Double shift. Has immediate operand specifying the shift. */ 3296179237Sjb case DSHIFT: 3297179237Sjb wbit = LONG_OPND; 3298179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3299179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 3300179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 2); 3301179237Sjb dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 3302179237Sjb dtrace_imm_opnd(x, wbit, 1, 0); 3303179237Sjb break; 3304179237Sjb 3305179237Sjb /* 3306179237Sjb * Double shift. With no immediate operand, specifies using %cl. 3307179237Sjb */ 3308179237Sjb case DSHIFTcl: 3309179237Sjb wbit = LONG_OPND; 3310179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 3311179237Sjb break; 3312179237Sjb 3313179237Sjb /* immediate to memory or register operand */ 3314179237Sjb case IMlw: 3315179237Sjb wbit = WBIT(opcode2); 3316179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 3317179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 1); 3318179237Sjb /* 3319179237Sjb * Have long immediate for opcode 0x81, but not 0x80 nor 0x83 3320179237Sjb */ 3321179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, opcode2 == 1), 0); 3322179237Sjb break; 3323179237Sjb 3324179237Sjb /* immediate to memory or register operand with the */ 3325179237Sjb /* 'w' bit present */ 3326179237Sjb case IMw: 3327179237Sjb wbit = WBIT(opcode2); 3328179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3329179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 3330179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 1); 3331179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0); 3332179237Sjb break; 3333179237Sjb 3334179237Sjb /* immediate to register with register in low 3 bits */ 3335179237Sjb /* of op code */ 3336179237Sjb case IR: 3337179237Sjb /* w-bit here (with regs) is bit 3 */ 3338179237Sjb wbit = opcode2 >>3 & 0x1; 3339179237Sjb reg = REGNO(opcode2); 3340179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 3341179237Sjb mode = REG_ONLY; 3342179237Sjb r_m = reg; 3343179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 1); 3344179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE64(opnd_size, wbit), 0); 3345179237Sjb break; 3346179237Sjb 3347179237Sjb /* MMX immediate shift of register */ 3348179237Sjb case MMSH: 3349179237Sjb case MMOSH: 3350179237Sjb wbit = MM_OPND; 3351179237Sjb goto mm_shift; /* in next case */ 3352179237Sjb 3353179237Sjb /* SIMD immediate shift of register */ 3354179237Sjb case XMMSH: 3355179237Sjb wbit = XMM_OPND; 3356179237Sjbmm_shift: 3357179237Sjb reg = REGNO(opcode7); 3358179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 3359179237Sjb dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 3360179237Sjb dtrace_imm_opnd(x, wbit, 1, 0); 3361179237Sjb NOMEM; 3362179237Sjb break; 3363179237Sjb 3364179237Sjb /* accumulator to memory operand */ 3365179237Sjb case AO: 3366179237Sjb vbit = 1; 3367179237Sjb /*FALLTHROUGH*/ 3368179237Sjb 3369179237Sjb /* memory operand to accumulator */ 3370179237Sjb case OA: 3371179237Sjb wbit = WBIT(opcode2); 3372179237Sjb dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1 - vbit); 3373179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE64(addr_size, LONG_OPND), vbit); 3374179237Sjb#ifdef DIS_TEXT 3375179237Sjb x->d86_opnd[vbit].d86_mode = MODE_OFFSET; 3376179237Sjb#endif 3377179237Sjb break; 3378179237Sjb 3379179237Sjb 3380179237Sjb /* segment register to memory or register operand */ 3381179237Sjb case SM: 3382179237Sjb vbit = 1; 3383179237Sjb /*FALLTHROUGH*/ 3384179237Sjb 3385179237Sjb /* memory or register operand to segment register */ 3386179237Sjb case MS: 3387179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3388179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 3389179237Sjb dtrace_get_operand(x, mode, r_m, LONG_OPND, vbit); 3390179237Sjb dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 1 - vbit); 3391179237Sjb break; 3392179237Sjb 3393179237Sjb /* 3394179237Sjb * rotate or shift instructions, which may shift by 1 or 3395179237Sjb * consult the cl register, depending on the 'v' bit 3396179237Sjb */ 3397179237Sjb case Mv: 3398179237Sjb vbit = VBIT(opcode2); 3399179237Sjb wbit = WBIT(opcode2); 3400179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 3401179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 1); 3402179237Sjb#ifdef DIS_TEXT 3403179237Sjb if (vbit) { 3404179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "%cl", OPLEN); 3405179237Sjb } else { 3406179237Sjb x->d86_opnd[0].d86_mode = MODE_SIGNED; 3407179237Sjb x->d86_opnd[0].d86_value_size = 1; 3408179237Sjb x->d86_opnd[0].d86_value = 1; 3409179237Sjb } 3410179237Sjb#endif 3411179237Sjb break; 3412179237Sjb /* 3413179237Sjb * immediate rotate or shift instructions 3414179237Sjb */ 3415179237Sjb case MvI: 3416179237Sjb wbit = WBIT(opcode2); 3417179237Sjbnormal_imm_mem: 3418179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 3419179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 1); 3420179237Sjb dtrace_imm_opnd(x, wbit, 1, 0); 3421179237Sjb break; 3422179237Sjb 3423179237Sjb /* bit test instructions */ 3424179237Sjb case MIb: 3425179237Sjb wbit = LONG_OPND; 3426179237Sjb goto normal_imm_mem; 3427179237Sjb 3428179237Sjb /* single memory or register operand with 'w' bit present */ 3429179237Sjb case Mw: 3430179237Sjb wbit = WBIT(opcode2); 3431179237Sjbjust_mem: 3432179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3433179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 3434179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 0); 3435179237Sjb break; 3436179237Sjb 3437179237Sjb case SWAPGS: 3438179237Sjb if (cpu_mode == SIZE64 && mode == 3 && r_m == 0) { 3439179237Sjb#ifdef DIS_TEXT 3440253772Savg (void) strncpy(x->d86_mnem, "swapgs", OPLEN); 3441179237Sjb#endif 3442179237Sjb NOMEM; 3443179237Sjb break; 3444179237Sjb } 3445179237Sjb /*FALLTHROUGH*/ 3446179237Sjb 3447179237Sjb /* prefetch instruction - memory operand, but no memory acess */ 3448179237Sjb case PREF: 3449179237Sjb NOMEM; 3450179237Sjb /*FALLTHROUGH*/ 3451179237Sjb 3452179237Sjb /* single memory or register operand */ 3453179237Sjb case M: 3454179237Sjb wbit = LONG_OPND; 3455179237Sjb goto just_mem; 3456179237Sjb 3457179237Sjb /* single memory or register byte operand */ 3458179237Sjb case Mb: 3459179237Sjb wbit = BYTE_OPND; 3460179237Sjb goto just_mem; 3461179237Sjb 3462253772Savg case MONITOR_MWAIT: 3463253772Savg if (mode == 3) { 3464253772Savg if (r_m == 0) { 3465253772Savg#ifdef DIS_TEXT 3466253772Savg (void) strncpy(x->d86_mnem, "monitor", OPLEN); 3467253772Savg#endif 3468253772Savg NOMEM; 3469253772Savg break; 3470253772Savg } else if (r_m == 1) { 3471253772Savg#ifdef DIS_TEXT 3472253772Savg (void) strncpy(x->d86_mnem, "mwait", OPLEN); 3473253772Savg#endif 3474253772Savg NOMEM; 3475253772Savg break; 3476253772Savg } else { 3477253772Savg goto error; 3478253772Savg } 3479253772Savg } 3480253772Savg /*FALLTHROUGH*/ 3481253772Savg case XGETBV_XSETBV: 3482253772Savg if (mode == 3) { 3483253772Savg if (r_m == 0) { 3484253772Savg#ifdef DIS_TEXT 3485253772Savg (void) strncpy(x->d86_mnem, "xgetbv", OPLEN); 3486253772Savg#endif 3487253772Savg NOMEM; 3488253772Savg break; 3489253772Savg } else if (r_m == 1) { 3490253772Savg#ifdef DIS_TEXT 3491253772Savg (void) strncpy(x->d86_mnem, "xsetbv", OPLEN); 3492253772Savg#endif 3493253772Savg NOMEM; 3494253772Savg break; 3495253772Savg } else { 3496253772Savg goto error; 3497253772Savg } 3498253772Savg 3499253772Savg } 3500253772Savg /*FALLTHROUGH*/ 3501179237Sjb case MO: 3502179237Sjb /* Similar to M, but only memory (no direct registers) */ 3503179237Sjb wbit = LONG_OPND; 3504179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3505179237Sjb if (mode == 3) 3506179237Sjb goto error; 3507179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 3508179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 0); 3509179237Sjb break; 3510179237Sjb 3511179237Sjb /* move special register to register or reverse if vbit */ 3512179237Sjb case SREG: 3513179237Sjb switch (opcode5) { 3514179237Sjb 3515179237Sjb case 2: 3516179237Sjb vbit = 1; 3517179237Sjb /*FALLTHROUGH*/ 3518179237Sjb case 0: 3519179237Sjb wbit = CONTROL_OPND; 3520179237Sjb break; 3521179237Sjb 3522179237Sjb case 3: 3523179237Sjb vbit = 1; 3524179237Sjb /*FALLTHROUGH*/ 3525179237Sjb case 1: 3526179237Sjb wbit = DEBUG_OPND; 3527179237Sjb break; 3528179237Sjb 3529179237Sjb case 6: 3530179237Sjb vbit = 1; 3531179237Sjb /*FALLTHROUGH*/ 3532179237Sjb case 4: 3533179237Sjb wbit = TEST_OPND; 3534179237Sjb break; 3535179237Sjb 3536179237Sjb } 3537179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3538179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 3539179237Sjb dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit); 3540179237Sjb dtrace_get_operand(x, REG_ONLY, r_m, LONG_OPND, 1 - vbit); 3541179237Sjb NOMEM; 3542179237Sjb break; 3543179237Sjb 3544179237Sjb /* 3545179237Sjb * single register operand with register in the low 3 3546179237Sjb * bits of op code 3547179237Sjb */ 3548179237Sjb case R: 3549179237Sjb if (opcode_bytes == 2) 3550179237Sjb reg = REGNO(opcode5); 3551179237Sjb else 3552179237Sjb reg = REGNO(opcode2); 3553179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 3554179237Sjb dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 3555179237Sjb NOMEM; 3556179237Sjb break; 3557179237Sjb 3558179237Sjb /* 3559179237Sjb * register to accumulator with register in the low 3 3560179237Sjb * bits of op code, xchg instructions 3561179237Sjb */ 3562179237Sjb case RA: 3563179237Sjb NOMEM; 3564179237Sjb reg = REGNO(opcode2); 3565179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 3566179237Sjb dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 3567179237Sjb dtrace_get_operand(x, REG_ONLY, EAX_REGNO, LONG_OPND, 1); 3568179237Sjb break; 3569179237Sjb 3570179237Sjb /* 3571179237Sjb * single segment register operand, with register in 3572179237Sjb * bits 3-4 of op code byte 3573179237Sjb */ 3574179237Sjb case SEG: 3575179237Sjb NOMEM; 3576179237Sjb reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x3; 3577179237Sjb dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0); 3578179237Sjb break; 3579179237Sjb 3580179237Sjb /* 3581179237Sjb * single segment register operand, with register in 3582179237Sjb * bits 3-5 of op code 3583179237Sjb */ 3584179237Sjb case LSEG: 3585179237Sjb NOMEM; 3586179237Sjb /* long seg reg from opcode */ 3587179237Sjb reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x7; 3588179237Sjb dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0); 3589179237Sjb break; 3590179237Sjb 3591179237Sjb /* memory or register operand to register */ 3592179237Sjb case MR: 3593253772Savg if (vex_prefetch) 3594253772Savg x->d86_got_modrm = 1; 3595179237Sjb wbit = LONG_OPND; 3596179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 3597179237Sjb break; 3598179237Sjb 3599179237Sjb case RM: 3600179237Sjb wbit = LONG_OPND; 3601179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 3602179237Sjb break; 3603179237Sjb 3604179237Sjb /* MMX/SIMD-Int memory or mm reg to mm reg */ 3605179237Sjb case MM: 3606179237Sjb case MMO: 3607179237Sjb#ifdef DIS_TEXT 3608179237Sjb wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 3609179237Sjb#else 3610179237Sjb wbit = LONG_OPND; 3611179237Sjb#endif 3612179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0); 3613179237Sjb break; 3614179237Sjb 3615179237Sjb case MMOIMPL: 3616179237Sjb#ifdef DIS_TEXT 3617179237Sjb wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 3618179237Sjb#else 3619179237Sjb wbit = LONG_OPND; 3620179237Sjb#endif 3621179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3622179237Sjb if (mode != REG_ONLY) 3623179237Sjb goto error; 3624179237Sjb 3625179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 3626179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 0); 3627179237Sjb dtrace_get_operand(x, REG_ONLY, reg, MM_OPND, 1); 3628179237Sjb mode = 0; /* change for memory access size... */ 3629179237Sjb break; 3630179237Sjb 3631179237Sjb /* MMX/SIMD-Int and SIMD-FP predicated mm reg to r32 */ 3632179237Sjb case MMO3P: 3633179237Sjb wbit = MM_OPND; 3634179237Sjb goto xmm3p; 3635179237Sjb case XMM3P: 3636179237Sjb wbit = XMM_OPND; 3637179237Sjbxmm3p: 3638179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3639179237Sjb if (mode != REG_ONLY) 3640179237Sjb goto error; 3641179237Sjb 3642253772Savg THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 1, 3643253772Savg 1); 3644179237Sjb NOMEM; 3645179237Sjb break; 3646179237Sjb 3647253772Savg case XMM3PM_66r: 3648253772Savg THREEOPERAND(x, mode, reg, r_m, rex_prefix, LONG_OPND, XMM_OPND, 3649253772Savg 1, 0); 3650253772Savg break; 3651253772Savg 3652179237Sjb /* MMX/SIMD-Int predicated r32/mem to mm reg */ 3653179237Sjb case MMOPRM: 3654179237Sjb wbit = LONG_OPND; 3655179237Sjb w2 = MM_OPND; 3656179237Sjb goto xmmprm; 3657179237Sjb case XMMPRM: 3658253772Savg case XMMPRM_66r: 3659179237Sjb wbit = LONG_OPND; 3660179237Sjb w2 = XMM_OPND; 3661179237Sjbxmmprm: 3662253772Savg THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, 1, 1); 3663179237Sjb break; 3664179237Sjb 3665179237Sjb /* MMX/SIMD-Int predicated mm/mem to mm reg */ 3666179237Sjb case MMOPM: 3667253772Savg case MMOPM_66o: 3668179237Sjb wbit = w2 = MM_OPND; 3669179237Sjb goto xmmprm; 3670179237Sjb 3671179237Sjb /* MMX/SIMD-Int mm reg to r32 */ 3672179237Sjb case MMOM3: 3673179237Sjb NOMEM; 3674179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3675179237Sjb if (mode != REG_ONLY) 3676179237Sjb goto error; 3677179237Sjb wbit = MM_OPND; 3678179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0); 3679179237Sjb break; 3680179237Sjb 3681179237Sjb /* SIMD memory or xmm reg operand to xmm reg */ 3682179237Sjb case XMM: 3683253772Savg case XMM_66o: 3684253772Savg case XMM_66r: 3685179237Sjb case XMMO: 3686179237Sjb case XMMXIMPL: 3687179237Sjb wbit = XMM_OPND; 3688179237Sjb STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 3689179237Sjb 3690179237Sjb if (dp->it_adrmode == XMMXIMPL && mode != REG_ONLY) 3691179237Sjb goto error; 3692179237Sjb 3693179237Sjb#ifdef DIS_TEXT 3694179237Sjb /* 3695179237Sjb * movlps and movhlps share opcodes. They differ in the 3696179237Sjb * addressing modes allowed for their operands. 3697179237Sjb * movhps and movlhps behave similarly. 3698179237Sjb */ 3699179237Sjb if (mode == REG_ONLY) { 3700179237Sjb if (strcmp(dp->it_name, "movlps") == 0) 3701253772Savg (void) strncpy(x->d86_mnem, "movhlps", OPLEN); 3702179237Sjb else if (strcmp(dp->it_name, "movhps") == 0) 3703253772Savg (void) strncpy(x->d86_mnem, "movlhps", OPLEN); 3704179237Sjb } 3705179237Sjb#endif 3706179237Sjb if (dp->it_adrmode == XMMXIMPL) 3707179237Sjb mode = 0; /* change for memory access size... */ 3708179237Sjb break; 3709179237Sjb 3710179237Sjb /* SIMD xmm reg to memory or xmm reg */ 3711179237Sjb case XMMS: 3712179237Sjb case XMMOS: 3713179237Sjb case XMMMS: 3714179237Sjb case XMMOMS: 3715179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3716179237Sjb#ifdef DIS_TEXT 3717179237Sjb if ((strcmp(dp->it_name, "movlps") == 0 || 3718179237Sjb strcmp(dp->it_name, "movhps") == 0 || 3719179237Sjb strcmp(dp->it_name, "movntps") == 0) && 3720179237Sjb mode == REG_ONLY) 3721179237Sjb goto error; 3722179237Sjb#endif 3723179237Sjb wbit = XMM_OPND; 3724179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1); 3725179237Sjb break; 3726179237Sjb 3727179237Sjb /* SIMD memory to xmm reg */ 3728179237Sjb case XMMM: 3729253772Savg case XMMM_66r: 3730179237Sjb case XMMOM: 3731179237Sjb wbit = XMM_OPND; 3732179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3733179237Sjb#ifdef DIS_TEXT 3734179237Sjb if (mode == REG_ONLY) { 3735179237Sjb if (strcmp(dp->it_name, "movhps") == 0) 3736253772Savg (void) strncpy(x->d86_mnem, "movlhps", OPLEN); 3737179237Sjb else 3738179237Sjb goto error; 3739179237Sjb } 3740179237Sjb#endif 3741179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 3742179237Sjb break; 3743179237Sjb 3744179237Sjb /* SIMD memory or r32 to xmm reg */ 3745179237Sjb case XMM3MX: 3746179237Sjb wbit = LONG_OPND; 3747179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 3748179237Sjb break; 3749179237Sjb 3750179237Sjb case XMM3MXS: 3751179237Sjb wbit = LONG_OPND; 3752179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1); 3753179237Sjb break; 3754179237Sjb 3755179237Sjb /* SIMD memory or mm reg to xmm reg */ 3756179237Sjb case XMMOMX: 3757179237Sjb /* SIMD mm to xmm */ 3758179237Sjb case XMMMX: 3759179237Sjb wbit = MM_OPND; 3760179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 3761179237Sjb break; 3762179237Sjb 3763179237Sjb /* SIMD memory or xmm reg to mm reg */ 3764179237Sjb case XMMXMM: 3765179237Sjb case XMMOXMM: 3766179237Sjb case XMMXM: 3767179237Sjb wbit = XMM_OPND; 3768179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0); 3769179237Sjb break; 3770179237Sjb 3771179237Sjb 3772179237Sjb /* SIMD memory or xmm reg to r32 */ 3773179237Sjb case XMMXM3: 3774179237Sjb wbit = XMM_OPND; 3775179237Sjb MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0); 3776179237Sjb break; 3777179237Sjb 3778179237Sjb /* SIMD xmm to r32 */ 3779179237Sjb case XMMX3: 3780179237Sjb case XMMOX3: 3781179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 3782179237Sjb if (mode != REG_ONLY) 3783179237Sjb goto error; 3784179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 3785179237Sjb dtrace_get_operand(x, mode, r_m, XMM_OPND, 0); 3786179237Sjb dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 3787179237Sjb NOMEM; 3788179237Sjb break; 3789179237Sjb 3790179237Sjb /* SIMD predicated memory or xmm reg with/to xmm reg */ 3791179237Sjb case XMMP: 3792253772Savg case XMMP_66r: 3793253772Savg case XMMP_66o: 3794179237Sjb case XMMOPM: 3795179237Sjb wbit = XMM_OPND; 3796253772Savg THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1, 3797253772Savg 1); 3798179237Sjb 3799179237Sjb#ifdef DIS_TEXT 3800179237Sjb /* 3801179237Sjb * cmpps and cmpss vary their instruction name based 3802179237Sjb * on the value of imm8. Other XMMP instructions, 3803179237Sjb * such as shufps, require explicit specification of 3804179237Sjb * the predicate. 3805179237Sjb */ 3806179237Sjb if (dp->it_name[0] == 'c' && 3807179237Sjb dp->it_name[1] == 'm' && 3808179237Sjb dp->it_name[2] == 'p' && 3809179237Sjb strlen(dp->it_name) == 5) { 3810179237Sjb uchar_t pred = x->d86_opnd[0].d86_value & 0xff; 3811179237Sjb 3812179237Sjb if (pred >= (sizeof (dis_PREDSUFFIX) / sizeof (char *))) 3813179237Sjb goto error; 3814179237Sjb 3815253772Savg (void) strncpy(x->d86_mnem, "cmp", OPLEN); 3816253772Savg (void) strlcat(x->d86_mnem, dis_PREDSUFFIX[pred], 3817179237Sjb OPLEN); 3818253772Savg (void) strlcat(x->d86_mnem, 3819179237Sjb dp->it_name + strlen(dp->it_name) - 2, 3820179237Sjb OPLEN); 3821179237Sjb x->d86_opnd[0] = x->d86_opnd[1]; 3822179237Sjb x->d86_opnd[1] = x->d86_opnd[2]; 3823179237Sjb x->d86_numopnds = 2; 3824179237Sjb } 3825179237Sjb#endif 3826179237Sjb break; 3827179237Sjb 3828253772Savg case XMMX2I: 3829253772Savg FOUROPERAND(x, mode, reg, r_m, rex_prefix, XMM_OPND, XMM_OPND, 3830253772Savg 1); 3831253772Savg NOMEM; 3832253772Savg break; 3833253772Savg 3834253772Savg case XMM2I: 3835253772Savg ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, XMM_OPND, 1); 3836253772Savg NOMEM; 3837253772Savg break; 3838253772Savg 3839179237Sjb /* immediate operand to accumulator */ 3840179237Sjb case IA: 3841179237Sjb wbit = WBIT(opcode2); 3842179237Sjb dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1); 3843179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0); 3844179237Sjb NOMEM; 3845179237Sjb break; 3846179237Sjb 3847179237Sjb /* memory or register operand to accumulator */ 3848179237Sjb case MA: 3849179237Sjb wbit = WBIT(opcode2); 3850179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 3851179237Sjb dtrace_get_operand(x, mode, r_m, wbit, 0); 3852179237Sjb break; 3853179237Sjb 3854179237Sjb /* si register to di register used to reference memory */ 3855179237Sjb case SD: 3856179237Sjb#ifdef DIS_TEXT 3857179237Sjb dtrace_check_override(x, 0); 3858179237Sjb x->d86_numopnds = 2; 3859179237Sjb if (addr_size == SIZE64) { 3860179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", 3861179237Sjb OPLEN); 3862179237Sjb (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", 3863179237Sjb OPLEN); 3864179237Sjb } else if (addr_size == SIZE32) { 3865179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", 3866179237Sjb OPLEN); 3867179237Sjb (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", 3868179237Sjb OPLEN); 3869179237Sjb } else { 3870179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)", 3871179237Sjb OPLEN); 3872179237Sjb (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)", 3873179237Sjb OPLEN); 3874179237Sjb } 3875179237Sjb#endif 3876179237Sjb wbit = LONG_OPND; 3877179237Sjb break; 3878179237Sjb 3879179237Sjb /* accumulator to di register */ 3880179237Sjb case AD: 3881179237Sjb wbit = WBIT(opcode2); 3882179237Sjb#ifdef DIS_TEXT 3883179237Sjb dtrace_check_override(x, 1); 3884179237Sjb x->d86_numopnds = 2; 3885179237Sjb dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 0); 3886179237Sjb if (addr_size == SIZE64) 3887179237Sjb (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", 3888179237Sjb OPLEN); 3889179237Sjb else if (addr_size == SIZE32) 3890179237Sjb (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", 3891179237Sjb OPLEN); 3892179237Sjb else 3893179237Sjb (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)", 3894179237Sjb OPLEN); 3895179237Sjb#endif 3896179237Sjb break; 3897179237Sjb 3898179237Sjb /* si register to accumulator */ 3899179237Sjb case SA: 3900179237Sjb wbit = WBIT(opcode2); 3901179237Sjb#ifdef DIS_TEXT 3902179237Sjb dtrace_check_override(x, 0); 3903179237Sjb x->d86_numopnds = 2; 3904179237Sjb if (addr_size == SIZE64) 3905179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", 3906179237Sjb OPLEN); 3907179237Sjb else if (addr_size == SIZE32) 3908179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", 3909179237Sjb OPLEN); 3910179237Sjb else 3911179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)", 3912179237Sjb OPLEN); 3913179237Sjb dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1); 3914179237Sjb#endif 3915179237Sjb break; 3916179237Sjb 3917179237Sjb /* 3918179237Sjb * single operand, a 16/32 bit displacement 3919179237Sjb */ 3920179237Sjb case D: 3921179237Sjb wbit = LONG_OPND; 3922179237Sjb dtrace_disp_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0); 3923179237Sjb NOMEM; 3924179237Sjb break; 3925179237Sjb 3926179237Sjb /* jmp/call indirect to memory or register operand */ 3927179237Sjb case INM: 3928179237Sjb#ifdef DIS_TEXT 3929179237Sjb (void) strlcat(x->d86_opnd[0].d86_prefix, "*", OPLEN); 3930179237Sjb#endif 3931179237Sjb dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 3932179237Sjb dtrace_get_operand(x, mode, r_m, LONG_OPND, 0); 3933179237Sjb wbit = LONG_OPND; 3934179237Sjb break; 3935179237Sjb 3936179237Sjb /* 3937179237Sjb * for long jumps and long calls -- a new code segment 3938179237Sjb * register and an offset in IP -- stored in object 3939179237Sjb * code in reverse order. Note - not valid in amd64 3940179237Sjb */ 3941179237Sjb case SO: 3942179237Sjb dtrace_check_override(x, 1); 3943179237Sjb wbit = LONG_OPND; 3944179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 1); 3945179237Sjb#ifdef DIS_TEXT 3946179237Sjb x->d86_opnd[1].d86_mode = MODE_SIGNED; 3947179237Sjb#endif 3948179237Sjb /* will now get segment operand */ 3949179237Sjb dtrace_imm_opnd(x, wbit, 2, 0); 3950179237Sjb break; 3951179237Sjb 3952179237Sjb /* 3953179237Sjb * jmp/call. single operand, 8 bit displacement. 3954179237Sjb * added to current EIP in 'compofff' 3955179237Sjb */ 3956179237Sjb case BD: 3957179237Sjb dtrace_disp_opnd(x, BYTE_OPND, 1, 0); 3958179237Sjb NOMEM; 3959179237Sjb break; 3960179237Sjb 3961179237Sjb /* single 32/16 bit immediate operand */ 3962179237Sjb case I: 3963179237Sjb wbit = LONG_OPND; 3964179237Sjb dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0); 3965179237Sjb break; 3966179237Sjb 3967179237Sjb /* single 8 bit immediate operand */ 3968179237Sjb case Ib: 3969179237Sjb wbit = LONG_OPND; 3970179237Sjb dtrace_imm_opnd(x, wbit, 1, 0); 3971179237Sjb break; 3972179237Sjb 3973179237Sjb case ENTER: 3974179237Sjb wbit = LONG_OPND; 3975179237Sjb dtrace_imm_opnd(x, wbit, 2, 0); 3976179237Sjb dtrace_imm_opnd(x, wbit, 1, 1); 3977179237Sjb switch (opnd_size) { 3978179237Sjb case SIZE64: 3979179237Sjb x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 8; 3980179237Sjb break; 3981179237Sjb case SIZE32: 3982179237Sjb x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 4; 3983179237Sjb break; 3984179237Sjb case SIZE16: 3985179237Sjb x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 2; 3986179237Sjb break; 3987179237Sjb } 3988179237Sjb 3989179237Sjb break; 3990179237Sjb 3991179237Sjb /* 16-bit immediate operand */ 3992179237Sjb case RET: 3993179237Sjb wbit = LONG_OPND; 3994179237Sjb dtrace_imm_opnd(x, wbit, 2, 0); 3995179237Sjb break; 3996179237Sjb 3997179237Sjb /* single 8 bit port operand */ 3998179237Sjb case P: 3999179237Sjb dtrace_check_override(x, 0); 4000179237Sjb dtrace_imm_opnd(x, BYTE_OPND, 1, 0); 4001179237Sjb NOMEM; 4002179237Sjb break; 4003179237Sjb 4004179237Sjb /* single operand, dx register (variable port instruction) */ 4005179237Sjb case V: 4006179237Sjb x->d86_numopnds = 1; 4007179237Sjb dtrace_check_override(x, 0); 4008179237Sjb#ifdef DIS_TEXT 4009179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "(%dx)", OPLEN); 4010179237Sjb#endif 4011179237Sjb NOMEM; 4012179237Sjb break; 4013179237Sjb 4014179237Sjb /* 4015179237Sjb * The int instruction, which has two forms: 4016179237Sjb * int 3 (breakpoint) or 4017179237Sjb * int n, where n is indicated in the subsequent 4018179237Sjb * byte (format Ib). The int 3 instruction (opcode 0xCC), 4019179237Sjb * where, although the 3 looks like an operand, 4020179237Sjb * it is implied by the opcode. It must be converted 4021179237Sjb * to the correct base and output. 4022179237Sjb */ 4023179237Sjb case INT3: 4024179237Sjb#ifdef DIS_TEXT 4025179237Sjb x->d86_numopnds = 1; 4026179237Sjb x->d86_opnd[0].d86_mode = MODE_SIGNED; 4027179237Sjb x->d86_opnd[0].d86_value_size = 1; 4028179237Sjb x->d86_opnd[0].d86_value = 3; 4029179237Sjb#endif 4030179237Sjb NOMEM; 4031179237Sjb break; 4032179237Sjb 4033179237Sjb /* single 8 bit immediate operand */ 4034179237Sjb case INTx: 4035179237Sjb dtrace_imm_opnd(x, BYTE_OPND, 1, 0); 4036179237Sjb NOMEM; 4037179237Sjb break; 4038179237Sjb 4039179237Sjb /* an unused byte must be discarded */ 4040179237Sjb case U: 4041179237Sjb if (x->d86_get_byte(x->d86_data) < 0) 4042179237Sjb goto error; 4043179237Sjb x->d86_len++; 4044179237Sjb NOMEM; 4045179237Sjb break; 4046179237Sjb 4047179237Sjb case CBW: 4048179237Sjb#ifdef DIS_TEXT 4049179237Sjb if (opnd_size == SIZE16) 4050253772Savg (void) strlcat(x->d86_mnem, "cbtw", OPLEN); 4051179237Sjb else if (opnd_size == SIZE32) 4052253772Savg (void) strlcat(x->d86_mnem, "cwtl", OPLEN); 4053179237Sjb else 4054253772Savg (void) strlcat(x->d86_mnem, "cltq", OPLEN); 4055179237Sjb#endif 4056179237Sjb wbit = LONG_OPND; 4057179237Sjb NOMEM; 4058179237Sjb break; 4059179237Sjb 4060179237Sjb case CWD: 4061179237Sjb#ifdef DIS_TEXT 4062179237Sjb if (opnd_size == SIZE16) 4063253772Savg (void) strlcat(x->d86_mnem, "cwtd", OPLEN); 4064179237Sjb else if (opnd_size == SIZE32) 4065253772Savg (void) strlcat(x->d86_mnem, "cltd", OPLEN); 4066179237Sjb else 4067253772Savg (void) strlcat(x->d86_mnem, "cqtd", OPLEN); 4068179237Sjb#endif 4069179237Sjb wbit = LONG_OPND; 4070179237Sjb NOMEM; 4071179237Sjb break; 4072179237Sjb 4073179237Sjb case XMMSFNC: 4074179237Sjb /* 4075179237Sjb * sfence is sfence if mode is REG_ONLY. If mode isn't 4076179237Sjb * REG_ONLY, mnemonic should be 'clflush'. 4077179237Sjb */ 4078179237Sjb dtrace_get_modrm(x, &mode, ®, &r_m); 4079179237Sjb 4080179237Sjb /* sfence doesn't take operands */ 4081179237Sjb#ifdef DIS_TEXT 4082179237Sjb if (mode == REG_ONLY) { 4083253772Savg (void) strlcat(x->d86_mnem, "sfence", OPLEN); 4084179237Sjb } else { 4085253772Savg (void) strlcat(x->d86_mnem, "clflush", OPLEN); 4086179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 4087179237Sjb dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0); 4088179237Sjb NOMEM; 4089179237Sjb } 4090179237Sjb#else 4091179237Sjb if (mode != REG_ONLY) { 4092179237Sjb dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 4093253772Savg dtrace_get_operand(x, mode, r_m, LONG_OPND, 0); 4094179237Sjb NOMEM; 4095179237Sjb } 4096179237Sjb#endif 4097179237Sjb break; 4098179237Sjb 4099179237Sjb /* 4100179237Sjb * no disassembly, the mnemonic was all there was so go on 4101179237Sjb */ 4102179237Sjb case NORM: 4103179237Sjb if (dp->it_invalid32 && cpu_mode != SIZE64) 4104179237Sjb goto error; 4105179237Sjb NOMEM; 4106179237Sjb /*FALLTHROUGH*/ 4107179237Sjb case IMPLMEM: 4108179237Sjb break; 4109179237Sjb 4110179237Sjb case XMMFENCE: 4111179237Sjb /* 4112253772Savg * XRSTOR and LFENCE share the same opcode but differ in mode 4113179237Sjb */ 4114253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4115179237Sjb 4116253772Savg if (mode == REG_ONLY) { 4117253772Savg /* 4118253772Savg * Only the following exact byte sequences are allowed: 4119253772Savg * 4120253772Savg * 0f ae e8 lfence 4121253772Savg * 0f ae f0 mfence 4122253772Savg */ 4123253772Savg if ((uint8_t)x->d86_bytes[x->d86_len - 1] != 0xe8 && 4124253772Savg (uint8_t)x->d86_bytes[x->d86_len - 1] != 0xf0) 4125253772Savg goto error; 4126253772Savg } else { 4127253772Savg#ifdef DIS_TEXT 4128253772Savg (void) strncpy(x->d86_mnem, "xrstor", OPLEN); 4129253772Savg#endif 4130253772Savg dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 4131253772Savg dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0); 4132253772Savg } 4133179237Sjb break; 4134179237Sjb 4135179237Sjb /* float reg */ 4136179237Sjb case F: 4137179237Sjb#ifdef DIS_TEXT 4138179237Sjb x->d86_numopnds = 1; 4139179237Sjb (void) strlcat(x->d86_opnd[0].d86_opnd, "%st(X)", OPLEN); 4140179237Sjb x->d86_opnd[0].d86_opnd[4] = r_m + '0'; 4141179237Sjb#endif 4142179237Sjb NOMEM; 4143179237Sjb break; 4144179237Sjb 4145179237Sjb /* float reg to float reg, with ret bit present */ 4146179237Sjb case FF: 4147179237Sjb vbit = opcode2 >> 2 & 0x1; /* vbit = 1: st -> st(i) */ 4148179237Sjb /*FALLTHROUGH*/ 4149179237Sjb case FFC: /* case for vbit always = 0 */ 4150179237Sjb#ifdef DIS_TEXT 4151179237Sjb x->d86_numopnds = 2; 4152179237Sjb (void) strlcat(x->d86_opnd[1 - vbit].d86_opnd, "%st", OPLEN); 4153179237Sjb (void) strlcat(x->d86_opnd[vbit].d86_opnd, "%st(X)", OPLEN); 4154179237Sjb x->d86_opnd[vbit].d86_opnd[4] = r_m + '0'; 4155179237Sjb#endif 4156179237Sjb NOMEM; 4157179237Sjb break; 4158179237Sjb 4159253772Savg /* AVX instructions */ 4160253772Savg case VEX_MO: 4161253772Savg /* op(ModR/M.r/m) */ 4162253772Savg x->d86_numopnds = 1; 4163253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4164253772Savg#ifdef DIS_TEXT 4165253772Savg if ((dp == &dis_opAVX0F[0xA][0xE]) && (reg == 3)) 4166253772Savg (void) strncpy(x->d86_mnem, "vstmxcsr", OPLEN); 4167253772Savg#endif 4168253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4169253772Savg dtrace_get_operand(x, mode, r_m, wbit, 0); 4170253772Savg break; 4171253772Savg case VEX_RMrX: 4172253772Savg /* ModR/M.reg := op(VEX.vvvv, ModR/M.r/m) */ 4173253772Savg x->d86_numopnds = 3; 4174253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4175253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4176253772Savg 4177253772Savg if (mode != REG_ONLY) { 4178253772Savg if ((dp == &dis_opAVXF20F[0x10]) || 4179253772Savg (dp == &dis_opAVXF30F[0x10])) { 4180253772Savg /* vmovsd <m64>, <xmm> */ 4181253772Savg /* or vmovss <m64>, <xmm> */ 4182253772Savg x->d86_numopnds = 2; 4183253772Savg goto L_VEX_MX; 4184253772Savg } 4185253772Savg } 4186253772Savg 4187253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 2); 4188253772Savg /* 4189253772Savg * VEX prefix uses the 1's complement form to encode the 4190253772Savg * XMM/YMM regs 4191253772Savg */ 4192253772Savg dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 4193253772Savg 4194253772Savg if ((dp == &dis_opAVXF20F[0x2A]) || 4195253772Savg (dp == &dis_opAVXF30F[0x2A])) { 4196253772Savg /* 4197253772Savg * vcvtsi2si </r,m>, <xmm>, <xmm> or vcvtsi2ss </r,m>, 4198253772Savg * <xmm>, <xmm> 4199253772Savg */ 4200253772Savg wbit = LONG_OPND; 4201253772Savg } 4202253772Savg#ifdef DIS_TEXT 4203253772Savg else if ((mode == REG_ONLY) && 4204253772Savg (dp == &dis_opAVX0F[0x1][0x6])) { /* vmovlhps */ 4205253772Savg (void) strncpy(x->d86_mnem, "vmovlhps", OPLEN); 4206253772Savg } else if ((mode == REG_ONLY) && 4207253772Savg (dp == &dis_opAVX0F[0x1][0x2])) { /* vmovhlps */ 4208253772Savg (void) strncpy(x->d86_mnem, "vmovhlps", OPLEN); 4209253772Savg } 4210253772Savg#endif 4211253772Savg dtrace_get_operand(x, mode, r_m, wbit, 0); 4212253772Savg 4213253772Savg break; 4214253772Savg 4215253772Savg case VEX_RRX: 4216253772Savg /* ModR/M.rm := op(VEX.vvvv, ModR/M.reg) */ 4217253772Savg x->d86_numopnds = 3; 4218253772Savg 4219253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4220253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4221253772Savg 4222253772Savg if (mode != REG_ONLY) { 4223253772Savg if ((dp == &dis_opAVXF20F[0x11]) || 4224253772Savg (dp == &dis_opAVXF30F[0x11])) { 4225253772Savg /* vmovsd <xmm>, <m64> */ 4226253772Savg /* or vmovss <xmm>, <m64> */ 4227253772Savg x->d86_numopnds = 2; 4228253772Savg goto L_VEX_RM; 4229253772Savg } 4230253772Savg } 4231253772Savg 4232253772Savg dtrace_get_operand(x, mode, r_m, wbit, 2); 4233253772Savg dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 4234253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 0); 4235253772Savg break; 4236253772Savg 4237253772Savg case VEX_RMRX: 4238253772Savg /* ModR/M.reg := op(VEX.vvvv, ModR/M.r_m, imm8[7:4]) */ 4239253772Savg x->d86_numopnds = 4; 4240253772Savg 4241253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4242253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4243253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 3); 4244253772Savg dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 2); 4245253772Savg if (dp == &dis_opAVX660F3A[0x18]) { 4246253772Savg /* vinsertf128 <imm8>, <xmm>, <ymm>, <ymm> */ 4247253772Savg dtrace_get_operand(x, mode, r_m, XMM_OPND, 1); 4248253772Savg } else if ((dp == &dis_opAVX660F3A[0x20]) || 4249253772Savg (dp == & dis_opAVX660F[0xC4])) { 4250253772Savg /* vpinsrb <imm8>, <reg/mm>, <xmm>, <xmm> */ 4251253772Savg /* or vpinsrw <imm8>, <reg/mm>, <xmm>, <xmm> */ 4252253772Savg dtrace_get_operand(x, mode, r_m, LONG_OPND, 1); 4253253772Savg } else if (dp == &dis_opAVX660F3A[0x22]) { 4254253772Savg /* vpinsrd/q <imm8>, <reg/mm>, <xmm>, <xmm> */ 4255253772Savg#ifdef DIS_TEXT 4256253772Savg if (vex_W) 4257253772Savg x->d86_mnem[6] = 'q'; 4258253772Savg#endif 4259253772Savg dtrace_get_operand(x, mode, r_m, LONG_OPND, 1); 4260253772Savg } else { 4261253772Savg dtrace_get_operand(x, mode, r_m, wbit, 1); 4262253772Savg } 4263253772Savg 4264253772Savg /* one byte immediate number */ 4265253772Savg dtrace_imm_opnd(x, wbit, 1, 0); 4266253772Savg 4267253772Savg /* vblendvpd, vblendvps, vblendvb use the imm encode the regs */ 4268253772Savg if ((dp == &dis_opAVX660F3A[0x4A]) || 4269253772Savg (dp == &dis_opAVX660F3A[0x4B]) || 4270253772Savg (dp == &dis_opAVX660F3A[0x4C])) { 4271253772Savg#ifdef DIS_TEXT 4272253772Savg int regnum = (x->d86_opnd[0].d86_value & 0xF0) >> 4; 4273253772Savg#endif 4274253772Savg x->d86_opnd[0].d86_mode = MODE_NONE; 4275253772Savg#ifdef DIS_TEXT 4276253772Savg if (vex_L) 4277253772Savg (void) strncpy(x->d86_opnd[0].d86_opnd, 4278253772Savg dis_YMMREG[regnum], OPLEN); 4279253772Savg else 4280253772Savg (void) strncpy(x->d86_opnd[0].d86_opnd, 4281253772Savg dis_XMMREG[regnum], OPLEN); 4282253772Savg#endif 4283253772Savg } 4284253772Savg break; 4285253772Savg 4286253772Savg case VEX_MX: 4287253772Savg /* ModR/M.reg := op(ModR/M.rm) */ 4288253772Savg x->d86_numopnds = 2; 4289253772Savg 4290253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4291253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4292253772SavgL_VEX_MX: 4293253772Savg 4294253772Savg if ((dp == &dis_opAVXF20F[0xE6]) || 4295253772Savg (dp == &dis_opAVX660F[0x5A]) || 4296253772Savg (dp == &dis_opAVX660F[0xE6])) { 4297253772Savg /* vcvtpd2dq <ymm>, <xmm> */ 4298253772Savg /* or vcvtpd2ps <ymm>, <xmm> */ 4299253772Savg /* or vcvttpd2dq <ymm>, <xmm> */ 4300253772Savg dtrace_get_operand(x, REG_ONLY, reg, XMM_OPND, 1); 4301253772Savg dtrace_get_operand(x, mode, r_m, wbit, 0); 4302253772Savg } else if ((dp == &dis_opAVXF30F[0xE6]) || 4303253772Savg (dp == &dis_opAVX0F[0x5][0xA])) { 4304253772Savg /* vcvtdq2pd <xmm>, <ymm> */ 4305253772Savg /* or vcvtps2pd <xmm>, <ymm> */ 4306253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 4307253772Savg dtrace_get_operand(x, mode, r_m, XMM_OPND, 0); 4308253772Savg } else if (dp == &dis_opAVX660F[0x6E]) { 4309253772Savg /* vmovd/q <reg/mem 32/64>, <xmm> */ 4310253772Savg#ifdef DIS_TEXT 4311253772Savg if (vex_W) 4312253772Savg x->d86_mnem[4] = 'q'; 4313253772Savg#endif 4314253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 4315253772Savg dtrace_get_operand(x, mode, r_m, LONG_OPND, 0); 4316253772Savg } else { 4317253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 4318253772Savg dtrace_get_operand(x, mode, r_m, wbit, 0); 4319253772Savg } 4320253772Savg 4321253772Savg break; 4322253772Savg 4323253772Savg case VEX_MXI: 4324253772Savg /* ModR/M.reg := op(ModR/M.rm, imm8) */ 4325253772Savg x->d86_numopnds = 3; 4326253772Savg 4327253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4328253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4329253772Savg 4330253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 2); 4331253772Savg dtrace_get_operand(x, mode, r_m, wbit, 1); 4332253772Savg 4333253772Savg /* one byte immediate number */ 4334253772Savg dtrace_imm_opnd(x, wbit, 1, 0); 4335253772Savg break; 4336253772Savg 4337253772Savg case VEX_XXI: 4338253772Savg /* VEX.vvvv := op(ModR/M.rm, imm8) */ 4339253772Savg x->d86_numopnds = 3; 4340253772Savg 4341253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4342253772Savg#ifdef DIS_TEXT 4343253772Savg (void) strncpy(x->d86_mnem, dis_AVXvgrp7[opcode2 - 1][reg], 4344253772Savg OPLEN); 4345253772Savg#endif 4346253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4347253772Savg 4348253772Savg dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 2); 4349253772Savg dtrace_get_operand(x, REG_ONLY, r_m, wbit, 1); 4350253772Savg 4351253772Savg /* one byte immediate number */ 4352253772Savg dtrace_imm_opnd(x, wbit, 1, 0); 4353253772Savg break; 4354253772Savg 4355253772Savg case VEX_MR: 4356253772Savg /* ModR/M.reg (reg32/64) := op(ModR/M.rm) */ 4357253772Savg if (dp == &dis_opAVX660F[0xC5]) { 4358253772Savg /* vpextrw <imm8>, <xmm>, <reg> */ 4359253772Savg x->d86_numopnds = 2; 4360253772Savg vbit = 2; 4361253772Savg } else { 4362253772Savg x->d86_numopnds = 2; 4363253772Savg vbit = 1; 4364253772Savg } 4365253772Savg 4366253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4367253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4368253772Savg dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, vbit); 4369253772Savg dtrace_get_operand(x, mode, r_m, wbit, vbit - 1); 4370253772Savg 4371253772Savg if (vbit == 2) 4372253772Savg dtrace_imm_opnd(x, wbit, 1, 0); 4373253772Savg 4374253772Savg break; 4375253772Savg 4376253772Savg case VEX_RRI: 4377253772Savg /* implicit(eflags/r32) := op(ModR/M.reg, ModR/M.rm) */ 4378253772Savg x->d86_numopnds = 2; 4379253772Savg 4380253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4381253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4382253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 4383253772Savg dtrace_get_operand(x, mode, r_m, wbit, 0); 4384253772Savg break; 4385253772Savg 4386253772Savg case VEX_RX: 4387253772Savg /* ModR/M.rm := op(ModR/M.reg) */ 4388253772Savg if (dp == &dis_opAVX660F3A[0x19]) { /* vextractf128 */ 4389253772Savg x->d86_numopnds = 3; 4390253772Savg 4391253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4392253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4393253772Savg 4394253772Savg dtrace_get_operand(x, mode, r_m, XMM_OPND, 2); 4395253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 4396253772Savg 4397253772Savg /* one byte immediate number */ 4398253772Savg dtrace_imm_opnd(x, wbit, 1, 0); 4399253772Savg break; 4400253772Savg } 4401253772Savg 4402253772Savg x->d86_numopnds = 2; 4403253772Savg 4404253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4405253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4406253772Savg dtrace_get_operand(x, mode, r_m, wbit, 1); 4407253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 0); 4408253772Savg break; 4409253772Savg 4410253772Savg case VEX_RR: 4411253772Savg /* ModR/M.rm := op(ModR/M.reg) */ 4412253772Savg x->d86_numopnds = 2; 4413253772Savg 4414253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4415253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4416253772Savg 4417253772Savg if (dp == &dis_opAVX660F[0x7E]) { 4418253772Savg /* vmovd/q <reg/mem 32/64>, <xmm> */ 4419253772Savg#ifdef DIS_TEXT 4420253772Savg if (vex_W) 4421253772Savg x->d86_mnem[4] = 'q'; 4422253772Savg#endif 4423253772Savg dtrace_get_operand(x, mode, r_m, LONG_OPND, 1); 4424253772Savg } else 4425253772Savg dtrace_get_operand(x, mode, r_m, wbit, 1); 4426253772Savg 4427253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 0); 4428253772Savg break; 4429253772Savg 4430253772Savg case VEX_RRi: 4431253772Savg /* ModR/M.rm := op(ModR/M.reg, imm) */ 4432253772Savg x->d86_numopnds = 3; 4433253772Savg 4434253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4435253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4436253772Savg 4437253772Savg#ifdef DIS_TEXT 4438253772Savg if (dp == &dis_opAVX660F3A[0x16]) { 4439253772Savg /* vpextrd/q <imm>, <xmm>, <reg/mem 32/64> */ 4440253772Savg if (vex_W) 4441253772Savg x->d86_mnem[6] = 'q'; 4442253772Savg } 4443253772Savg#endif 4444253772Savg dtrace_get_operand(x, mode, r_m, LONG_OPND, 2); 4445253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 4446253772Savg 4447253772Savg /* one byte immediate number */ 4448253772Savg dtrace_imm_opnd(x, wbit, 1, 0); 4449253772Savg break; 4450253772Savg 4451253772Savg case VEX_RM: 4452253772Savg /* ModR/M.rm := op(ModR/M.reg) */ 4453253772Savg if (dp == &dis_opAVX660F3A[0x17]) { /* vextractps */ 4454253772Savg x->d86_numopnds = 3; 4455253772Savg 4456253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4457253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4458253772Savg 4459253772Savg dtrace_get_operand(x, mode, r_m, LONG_OPND, 2); 4460253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 4461253772Savg /* one byte immediate number */ 4462253772Savg dtrace_imm_opnd(x, wbit, 1, 0); 4463253772Savg break; 4464253772Savg } 4465253772Savg x->d86_numopnds = 2; 4466253772Savg 4467253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4468253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4469253772SavgL_VEX_RM: 4470253772Savg vbit = 1; 4471253772Savg dtrace_get_operand(x, mode, r_m, wbit, vbit); 4472253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit - 1); 4473253772Savg 4474253772Savg break; 4475253772Savg 4476253772Savg case VEX_RRM: 4477253772Savg /* ModR/M.rm := op(VEX.vvvv, ModR/M.reg) */ 4478253772Savg x->d86_numopnds = 3; 4479253772Savg 4480253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4481253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4482253772Savg dtrace_get_operand(x, mode, r_m, wbit, 2); 4483253772Savg /* VEX use the 1's complement form encode the XMM/YMM regs */ 4484253772Savg dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 4485253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 0); 4486253772Savg break; 4487253772Savg 4488253772Savg case VEX_RMX: 4489253772Savg /* ModR/M.reg := op(VEX.vvvv, ModR/M.rm) */ 4490253772Savg x->d86_numopnds = 3; 4491253772Savg 4492253772Savg dtrace_get_modrm(x, &mode, ®, &r_m); 4493253772Savg dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4494253772Savg dtrace_get_operand(x, REG_ONLY, reg, wbit, 2); 4495253772Savg dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 4496253772Savg dtrace_get_operand(x, REG_ONLY, r_m, wbit, 0); 4497253772Savg break; 4498253772Savg 4499253772Savg case VEX_NONE: 4500253772Savg#ifdef DIS_TEXT 4501253772Savg if (vex_L) 4502253772Savg (void) strncpy(x->d86_mnem, "vzeroall", OPLEN); 4503253772Savg#endif 4504253772Savg break; 4505179237Sjb /* an invalid op code */ 4506179237Sjb case AM: 4507179237Sjb case DM: 4508179237Sjb case OVERRIDE: 4509179237Sjb case PREFIX: 4510179237Sjb case UNKNOWN: 4511179237Sjb NOMEM; 4512179237Sjb default: 4513179237Sjb goto error; 4514179237Sjb } /* end switch */ 4515179237Sjb if (x->d86_error) 4516179237Sjb goto error; 4517179237Sjb 4518179237Sjbdone: 4519179237Sjb#ifdef DIS_MEM 4520179237Sjb /* 4521179237Sjb * compute the size of any memory accessed by the instruction 4522179237Sjb */ 4523179237Sjb if (x->d86_memsize != 0) { 4524179237Sjb return (0); 4525179237Sjb } else if (dp->it_stackop) { 4526179237Sjb switch (opnd_size) { 4527179237Sjb case SIZE16: 4528179237Sjb x->d86_memsize = 2; 4529179237Sjb break; 4530179237Sjb case SIZE32: 4531179237Sjb x->d86_memsize = 4; 4532179237Sjb break; 4533179237Sjb case SIZE64: 4534179237Sjb x->d86_memsize = 8; 4535179237Sjb break; 4536179237Sjb } 4537179237Sjb } else if (nomem || mode == REG_ONLY) { 4538179237Sjb x->d86_memsize = 0; 4539179237Sjb 4540179237Sjb } else if (dp->it_size != 0) { 4541179237Sjb /* 4542179237Sjb * In 64 bit mode descriptor table entries 4543179237Sjb * go up to 10 bytes and popf/pushf are always 8 bytes 4544179237Sjb */ 4545179237Sjb if (x->d86_mode == SIZE64 && dp->it_size == 6) 4546179237Sjb x->d86_memsize = 10; 4547179237Sjb else if (x->d86_mode == SIZE64 && opcode1 == 0x9 && 4548179237Sjb (opcode2 == 0xc || opcode2 == 0xd)) 4549179237Sjb x->d86_memsize = 8; 4550179237Sjb else 4551179237Sjb x->d86_memsize = dp->it_size; 4552179237Sjb 4553179237Sjb } else if (wbit == 0) { 4554179237Sjb x->d86_memsize = 1; 4555179237Sjb 4556179237Sjb } else if (wbit == LONG_OPND) { 4557179237Sjb if (opnd_size == SIZE64) 4558179237Sjb x->d86_memsize = 8; 4559179237Sjb else if (opnd_size == SIZE32) 4560179237Sjb x->d86_memsize = 4; 4561179237Sjb else 4562179237Sjb x->d86_memsize = 2; 4563179237Sjb 4564179237Sjb } else if (wbit == SEG_OPND) { 4565179237Sjb x->d86_memsize = 4; 4566179237Sjb 4567179237Sjb } else { 4568179237Sjb x->d86_memsize = 8; 4569179237Sjb } 4570179237Sjb#endif 4571179237Sjb return (0); 4572179237Sjb 4573179237Sjberror: 4574179237Sjb#ifdef DIS_TEXT 4575253772Savg (void) strlcat(x->d86_mnem, "undef", OPLEN); 4576179237Sjb#endif 4577179237Sjb return (1); 4578179237Sjb} 4579179237Sjb 4580179237Sjb#ifdef DIS_TEXT 4581179237Sjb 4582179237Sjb/* 4583179237Sjb * Some instructions should have immediate operands printed 4584179237Sjb * as unsigned integers. We compare against this table. 4585179237Sjb */ 4586179237Sjbstatic char *unsigned_ops[] = { 4587179237Sjb "or", "and", "xor", "test", "in", "out", "lcall", "ljmp", 4588179237Sjb "rcr", "rcl", "ror", "rol", "shl", "shr", "sal", "psr", "psl", 4589179237Sjb 0 4590179237Sjb}; 4591179237Sjb 4592253772Savg 4593179237Sjbstatic int 4594179237Sjbisunsigned_op(char *opcode) 4595179237Sjb{ 4596179237Sjb char *where; 4597179237Sjb int i; 4598179237Sjb int is_unsigned = 0; 4599179237Sjb 4600179237Sjb /* 4601179237Sjb * Work back to start of last mnemonic, since we may have 4602179237Sjb * prefixes on some opcodes. 4603179237Sjb */ 4604179237Sjb where = opcode + strlen(opcode) - 1; 4605179237Sjb while (where > opcode && *where != ' ') 4606179237Sjb --where; 4607179237Sjb if (*where == ' ') 4608179237Sjb ++where; 4609179237Sjb 4610179237Sjb for (i = 0; unsigned_ops[i]; ++i) { 4611179237Sjb if (strncmp(where, unsigned_ops[i], 4612179237Sjb strlen(unsigned_ops[i]))) 4613179237Sjb continue; 4614179237Sjb is_unsigned = 1; 4615179237Sjb break; 4616179237Sjb } 4617179237Sjb return (is_unsigned); 4618179237Sjb} 4619179237Sjb 4620253772Savg/* 4621253772Savg * Print a numeric immediate into end of buf, maximum length buflen. 4622253772Savg * The immediate may be an address or a displacement. Mask is set 4623253772Savg * for address size. If the immediate is a "small negative", or 4624253772Savg * if it's a negative displacement of any magnitude, print as -<absval>. 4625253772Savg * Respect the "octal" flag. "Small negative" is defined as "in the 4626253772Savg * interval [NEG_LIMIT, 0)". 4627253772Savg * 4628253772Savg * Also, "isunsigned_op()" instructions never print negatives. 4629253772Savg * 4630253772Savg * Return whether we decided to print a negative value or not. 4631253772Savg */ 4632253772Savg 4633253772Savg#define NEG_LIMIT -255 4634253772Savgenum {IMM, DISP}; 4635253772Savgenum {POS, TRY_NEG}; 4636253772Savg 4637253772Savgstatic int 4638253772Savgprint_imm(dis86_t *dis, uint64_t usv, uint64_t mask, char *buf, 4639253772Savg size_t buflen, int disp, int try_neg) 4640253772Savg{ 4641253772Savg int curlen; 4642253772Savg int64_t sv = (int64_t)usv; 4643253772Savg int octal = dis->d86_flags & DIS_F_OCTAL; 4644253772Savg 4645253772Savg curlen = strlen(buf); 4646253772Savg 4647253772Savg if (try_neg == TRY_NEG && sv < 0 && 4648253772Savg (disp || sv >= NEG_LIMIT) && 4649253772Savg !isunsigned_op(dis->d86_mnem)) { 4650253772Savg dis->d86_sprintf_func(buf + curlen, buflen - curlen, 4651253772Savg octal ? "-0%llo" : "-0x%llx", (-sv) & mask); 4652253772Savg return (1); 4653253772Savg } else { 4654253772Savg if (disp == DISP) 4655253772Savg dis->d86_sprintf_func(buf + curlen, buflen - curlen, 4656253772Savg octal ? "+0%llo" : "+0x%llx", usv & mask); 4657253772Savg else 4658253772Savg dis->d86_sprintf_func(buf + curlen, buflen - curlen, 4659253772Savg octal ? "0%llo" : "0x%llx", usv & mask); 4660253772Savg return (0); 4661253772Savg 4662253772Savg } 4663253772Savg} 4664253772Savg 4665253772Savg 4666253772Savgstatic int 4667253772Savglog2(int size) 4668253772Savg{ 4669253772Savg switch (size) { 4670253772Savg case 1: return (0); 4671253772Savg case 2: return (1); 4672253772Savg case 4: return (2); 4673253772Savg case 8: return (3); 4674253772Savg } 4675253772Savg return (0); 4676253772Savg} 4677253772Savg 4678179237Sjb/* ARGSUSED */ 4679179237Sjbvoid 4680253772Savgdtrace_disx86_str(dis86_t *dis, uint_t mode, uint64_t pc, char *buf, 4681179237Sjb size_t buflen) 4682179237Sjb{ 4683253772Savg uint64_t reltgt = 0; 4684253772Savg uint64_t tgt = 0; 4685253772Savg int curlen; 4686253772Savg int (*lookup)(void *, uint64_t, char *, size_t); 4687179237Sjb int i; 4688253772Savg int64_t sv; 4689253772Savg uint64_t usv, mask, save_mask, save_usv; 4690253772Savg static uint64_t masks[] = 4691253772Savg {0xffU, 0xffffU, 0xffffffffU, 0xffffffffffffffffULL}; 4692253772Savg save_usv = 0; 4693179237Sjb 4694253772Savg dis->d86_sprintf_func(buf, buflen, "%-6s ", dis->d86_mnem); 4695179237Sjb 4696179237Sjb /* 4697179237Sjb * For PC-relative jumps, the pc is really the next pc after executing 4698179237Sjb * this instruction, so increment it appropriately. 4699179237Sjb */ 4700179237Sjb pc += dis->d86_len; 4701179237Sjb 4702179237Sjb for (i = 0; i < dis->d86_numopnds; i++) { 4703179237Sjb d86opnd_t *op = &dis->d86_opnd[i]; 4704179237Sjb 4705179237Sjb if (i != 0) 4706179237Sjb (void) strlcat(buf, ",", buflen); 4707179237Sjb 4708179237Sjb (void) strlcat(buf, op->d86_prefix, buflen); 4709179237Sjb 4710253772Savg /* 4711253772Savg * sv is for the signed, possibly-truncated immediate or 4712253772Savg * displacement; usv retains the original size and 4713253772Savg * unsignedness for symbol lookup. 4714253772Savg */ 4715179237Sjb 4716253772Savg sv = usv = op->d86_value; 4717253772Savg 4718253772Savg /* 4719253772Savg * About masks: for immediates that represent 4720253772Savg * addresses, the appropriate display size is 4721253772Savg * the effective address size of the instruction. 4722253772Savg * This includes MODE_OFFSET, MODE_IPREL, and 4723253772Savg * MODE_RIPREL. Immediates that are simply 4724253772Savg * immediate values should display in the operand's 4725253772Savg * size, however, since they don't represent addresses. 4726253772Savg */ 4727253772Savg 4728253772Savg /* d86_addr_size is SIZEnn, which is log2(real size) */ 4729253772Savg mask = masks[dis->d86_addr_size]; 4730253772Savg 4731253772Savg /* d86_value_size and d86_imm_bytes are in bytes */ 4732253772Savg if (op->d86_mode == MODE_SIGNED || 4733253772Savg op->d86_mode == MODE_IMPLIED) 4734253772Savg mask = masks[log2(op->d86_value_size)]; 4735253772Savg 4736179237Sjb switch (op->d86_mode) { 4737179237Sjb 4738179237Sjb case MODE_NONE: 4739179237Sjb 4740179237Sjb (void) strlcat(buf, op->d86_opnd, buflen); 4741179237Sjb break; 4742179237Sjb 4743179237Sjb case MODE_SIGNED: 4744179237Sjb case MODE_IMPLIED: 4745179237Sjb case MODE_OFFSET: 4746179237Sjb 4747253772Savg tgt = usv; 4748253772Savg 4749179237Sjb if (dis->d86_seg_prefix) 4750179237Sjb (void) strlcat(buf, dis->d86_seg_prefix, 4751179237Sjb buflen); 4752179237Sjb 4753179237Sjb if (op->d86_mode == MODE_SIGNED || 4754253772Savg op->d86_mode == MODE_IMPLIED) { 4755179237Sjb (void) strlcat(buf, "$", buflen); 4756253772Savg } 4757179237Sjb 4758253772Savg if (print_imm(dis, usv, mask, buf, buflen, 4759253772Savg IMM, TRY_NEG) && 4760253772Savg (op->d86_mode == MODE_SIGNED || 4761253772Savg op->d86_mode == MODE_IMPLIED)) { 4762253772Savg 4763253772Savg /* 4764253772Savg * We printed a negative value for an 4765253772Savg * immediate that wasn't a 4766253772Savg * displacement. Note that fact so we can 4767253772Savg * print the positive value as an 4768253772Savg * annotation. 4769253772Savg */ 4770253772Savg 4771253772Savg save_usv = usv; 4772253772Savg save_mask = mask; 4773179237Sjb } 4774179237Sjb (void) strlcat(buf, op->d86_opnd, buflen); 4775253772Savg 4776179237Sjb break; 4777179237Sjb 4778179237Sjb case MODE_IPREL: 4779253772Savg case MODE_RIPREL: 4780179237Sjb 4781253772Savg reltgt = pc + sv; 4782253772Savg 4783253772Savg switch (mode) { 4784253772Savg case SIZE16: 4785253772Savg reltgt = (uint16_t)reltgt; 4786179237Sjb break; 4787253772Savg case SIZE32: 4788253772Savg reltgt = (uint32_t)reltgt; 4789179237Sjb break; 4790179237Sjb } 4791179237Sjb 4792253772Savg (void) print_imm(dis, usv, mask, buf, buflen, 4793253772Savg DISP, TRY_NEG); 4794179237Sjb 4795253772Savg if (op->d86_mode == MODE_RIPREL) 4796253772Savg (void) strlcat(buf, "(%rip)", buflen); 4797253772Savg break; 4798253772Savg } 4799253772Savg } 4800179237Sjb 4801253772Savg /* 4802253772Savg * The symbol lookups may result in false positives, 4803253772Savg * particularly on object files, where small numbers may match 4804253772Savg * the 0-relative non-relocated addresses of symbols. 4805253772Savg */ 4806179237Sjb 4807253772Savg lookup = dis->d86_sym_lookup; 4808253772Savg if (tgt != 0) { 4809253772Savg if ((dis->d86_flags & DIS_F_NOIMMSYM) == 0 && 4810253772Savg lookup(dis->d86_data, tgt, NULL, 0) == 0) { 4811253772Savg (void) strlcat(buf, "\t<", buflen); 4812253772Savg curlen = strlen(buf); 4813253772Savg lookup(dis->d86_data, tgt, buf + curlen, 4814253772Savg buflen - curlen); 4815179237Sjb (void) strlcat(buf, ">", buflen); 4816253772Savg } 4817179237Sjb 4818253772Savg /* 4819253772Savg * If we printed a negative immediate above, print the 4820253772Savg * positive in case our heuristic was unhelpful 4821253772Savg */ 4822253772Savg if (save_usv) { 4823253772Savg (void) strlcat(buf, "\t<", buflen); 4824253772Savg (void) print_imm(dis, save_usv, save_mask, buf, buflen, 4825253772Savg IMM, POS); 4826253772Savg (void) strlcat(buf, ">", buflen); 4827179237Sjb } 4828179237Sjb } 4829253772Savg 4830253772Savg if (reltgt != 0) { 4831253772Savg /* Print symbol or effective address for reltgt */ 4832253772Savg 4833253772Savg (void) strlcat(buf, "\t<", buflen); 4834253772Savg curlen = strlen(buf); 4835253772Savg lookup(dis->d86_data, reltgt, buf + curlen, 4836253772Savg buflen - curlen); 4837253772Savg (void) strlcat(buf, ">", buflen); 4838253772Savg } 4839179237Sjb} 4840179237Sjb 4841179237Sjb#endif /* DIS_TEXT */ 4842