10339a1c2SMark Johnston /* 20339a1c2SMark Johnston * 30339a1c2SMark Johnston * CDDL HEADER START 40339a1c2SMark Johnston * 50339a1c2SMark Johnston * The contents of this file are subject to the terms of the 60339a1c2SMark Johnston * Common Development and Distribution License (the "License"). 70339a1c2SMark Johnston * You may not use this file except in compliance with the License. 80339a1c2SMark Johnston * 90339a1c2SMark Johnston * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100339a1c2SMark Johnston * or http://www.opensolaris.org/os/licensing. 110339a1c2SMark Johnston * See the License for the specific language governing permissions 120339a1c2SMark Johnston * and limitations under the License. 130339a1c2SMark Johnston * 140339a1c2SMark Johnston * When distributing Covered Code, include this CDDL HEADER in each 150339a1c2SMark Johnston * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160339a1c2SMark Johnston * If applicable, add the following below this CDDL HEADER, with the 170339a1c2SMark Johnston * fields enclosed by brackets "[]" replaced with your own identifying 180339a1c2SMark Johnston * information: Portions Copyright [yyyy] [name of copyright owner] 190339a1c2SMark Johnston * 200339a1c2SMark Johnston * CDDL HEADER END 210339a1c2SMark Johnston */ 220339a1c2SMark Johnston /* 230339a1c2SMark Johnston * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 24*b3b5bfebSMark Johnston * Copyright 2016 Joyent, Inc. 250339a1c2SMark Johnston */ 260339a1c2SMark Johnston 270339a1c2SMark Johnston /* 280339a1c2SMark Johnston * Copyright (c) 2010, Intel Corporation. 290339a1c2SMark Johnston * All rights reserved. 300339a1c2SMark Johnston */ 310339a1c2SMark Johnston 320339a1c2SMark Johnston /* Copyright (c) 1988 AT&T */ 330339a1c2SMark Johnston /* All Rights Reserved */ 340339a1c2SMark Johnston 350339a1c2SMark Johnston /* 360339a1c2SMark Johnston * $FreeBSD$ 370339a1c2SMark Johnston */ 380339a1c2SMark Johnston 390339a1c2SMark Johnston #include "dis_tables.h" 400339a1c2SMark Johnston 410339a1c2SMark Johnston /* BEGIN CSTYLED */ 420339a1c2SMark Johnston 430339a1c2SMark Johnston /* 440339a1c2SMark Johnston * Disassembly begins in dis_distable, which is equivalent to the One-byte 450339a1c2SMark Johnston * Opcode Map in the Intel IA32 ISA Reference (page A-6 in my copy). The 460339a1c2SMark Johnston * decoding loops then traverse out through the other tables as necessary to 470339a1c2SMark Johnston * decode a given instruction. 480339a1c2SMark Johnston * 490339a1c2SMark Johnston * The behavior of this file can be controlled by one of the following flags: 500339a1c2SMark Johnston * 510339a1c2SMark Johnston * DIS_TEXT Include text for disassembly 520339a1c2SMark Johnston * DIS_MEM Include memory-size calculations 530339a1c2SMark Johnston * 540339a1c2SMark Johnston * Either or both of these can be defined. 550339a1c2SMark Johnston * 560339a1c2SMark Johnston * This file is not, and will never be, cstyled. If anything, the tables should 570339a1c2SMark Johnston * be taken out another tab stop or two so nothing overlaps. 580339a1c2SMark Johnston */ 590339a1c2SMark Johnston 600339a1c2SMark Johnston /* 610339a1c2SMark Johnston * These functions must be provided for the consumer to do disassembly. 620339a1c2SMark Johnston */ 630339a1c2SMark Johnston #ifdef DIS_TEXT 640339a1c2SMark Johnston extern char *strncpy(char *, const char *, size_t); 650339a1c2SMark Johnston extern size_t strlen(const char *); 660339a1c2SMark Johnston extern int strcmp(const char *, const char *); 670339a1c2SMark Johnston extern int strncmp(const char *, const char *, size_t); 680339a1c2SMark Johnston extern size_t strlcat(char *, const char *, size_t); 690339a1c2SMark Johnston #endif 700339a1c2SMark Johnston 710339a1c2SMark Johnston 720339a1c2SMark Johnston #define TERM 0 /* used to indicate that the 'indirect' */ 730339a1c2SMark Johnston /* field terminates - no pointer. */ 740339a1c2SMark Johnston 750339a1c2SMark Johnston /* Used to decode instructions. */ 760339a1c2SMark Johnston typedef struct instable { 770339a1c2SMark Johnston struct instable *it_indirect; /* for decode op codes */ 780339a1c2SMark Johnston uchar_t it_adrmode; 790339a1c2SMark Johnston #ifdef DIS_TEXT 800339a1c2SMark Johnston char it_name[NCPS]; 810339a1c2SMark Johnston uint_t it_suffix:1; /* mnem + "w", "l", or "d" */ 820339a1c2SMark Johnston #endif 830339a1c2SMark Johnston #ifdef DIS_MEM 840339a1c2SMark Johnston uint_t it_size:16; 850339a1c2SMark Johnston #endif 860339a1c2SMark Johnston uint_t it_invalid64:1; /* opcode invalid in amd64 */ 870339a1c2SMark Johnston uint_t it_always64:1; /* 64 bit when in 64 bit mode */ 880339a1c2SMark Johnston uint_t it_invalid32:1; /* invalid in IA32 */ 890339a1c2SMark Johnston uint_t it_stackop:1; /* push/pop stack operation */ 90*b3b5bfebSMark Johnston uint_t it_vexwoxmm:1; /* VEX instructions that don't use XMM/YMM */ 91*b3b5bfebSMark Johnston uint_t it_avxsuf:1; /* AVX suffix required */ 920339a1c2SMark Johnston } instable_t; 930339a1c2SMark Johnston 940339a1c2SMark Johnston /* 950339a1c2SMark Johnston * Instruction formats. 960339a1c2SMark Johnston */ 970339a1c2SMark Johnston enum { 980339a1c2SMark Johnston UNKNOWN, 990339a1c2SMark Johnston MRw, 1000339a1c2SMark Johnston IMlw, 1010339a1c2SMark Johnston IMw, 1020339a1c2SMark Johnston IR, 1030339a1c2SMark Johnston OA, 1040339a1c2SMark Johnston AO, 1050339a1c2SMark Johnston MS, 1060339a1c2SMark Johnston SM, 1070339a1c2SMark Johnston Mv, 1080339a1c2SMark Johnston Mw, 1090339a1c2SMark Johnston M, /* register or memory */ 110c3ddb60eSPeter Grehan MG9, /* register or memory in group 9 (prefix optional) */ 1110339a1c2SMark Johnston Mb, /* register or memory, always byte sized */ 1120339a1c2SMark Johnston MO, /* memory only (no registers) */ 1130339a1c2SMark Johnston PREF, 114c3ddb60eSPeter Grehan SWAPGS_RDTSCP, 1150339a1c2SMark Johnston MONITOR_MWAIT, 1160339a1c2SMark Johnston R, 1170339a1c2SMark Johnston RA, 1180339a1c2SMark Johnston SEG, 1190339a1c2SMark Johnston MR, 1200339a1c2SMark Johnston RM, 121c3ddb60eSPeter Grehan RM_66r, /* RM, but with a required 0x66 prefix */ 1220339a1c2SMark Johnston IA, 1230339a1c2SMark Johnston MA, 1240339a1c2SMark Johnston SD, 1250339a1c2SMark Johnston AD, 1260339a1c2SMark Johnston SA, 1270339a1c2SMark Johnston D, 1280339a1c2SMark Johnston INM, 1290339a1c2SMark Johnston SO, 1300339a1c2SMark Johnston BD, 1310339a1c2SMark Johnston I, 1320339a1c2SMark Johnston P, 1330339a1c2SMark Johnston V, 1340339a1c2SMark Johnston DSHIFT, /* for double shift that has an 8-bit immediate */ 1350339a1c2SMark Johnston U, 1360339a1c2SMark Johnston OVERRIDE, 1370339a1c2SMark Johnston NORM, /* instructions w/o ModR/M byte, no memory access */ 1380339a1c2SMark Johnston IMPLMEM, /* instructions w/o ModR/M byte, implicit mem access */ 1390339a1c2SMark Johnston O, /* for call */ 1400339a1c2SMark Johnston JTAB, /* jump table */ 1410339a1c2SMark Johnston IMUL, /* for 186 iimul instr */ 1420339a1c2SMark Johnston CBW, /* so data16 can be evaluated for cbw and variants */ 1430339a1c2SMark Johnston MvI, /* for 186 logicals */ 1440339a1c2SMark Johnston ENTER, /* for 186 enter instr */ 1450339a1c2SMark Johnston RMw, /* for 286 arpl instr */ 1460339a1c2SMark Johnston Ib, /* for push immediate byte */ 1470339a1c2SMark Johnston F, /* for 287 instructions */ 1480339a1c2SMark Johnston FF, /* for 287 instructions */ 1490339a1c2SMark Johnston FFC, /* for 287 instructions */ 1500339a1c2SMark Johnston DM, /* 16-bit data */ 1510339a1c2SMark Johnston AM, /* 16-bit addr */ 1520339a1c2SMark Johnston LSEG, /* for 3-bit seg reg encoding */ 1530339a1c2SMark Johnston MIb, /* for 386 logicals */ 1540339a1c2SMark Johnston SREG, /* for 386 special registers */ 1550339a1c2SMark Johnston PREFIX, /* a REP instruction prefix */ 1560339a1c2SMark Johnston LOCK, /* a LOCK instruction prefix */ 1570339a1c2SMark Johnston INT3, /* The int 3 instruction, which has a fake operand */ 1580339a1c2SMark Johnston INTx, /* The normal int instruction, with explicit int num */ 1590339a1c2SMark Johnston DSHIFTcl, /* for double shift that implicitly uses %cl */ 1600339a1c2SMark Johnston CWD, /* so data16 can be evaluated for cwd and variants */ 1610339a1c2SMark Johnston RET, /* single immediate 16-bit operand */ 1620339a1c2SMark Johnston MOVZ, /* for movs and movz, with different size operands */ 1630339a1c2SMark Johnston CRC32, /* for crc32, with different size operands */ 1640339a1c2SMark Johnston XADDB, /* for xaddb */ 1650339a1c2SMark Johnston MOVSXZ, /* AMD64 mov sign extend 32 to 64 bit instruction */ 1660339a1c2SMark Johnston MOVBE, /* movbe instruction */ 1670339a1c2SMark Johnston 1680339a1c2SMark Johnston /* 1690339a1c2SMark Johnston * MMX/SIMD addressing modes. 1700339a1c2SMark Johnston */ 1710339a1c2SMark Johnston 1720339a1c2SMark Johnston MMO, /* Prefixable MMX/SIMD-Int mm/mem -> mm */ 1730339a1c2SMark Johnston MMOIMPL, /* Prefixable MMX/SIMD-Int mm -> mm (mem) */ 1740339a1c2SMark Johnston MMO3P, /* Prefixable MMX/SIMD-Int mm -> r32,imm8 */ 1750339a1c2SMark Johnston MMOM3, /* Prefixable MMX/SIMD-Int mm -> r32 */ 1760339a1c2SMark Johnston MMOS, /* Prefixable MMX/SIMD-Int mm -> mm/mem */ 1770339a1c2SMark Johnston MMOMS, /* Prefixable MMX/SIMD-Int mm -> mem */ 1780339a1c2SMark Johnston MMOPM, /* MMX/SIMD-Int mm/mem -> mm,imm8 */ 1790339a1c2SMark Johnston MMOPM_66o, /* MMX/SIMD-Int 0x66 optional mm/mem -> mm,imm8 */ 1800339a1c2SMark Johnston MMOPRM, /* Prefixable MMX/SIMD-Int r32/mem -> mm,imm8 */ 1810339a1c2SMark Johnston MMOSH, /* Prefixable MMX mm,imm8 */ 1820339a1c2SMark Johnston MM, /* MMX/SIMD-Int mm/mem -> mm */ 1830339a1c2SMark Johnston MMS, /* MMX/SIMD-Int mm -> mm/mem */ 1840339a1c2SMark Johnston MMSH, /* MMX mm,imm8 */ 1850339a1c2SMark Johnston XMMO, /* Prefixable SIMD xmm/mem -> xmm */ 1860339a1c2SMark Johnston XMMOS, /* Prefixable SIMD xmm -> xmm/mem */ 1870339a1c2SMark Johnston XMMOPM, /* Prefixable SIMD xmm/mem w/to xmm,imm8 */ 1880339a1c2SMark Johnston XMMOMX, /* Prefixable SIMD mm/mem -> xmm */ 1890339a1c2SMark Johnston XMMOX3, /* Prefixable SIMD xmm -> r32 */ 1900339a1c2SMark Johnston XMMOXMM, /* Prefixable SIMD xmm/mem -> mm */ 1910339a1c2SMark Johnston XMMOM, /* Prefixable SIMD xmm -> mem */ 1920339a1c2SMark Johnston XMMOMS, /* Prefixable SIMD mem -> xmm */ 1930339a1c2SMark Johnston XMM, /* SIMD xmm/mem -> xmm */ 1940339a1c2SMark Johnston XMM_66r, /* SIMD 0x66 prefix required xmm/mem -> xmm */ 1950339a1c2SMark Johnston XMM_66o, /* SIMD 0x66 prefix optional xmm/mem -> xmm */ 1960339a1c2SMark Johnston XMMXIMPL, /* SIMD xmm -> xmm (mem) */ 1970339a1c2SMark Johnston XMM3P, /* SIMD xmm -> r32,imm8 */ 1980339a1c2SMark Johnston XMM3PM_66r, /* SIMD 0x66 prefix required xmm -> r32/mem,imm8 */ 1990339a1c2SMark Johnston XMMP, /* SIMD xmm/mem w/to xmm,imm8 */ 2000339a1c2SMark Johnston XMMP_66o, /* SIMD 0x66 prefix optional xmm/mem w/to xmm,imm8 */ 2010339a1c2SMark Johnston XMMP_66r, /* SIMD 0x66 prefix required xmm/mem w/to xmm,imm8 */ 2020339a1c2SMark Johnston XMMPRM, /* SIMD r32/mem -> xmm,imm8 */ 2030339a1c2SMark Johnston XMMPRM_66r, /* SIMD 0x66 prefix required r32/mem -> xmm,imm8 */ 2040339a1c2SMark Johnston XMMS, /* SIMD xmm -> xmm/mem */ 2050339a1c2SMark Johnston XMMM, /* SIMD mem -> xmm */ 2060339a1c2SMark Johnston XMMM_66r, /* SIMD 0x66 prefix required mem -> xmm */ 2070339a1c2SMark Johnston XMMMS, /* SIMD xmm -> mem */ 2080339a1c2SMark Johnston XMM3MX, /* SIMD r32/mem -> xmm */ 2090339a1c2SMark Johnston XMM3MXS, /* SIMD xmm -> r32/mem */ 2100339a1c2SMark Johnston XMMSH, /* SIMD xmm,imm8 */ 2110339a1c2SMark Johnston XMMXM3, /* SIMD xmm/mem -> r32 */ 2120339a1c2SMark Johnston XMMX3, /* SIMD xmm -> r32 */ 2130339a1c2SMark Johnston XMMXMM, /* SIMD xmm/mem -> mm */ 2140339a1c2SMark Johnston XMMMX, /* SIMD mm -> xmm */ 2150339a1c2SMark Johnston XMMXM, /* SIMD xmm -> mm */ 2160339a1c2SMark Johnston XMMX2I, /* SIMD xmm -> xmm, imm, imm */ 2170339a1c2SMark Johnston XMM2I, /* SIMD xmm, imm, imm */ 2180339a1c2SMark Johnston XMMFENCE, /* SIMD lfence or mfence */ 2190339a1c2SMark Johnston XMMSFNC, /* SIMD sfence (none or mem) */ 2200339a1c2SMark Johnston XGETBV_XSETBV, 2210339a1c2SMark Johnston VEX_NONE, /* VEX no operand */ 2220339a1c2SMark Johnston VEX_MO, /* VEX mod_rm -> implicit reg */ 2230339a1c2SMark Johnston VEX_RMrX, /* VEX VEX.vvvv, mod_rm -> mod_reg */ 224*b3b5bfebSMark Johnston VEX_VRMrX, /* VEX mod_rm, VEX.vvvv -> mod_rm */ 2250339a1c2SMark Johnston VEX_RRX, /* VEX VEX.vvvv, mod_reg -> mod_rm */ 2260339a1c2SMark Johnston VEX_RMRX, /* VEX VEX.vvvv, mod_rm, imm8[7:4] -> mod_reg */ 2270339a1c2SMark Johnston VEX_MX, /* VEX mod_rm -> mod_reg */ 2280339a1c2SMark Johnston VEX_MXI, /* VEX mod_rm, imm8 -> mod_reg */ 2290339a1c2SMark Johnston VEX_XXI, /* VEX mod_rm, imm8 -> VEX.vvvv */ 2300339a1c2SMark Johnston VEX_MR, /* VEX mod_rm -> mod_reg */ 2310339a1c2SMark Johnston VEX_RRI, /* VEX mod_reg, mod_rm -> implicit(eflags/r32) */ 2320339a1c2SMark Johnston VEX_RX, /* VEX mod_reg -> mod_rm */ 2330339a1c2SMark Johnston VEX_RR, /* VEX mod_rm -> mod_reg */ 2340339a1c2SMark Johnston VEX_RRi, /* VEX mod_rm, imm8 -> mod_reg */ 2350339a1c2SMark Johnston VEX_RM, /* VEX mod_reg -> mod_rm */ 236*b3b5bfebSMark Johnston VEX_RIM, /* VEX mod_reg, imm8 -> mod_rm */ 2370339a1c2SMark Johnston VEX_RRM, /* VEX VEX.vvvv, mod_reg -> mod_rm */ 238c3ddb60eSPeter Grehan VEX_RMX, /* VEX VEX.vvvv, mod_rm -> mod_reg */ 239*b3b5bfebSMark Johnston VEX_SbVM, /* VEX SIB, VEX.vvvv -> mod_rm */ 240c3ddb60eSPeter Grehan VMx, /* vmcall/vmlaunch/vmresume/vmxoff */ 241c3ddb60eSPeter Grehan VMxo, /* VMx instruction with optional prefix */ 242*b3b5bfebSMark Johnston SVM, /* AMD SVM instructions */ 243*b3b5bfebSMark Johnston BLS, /* BLSR, BLSMSK, BLSI */ 244*b3b5bfebSMark Johnston FMA, /* FMA instructions, all VEX_RMrX */ 245*b3b5bfebSMark Johnston ADX /* ADX instructions, support REX.w, mod_rm->mod_reg */ 2460339a1c2SMark Johnston }; 2470339a1c2SMark Johnston 2480339a1c2SMark Johnston /* 2490339a1c2SMark Johnston * VEX prefixes 2500339a1c2SMark Johnston */ 2510339a1c2SMark Johnston #define VEX_2bytes 0xC5 /* the first byte of two-byte form */ 2520339a1c2SMark Johnston #define VEX_3bytes 0xC4 /* the first byte of three-byte form */ 2530339a1c2SMark Johnston 2540339a1c2SMark Johnston #define FILL 0x90 /* Fill byte used for alignment (nop) */ 2550339a1c2SMark Johnston 2560339a1c2SMark Johnston /* 2570339a1c2SMark Johnston ** Register numbers for the i386 2580339a1c2SMark Johnston */ 2590339a1c2SMark Johnston #define EAX_REGNO 0 2600339a1c2SMark Johnston #define ECX_REGNO 1 2610339a1c2SMark Johnston #define EDX_REGNO 2 2620339a1c2SMark Johnston #define EBX_REGNO 3 2630339a1c2SMark Johnston #define ESP_REGNO 4 2640339a1c2SMark Johnston #define EBP_REGNO 5 2650339a1c2SMark Johnston #define ESI_REGNO 6 2660339a1c2SMark Johnston #define EDI_REGNO 7 2670339a1c2SMark Johnston 2680339a1c2SMark Johnston /* 2690339a1c2SMark Johnston * modes for immediate values 2700339a1c2SMark Johnston */ 2710339a1c2SMark Johnston #define MODE_NONE 0 2720339a1c2SMark Johnston #define MODE_IPREL 1 /* signed IP relative value */ 2730339a1c2SMark Johnston #define MODE_SIGNED 2 /* sign extended immediate */ 2740339a1c2SMark Johnston #define MODE_IMPLIED 3 /* constant value implied from opcode */ 2750339a1c2SMark Johnston #define MODE_OFFSET 4 /* offset part of an address */ 2760339a1c2SMark Johnston #define MODE_RIPREL 5 /* like IPREL, but from %rip (amd64) */ 2770339a1c2SMark Johnston 2780339a1c2SMark Johnston /* 2790339a1c2SMark Johnston * The letters used in these macros are: 2800339a1c2SMark Johnston * IND - indirect to another to another table 2810339a1c2SMark Johnston * "T" - means to Terminate indirections (this is the final opcode) 2820339a1c2SMark Johnston * "S" - means "operand length suffix required" 283*b3b5bfebSMark Johnston * "Sa" - means AVX2 suffix (d/q) required 2840339a1c2SMark Johnston * "NS" - means "no suffix" which is the operand length suffix of the opcode 2850339a1c2SMark Johnston * "Z" - means instruction size arg required 2860339a1c2SMark Johnston * "u" - means the opcode is invalid in IA32 but valid in amd64 2870339a1c2SMark Johnston * "x" - means the opcode is invalid in amd64, but not IA32 2880339a1c2SMark Johnston * "y" - means the operand size is always 64 bits in 64 bit mode 2890339a1c2SMark Johnston * "p" - means push/pop stack operation 290*b3b5bfebSMark Johnston * "vr" - means VEX instruction that operates on normal registers, not fpu 2910339a1c2SMark Johnston */ 2920339a1c2SMark Johnston 2930339a1c2SMark Johnston #if defined(DIS_TEXT) && defined(DIS_MEM) 2940339a1c2SMark Johnston #define IND(table) {(instable_t *)table, 0, "", 0, 0, 0, 0, 0, 0} 2950339a1c2SMark Johnston #define INDx(table) {(instable_t *)table, 0, "", 0, 0, 1, 0, 0, 0} 2960339a1c2SMark Johnston #define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0, 0} 2970339a1c2SMark Johnston #define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 0, 1, 0} 2980339a1c2SMark Johnston #define TNSx(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0, 0} 2990339a1c2SMark Johnston #define TNSy(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 0} 3000339a1c2SMark Johnston #define TNSyp(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 1} 3010339a1c2SMark Johnston #define TNSZ(name, amode, sz) {TERM, amode, name, 0, sz, 0, 0, 0, 0} 3020339a1c2SMark Johnston #define TNSZy(name, amode, sz) {TERM, amode, name, 0, sz, 0, 1, 0, 0} 303*b3b5bfebSMark Johnston #define TNSZvr(name, amode, sz) {TERM, amode, name, 0, sz, 0, 0, 0, 0, 1} 3040339a1c2SMark Johnston #define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 0} 3050339a1c2SMark Johnston #define TSx(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0, 0} 3060339a1c2SMark Johnston #define TSy(name, amode) {TERM, amode, name, 1, 0, 0, 1, 0, 0} 3070339a1c2SMark Johnston #define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 1} 3080339a1c2SMark Johnston #define TSZ(name, amode, sz) {TERM, amode, name, 1, sz, 0, 0, 0, 0} 309*b3b5bfebSMark Johnston #define TSaZ(name, amode, sz) {TERM, amode, name, 1, sz, 0, 0, 0, 0, 0, 1} 3100339a1c2SMark Johnston #define TSZx(name, amode, sz) {TERM, amode, name, 1, sz, 1, 0, 0, 0} 3110339a1c2SMark Johnston #define TSZy(name, amode, sz) {TERM, amode, name, 1, sz, 0, 1, 0, 0} 3120339a1c2SMark Johnston #define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0} 3130339a1c2SMark Johnston #elif defined(DIS_TEXT) 3140339a1c2SMark Johnston #define IND(table) {(instable_t *)table, 0, "", 0, 0, 0, 0, 0} 3150339a1c2SMark Johnston #define INDx(table) {(instable_t *)table, 0, "", 0, 1, 0, 0, 0} 3160339a1c2SMark Johnston #define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0} 3170339a1c2SMark Johnston #define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0} 3180339a1c2SMark Johnston #define TNSx(name, amode) {TERM, amode, name, 0, 1, 0, 0, 0} 3190339a1c2SMark Johnston #define TNSy(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0} 3200339a1c2SMark Johnston #define TNSyp(name, amode) {TERM, amode, name, 0, 0, 1, 0, 1} 3210339a1c2SMark Johnston #define TNSZ(name, amode, sz) {TERM, amode, name, 0, 0, 0, 0, 0} 3220339a1c2SMark Johnston #define TNSZy(name, amode, sz) {TERM, amode, name, 0, 0, 1, 0, 0} 323*b3b5bfebSMark Johnston #define TNSZvr(name, amode, sz) {TERM, amode, name, 0, 0, 0, 0, 0, 1} 3240339a1c2SMark Johnston #define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0} 3250339a1c2SMark Johnston #define TSx(name, amode) {TERM, amode, name, 1, 1, 0, 0, 0} 3260339a1c2SMark Johnston #define TSy(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0} 3270339a1c2SMark Johnston #define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 1} 3280339a1c2SMark Johnston #define TSZ(name, amode, sz) {TERM, amode, name, 1, 0, 0, 0, 0} 329*b3b5bfebSMark Johnston #define TSaZ(name, amode, sz) {TERM, amode, name, 1, 0, 0, 0, 0, 0, 1} 3300339a1c2SMark Johnston #define TSZx(name, amode, sz) {TERM, amode, name, 1, 1, 0, 0, 0} 3310339a1c2SMark Johnston #define TSZy(name, amode, sz) {TERM, amode, name, 1, 0, 1, 0, 0} 3320339a1c2SMark Johnston #define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0} 3330339a1c2SMark Johnston #elif defined(DIS_MEM) 3340339a1c2SMark Johnston #define IND(table) {(instable_t *)table, 0, 0, 0, 0, 0, 0} 3350339a1c2SMark Johnston #define INDx(table) {(instable_t *)table, 0, 0, 1, 0, 0, 0} 3360339a1c2SMark Johnston #define TNS(name, amode) {TERM, amode, 0, 0, 0, 0, 0} 3370339a1c2SMark Johnston #define TNSu(name, amode) {TERM, amode, 0, 0, 0, 1, 0} 3380339a1c2SMark Johnston #define TNSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0} 3390339a1c2SMark Johnston #define TNSyp(name, amode) {TERM, amode, 0, 0, 1, 0, 1} 3400339a1c2SMark Johnston #define TNSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0} 3410339a1c2SMark Johnston #define TNSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0} 3420339a1c2SMark Johnston #define TNSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0} 343*b3b5bfebSMark Johnston #define TNSZvr(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0, 1} 3440339a1c2SMark Johnston #define TS(name, amode) {TERM, amode, 0, 0, 0, 0, 0} 3450339a1c2SMark Johnston #define TSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0} 3460339a1c2SMark Johnston #define TSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0} 3470339a1c2SMark Johnston #define TSp(name, amode) {TERM, amode, 0, 0, 0, 0, 1} 3480339a1c2SMark Johnston #define TSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0} 349*b3b5bfebSMark Johnston #define TSaZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0, 0, 1} 3500339a1c2SMark Johnston #define TSZx(name, amode, sz) {TERM, amode, sz, 1, 0, 0, 0} 3510339a1c2SMark Johnston #define TSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0} 3520339a1c2SMark Johnston #define INVALID {TERM, UNKNOWN, 0, 0, 0, 0, 0} 3530339a1c2SMark Johnston #else 3540339a1c2SMark Johnston #define IND(table) {(instable_t *)table, 0, 0, 0, 0, 0} 3550339a1c2SMark Johnston #define INDx(table) {(instable_t *)table, 0, 1, 0, 0, 0} 3560339a1c2SMark Johnston #define TNS(name, amode) {TERM, amode, 0, 0, 0, 0} 3570339a1c2SMark Johnston #define TNSu(name, amode) {TERM, amode, 0, 0, 1, 0} 3580339a1c2SMark Johnston #define TNSy(name, amode) {TERM, amode, 0, 1, 0, 0} 3590339a1c2SMark Johnston #define TNSyp(name, amode) {TERM, amode, 0, 1, 0, 1} 3600339a1c2SMark Johnston #define TNSx(name, amode) {TERM, amode, 1, 0, 0, 0} 3610339a1c2SMark Johnston #define TNSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0} 3620339a1c2SMark Johnston #define TNSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0} 363*b3b5bfebSMark Johnston #define TNSZvr(name, amode, sz) {TERM, amode, 0, 0, 0, 0, 1} 3640339a1c2SMark Johnston #define TS(name, amode) {TERM, amode, 0, 0, 0, 0} 3650339a1c2SMark Johnston #define TSx(name, amode) {TERM, amode, 1, 0, 0, 0} 3660339a1c2SMark Johnston #define TSy(name, amode) {TERM, amode, 0, 1, 0, 0} 3670339a1c2SMark Johnston #define TSp(name, amode) {TERM, amode, 0, 0, 0, 1} 3680339a1c2SMark Johnston #define TSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0} 369*b3b5bfebSMark Johnston #define TSaZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0, 0, 1} 3700339a1c2SMark Johnston #define TSZx(name, amode, sz) {TERM, amode, 1, 0, 0, 0} 3710339a1c2SMark Johnston #define TSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0} 3720339a1c2SMark Johnston #define INVALID {TERM, UNKNOWN, 0, 0, 0, 0} 3730339a1c2SMark Johnston #endif 3740339a1c2SMark Johnston 3750339a1c2SMark Johnston #ifdef DIS_TEXT 3760339a1c2SMark Johnston /* 3770339a1c2SMark Johnston * this decodes the r_m field for mode's 0, 1, 2 in 16 bit mode 3780339a1c2SMark Johnston */ 3790339a1c2SMark Johnston const char *const dis_addr16[3][8] = { 3800339a1c2SMark Johnston "(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "", 3810339a1c2SMark Johnston "(%bx)", 3820339a1c2SMark Johnston "(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di", "(%bp)", 3830339a1c2SMark Johnston "(%bx)", 3840339a1c2SMark Johnston "(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "(%bp)", 3850339a1c2SMark Johnston "(%bx)", 3860339a1c2SMark Johnston }; 3870339a1c2SMark Johnston 3880339a1c2SMark Johnston 3890339a1c2SMark Johnston /* 3900339a1c2SMark Johnston * This decodes 32 bit addressing mode r_m field for modes 0, 1, 2 3910339a1c2SMark Johnston */ 3920339a1c2SMark Johnston const char *const dis_addr32_mode0[16] = { 3930339a1c2SMark Johnston "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "", "(%esi)", "(%edi)", 3940339a1c2SMark Johnston "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "", "(%r14d)", "(%r15d)" 3950339a1c2SMark Johnston }; 3960339a1c2SMark Johnston 3970339a1c2SMark Johnston const char *const dis_addr32_mode12[16] = { 3980339a1c2SMark Johnston "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "(%ebp)", "(%esi)", "(%edi)", 3990339a1c2SMark Johnston "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "(%r13d)", "(%r14d)", "(%r15d)" 4000339a1c2SMark Johnston }; 4010339a1c2SMark Johnston 4020339a1c2SMark Johnston /* 4030339a1c2SMark Johnston * This decodes 64 bit addressing mode r_m field for modes 0, 1, 2 4040339a1c2SMark Johnston */ 4050339a1c2SMark Johnston const char *const dis_addr64_mode0[16] = { 4060339a1c2SMark Johnston "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rip)", "(%rsi)", "(%rdi)", 4070339a1c2SMark Johnston "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%rip)", "(%r14)", "(%r15)" 4080339a1c2SMark Johnston }; 4090339a1c2SMark Johnston const char *const dis_addr64_mode12[16] = { 4100339a1c2SMark Johnston "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rbp)", "(%rsi)", "(%rdi)", 4110339a1c2SMark Johnston "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%r13)", "(%r14)", "(%r15)" 4120339a1c2SMark Johnston }; 4130339a1c2SMark Johnston 4140339a1c2SMark Johnston /* 4150339a1c2SMark Johnston * decode for scale from SIB byte 4160339a1c2SMark Johnston */ 4170339a1c2SMark Johnston const char *const dis_scale_factor[4] = { ")", ",2)", ",4)", ",8)" }; 4180339a1c2SMark Johnston 4190339a1c2SMark Johnston /* 420*b3b5bfebSMark Johnston * decode for scale from VSIB byte, note that we always include the scale factor 421*b3b5bfebSMark Johnston * to match gas. 422*b3b5bfebSMark Johnston */ 423*b3b5bfebSMark Johnston const char *const dis_vscale_factor[4] = { ",1)", ",2)", ",4)", ",8)" }; 424*b3b5bfebSMark Johnston 425*b3b5bfebSMark Johnston /* 4260339a1c2SMark Johnston * register decoding for normal references to registers (ie. not addressing) 4270339a1c2SMark Johnston */ 4280339a1c2SMark Johnston const char *const dis_REG8[16] = { 4290339a1c2SMark Johnston "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", 4300339a1c2SMark Johnston "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" 4310339a1c2SMark Johnston }; 4320339a1c2SMark Johnston 4330339a1c2SMark Johnston const char *const dis_REG8_REX[16] = { 4340339a1c2SMark Johnston "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", 4350339a1c2SMark Johnston "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" 4360339a1c2SMark Johnston }; 4370339a1c2SMark Johnston 4380339a1c2SMark Johnston const char *const dis_REG16[16] = { 4390339a1c2SMark Johnston "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", 4400339a1c2SMark Johnston "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" 4410339a1c2SMark Johnston }; 4420339a1c2SMark Johnston 4430339a1c2SMark Johnston const char *const dis_REG32[16] = { 4440339a1c2SMark Johnston "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", 4450339a1c2SMark Johnston "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" 4460339a1c2SMark Johnston }; 4470339a1c2SMark Johnston 4480339a1c2SMark Johnston const char *const dis_REG64[16] = { 4490339a1c2SMark Johnston "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", 4500339a1c2SMark Johnston "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" 4510339a1c2SMark Johnston }; 4520339a1c2SMark Johnston 4530339a1c2SMark Johnston const char *const dis_DEBUGREG[16] = { 4540339a1c2SMark Johnston "%db0", "%db1", "%db2", "%db3", "%db4", "%db5", "%db6", "%db7", 4550339a1c2SMark Johnston "%db8", "%db9", "%db10", "%db11", "%db12", "%db13", "%db14", "%db15" 4560339a1c2SMark Johnston }; 4570339a1c2SMark Johnston 4580339a1c2SMark Johnston const char *const dis_CONTROLREG[16] = { 4590339a1c2SMark Johnston "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5?", "%cr6?", "%cr7?", 4600339a1c2SMark Johnston "%cr8", "%cr9?", "%cr10?", "%cr11?", "%cr12?", "%cr13?", "%cr14?", "%cr15?" 4610339a1c2SMark Johnston }; 4620339a1c2SMark Johnston 4630339a1c2SMark Johnston const char *const dis_TESTREG[16] = { 4640339a1c2SMark Johnston "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7", 4650339a1c2SMark Johnston "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7" 4660339a1c2SMark Johnston }; 4670339a1c2SMark Johnston 4680339a1c2SMark Johnston const char *const dis_MMREG[16] = { 4690339a1c2SMark Johnston "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", 4700339a1c2SMark Johnston "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" 4710339a1c2SMark Johnston }; 4720339a1c2SMark Johnston 4730339a1c2SMark Johnston const char *const dis_XMMREG[16] = { 4740339a1c2SMark Johnston "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", 4750339a1c2SMark Johnston "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" 4760339a1c2SMark Johnston }; 4770339a1c2SMark Johnston 4780339a1c2SMark Johnston const char *const dis_YMMREG[16] = { 4790339a1c2SMark Johnston "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6", "%ymm7", 4800339a1c2SMark Johnston "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13", "%ymm14", "%ymm15" 4810339a1c2SMark Johnston }; 4820339a1c2SMark Johnston 4830339a1c2SMark Johnston const char *const dis_SEGREG[16] = { 4840339a1c2SMark Johnston "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>", 4850339a1c2SMark Johnston "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>" 4860339a1c2SMark Johnston }; 4870339a1c2SMark Johnston 4880339a1c2SMark Johnston /* 4890339a1c2SMark Johnston * SIMD predicate suffixes 4900339a1c2SMark Johnston */ 4910339a1c2SMark Johnston const char *const dis_PREDSUFFIX[8] = { 4920339a1c2SMark Johnston "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord" 4930339a1c2SMark Johnston }; 4940339a1c2SMark Johnston 4950339a1c2SMark Johnston const char *const dis_AVXvgrp7[3][8] = { 4960339a1c2SMark Johnston /*0 1 2 3 4 5 6 7*/ 4970339a1c2SMark Johnston /*71*/ {"", "", "vpsrlw", "", "vpsraw", "", "vpsllw", ""}, 4980339a1c2SMark Johnston /*72*/ {"", "", "vpsrld", "", "vpsrad", "", "vpslld", ""}, 4990339a1c2SMark Johnston /*73*/ {"", "", "vpsrlq", "vpsrldq", "", "", "vpsllq", "vpslldq"} 5000339a1c2SMark Johnston }; 5010339a1c2SMark Johnston 5020339a1c2SMark Johnston #endif /* DIS_TEXT */ 5030339a1c2SMark Johnston 5040339a1c2SMark Johnston /* 5050339a1c2SMark Johnston * "decode table" for 64 bit mode MOVSXD instruction (opcode 0x63) 5060339a1c2SMark Johnston */ 5070339a1c2SMark Johnston const instable_t dis_opMOVSLD = TNS("movslq",MOVSXZ); 5080339a1c2SMark Johnston 5090339a1c2SMark Johnston /* 5100339a1c2SMark Johnston * "decode table" for pause and clflush instructions 5110339a1c2SMark Johnston */ 5120339a1c2SMark Johnston const instable_t dis_opPause = TNS("pause", NORM); 5130339a1c2SMark Johnston 5140339a1c2SMark Johnston /* 5150339a1c2SMark Johnston * Decode table for 0x0F00 opcodes 5160339a1c2SMark Johnston */ 5170339a1c2SMark Johnston const instable_t dis_op0F00[8] = { 5180339a1c2SMark Johnston 5190339a1c2SMark Johnston /* [0] */ TNS("sldt",M), TNS("str",M), TNSy("lldt",M), TNSy("ltr",M), 5200339a1c2SMark Johnston /* [4] */ TNSZ("verr",M,2), TNSZ("verw",M,2), INVALID, INVALID, 5210339a1c2SMark Johnston }; 5220339a1c2SMark Johnston 5230339a1c2SMark Johnston 5240339a1c2SMark Johnston /* 5250339a1c2SMark Johnston * Decode table for 0x0F01 opcodes 5260339a1c2SMark Johnston */ 5270339a1c2SMark Johnston const instable_t dis_op0F01[8] = { 5280339a1c2SMark Johnston 529c3ddb60eSPeter Grehan /* [0] */ TNSZ("sgdt",VMx,6), TNSZ("sidt",MONITOR_MWAIT,6), TNSZ("lgdt",XGETBV_XSETBV,6), TNSZ("lidt",SVM,6), 530c3ddb60eSPeter Grehan /* [4] */ TNSZ("smsw",M,2), INVALID, TNSZ("lmsw",M,2), TNS("invlpg",SWAPGS_RDTSCP), 5310339a1c2SMark Johnston }; 5320339a1c2SMark Johnston 5330339a1c2SMark Johnston /* 5340339a1c2SMark Johnston * Decode table for 0x0F18 opcodes -- SIMD prefetch 5350339a1c2SMark Johnston */ 5360339a1c2SMark Johnston const instable_t dis_op0F18[8] = { 5370339a1c2SMark Johnston 5380339a1c2SMark Johnston /* [0] */ TNS("prefetchnta",PREF),TNS("prefetcht0",PREF), TNS("prefetcht1",PREF), TNS("prefetcht2",PREF), 5390339a1c2SMark Johnston /* [4] */ INVALID, INVALID, INVALID, INVALID, 5400339a1c2SMark Johnston }; 5410339a1c2SMark Johnston 5420339a1c2SMark Johnston /* 5430339a1c2SMark Johnston * Decode table for 0x0FAE opcodes -- SIMD state save/restore 5440339a1c2SMark Johnston */ 5450339a1c2SMark Johnston const instable_t dis_op0FAE[8] = { 5460339a1c2SMark Johnston /* [0] */ TNSZ("fxsave",M,512), TNSZ("fxrstor",M,512), TNS("ldmxcsr",M), TNS("stmxcsr",M), 5470339a1c2SMark Johnston /* [4] */ TNSZ("xsave",M,512), TNS("lfence",XMMFENCE), TNS("mfence",XMMFENCE), TNS("sfence",XMMSFNC), 5480339a1c2SMark Johnston }; 5490339a1c2SMark Johnston 5500339a1c2SMark Johnston /* 5510339a1c2SMark Johnston * Decode table for 0x0FBA opcodes 5520339a1c2SMark Johnston */ 5530339a1c2SMark Johnston 5540339a1c2SMark Johnston const instable_t dis_op0FBA[8] = { 5550339a1c2SMark Johnston 5560339a1c2SMark Johnston /* [0] */ INVALID, INVALID, INVALID, INVALID, 5570339a1c2SMark Johnston /* [4] */ TS("bt",MIb), TS("bts",MIb), TS("btr",MIb), TS("btc",MIb), 5580339a1c2SMark Johnston }; 5590339a1c2SMark Johnston 5600339a1c2SMark Johnston /* 561c3ddb60eSPeter Grehan * Decode table for 0x0FC7 opcode (group 9) 5620339a1c2SMark Johnston */ 5630339a1c2SMark Johnston 5640339a1c2SMark Johnston const instable_t dis_op0FC7[8] = { 5650339a1c2SMark Johnston 5660339a1c2SMark Johnston /* [0] */ INVALID, TNS("cmpxchg8b",M), INVALID, INVALID, 567c3ddb60eSPeter Grehan /* [4] */ INVALID, INVALID, TNS("vmptrld",MG9), TNS("vmptrst",MG9), 5680339a1c2SMark Johnston }; 5690339a1c2SMark Johnston 570c3ddb60eSPeter Grehan /* 571c3ddb60eSPeter Grehan * Decode table for 0x0FC7 opcode (group 9) mode 3 572c3ddb60eSPeter Grehan */ 573c3ddb60eSPeter Grehan 574c3ddb60eSPeter Grehan const instable_t dis_op0FC7m3[8] = { 575c3ddb60eSPeter Grehan 576c3ddb60eSPeter Grehan /* [0] */ INVALID, INVALID, INVALID, INVALID, 577*b3b5bfebSMark Johnston /* [4] */ INVALID, INVALID, TNS("rdrand",MG9), TNS("rdseed", MG9), 578c3ddb60eSPeter Grehan }; 579c3ddb60eSPeter Grehan 580c3ddb60eSPeter Grehan /* 581c3ddb60eSPeter Grehan * Decode table for 0x0FC7 opcode with 0x66 prefix 582c3ddb60eSPeter Grehan */ 583c3ddb60eSPeter Grehan 584c3ddb60eSPeter Grehan const instable_t dis_op660FC7[8] = { 585c3ddb60eSPeter Grehan 586c3ddb60eSPeter Grehan /* [0] */ INVALID, INVALID, INVALID, INVALID, 587c3ddb60eSPeter Grehan /* [4] */ INVALID, INVALID, TNS("vmclear",M), INVALID, 588c3ddb60eSPeter Grehan }; 589c3ddb60eSPeter Grehan 590c3ddb60eSPeter Grehan /* 591c3ddb60eSPeter Grehan * Decode table for 0x0FC7 opcode with 0xF3 prefix 592c3ddb60eSPeter Grehan */ 593c3ddb60eSPeter Grehan 594c3ddb60eSPeter Grehan const instable_t dis_opF30FC7[8] = { 595c3ddb60eSPeter Grehan 596c3ddb60eSPeter Grehan /* [0] */ INVALID, INVALID, INVALID, INVALID, 597c3ddb60eSPeter Grehan /* [4] */ INVALID, INVALID, TNS("vmxon",M), INVALID, 598c3ddb60eSPeter Grehan }; 5990339a1c2SMark Johnston 6000339a1c2SMark Johnston /* 6010339a1c2SMark Johnston * Decode table for 0x0FC8 opcode -- 486 bswap instruction 6020339a1c2SMark Johnston * 6030339a1c2SMark Johnston *bit pattern: 0000 1111 1100 1reg 6040339a1c2SMark Johnston */ 6050339a1c2SMark Johnston const instable_t dis_op0FC8[4] = { 6060339a1c2SMark Johnston /* [0] */ TNS("bswap",R), INVALID, INVALID, INVALID, 6070339a1c2SMark Johnston }; 6080339a1c2SMark Johnston 6090339a1c2SMark Johnston /* 6100339a1c2SMark Johnston * Decode table for 0x0F71, 0x0F72, and 0x0F73 opcodes -- MMX instructions 6110339a1c2SMark Johnston */ 6120339a1c2SMark Johnston const instable_t dis_op0F7123[4][8] = { 6130339a1c2SMark Johnston { 6140339a1c2SMark Johnston /* [70].0 */ INVALID, INVALID, INVALID, INVALID, 6150339a1c2SMark Johnston /* .4 */ INVALID, INVALID, INVALID, INVALID, 6160339a1c2SMark Johnston }, { 6170339a1c2SMark Johnston /* [71].0 */ INVALID, INVALID, TNS("psrlw",MMOSH), INVALID, 6180339a1c2SMark Johnston /* .4 */ TNS("psraw",MMOSH), INVALID, TNS("psllw",MMOSH), INVALID, 6190339a1c2SMark Johnston }, { 6200339a1c2SMark Johnston /* [72].0 */ INVALID, INVALID, TNS("psrld",MMOSH), INVALID, 6210339a1c2SMark Johnston /* .4 */ TNS("psrad",MMOSH), INVALID, TNS("pslld",MMOSH), INVALID, 6220339a1c2SMark Johnston }, { 6230339a1c2SMark Johnston /* [73].0 */ INVALID, INVALID, TNS("psrlq",MMOSH), TNS("INVALID",MMOSH), 6240339a1c2SMark Johnston /* .4 */ INVALID, INVALID, TNS("psllq",MMOSH), TNS("INVALID",MMOSH), 6250339a1c2SMark Johnston } }; 6260339a1c2SMark Johnston 6270339a1c2SMark Johnston /* 6280339a1c2SMark Johnston * Decode table for SIMD extensions to above 0x0F71-0x0F73 opcodes. 6290339a1c2SMark Johnston */ 6300339a1c2SMark Johnston const instable_t dis_opSIMD7123[32] = { 6310339a1c2SMark Johnston /* [70].0 */ INVALID, INVALID, INVALID, INVALID, 6320339a1c2SMark Johnston /* .4 */ INVALID, INVALID, INVALID, INVALID, 6330339a1c2SMark Johnston 6340339a1c2SMark Johnston /* [71].0 */ INVALID, INVALID, TNS("psrlw",XMMSH), INVALID, 6350339a1c2SMark Johnston /* .4 */ TNS("psraw",XMMSH), INVALID, TNS("psllw",XMMSH), INVALID, 6360339a1c2SMark Johnston 6370339a1c2SMark Johnston /* [72].0 */ INVALID, INVALID, TNS("psrld",XMMSH), INVALID, 6380339a1c2SMark Johnston /* .4 */ TNS("psrad",XMMSH), INVALID, TNS("pslld",XMMSH), INVALID, 6390339a1c2SMark Johnston 6400339a1c2SMark Johnston /* [73].0 */ INVALID, INVALID, TNS("psrlq",XMMSH), TNS("psrldq",XMMSH), 6410339a1c2SMark Johnston /* .4 */ INVALID, INVALID, TNS("psllq",XMMSH), TNS("pslldq",XMMSH), 6420339a1c2SMark Johnston }; 6430339a1c2SMark Johnston 6440339a1c2SMark Johnston /* 6450339a1c2SMark Johnston * SIMD instructions have been wedged into the existing IA32 instruction 6460339a1c2SMark Johnston * set through the use of prefixes. That is, while 0xf0 0x58 may be 6470339a1c2SMark Johnston * addps, 0xf3 0xf0 0x58 (literally, repz addps) is a completely different 6480339a1c2SMark Johnston * instruction - addss. At present, three prefixes have been coopted in 6490339a1c2SMark Johnston * this manner - address size (0x66), repnz (0xf2) and repz (0xf3). The 6500339a1c2SMark Johnston * following tables are used to provide the prefixed instruction names. 6510339a1c2SMark Johnston * The arrays are sparse, but they're fast. 6520339a1c2SMark Johnston */ 6530339a1c2SMark Johnston 6540339a1c2SMark Johnston /* 6550339a1c2SMark Johnston * Decode table for SIMD instructions with the address size (0x66) prefix. 6560339a1c2SMark Johnston */ 6570339a1c2SMark Johnston const instable_t dis_opSIMDdata16[256] = { 6580339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 6590339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 6600339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 6610339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 6620339a1c2SMark Johnston 6630339a1c2SMark Johnston /* [10] */ TNSZ("movupd",XMM,16), TNSZ("movupd",XMMS,16), TNSZ("movlpd",XMMM,8), TNSZ("movlpd",XMMMS,8), 6640339a1c2SMark Johnston /* [14] */ TNSZ("unpcklpd",XMM,16),TNSZ("unpckhpd",XMM,16),TNSZ("movhpd",XMMM,8), TNSZ("movhpd",XMMMS,8), 6650339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 6660339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 6670339a1c2SMark Johnston 6680339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 6690339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 6700339a1c2SMark Johnston /* [28] */ TNSZ("movapd",XMM,16), TNSZ("movapd",XMMS,16), TNSZ("cvtpi2pd",XMMOMX,8),TNSZ("movntpd",XMMOMS,16), 6710339a1c2SMark Johnston /* [2C] */ TNSZ("cvttpd2pi",XMMXMM,16),TNSZ("cvtpd2pi",XMMXMM,16),TNSZ("ucomisd",XMM,8),TNSZ("comisd",XMM,8), 6720339a1c2SMark Johnston 6730339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 6740339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 6750339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 6760339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 6770339a1c2SMark Johnston 6780339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 6790339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 6800339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 6810339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 6820339a1c2SMark Johnston 6830339a1c2SMark Johnston /* [50] */ TNS("movmskpd",XMMOX3), TNSZ("sqrtpd",XMM,16), INVALID, INVALID, 6840339a1c2SMark Johnston /* [54] */ TNSZ("andpd",XMM,16), TNSZ("andnpd",XMM,16), TNSZ("orpd",XMM,16), TNSZ("xorpd",XMM,16), 6850339a1c2SMark Johnston /* [58] */ TNSZ("addpd",XMM,16), TNSZ("mulpd",XMM,16), TNSZ("cvtpd2ps",XMM,16),TNSZ("cvtps2dq",XMM,16), 6860339a1c2SMark Johnston /* [5C] */ TNSZ("subpd",XMM,16), TNSZ("minpd",XMM,16), TNSZ("divpd",XMM,16), TNSZ("maxpd",XMM,16), 6870339a1c2SMark Johnston 6880339a1c2SMark Johnston /* [60] */ TNSZ("punpcklbw",XMM,16),TNSZ("punpcklwd",XMM,16),TNSZ("punpckldq",XMM,16),TNSZ("packsswb",XMM,16), 6890339a1c2SMark Johnston /* [64] */ TNSZ("pcmpgtb",XMM,16), TNSZ("pcmpgtw",XMM,16), TNSZ("pcmpgtd",XMM,16), TNSZ("packuswb",XMM,16), 6900339a1c2SMark Johnston /* [68] */ TNSZ("punpckhbw",XMM,16),TNSZ("punpckhwd",XMM,16),TNSZ("punpckhdq",XMM,16),TNSZ("packssdw",XMM,16), 6910339a1c2SMark Johnston /* [6C] */ TNSZ("punpcklqdq",XMM,16),TNSZ("punpckhqdq",XMM,16),TNSZ("movd",XMM3MX,4),TNSZ("movdqa",XMM,16), 6920339a1c2SMark Johnston 6930339a1c2SMark Johnston /* [70] */ TNSZ("pshufd",XMMP,16), INVALID, INVALID, INVALID, 6940339a1c2SMark Johnston /* [74] */ TNSZ("pcmpeqb",XMM,16), TNSZ("pcmpeqw",XMM,16), TNSZ("pcmpeqd",XMM,16), INVALID, 6950339a1c2SMark Johnston /* [78] */ TNSZ("extrq",XMM2I,16), TNSZ("extrq",XMM,16), INVALID, INVALID, 696*b3b5bfebSMark Johnston /* [7C] */ TNSZ("haddpd",XMM,16), TNSZ("hsubpd",XMM,16), TNSZ("movd",XMM3MXS,4), TNSZ("movdqa",XMMS,16), 6970339a1c2SMark Johnston 6980339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 6990339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 7000339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 7010339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 7020339a1c2SMark Johnston 7030339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 7040339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 7050339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 7060339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 7070339a1c2SMark Johnston 7080339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 7090339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 7100339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 7110339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 7120339a1c2SMark Johnston 7130339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 7140339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 7150339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 7160339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 7170339a1c2SMark Johnston 7180339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("cmppd",XMMP,16), INVALID, 7190339a1c2SMark Johnston /* [C4] */ TNSZ("pinsrw",XMMPRM,2),TNS("pextrw",XMM3P), TNSZ("shufpd",XMMP,16), INVALID, 7200339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 7210339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 7220339a1c2SMark Johnston 723*b3b5bfebSMark Johnston /* [D0] */ TNSZ("addsubpd",XMM,16),TNSZ("psrlw",XMM,16), TNSZ("psrld",XMM,16), TNSZ("psrlq",XMM,16), 7240339a1c2SMark Johnston /* [D4] */ TNSZ("paddq",XMM,16), TNSZ("pmullw",XMM,16), TNSZ("movq",XMMS,8), TNS("pmovmskb",XMMX3), 7250339a1c2SMark Johnston /* [D8] */ TNSZ("psubusb",XMM,16), TNSZ("psubusw",XMM,16), TNSZ("pminub",XMM,16), TNSZ("pand",XMM,16), 7260339a1c2SMark Johnston /* [DC] */ TNSZ("paddusb",XMM,16), TNSZ("paddusw",XMM,16), TNSZ("pmaxub",XMM,16), TNSZ("pandn",XMM,16), 7270339a1c2SMark Johnston 7280339a1c2SMark Johnston /* [E0] */ TNSZ("pavgb",XMM,16), TNSZ("psraw",XMM,16), TNSZ("psrad",XMM,16), TNSZ("pavgw",XMM,16), 7290339a1c2SMark Johnston /* [E4] */ TNSZ("pmulhuw",XMM,16), TNSZ("pmulhw",XMM,16), TNSZ("cvttpd2dq",XMM,16),TNSZ("movntdq",XMMS,16), 7300339a1c2SMark Johnston /* [E8] */ TNSZ("psubsb",XMM,16), TNSZ("psubsw",XMM,16), TNSZ("pminsw",XMM,16), TNSZ("por",XMM,16), 7310339a1c2SMark Johnston /* [EC] */ TNSZ("paddsb",XMM,16), TNSZ("paddsw",XMM,16), TNSZ("pmaxsw",XMM,16), TNSZ("pxor",XMM,16), 7320339a1c2SMark Johnston 7330339a1c2SMark Johnston /* [F0] */ INVALID, TNSZ("psllw",XMM,16), TNSZ("pslld",XMM,16), TNSZ("psllq",XMM,16), 7340339a1c2SMark Johnston /* [F4] */ TNSZ("pmuludq",XMM,16), TNSZ("pmaddwd",XMM,16), TNSZ("psadbw",XMM,16), TNSZ("maskmovdqu", XMMXIMPL,16), 7350339a1c2SMark Johnston /* [F8] */ TNSZ("psubb",XMM,16), TNSZ("psubw",XMM,16), TNSZ("psubd",XMM,16), TNSZ("psubq",XMM,16), 7360339a1c2SMark Johnston /* [FC] */ TNSZ("paddb",XMM,16), TNSZ("paddw",XMM,16), TNSZ("paddd",XMM,16), INVALID, 7370339a1c2SMark Johnston }; 7380339a1c2SMark Johnston 7390339a1c2SMark Johnston const instable_t dis_opAVX660F[256] = { 7400339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 7410339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 7420339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 7430339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 7440339a1c2SMark Johnston 7450339a1c2SMark Johnston /* [10] */ TNSZ("vmovupd",VEX_MX,16), TNSZ("vmovupd",VEX_RX,16), TNSZ("vmovlpd",VEX_RMrX,8), TNSZ("vmovlpd",VEX_RM,8), 7460339a1c2SMark Johnston /* [14] */ TNSZ("vunpcklpd",VEX_RMrX,16),TNSZ("vunpckhpd",VEX_RMrX,16),TNSZ("vmovhpd",VEX_RMrX,8), TNSZ("vmovhpd",VEX_RM,8), 7470339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 7480339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 7490339a1c2SMark Johnston 7500339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 7510339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 7520339a1c2SMark Johnston /* [28] */ TNSZ("vmovapd",VEX_MX,16), TNSZ("vmovapd",VEX_RX,16), INVALID, TNSZ("vmovntpd",VEX_RM,16), 7530339a1c2SMark Johnston /* [2C] */ INVALID, INVALID, TNSZ("vucomisd",VEX_MX,8),TNSZ("vcomisd",VEX_MX,8), 7540339a1c2SMark Johnston 7550339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 7560339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 7570339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 7580339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 7590339a1c2SMark Johnston 7600339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 7610339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 7620339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 7630339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 7640339a1c2SMark Johnston 7650339a1c2SMark Johnston /* [50] */ TNS("vmovmskpd",VEX_MR), TNSZ("vsqrtpd",VEX_MX,16), INVALID, INVALID, 7660339a1c2SMark Johnston /* [54] */ TNSZ("vandpd",VEX_RMrX,16), TNSZ("vandnpd",VEX_RMrX,16), TNSZ("vorpd",VEX_RMrX,16), TNSZ("vxorpd",VEX_RMrX,16), 7670339a1c2SMark Johnston /* [58] */ TNSZ("vaddpd",VEX_RMrX,16), TNSZ("vmulpd",VEX_RMrX,16), TNSZ("vcvtpd2ps",VEX_MX,16),TNSZ("vcvtps2dq",VEX_MX,16), 7680339a1c2SMark Johnston /* [5C] */ TNSZ("vsubpd",VEX_RMrX,16), TNSZ("vminpd",VEX_RMrX,16), TNSZ("vdivpd",VEX_RMrX,16), TNSZ("vmaxpd",VEX_RMrX,16), 7690339a1c2SMark Johnston 7700339a1c2SMark Johnston /* [60] */ TNSZ("vpunpcklbw",VEX_RMrX,16),TNSZ("vpunpcklwd",VEX_RMrX,16),TNSZ("vpunpckldq",VEX_RMrX,16),TNSZ("vpacksswb",VEX_RMrX,16), 7710339a1c2SMark Johnston /* [64] */ TNSZ("vpcmpgtb",VEX_RMrX,16), TNSZ("vpcmpgtw",VEX_RMrX,16), TNSZ("vpcmpgtd",VEX_RMrX,16), TNSZ("vpackuswb",VEX_RMrX,16), 7720339a1c2SMark Johnston /* [68] */ TNSZ("vpunpckhbw",VEX_RMrX,16),TNSZ("vpunpckhwd",VEX_RMrX,16),TNSZ("vpunpckhdq",VEX_RMrX,16),TNSZ("vpackssdw",VEX_RMrX,16), 7730339a1c2SMark Johnston /* [6C] */ TNSZ("vpunpcklqdq",VEX_RMrX,16),TNSZ("vpunpckhqdq",VEX_RMrX,16),TNSZ("vmovd",VEX_MX,4),TNSZ("vmovdqa",VEX_MX,16), 7740339a1c2SMark Johnston 7750339a1c2SMark Johnston /* [70] */ TNSZ("vpshufd",VEX_MXI,16), TNSZ("vgrp71",VEX_XXI,16), TNSZ("vgrp72",VEX_XXI,16), TNSZ("vgrp73",VEX_XXI,16), 7760339a1c2SMark Johnston /* [74] */ TNSZ("vpcmpeqb",VEX_RMrX,16), TNSZ("vpcmpeqw",VEX_RMrX,16), TNSZ("vpcmpeqd",VEX_RMrX,16), INVALID, 7770339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 7780339a1c2SMark Johnston /* [7C] */ TNSZ("vhaddpd",VEX_RMrX,16), TNSZ("vhsubpd",VEX_RMrX,16), TNSZ("vmovd",VEX_RR,4), TNSZ("vmovdqa",VEX_RX,16), 7790339a1c2SMark Johnston 7800339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 7810339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 7820339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 7830339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 7840339a1c2SMark Johnston 7850339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 7860339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 7870339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 7880339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 7890339a1c2SMark Johnston 7900339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 7910339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 7920339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 7930339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 7940339a1c2SMark Johnston 7950339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 7960339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 7970339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 7980339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 7990339a1c2SMark Johnston 8000339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("vcmppd",VEX_RMRX,16), INVALID, 8010339a1c2SMark Johnston /* [C4] */ TNSZ("vpinsrw",VEX_RMRX,2),TNS("vpextrw",VEX_MR), TNSZ("vshufpd",VEX_RMRX,16), INVALID, 8020339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 8030339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 8040339a1c2SMark Johnston 8050339a1c2SMark Johnston /* [D0] */ TNSZ("vaddsubpd",VEX_RMrX,16),TNSZ("vpsrlw",VEX_RMrX,16), TNSZ("vpsrld",VEX_RMrX,16), TNSZ("vpsrlq",VEX_RMrX,16), 8060339a1c2SMark Johnston /* [D4] */ TNSZ("vpaddq",VEX_RMrX,16), TNSZ("vpmullw",VEX_RMrX,16), TNSZ("vmovq",VEX_RX,8), TNS("vpmovmskb",VEX_MR), 8070339a1c2SMark Johnston /* [D8] */ TNSZ("vpsubusb",VEX_RMrX,16), TNSZ("vpsubusw",VEX_RMrX,16), TNSZ("vpminub",VEX_RMrX,16), TNSZ("vpand",VEX_RMrX,16), 8080339a1c2SMark Johnston /* [DC] */ TNSZ("vpaddusb",VEX_RMrX,16), TNSZ("vpaddusw",VEX_RMrX,16), TNSZ("vpmaxub",VEX_RMrX,16), TNSZ("vpandn",VEX_RMrX,16), 8090339a1c2SMark Johnston 8100339a1c2SMark Johnston /* [E0] */ TNSZ("vpavgb",VEX_RMrX,16), TNSZ("vpsraw",VEX_RMrX,16), TNSZ("vpsrad",VEX_RMrX,16), TNSZ("vpavgw",VEX_RMrX,16), 8110339a1c2SMark Johnston /* [E4] */ TNSZ("vpmulhuw",VEX_RMrX,16), TNSZ("vpmulhw",VEX_RMrX,16), TNSZ("vcvttpd2dq",VEX_MX,16),TNSZ("vmovntdq",VEX_RM,16), 8120339a1c2SMark Johnston /* [E8] */ TNSZ("vpsubsb",VEX_RMrX,16), TNSZ("vpsubsw",VEX_RMrX,16), TNSZ("vpminsw",VEX_RMrX,16), TNSZ("vpor",VEX_RMrX,16), 8130339a1c2SMark Johnston /* [EC] */ TNSZ("vpaddsb",VEX_RMrX,16), TNSZ("vpaddsw",VEX_RMrX,16), TNSZ("vpmaxsw",VEX_RMrX,16), TNSZ("vpxor",VEX_RMrX,16), 8140339a1c2SMark Johnston 8150339a1c2SMark Johnston /* [F0] */ INVALID, TNSZ("vpsllw",VEX_RMrX,16), TNSZ("vpslld",VEX_RMrX,16), TNSZ("vpsllq",VEX_RMrX,16), 8160339a1c2SMark Johnston /* [F4] */ TNSZ("vpmuludq",VEX_RMrX,16), TNSZ("vpmaddwd",VEX_RMrX,16), TNSZ("vpsadbw",VEX_RMrX,16), TNS("vmaskmovdqu",VEX_MX), 8170339a1c2SMark Johnston /* [F8] */ TNSZ("vpsubb",VEX_RMrX,16), TNSZ("vpsubw",VEX_RMrX,16), TNSZ("vpsubd",VEX_RMrX,16), TNSZ("vpsubq",VEX_RMrX,16), 8180339a1c2SMark Johnston /* [FC] */ TNSZ("vpaddb",VEX_RMrX,16), TNSZ("vpaddw",VEX_RMrX,16), TNSZ("vpaddd",VEX_RMrX,16), INVALID, 8190339a1c2SMark Johnston }; 8200339a1c2SMark Johnston 8210339a1c2SMark Johnston /* 8220339a1c2SMark Johnston * Decode table for SIMD instructions with the repnz (0xf2) prefix. 8230339a1c2SMark Johnston */ 8240339a1c2SMark Johnston const instable_t dis_opSIMDrepnz[256] = { 8250339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 8260339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 8270339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 8280339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 8290339a1c2SMark Johnston 830*b3b5bfebSMark Johnston /* [10] */ TNSZ("movsd",XMM,8), TNSZ("movsd",XMMS,8), TNSZ("movddup",XMM,8), INVALID, 8310339a1c2SMark Johnston /* [14] */ INVALID, INVALID, INVALID, INVALID, 8320339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 8330339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 8340339a1c2SMark Johnston 8350339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 8360339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 8370339a1c2SMark Johnston /* [28] */ INVALID, INVALID, TNSZ("cvtsi2sd",XMM3MX,4),TNSZ("movntsd",XMMMS,8), 8380339a1c2SMark Johnston /* [2C] */ TNSZ("cvttsd2si",XMMXM3,8),TNSZ("cvtsd2si",XMMXM3,8),INVALID, INVALID, 8390339a1c2SMark Johnston 8400339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 8410339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 8420339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 8430339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 8440339a1c2SMark Johnston 8450339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 8460339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 8470339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 8480339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 8490339a1c2SMark Johnston 8500339a1c2SMark Johnston /* [50] */ INVALID, TNSZ("sqrtsd",XMM,8), INVALID, INVALID, 8510339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 8520339a1c2SMark Johnston /* [58] */ TNSZ("addsd",XMM,8), TNSZ("mulsd",XMM,8), TNSZ("cvtsd2ss",XMM,8), INVALID, 8530339a1c2SMark Johnston /* [5C] */ TNSZ("subsd",XMM,8), TNSZ("minsd",XMM,8), TNSZ("divsd",XMM,8), TNSZ("maxsd",XMM,8), 8540339a1c2SMark Johnston 8550339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 8560339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 8570339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 8580339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 8590339a1c2SMark Johnston 8600339a1c2SMark Johnston /* [70] */ TNSZ("pshuflw",XMMP,16),INVALID, INVALID, INVALID, 8610339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 8620339a1c2SMark Johnston /* [78] */ TNSZ("insertq",XMMX2I,16),TNSZ("insertq",XMM,8),INVALID, INVALID, 863*b3b5bfebSMark Johnston /* [7C] */ TNSZ("haddps",XMM,16), TNSZ("hsubps",XMM,16), INVALID, INVALID, 8640339a1c2SMark Johnston 8650339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 8660339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 8670339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 8680339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 8690339a1c2SMark Johnston 8700339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 8710339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 8720339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 8730339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 8740339a1c2SMark Johnston 8750339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 8760339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 8770339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 8780339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 8790339a1c2SMark Johnston 8800339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 8810339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 8820339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 8830339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 8840339a1c2SMark Johnston 8850339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("cmpsd",XMMP,8), INVALID, 8860339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 8870339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 8880339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 8890339a1c2SMark Johnston 890*b3b5bfebSMark Johnston /* [D0] */ TNSZ("addsubps",XMM,16),INVALID, INVALID, INVALID, 8910339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, TNS("movdq2q",XMMXM), INVALID, 8920339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 8930339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 8940339a1c2SMark Johnston 8950339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 8960339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, TNSZ("cvtpd2dq",XMM,16),INVALID, 8970339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 8980339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 8990339a1c2SMark Johnston 900*b3b5bfebSMark Johnston /* [F0] */ TNS("lddqu",XMMM), INVALID, INVALID, INVALID, 9010339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 9020339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 9030339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 9040339a1c2SMark Johnston }; 9050339a1c2SMark Johnston 9060339a1c2SMark Johnston const instable_t dis_opAVXF20F[256] = { 9070339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 9080339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 9090339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 9100339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 9110339a1c2SMark Johnston 9120339a1c2SMark Johnston /* [10] */ TNSZ("vmovsd",VEX_RMrX,8), TNSZ("vmovsd",VEX_RRX,8), TNSZ("vmovddup",VEX_MX,8), INVALID, 9130339a1c2SMark Johnston /* [14] */ INVALID, INVALID, INVALID, INVALID, 9140339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 9150339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 9160339a1c2SMark Johnston 9170339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 9180339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 9190339a1c2SMark Johnston /* [28] */ INVALID, INVALID, TNSZ("vcvtsi2sd",VEX_RMrX,4),INVALID, 9200339a1c2SMark Johnston /* [2C] */ TNSZ("vcvttsd2si",VEX_MR,8),TNSZ("vcvtsd2si",VEX_MR,8),INVALID, INVALID, 9210339a1c2SMark Johnston 9220339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 9230339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 9240339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 9250339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 9260339a1c2SMark Johnston 9270339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 9280339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 9290339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 9300339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 9310339a1c2SMark Johnston 9320339a1c2SMark Johnston /* [50] */ INVALID, TNSZ("vsqrtsd",VEX_RMrX,8), INVALID, INVALID, 9330339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 9340339a1c2SMark Johnston /* [58] */ TNSZ("vaddsd",VEX_RMrX,8), TNSZ("vmulsd",VEX_RMrX,8), TNSZ("vcvtsd2ss",VEX_RMrX,8), INVALID, 9350339a1c2SMark Johnston /* [5C] */ TNSZ("vsubsd",VEX_RMrX,8), TNSZ("vminsd",VEX_RMrX,8), TNSZ("vdivsd",VEX_RMrX,8), TNSZ("vmaxsd",VEX_RMrX,8), 9360339a1c2SMark Johnston 9370339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 9380339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 9390339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 9400339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 9410339a1c2SMark Johnston 9420339a1c2SMark Johnston /* [70] */ TNSZ("vpshuflw",VEX_MXI,16),INVALID, INVALID, INVALID, 9430339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 9440339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 9450339a1c2SMark Johnston /* [7C] */ TNSZ("vhaddps",VEX_RMrX,8), TNSZ("vhsubps",VEX_RMrX,8), INVALID, INVALID, 9460339a1c2SMark Johnston 9470339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 9480339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 9490339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 9500339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 9510339a1c2SMark Johnston 9520339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 9530339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 9540339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 9550339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 9560339a1c2SMark Johnston 9570339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 9580339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 9590339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 9600339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 9610339a1c2SMark Johnston 9620339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 9630339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 9640339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 9650339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 9660339a1c2SMark Johnston 9670339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("vcmpsd",VEX_RMRX,8), INVALID, 9680339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 9690339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 9700339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 9710339a1c2SMark Johnston 9720339a1c2SMark Johnston /* [D0] */ TNSZ("vaddsubps",VEX_RMrX,8), INVALID, INVALID, INVALID, 9730339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 9740339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 9750339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 9760339a1c2SMark Johnston 9770339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 9780339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, TNSZ("vcvtpd2dq",VEX_MX,16),INVALID, 9790339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 9800339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 9810339a1c2SMark Johnston 9820339a1c2SMark Johnston /* [F0] */ TNSZ("vlddqu",VEX_MX,16), INVALID, INVALID, INVALID, 9830339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 9840339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 9850339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 9860339a1c2SMark Johnston }; 9870339a1c2SMark Johnston 988*b3b5bfebSMark Johnston const instable_t dis_opAVXF20F3A[256] = { 989*b3b5bfebSMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 990*b3b5bfebSMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 991*b3b5bfebSMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 992*b3b5bfebSMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 993*b3b5bfebSMark Johnston 994*b3b5bfebSMark Johnston /* [10] */ INVALID, INVALID, INVALID, INVALID, 995*b3b5bfebSMark Johnston /* [14] */ INVALID, INVALID, INVALID, INVALID, 996*b3b5bfebSMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 997*b3b5bfebSMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 998*b3b5bfebSMark Johnston 999*b3b5bfebSMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 1000*b3b5bfebSMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 1001*b3b5bfebSMark Johnston /* [28] */ INVALID, INVALID, INVALID, INVALID, 1002*b3b5bfebSMark Johnston /* [2C] */ INVALID, INVALID, INVALID, INVALID, 1003*b3b5bfebSMark Johnston 1004*b3b5bfebSMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 1005*b3b5bfebSMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 1006*b3b5bfebSMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 1007*b3b5bfebSMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 1008*b3b5bfebSMark Johnston 1009*b3b5bfebSMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 1010*b3b5bfebSMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 1011*b3b5bfebSMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 1012*b3b5bfebSMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 1013*b3b5bfebSMark Johnston 1014*b3b5bfebSMark Johnston /* [50] */ INVALID, INVALID, INVALID, INVALID, 1015*b3b5bfebSMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 1016*b3b5bfebSMark Johnston /* [58] */ INVALID, INVALID, INVALID, INVALID, 1017*b3b5bfebSMark Johnston /* [5C] */ INVALID, INVALID, INVALID, INVALID, 1018*b3b5bfebSMark Johnston 1019*b3b5bfebSMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 1020*b3b5bfebSMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 1021*b3b5bfebSMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 1022*b3b5bfebSMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 1023*b3b5bfebSMark Johnston 1024*b3b5bfebSMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 1025*b3b5bfebSMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 1026*b3b5bfebSMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 1027*b3b5bfebSMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 1028*b3b5bfebSMark Johnston 1029*b3b5bfebSMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 1030*b3b5bfebSMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 1031*b3b5bfebSMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 1032*b3b5bfebSMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 1033*b3b5bfebSMark Johnston 1034*b3b5bfebSMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 1035*b3b5bfebSMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 1036*b3b5bfebSMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 1037*b3b5bfebSMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 1038*b3b5bfebSMark Johnston 1039*b3b5bfebSMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 1040*b3b5bfebSMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 1041*b3b5bfebSMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 1042*b3b5bfebSMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 1043*b3b5bfebSMark Johnston 1044*b3b5bfebSMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 1045*b3b5bfebSMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 1046*b3b5bfebSMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 1047*b3b5bfebSMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 1048*b3b5bfebSMark Johnston 1049*b3b5bfebSMark Johnston /* [C0] */ INVALID, INVALID, INVALID, INVALID, 1050*b3b5bfebSMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 1051*b3b5bfebSMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 1052*b3b5bfebSMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 1053*b3b5bfebSMark Johnston 1054*b3b5bfebSMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 1055*b3b5bfebSMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 1056*b3b5bfebSMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 1057*b3b5bfebSMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 1058*b3b5bfebSMark Johnston 1059*b3b5bfebSMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 1060*b3b5bfebSMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 1061*b3b5bfebSMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 1062*b3b5bfebSMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 1063*b3b5bfebSMark Johnston 1064*b3b5bfebSMark Johnston /* [F0] */ TNSZvr("rorx",VEX_MXI,6),INVALID, INVALID, INVALID, 1065*b3b5bfebSMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 1066*b3b5bfebSMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 1067*b3b5bfebSMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 1068*b3b5bfebSMark Johnston }; 1069*b3b5bfebSMark Johnston 1070*b3b5bfebSMark Johnston const instable_t dis_opAVXF20F38[256] = { 1071*b3b5bfebSMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 1072*b3b5bfebSMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 1073*b3b5bfebSMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 1074*b3b5bfebSMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 1075*b3b5bfebSMark Johnston 1076*b3b5bfebSMark Johnston /* [10] */ INVALID, INVALID, INVALID, INVALID, 1077*b3b5bfebSMark Johnston /* [14] */ INVALID, INVALID, INVALID, INVALID, 1078*b3b5bfebSMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 1079*b3b5bfebSMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 1080*b3b5bfebSMark Johnston 1081*b3b5bfebSMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 1082*b3b5bfebSMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 1083*b3b5bfebSMark Johnston /* [28] */ INVALID, INVALID, INVALID, INVALID, 1084*b3b5bfebSMark Johnston /* [2C] */ INVALID, INVALID, INVALID, INVALID, 1085*b3b5bfebSMark Johnston 1086*b3b5bfebSMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 1087*b3b5bfebSMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 1088*b3b5bfebSMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 1089*b3b5bfebSMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 1090*b3b5bfebSMark Johnston 1091*b3b5bfebSMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 1092*b3b5bfebSMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 1093*b3b5bfebSMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 1094*b3b5bfebSMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 1095*b3b5bfebSMark Johnston 1096*b3b5bfebSMark Johnston /* [50] */ INVALID, INVALID, INVALID, INVALID, 1097*b3b5bfebSMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 1098*b3b5bfebSMark Johnston /* [58] */ INVALID, INVALID, INVALID, INVALID, 1099*b3b5bfebSMark Johnston /* [5C] */ INVALID, INVALID, INVALID, INVALID, 1100*b3b5bfebSMark Johnston 1101*b3b5bfebSMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 1102*b3b5bfebSMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 1103*b3b5bfebSMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 1104*b3b5bfebSMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 1105*b3b5bfebSMark Johnston 1106*b3b5bfebSMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 1107*b3b5bfebSMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 1108*b3b5bfebSMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 1109*b3b5bfebSMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 1110*b3b5bfebSMark Johnston 1111*b3b5bfebSMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 1112*b3b5bfebSMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 1113*b3b5bfebSMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 1114*b3b5bfebSMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 1115*b3b5bfebSMark Johnston 1116*b3b5bfebSMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 1117*b3b5bfebSMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 1118*b3b5bfebSMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 1119*b3b5bfebSMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 1120*b3b5bfebSMark Johnston 1121*b3b5bfebSMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 1122*b3b5bfebSMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 1123*b3b5bfebSMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 1124*b3b5bfebSMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 1125*b3b5bfebSMark Johnston 1126*b3b5bfebSMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 1127*b3b5bfebSMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 1128*b3b5bfebSMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 1129*b3b5bfebSMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 1130*b3b5bfebSMark Johnston 1131*b3b5bfebSMark Johnston /* [C0] */ INVALID, INVALID, INVALID, INVALID, 1132*b3b5bfebSMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 1133*b3b5bfebSMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 1134*b3b5bfebSMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 1135*b3b5bfebSMark Johnston 1136*b3b5bfebSMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 1137*b3b5bfebSMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 1138*b3b5bfebSMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 1139*b3b5bfebSMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 1140*b3b5bfebSMark Johnston 1141*b3b5bfebSMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 1142*b3b5bfebSMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 1143*b3b5bfebSMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 1144*b3b5bfebSMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 1145*b3b5bfebSMark Johnston 1146*b3b5bfebSMark Johnston /* [F0] */ INVALID, INVALID, INVALID, INVALID, 1147*b3b5bfebSMark Johnston /* [F4] */ INVALID, TNSZvr("pdep",VEX_RMrX,5),TNSZvr("mulx",VEX_RMrX,5),TNSZvr("shrx",VEX_VRMrX,5), 1148*b3b5bfebSMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 1149*b3b5bfebSMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 1150*b3b5bfebSMark Johnston }; 1151*b3b5bfebSMark Johnston 1152*b3b5bfebSMark Johnston const instable_t dis_opAVXF30F38[256] = { 1153*b3b5bfebSMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 1154*b3b5bfebSMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 1155*b3b5bfebSMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 1156*b3b5bfebSMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 1157*b3b5bfebSMark Johnston 1158*b3b5bfebSMark Johnston /* [10] */ INVALID, INVALID, INVALID, INVALID, 1159*b3b5bfebSMark Johnston /* [14] */ INVALID, INVALID, INVALID, INVALID, 1160*b3b5bfebSMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 1161*b3b5bfebSMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 1162*b3b5bfebSMark Johnston 1163*b3b5bfebSMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 1164*b3b5bfebSMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 1165*b3b5bfebSMark Johnston /* [28] */ INVALID, INVALID, INVALID, INVALID, 1166*b3b5bfebSMark Johnston /* [2C] */ INVALID, INVALID, INVALID, INVALID, 1167*b3b5bfebSMark Johnston 1168*b3b5bfebSMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 1169*b3b5bfebSMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 1170*b3b5bfebSMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 1171*b3b5bfebSMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 1172*b3b5bfebSMark Johnston 1173*b3b5bfebSMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 1174*b3b5bfebSMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 1175*b3b5bfebSMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 1176*b3b5bfebSMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 1177*b3b5bfebSMark Johnston 1178*b3b5bfebSMark Johnston /* [50] */ INVALID, INVALID, INVALID, INVALID, 1179*b3b5bfebSMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 1180*b3b5bfebSMark Johnston /* [58] */ INVALID, INVALID, INVALID, INVALID, 1181*b3b5bfebSMark Johnston /* [5C] */ INVALID, INVALID, INVALID, INVALID, 1182*b3b5bfebSMark Johnston 1183*b3b5bfebSMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 1184*b3b5bfebSMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 1185*b3b5bfebSMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 1186*b3b5bfebSMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 1187*b3b5bfebSMark Johnston 1188*b3b5bfebSMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 1189*b3b5bfebSMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 1190*b3b5bfebSMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 1191*b3b5bfebSMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 1192*b3b5bfebSMark Johnston 1193*b3b5bfebSMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 1194*b3b5bfebSMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 1195*b3b5bfebSMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 1196*b3b5bfebSMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 1197*b3b5bfebSMark Johnston 1198*b3b5bfebSMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 1199*b3b5bfebSMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 1200*b3b5bfebSMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 1201*b3b5bfebSMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 1202*b3b5bfebSMark Johnston 1203*b3b5bfebSMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 1204*b3b5bfebSMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 1205*b3b5bfebSMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 1206*b3b5bfebSMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 1207*b3b5bfebSMark Johnston 1208*b3b5bfebSMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 1209*b3b5bfebSMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 1210*b3b5bfebSMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 1211*b3b5bfebSMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 1212*b3b5bfebSMark Johnston 1213*b3b5bfebSMark Johnston /* [C0] */ INVALID, INVALID, INVALID, INVALID, 1214*b3b5bfebSMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 1215*b3b5bfebSMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 1216*b3b5bfebSMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 1217*b3b5bfebSMark Johnston 1218*b3b5bfebSMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 1219*b3b5bfebSMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 1220*b3b5bfebSMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 1221*b3b5bfebSMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 1222*b3b5bfebSMark Johnston 1223*b3b5bfebSMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 1224*b3b5bfebSMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 1225*b3b5bfebSMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 1226*b3b5bfebSMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 1227*b3b5bfebSMark Johnston 1228*b3b5bfebSMark Johnston /* [F0] */ INVALID, INVALID, INVALID, INVALID, 1229*b3b5bfebSMark Johnston /* [F4] */ INVALID, TNSZvr("pext",VEX_RMrX,5),INVALID, TNSZvr("sarx",VEX_VRMrX,5), 1230*b3b5bfebSMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 1231*b3b5bfebSMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 1232*b3b5bfebSMark Johnston }; 12330339a1c2SMark Johnston /* 12340339a1c2SMark Johnston * Decode table for SIMD instructions with the repz (0xf3) prefix. 12350339a1c2SMark Johnston */ 12360339a1c2SMark Johnston const instable_t dis_opSIMDrepz[256] = { 12370339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 12380339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 12390339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 12400339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 12410339a1c2SMark Johnston 1242*b3b5bfebSMark Johnston /* [10] */ TNSZ("movss",XMM,4), TNSZ("movss",XMMS,4), TNSZ("movsldup",XMM,16),INVALID, 1243*b3b5bfebSMark Johnston /* [14] */ INVALID, INVALID, TNSZ("movshdup",XMM,16),INVALID, 12440339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 12450339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 12460339a1c2SMark Johnston 12470339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 12480339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 12490339a1c2SMark Johnston /* [28] */ INVALID, INVALID, TNSZ("cvtsi2ss",XMM3MX,4),TNSZ("movntss",XMMMS,4), 12500339a1c2SMark Johnston /* [2C] */ TNSZ("cvttss2si",XMMXM3,4),TNSZ("cvtss2si",XMMXM3,4),INVALID, INVALID, 12510339a1c2SMark Johnston 12520339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 12530339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 12540339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 12550339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 12560339a1c2SMark Johnston 12570339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 12580339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 12590339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 12600339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 12610339a1c2SMark Johnston 12620339a1c2SMark Johnston /* [50] */ INVALID, TNSZ("sqrtss",XMM,4), TNSZ("rsqrtss",XMM,4), TNSZ("rcpss",XMM,4), 12630339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 12640339a1c2SMark Johnston /* [58] */ TNSZ("addss",XMM,4), TNSZ("mulss",XMM,4), TNSZ("cvtss2sd",XMM,4), TNSZ("cvttps2dq",XMM,16), 12650339a1c2SMark Johnston /* [5C] */ TNSZ("subss",XMM,4), TNSZ("minss",XMM,4), TNSZ("divss",XMM,4), TNSZ("maxss",XMM,4), 12660339a1c2SMark Johnston 12670339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 12680339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 12690339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 12700339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, TNSZ("movdqu",XMM,16), 12710339a1c2SMark Johnston 12720339a1c2SMark Johnston /* [70] */ TNSZ("pshufhw",XMMP,16),INVALID, INVALID, INVALID, 12730339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 12740339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 12750339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, TNSZ("movq",XMM,8), TNSZ("movdqu",XMMS,16), 12760339a1c2SMark Johnston 12770339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 12780339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 12790339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 12800339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 12810339a1c2SMark Johnston 12820339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 12830339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 12840339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 12850339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 12860339a1c2SMark Johnston 12870339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 12880339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 12890339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 12900339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 12910339a1c2SMark Johnston 12920339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 12930339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 12940339a1c2SMark Johnston /* [B8] */ TS("popcnt",MRw), INVALID, INVALID, INVALID, 1295*b3b5bfebSMark Johnston /* [BC] */ TNSZ("tzcnt",MRw,5), TS("lzcnt",MRw), INVALID, INVALID, 12960339a1c2SMark Johnston 12970339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("cmpss",XMMP,4), INVALID, 12980339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 12990339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 13000339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 13010339a1c2SMark Johnston 13020339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 13030339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, TNS("movq2dq",XMMMX), INVALID, 13040339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 13050339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 13060339a1c2SMark Johnston 13070339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 13080339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, TNSZ("cvtdq2pd",XMM,8), INVALID, 13090339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 13100339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 13110339a1c2SMark Johnston 13120339a1c2SMark Johnston /* [F0] */ INVALID, INVALID, INVALID, INVALID, 13130339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 13140339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 13150339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 13160339a1c2SMark Johnston }; 13170339a1c2SMark Johnston 13180339a1c2SMark Johnston const instable_t dis_opAVXF30F[256] = { 13190339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 13200339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 13210339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 13220339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 13230339a1c2SMark Johnston 13240339a1c2SMark Johnston /* [10] */ TNSZ("vmovss",VEX_RMrX,4), TNSZ("vmovss",VEX_RRX,4), TNSZ("vmovsldup",VEX_MX,4), INVALID, 13250339a1c2SMark Johnston /* [14] */ INVALID, INVALID, TNSZ("vmovshdup",VEX_MX,4), INVALID, 13260339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 13270339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 13280339a1c2SMark Johnston 13290339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 13300339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 13310339a1c2SMark Johnston /* [28] */ INVALID, INVALID, TNSZ("vcvtsi2ss",VEX_RMrX,4),INVALID, 13320339a1c2SMark Johnston /* [2C] */ TNSZ("vcvttss2si",VEX_MR,4),TNSZ("vcvtss2si",VEX_MR,4),INVALID, INVALID, 13330339a1c2SMark Johnston 13340339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 13350339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 13360339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 13370339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 13380339a1c2SMark Johnston 13390339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 13400339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 13410339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 13420339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 13430339a1c2SMark Johnston 13440339a1c2SMark Johnston /* [50] */ INVALID, TNSZ("vsqrtss",VEX_RMrX,4), TNSZ("vrsqrtss",VEX_RMrX,4), TNSZ("vrcpss",VEX_RMrX,4), 13450339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 13460339a1c2SMark Johnston /* [58] */ TNSZ("vaddss",VEX_RMrX,4), TNSZ("vmulss",VEX_RMrX,4), TNSZ("vcvtss2sd",VEX_RMrX,4), TNSZ("vcvttps2dq",VEX_MX,16), 13470339a1c2SMark Johnston /* [5C] */ TNSZ("vsubss",VEX_RMrX,4), TNSZ("vminss",VEX_RMrX,4), TNSZ("vdivss",VEX_RMrX,4), TNSZ("vmaxss",VEX_RMrX,4), 13480339a1c2SMark Johnston 13490339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 13500339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 13510339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 13520339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, TNSZ("vmovdqu",VEX_MX,16), 13530339a1c2SMark Johnston 13540339a1c2SMark Johnston /* [70] */ TNSZ("vpshufhw",VEX_MXI,16),INVALID, INVALID, INVALID, 13550339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 13560339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 13570339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, TNSZ("vmovq",VEX_MX,8), TNSZ("vmovdqu",VEX_RX,16), 13580339a1c2SMark Johnston 13590339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 13600339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 13610339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 13620339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 13630339a1c2SMark Johnston 13640339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 13650339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 13660339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 13670339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 13680339a1c2SMark Johnston 13690339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 13700339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 13710339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 13720339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 13730339a1c2SMark Johnston 13740339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 13750339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 13760339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 13770339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 13780339a1c2SMark Johnston 13790339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("vcmpss",VEX_RMRX,4), INVALID, 13800339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 13810339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 13820339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 13830339a1c2SMark Johnston 13840339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 13850339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 13860339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 13870339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 13880339a1c2SMark Johnston 13890339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 13900339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, TNSZ("vcvtdq2pd",VEX_MX,8), INVALID, 13910339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 13920339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 13930339a1c2SMark Johnston 13940339a1c2SMark Johnston /* [F0] */ INVALID, INVALID, INVALID, INVALID, 13950339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 13960339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 13970339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 13980339a1c2SMark Johnston }; 13990339a1c2SMark Johnston /* 14000339a1c2SMark Johnston * The following two tables are used to encode crc32 and movbe 14010339a1c2SMark Johnston * since they share the same opcodes. 14020339a1c2SMark Johnston */ 14030339a1c2SMark Johnston const instable_t dis_op0F38F0[2] = { 14040339a1c2SMark Johnston /* [00] */ TNS("crc32b",CRC32), 14050339a1c2SMark Johnston TS("movbe",MOVBE), 14060339a1c2SMark Johnston }; 14070339a1c2SMark Johnston 14080339a1c2SMark Johnston const instable_t dis_op0F38F1[2] = { 14090339a1c2SMark Johnston /* [00] */ TS("crc32",CRC32), 14100339a1c2SMark Johnston TS("movbe",MOVBE), 14110339a1c2SMark Johnston }; 14120339a1c2SMark Johnston 1413*b3b5bfebSMark Johnston /* 1414*b3b5bfebSMark Johnston * The following table is used to distinguish between adox and adcx which share 1415*b3b5bfebSMark Johnston * the same opcodes. 1416*b3b5bfebSMark Johnston */ 1417*b3b5bfebSMark Johnston const instable_t dis_op0F38F6[2] = { 1418*b3b5bfebSMark Johnston /* [00] */ TNS("adcx",ADX), 1419*b3b5bfebSMark Johnston TNS("adox",ADX), 1420*b3b5bfebSMark Johnston }; 1421*b3b5bfebSMark Johnston 14220339a1c2SMark Johnston const instable_t dis_op0F38[256] = { 14230339a1c2SMark Johnston /* [00] */ TNSZ("pshufb",XMM_66o,16),TNSZ("phaddw",XMM_66o,16),TNSZ("phaddd",XMM_66o,16),TNSZ("phaddsw",XMM_66o,16), 14240339a1c2SMark Johnston /* [04] */ TNSZ("pmaddubsw",XMM_66o,16),TNSZ("phsubw",XMM_66o,16), TNSZ("phsubd",XMM_66o,16),TNSZ("phsubsw",XMM_66o,16), 14250339a1c2SMark Johnston /* [08] */ TNSZ("psignb",XMM_66o,16),TNSZ("psignw",XMM_66o,16),TNSZ("psignd",XMM_66o,16),TNSZ("pmulhrsw",XMM_66o,16), 14260339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 14270339a1c2SMark Johnston 14280339a1c2SMark Johnston /* [10] */ TNSZ("pblendvb",XMM_66r,16),INVALID, INVALID, INVALID, 14290339a1c2SMark Johnston /* [14] */ TNSZ("blendvps",XMM_66r,16),TNSZ("blendvpd",XMM_66r,16),INVALID, TNSZ("ptest",XMM_66r,16), 14300339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 14310339a1c2SMark Johnston /* [1C] */ TNSZ("pabsb",XMM_66o,16),TNSZ("pabsw",XMM_66o,16),TNSZ("pabsd",XMM_66o,16),INVALID, 14320339a1c2SMark Johnston 14330339a1c2SMark Johnston /* [20] */ TNSZ("pmovsxbw",XMM_66r,16),TNSZ("pmovsxbd",XMM_66r,16),TNSZ("pmovsxbq",XMM_66r,16),TNSZ("pmovsxwd",XMM_66r,16), 14340339a1c2SMark Johnston /* [24] */ TNSZ("pmovsxwq",XMM_66r,16),TNSZ("pmovsxdq",XMM_66r,16),INVALID, INVALID, 14350339a1c2SMark Johnston /* [28] */ TNSZ("pmuldq",XMM_66r,16),TNSZ("pcmpeqq",XMM_66r,16),TNSZ("movntdqa",XMMM_66r,16),TNSZ("packusdw",XMM_66r,16), 14360339a1c2SMark Johnston /* [2C] */ INVALID, INVALID, INVALID, INVALID, 14370339a1c2SMark Johnston 14380339a1c2SMark Johnston /* [30] */ TNSZ("pmovzxbw",XMM_66r,16),TNSZ("pmovzxbd",XMM_66r,16),TNSZ("pmovzxbq",XMM_66r,16),TNSZ("pmovzxwd",XMM_66r,16), 14390339a1c2SMark Johnston /* [34] */ TNSZ("pmovzxwq",XMM_66r,16),TNSZ("pmovzxdq",XMM_66r,16),INVALID, TNSZ("pcmpgtq",XMM_66r,16), 14400339a1c2SMark Johnston /* [38] */ TNSZ("pminsb",XMM_66r,16),TNSZ("pminsd",XMM_66r,16),TNSZ("pminuw",XMM_66r,16),TNSZ("pminud",XMM_66r,16), 14410339a1c2SMark Johnston /* [3C] */ TNSZ("pmaxsb",XMM_66r,16),TNSZ("pmaxsd",XMM_66r,16),TNSZ("pmaxuw",XMM_66r,16),TNSZ("pmaxud",XMM_66r,16), 14420339a1c2SMark Johnston 14430339a1c2SMark Johnston /* [40] */ TNSZ("pmulld",XMM_66r,16),TNSZ("phminposuw",XMM_66r,16),INVALID, INVALID, 14440339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 14450339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 14460339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 14470339a1c2SMark Johnston 14480339a1c2SMark Johnston /* [50] */ INVALID, INVALID, INVALID, INVALID, 14490339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 14500339a1c2SMark Johnston /* [58] */ INVALID, INVALID, INVALID, INVALID, 14510339a1c2SMark Johnston /* [5C] */ INVALID, INVALID, INVALID, INVALID, 14520339a1c2SMark Johnston 14530339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 14540339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 14550339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 14560339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 14570339a1c2SMark Johnston 14580339a1c2SMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 14590339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 14600339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 14610339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 14620339a1c2SMark Johnston 146327b6c497SAndriy Gapon /* [80] */ TNSy("invept", RM_66r), TNSy("invvpid", RM_66r),TNSy("invpcid", RM_66r),INVALID, 14640339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 14650339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 14660339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 14670339a1c2SMark Johnston 14680339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 14690339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 14700339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 14710339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 14720339a1c2SMark Johnston 14730339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 14740339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 14750339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 14760339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 14770339a1c2SMark Johnston 14780339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 14790339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 14800339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 14810339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 14820339a1c2SMark Johnston 14830339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, INVALID, INVALID, 14840339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 1485*b3b5bfebSMark Johnston /* [C8] */ TNSZ("sha1nexte",XMM,16),TNSZ("sha1msg1",XMM,16),TNSZ("sha1msg2",XMM,16),TNSZ("sha256rnds2",XMM,16), 1486*b3b5bfebSMark Johnston /* [CC] */ TNSZ("sha256msg1",XMM,16),TNSZ("sha256msg2",XMM,16),INVALID, INVALID, 14870339a1c2SMark Johnston 14880339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 14890339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 14900339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, TNSZ("aesimc",XMM_66r,16), 14910339a1c2SMark Johnston /* [DC] */ TNSZ("aesenc",XMM_66r,16),TNSZ("aesenclast",XMM_66r,16),TNSZ("aesdec",XMM_66r,16),TNSZ("aesdeclast",XMM_66r,16), 14920339a1c2SMark Johnston 14930339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 14940339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 14950339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 14960339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 14970339a1c2SMark Johnston /* [F0] */ IND(dis_op0F38F0), IND(dis_op0F38F1), INVALID, INVALID, 1498*b3b5bfebSMark Johnston /* [F4] */ INVALID, INVALID, IND(dis_op0F38F6), INVALID, 14990339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 15000339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 15010339a1c2SMark Johnston }; 15020339a1c2SMark Johnston 15030339a1c2SMark Johnston const instable_t dis_opAVX660F38[256] = { 15040339a1c2SMark Johnston /* [00] */ TNSZ("vpshufb",VEX_RMrX,16),TNSZ("vphaddw",VEX_RMrX,16),TNSZ("vphaddd",VEX_RMrX,16),TNSZ("vphaddsw",VEX_RMrX,16), 15050339a1c2SMark Johnston /* [04] */ TNSZ("vpmaddubsw",VEX_RMrX,16),TNSZ("vphsubw",VEX_RMrX,16), TNSZ("vphsubd",VEX_RMrX,16),TNSZ("vphsubsw",VEX_RMrX,16), 15060339a1c2SMark Johnston /* [08] */ TNSZ("vpsignb",VEX_RMrX,16),TNSZ("vpsignw",VEX_RMrX,16),TNSZ("vpsignd",VEX_RMrX,16),TNSZ("vpmulhrsw",VEX_RMrX,16), 15070339a1c2SMark Johnston /* [0C] */ TNSZ("vpermilps",VEX_RMrX,8),TNSZ("vpermilpd",VEX_RMrX,16),TNSZ("vtestps",VEX_RRI,8), TNSZ("vtestpd",VEX_RRI,16), 15080339a1c2SMark Johnston 1509c3ddb60eSPeter Grehan /* [10] */ INVALID, INVALID, INVALID, TNSZ("vcvtph2ps",VEX_MX,16), 1510*b3b5bfebSMark Johnston /* [14] */ INVALID, INVALID, TNSZ("vpermps",VEX_RMrX,16),TNSZ("vptest",VEX_RRI,16), 15110339a1c2SMark Johnston /* [18] */ TNSZ("vbroadcastss",VEX_MX,4),TNSZ("vbroadcastsd",VEX_MX,8),TNSZ("vbroadcastf128",VEX_MX,16),INVALID, 15120339a1c2SMark Johnston /* [1C] */ TNSZ("vpabsb",VEX_MX,16),TNSZ("vpabsw",VEX_MX,16),TNSZ("vpabsd",VEX_MX,16),INVALID, 15130339a1c2SMark Johnston 15140339a1c2SMark Johnston /* [20] */ TNSZ("vpmovsxbw",VEX_MX,16),TNSZ("vpmovsxbd",VEX_MX,16),TNSZ("vpmovsxbq",VEX_MX,16),TNSZ("vpmovsxwd",VEX_MX,16), 15150339a1c2SMark Johnston /* [24] */ TNSZ("vpmovsxwq",VEX_MX,16),TNSZ("vpmovsxdq",VEX_MX,16),INVALID, INVALID, 15160339a1c2SMark Johnston /* [28] */ TNSZ("vpmuldq",VEX_RMrX,16),TNSZ("vpcmpeqq",VEX_RMrX,16),TNSZ("vmovntdqa",VEX_MX,16),TNSZ("vpackusdw",VEX_RMrX,16), 15170339a1c2SMark Johnston /* [2C] */ TNSZ("vmaskmovps",VEX_RMrX,8),TNSZ("vmaskmovpd",VEX_RMrX,16),TNSZ("vmaskmovps",VEX_RRM,8),TNSZ("vmaskmovpd",VEX_RRM,16), 15180339a1c2SMark Johnston 15190339a1c2SMark Johnston /* [30] */ TNSZ("vpmovzxbw",VEX_MX,16),TNSZ("vpmovzxbd",VEX_MX,16),TNSZ("vpmovzxbq",VEX_MX,16),TNSZ("vpmovzxwd",VEX_MX,16), 1520*b3b5bfebSMark Johnston /* [34] */ TNSZ("vpmovzxwq",VEX_MX,16),TNSZ("vpmovzxdq",VEX_MX,16),TNSZ("vpermd",VEX_RMrX,16),TNSZ("vpcmpgtq",VEX_RMrX,16), 15210339a1c2SMark Johnston /* [38] */ TNSZ("vpminsb",VEX_RMrX,16),TNSZ("vpminsd",VEX_RMrX,16),TNSZ("vpminuw",VEX_RMrX,16),TNSZ("vpminud",VEX_RMrX,16), 15220339a1c2SMark Johnston /* [3C] */ TNSZ("vpmaxsb",VEX_RMrX,16),TNSZ("vpmaxsd",VEX_RMrX,16),TNSZ("vpmaxuw",VEX_RMrX,16),TNSZ("vpmaxud",VEX_RMrX,16), 15230339a1c2SMark Johnston 15240339a1c2SMark Johnston /* [40] */ TNSZ("vpmulld",VEX_RMrX,16),TNSZ("vphminposuw",VEX_MX,16),INVALID, INVALID, 1525*b3b5bfebSMark Johnston /* [44] */ INVALID, TSaZ("vpsrlv",VEX_RMrX,16),TNSZ("vpsravd",VEX_RMrX,16),TSaZ("vpsllv",VEX_RMrX,16), 15260339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 15270339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 15280339a1c2SMark Johnston 15290339a1c2SMark Johnston /* [50] */ INVALID, INVALID, INVALID, INVALID, 15300339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 1531*b3b5bfebSMark Johnston /* [58] */ TNSZ("vpbroadcastd",VEX_MX,16),TNSZ("vpbroadcastq",VEX_MX,16),TNSZ("vbroadcasti128",VEX_MX,16),INVALID, 15320339a1c2SMark Johnston /* [5C] */ INVALID, INVALID, INVALID, INVALID, 15330339a1c2SMark Johnston 15340339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 15350339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 15360339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 15370339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 15380339a1c2SMark Johnston 15390339a1c2SMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 15400339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 1541*b3b5bfebSMark Johnston /* [78] */ TNSZ("vpbroadcastb",VEX_MX,16),TNSZ("vpbroadcastw",VEX_MX,16),INVALID, INVALID, 15420339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 15430339a1c2SMark Johnston 15440339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 15450339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 15460339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 1547*b3b5bfebSMark Johnston /* [8C] */ TSaZ("vpmaskmov",VEX_RMrX,16),INVALID, TSaZ("vpmaskmov",VEX_RRM,16),INVALID, 15480339a1c2SMark Johnston 1549*b3b5bfebSMark Johnston /* [90] */ TNSZ("vpgatherd",VEX_SbVM,16),TNSZ("vpgatherq",VEX_SbVM,16),TNSZ("vgatherdp",VEX_SbVM,16),TNSZ("vgatherqp",VEX_SbVM,16), 1550*b3b5bfebSMark Johnston /* [94] */ INVALID, INVALID, TNSZ("vfmaddsub132p",FMA,16),TNSZ("vfmsubadd132p",FMA,16), 1551*b3b5bfebSMark Johnston /* [98] */ TNSZ("vfmadd132p",FMA,16),TNSZ("vfmadd132s",FMA,16),TNSZ("vfmsub132p",FMA,16),TNSZ("vfmsub132s",FMA,16), 1552*b3b5bfebSMark Johnston /* [9C] */ TNSZ("vfnmadd132p",FMA,16),TNSZ("vfnmadd132s",FMA,16),TNSZ("vfnmsub132p",FMA,16),TNSZ("vfnmsub132s",FMA,16), 15530339a1c2SMark Johnston 15540339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 1555*b3b5bfebSMark Johnston /* [A4] */ INVALID, INVALID, TNSZ("vfmaddsub213p",FMA,16),TNSZ("vfmsubadd213p",FMA,16), 1556*b3b5bfebSMark Johnston /* [A8] */ TNSZ("vfmadd213p",FMA,16),TNSZ("vfmadd213s",FMA,16),TNSZ("vfmsub213p",FMA,16),TNSZ("vfmsub213s",FMA,16), 1557*b3b5bfebSMark Johnston /* [AC] */ TNSZ("vfnmadd213p",FMA,16),TNSZ("vfnmadd213s",FMA,16),TNSZ("vfnmsub213p",FMA,16),TNSZ("vfnmsub213s",FMA,16), 15580339a1c2SMark Johnston 15590339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 1560*b3b5bfebSMark Johnston /* [B4] */ INVALID, INVALID, TNSZ("vfmaddsub231p",FMA,16),TNSZ("vfmsubadd231p",FMA,16), 1561*b3b5bfebSMark Johnston /* [B8] */ TNSZ("vfmadd231p",FMA,16),TNSZ("vfmadd231s",FMA,16),TNSZ("vfmsub231p",FMA,16),TNSZ("vfmsub231s",FMA,16), 1562*b3b5bfebSMark Johnston /* [BC] */ TNSZ("vfnmadd231p",FMA,16),TNSZ("vfnmadd231s",FMA,16),TNSZ("vfnmsub231p",FMA,16),TNSZ("vfnmsub231s",FMA,16), 15630339a1c2SMark Johnston 15640339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, INVALID, INVALID, 15650339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 15660339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 15670339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 15680339a1c2SMark Johnston 15690339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 15700339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 15710339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, TNSZ("vaesimc",VEX_MX,16), 15720339a1c2SMark Johnston /* [DC] */ TNSZ("vaesenc",VEX_RMrX,16),TNSZ("vaesenclast",VEX_RMrX,16),TNSZ("vaesdec",VEX_RMrX,16),TNSZ("vaesdeclast",VEX_RMrX,16), 15730339a1c2SMark Johnston 15740339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 15750339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 15760339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 15770339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 15780339a1c2SMark Johnston /* [F0] */ IND(dis_op0F38F0), IND(dis_op0F38F1), INVALID, INVALID, 1579*b3b5bfebSMark Johnston /* [F4] */ INVALID, INVALID, INVALID, TNSZvr("shlx",VEX_VRMrX,5), 15800339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 15810339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 15820339a1c2SMark Johnston }; 15830339a1c2SMark Johnston 15840339a1c2SMark Johnston const instable_t dis_op0F3A[256] = { 15850339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 15860339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 15870339a1c2SMark Johnston /* [08] */ TNSZ("roundps",XMMP_66r,16),TNSZ("roundpd",XMMP_66r,16),TNSZ("roundss",XMMP_66r,16),TNSZ("roundsd",XMMP_66r,16), 15880339a1c2SMark Johnston /* [0C] */ TNSZ("blendps",XMMP_66r,16),TNSZ("blendpd",XMMP_66r,16),TNSZ("pblendw",XMMP_66r,16),TNSZ("palignr",XMMP_66o,16), 15890339a1c2SMark Johnston 15900339a1c2SMark Johnston /* [10] */ INVALID, INVALID, INVALID, INVALID, 15910339a1c2SMark Johnston /* [14] */ TNSZ("pextrb",XMM3PM_66r,8),TNSZ("pextrw",XMM3PM_66r,16),TSZ("pextr",XMM3PM_66r,16),TNSZ("extractps",XMM3PM_66r,16), 15920339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 15930339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 15940339a1c2SMark Johnston 15950339a1c2SMark Johnston /* [20] */ TNSZ("pinsrb",XMMPRM_66r,8),TNSZ("insertps",XMMP_66r,16),TSZ("pinsr",XMMPRM_66r,16),INVALID, 15960339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 15970339a1c2SMark Johnston /* [28] */ INVALID, INVALID, INVALID, INVALID, 15980339a1c2SMark Johnston /* [2C] */ INVALID, INVALID, INVALID, INVALID, 15990339a1c2SMark Johnston 16000339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 16010339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 16020339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 16030339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 16040339a1c2SMark Johnston 16050339a1c2SMark Johnston /* [40] */ TNSZ("dpps",XMMP_66r,16),TNSZ("dppd",XMMP_66r,16),TNSZ("mpsadbw",XMMP_66r,16),INVALID, 16060339a1c2SMark Johnston /* [44] */ TNSZ("pclmulqdq",XMMP_66r,16),INVALID, INVALID, INVALID, 16070339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 16080339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 16090339a1c2SMark Johnston 16100339a1c2SMark Johnston /* [50] */ INVALID, INVALID, INVALID, INVALID, 16110339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 16120339a1c2SMark Johnston /* [58] */ INVALID, INVALID, INVALID, INVALID, 16130339a1c2SMark Johnston /* [5C] */ INVALID, INVALID, INVALID, INVALID, 16140339a1c2SMark Johnston 16150339a1c2SMark Johnston /* [60] */ TNSZ("pcmpestrm",XMMP_66r,16),TNSZ("pcmpestri",XMMP_66r,16),TNSZ("pcmpistrm",XMMP_66r,16),TNSZ("pcmpistri",XMMP_66r,16), 16160339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 16170339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 16180339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 16190339a1c2SMark Johnston 16200339a1c2SMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 16210339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 16220339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 16230339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 16240339a1c2SMark Johnston 16250339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 16260339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 16270339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 16280339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 16290339a1c2SMark Johnston 16300339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 16310339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 16320339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 16330339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 16340339a1c2SMark Johnston 16350339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 16360339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 16370339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 16380339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 16390339a1c2SMark Johnston 16400339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 16410339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 16420339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 16430339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 16440339a1c2SMark Johnston 16450339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, INVALID, INVALID, 16460339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 16470339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 1648*b3b5bfebSMark Johnston /* [CC] */ TNSZ("sha1rnds4",XMMP,16),INVALID, INVALID, INVALID, 16490339a1c2SMark Johnston 16500339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 16510339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 16520339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 16530339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, TNSZ("aeskeygenassist",XMMP_66r,16), 16540339a1c2SMark Johnston 16550339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 16560339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 16570339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 16580339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 16590339a1c2SMark Johnston 16600339a1c2SMark Johnston /* [F0] */ INVALID, INVALID, INVALID, INVALID, 16610339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 16620339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 16630339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 16640339a1c2SMark Johnston }; 16650339a1c2SMark Johnston 16660339a1c2SMark Johnston const instable_t dis_opAVX660F3A[256] = { 1667*b3b5bfebSMark Johnston /* [00] */ TNSZ("vpermq",VEX_MXI,16),TNSZ("vpermpd",VEX_MXI,16),TNSZ("vpblendd",VEX_RMRX,16),INVALID, 16680339a1c2SMark Johnston /* [04] */ TNSZ("vpermilps",VEX_MXI,8),TNSZ("vpermilpd",VEX_MXI,16),TNSZ("vperm2f128",VEX_RMRX,16),INVALID, 16690339a1c2SMark Johnston /* [08] */ TNSZ("vroundps",VEX_MXI,16),TNSZ("vroundpd",VEX_MXI,16),TNSZ("vroundss",VEX_RMRX,16),TNSZ("vroundsd",VEX_RMRX,16), 16700339a1c2SMark Johnston /* [0C] */ TNSZ("vblendps",VEX_RMRX,16),TNSZ("vblendpd",VEX_RMRX,16),TNSZ("vpblendw",VEX_RMRX,16),TNSZ("vpalignr",VEX_RMRX,16), 16710339a1c2SMark Johnston 16720339a1c2SMark Johnston /* [10] */ INVALID, INVALID, INVALID, INVALID, 16730339a1c2SMark Johnston /* [14] */ TNSZ("vpextrb",VEX_RRi,8),TNSZ("vpextrw",VEX_RRi,16),TNSZ("vpextrd",VEX_RRi,16),TNSZ("vextractps",VEX_RM,16), 16740339a1c2SMark Johnston /* [18] */ TNSZ("vinsertf128",VEX_RMRX,16),TNSZ("vextractf128",VEX_RX,16),INVALID, INVALID, 1675c3ddb60eSPeter Grehan /* [1C] */ INVALID, TNSZ("vcvtps2ph",VEX_RX,16), INVALID, INVALID, 16760339a1c2SMark Johnston 16770339a1c2SMark Johnston /* [20] */ TNSZ("vpinsrb",VEX_RMRX,8),TNSZ("vinsertps",VEX_RMRX,16),TNSZ("vpinsrd",VEX_RMRX,16),INVALID, 16780339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 16790339a1c2SMark Johnston /* [28] */ INVALID, INVALID, INVALID, INVALID, 16800339a1c2SMark Johnston /* [2C] */ INVALID, INVALID, INVALID, INVALID, 16810339a1c2SMark Johnston 16820339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 16830339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 1684*b3b5bfebSMark Johnston /* [38] */ TNSZ("vinserti128",VEX_RMRX,16),TNSZ("vextracti128",VEX_RIM,16),INVALID, INVALID, 16850339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 16860339a1c2SMark Johnston 16870339a1c2SMark Johnston /* [40] */ TNSZ("vdpps",VEX_RMRX,16),TNSZ("vdppd",VEX_RMRX,16),TNSZ("vmpsadbw",VEX_RMRX,16),INVALID, 1688*b3b5bfebSMark Johnston /* [44] */ TNSZ("vpclmulqdq",VEX_RMRX,16),INVALID, TNSZ("vperm2i128",VEX_RMRX,16),INVALID, 16890339a1c2SMark Johnston /* [48] */ INVALID, INVALID, TNSZ("vblendvps",VEX_RMRX,8), TNSZ("vblendvpd",VEX_RMRX,16), 16900339a1c2SMark Johnston /* [4C] */ TNSZ("vpblendvb",VEX_RMRX,16),INVALID, INVALID, INVALID, 16910339a1c2SMark Johnston 16920339a1c2SMark Johnston /* [50] */ INVALID, INVALID, INVALID, INVALID, 16930339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 16940339a1c2SMark Johnston /* [58] */ INVALID, INVALID, INVALID, INVALID, 16950339a1c2SMark Johnston /* [5C] */ INVALID, INVALID, INVALID, INVALID, 16960339a1c2SMark Johnston 16970339a1c2SMark Johnston /* [60] */ TNSZ("vpcmpestrm",VEX_MXI,16),TNSZ("vpcmpestri",VEX_MXI,16),TNSZ("vpcmpistrm",VEX_MXI,16),TNSZ("vpcmpistri",VEX_MXI,16), 16980339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 16990339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 17000339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 17010339a1c2SMark Johnston 17020339a1c2SMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 17030339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 17040339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 17050339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 17060339a1c2SMark Johnston 17070339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 17080339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 17090339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 17100339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 17110339a1c2SMark Johnston 17120339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 17130339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 17140339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 17150339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 17160339a1c2SMark Johnston 17170339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 17180339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 17190339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 17200339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 17210339a1c2SMark Johnston 17220339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 17230339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 17240339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 17250339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 17260339a1c2SMark Johnston 17270339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, INVALID, INVALID, 17280339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 17290339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 17300339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 17310339a1c2SMark Johnston 17320339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 17330339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 17340339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 17350339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, TNSZ("vaeskeygenassist",VEX_MXI,16), 17360339a1c2SMark Johnston 17370339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 17380339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 17390339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 17400339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 17410339a1c2SMark Johnston 17420339a1c2SMark Johnston /* [F0] */ INVALID, INVALID, INVALID, INVALID, 17430339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 17440339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 17450339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 17460339a1c2SMark Johnston }; 17470339a1c2SMark Johnston 17480339a1c2SMark Johnston /* 1749*b3b5bfebSMark Johnston * Decode table for 0x0F0D which uses the first byte of the mod_rm to 1750*b3b5bfebSMark Johnston * indicate a sub-code. 1751*b3b5bfebSMark Johnston */ 1752*b3b5bfebSMark Johnston const instable_t dis_op0F0D[8] = { 1753*b3b5bfebSMark Johnston /* [00] */ INVALID, TNS("prefetchw",PREF), TNS("prefetchwt1",PREF),INVALID, 1754*b3b5bfebSMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 1755*b3b5bfebSMark Johnston }; 1756*b3b5bfebSMark Johnston 1757*b3b5bfebSMark Johnston /* 17580339a1c2SMark Johnston * Decode table for 0x0F opcodes 17590339a1c2SMark Johnston */ 17600339a1c2SMark Johnston 17610339a1c2SMark Johnston const instable_t dis_op0F[16][16] = { 17620339a1c2SMark Johnston { 17630339a1c2SMark Johnston /* [00] */ IND(dis_op0F00), IND(dis_op0F01), TNS("lar",MR), TNS("lsl",MR), 17640339a1c2SMark Johnston /* [04] */ INVALID, TNS("syscall",NORM), TNS("clts",NORM), TNS("sysret",NORM), 17650339a1c2SMark Johnston /* [08] */ TNS("invd",NORM), TNS("wbinvd",NORM), INVALID, TNS("ud2",NORM), 1766*b3b5bfebSMark Johnston /* [0C] */ INVALID, IND(dis_op0F0D), INVALID, INVALID, 17670339a1c2SMark Johnston }, { 17680339a1c2SMark Johnston /* [10] */ TNSZ("movups",XMMO,16), TNSZ("movups",XMMOS,16),TNSZ("movlps",XMMO,8), TNSZ("movlps",XMMOS,8), 17690339a1c2SMark Johnston /* [14] */ TNSZ("unpcklps",XMMO,16),TNSZ("unpckhps",XMMO,16),TNSZ("movhps",XMMOM,8),TNSZ("movhps",XMMOMS,8), 17700339a1c2SMark Johnston /* [18] */ IND(dis_op0F18), INVALID, INVALID, INVALID, 1771c3ddb60eSPeter Grehan /* [1C] */ INVALID, INVALID, INVALID, TS("nop",Mw), 17720339a1c2SMark Johnston }, { 17730339a1c2SMark Johnston /* [20] */ TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG), 17740339a1c2SMark Johnston /* [24] */ TSx("mov",SREG), INVALID, TSx("mov",SREG), INVALID, 17750339a1c2SMark Johnston /* [28] */ TNSZ("movaps",XMMO,16), TNSZ("movaps",XMMOS,16),TNSZ("cvtpi2ps",XMMOMX,8),TNSZ("movntps",XMMOS,16), 17760339a1c2SMark Johnston /* [2C] */ TNSZ("cvttps2pi",XMMOXMM,8),TNSZ("cvtps2pi",XMMOXMM,8),TNSZ("ucomiss",XMMO,4),TNSZ("comiss",XMMO,4), 17770339a1c2SMark Johnston }, { 17780339a1c2SMark Johnston /* [30] */ TNS("wrmsr",NORM), TNS("rdtsc",NORM), TNS("rdmsr",NORM), TNS("rdpmc",NORM), 17790339a1c2SMark Johnston /* [34] */ TNSx("sysenter",NORM), TNSx("sysexit",NORM), INVALID, INVALID, 17800339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 17810339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 17820339a1c2SMark Johnston }, { 17830339a1c2SMark Johnston /* [40] */ TS("cmovx.o",MR), TS("cmovx.no",MR), TS("cmovx.b",MR), TS("cmovx.ae",MR), 17840339a1c2SMark Johnston /* [44] */ TS("cmovx.e",MR), TS("cmovx.ne",MR), TS("cmovx.be",MR), TS("cmovx.a",MR), 17850339a1c2SMark Johnston /* [48] */ TS("cmovx.s",MR), TS("cmovx.ns",MR), TS("cmovx.pe",MR), TS("cmovx.po",MR), 17860339a1c2SMark Johnston /* [4C] */ TS("cmovx.l",MR), TS("cmovx.ge",MR), TS("cmovx.le",MR), TS("cmovx.g",MR), 17870339a1c2SMark Johnston }, { 17880339a1c2SMark Johnston /* [50] */ TNS("movmskps",XMMOX3), TNSZ("sqrtps",XMMO,16), TNSZ("rsqrtps",XMMO,16),TNSZ("rcpps",XMMO,16), 17890339a1c2SMark Johnston /* [54] */ TNSZ("andps",XMMO,16), TNSZ("andnps",XMMO,16), TNSZ("orps",XMMO,16), TNSZ("xorps",XMMO,16), 17900339a1c2SMark Johnston /* [58] */ TNSZ("addps",XMMO,16), TNSZ("mulps",XMMO,16), TNSZ("cvtps2pd",XMMO,8),TNSZ("cvtdq2ps",XMMO,16), 17910339a1c2SMark Johnston /* [5C] */ TNSZ("subps",XMMO,16), TNSZ("minps",XMMO,16), TNSZ("divps",XMMO,16), TNSZ("maxps",XMMO,16), 17920339a1c2SMark Johnston }, { 17930339a1c2SMark Johnston /* [60] */ TNSZ("punpcklbw",MMO,4),TNSZ("punpcklwd",MMO,4),TNSZ("punpckldq",MMO,4),TNSZ("packsswb",MMO,8), 17940339a1c2SMark Johnston /* [64] */ TNSZ("pcmpgtb",MMO,8), TNSZ("pcmpgtw",MMO,8), TNSZ("pcmpgtd",MMO,8), TNSZ("packuswb",MMO,8), 17950339a1c2SMark Johnston /* [68] */ TNSZ("punpckhbw",MMO,8),TNSZ("punpckhwd",MMO,8),TNSZ("punpckhdq",MMO,8),TNSZ("packssdw",MMO,8), 17960339a1c2SMark Johnston /* [6C] */ TNSZ("INVALID",MMO,0), TNSZ("INVALID",MMO,0), TNSZ("movd",MMO,4), TNSZ("movq",MMO,8), 17970339a1c2SMark Johnston }, { 17980339a1c2SMark Johnston /* [70] */ TNSZ("pshufw",MMOPM,8), TNS("psrXXX",MR), TNS("psrXXX",MR), TNS("psrXXX",MR), 17990339a1c2SMark Johnston /* [74] */ TNSZ("pcmpeqb",MMO,8), TNSZ("pcmpeqw",MMO,8), TNSZ("pcmpeqd",MMO,8), TNS("emms",NORM), 1800c3ddb60eSPeter Grehan /* [78] */ TNSy("vmread",RM), TNSy("vmwrite",MR), INVALID, INVALID, 18010339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, TNSZ("movd",MMOS,4), TNSZ("movq",MMOS,8), 18020339a1c2SMark Johnston }, { 18030339a1c2SMark Johnston /* [80] */ TNS("jo",D), TNS("jno",D), TNS("jb",D), TNS("jae",D), 18040339a1c2SMark Johnston /* [84] */ TNS("je",D), TNS("jne",D), TNS("jbe",D), TNS("ja",D), 18050339a1c2SMark Johnston /* [88] */ TNS("js",D), TNS("jns",D), TNS("jp",D), TNS("jnp",D), 18060339a1c2SMark Johnston /* [8C] */ TNS("jl",D), TNS("jge",D), TNS("jle",D), TNS("jg",D), 18070339a1c2SMark Johnston }, { 18080339a1c2SMark Johnston /* [90] */ TNS("seto",Mb), TNS("setno",Mb), TNS("setb",Mb), TNS("setae",Mb), 18090339a1c2SMark Johnston /* [94] */ TNS("sete",Mb), TNS("setne",Mb), TNS("setbe",Mb), TNS("seta",Mb), 18100339a1c2SMark Johnston /* [98] */ TNS("sets",Mb), TNS("setns",Mb), TNS("setp",Mb), TNS("setnp",Mb), 18110339a1c2SMark Johnston /* [9C] */ TNS("setl",Mb), TNS("setge",Mb), TNS("setle",Mb), TNS("setg",Mb), 18120339a1c2SMark Johnston }, { 18130339a1c2SMark Johnston /* [A0] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("cpuid",NORM), TS("bt",RMw), 18140339a1c2SMark Johnston /* [A4] */ TS("shld",DSHIFT), TS("shld",DSHIFTcl), INVALID, INVALID, 18150339a1c2SMark Johnston /* [A8] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("rsm",NORM), TS("bts",RMw), 18160339a1c2SMark Johnston /* [AC] */ TS("shrd",DSHIFT), TS("shrd",DSHIFTcl), IND(dis_op0FAE), TS("imul",MRw), 18170339a1c2SMark Johnston }, { 18180339a1c2SMark Johnston /* [B0] */ TNS("cmpxchgb",RMw), TS("cmpxchg",RMw), TS("lss",MR), TS("btr",RMw), 18190339a1c2SMark Johnston /* [B4] */ TS("lfs",MR), TS("lgs",MR), TS("movzb",MOVZ), TNS("movzwl",MOVZ), 18200339a1c2SMark Johnston /* [B8] */ TNS("INVALID",MRw), INVALID, IND(dis_op0FBA), TS("btc",RMw), 18210339a1c2SMark Johnston /* [BC] */ TS("bsf",MRw), TS("bsr",MRw), TS("movsb",MOVZ), TNS("movswl",MOVZ), 18220339a1c2SMark Johnston }, { 18230339a1c2SMark Johnston /* [C0] */ TNS("xaddb",XADDB), TS("xadd",RMw), TNSZ("cmpps",XMMOPM,16),TNS("movnti",RM), 18240339a1c2SMark Johnston /* [C4] */ TNSZ("pinsrw",MMOPRM,2),TNS("pextrw",MMO3P), TNSZ("shufps",XMMOPM,16),IND(dis_op0FC7), 18250339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 18260339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 18270339a1c2SMark Johnston }, { 18280339a1c2SMark Johnston /* [D0] */ INVALID, TNSZ("psrlw",MMO,8), TNSZ("psrld",MMO,8), TNSZ("psrlq",MMO,8), 18290339a1c2SMark Johnston /* [D4] */ TNSZ("paddq",MMO,8), TNSZ("pmullw",MMO,8), TNSZ("INVALID",MMO,0), TNS("pmovmskb",MMOM3), 18300339a1c2SMark Johnston /* [D8] */ TNSZ("psubusb",MMO,8), TNSZ("psubusw",MMO,8), TNSZ("pminub",MMO,8), TNSZ("pand",MMO,8), 18310339a1c2SMark Johnston /* [DC] */ TNSZ("paddusb",MMO,8), TNSZ("paddusw",MMO,8), TNSZ("pmaxub",MMO,8), TNSZ("pandn",MMO,8), 18320339a1c2SMark Johnston }, { 18330339a1c2SMark Johnston /* [E0] */ TNSZ("pavgb",MMO,8), TNSZ("psraw",MMO,8), TNSZ("psrad",MMO,8), TNSZ("pavgw",MMO,8), 18340339a1c2SMark Johnston /* [E4] */ TNSZ("pmulhuw",MMO,8), TNSZ("pmulhw",MMO,8), TNS("INVALID",XMMO), TNSZ("movntq",MMOMS,8), 18350339a1c2SMark Johnston /* [E8] */ TNSZ("psubsb",MMO,8), TNSZ("psubsw",MMO,8), TNSZ("pminsw",MMO,8), TNSZ("por",MMO,8), 18360339a1c2SMark Johnston /* [EC] */ TNSZ("paddsb",MMO,8), TNSZ("paddsw",MMO,8), TNSZ("pmaxsw",MMO,8), TNSZ("pxor",MMO,8), 18370339a1c2SMark Johnston }, { 18380339a1c2SMark Johnston /* [F0] */ INVALID, TNSZ("psllw",MMO,8), TNSZ("pslld",MMO,8), TNSZ("psllq",MMO,8), 18390339a1c2SMark Johnston /* [F4] */ TNSZ("pmuludq",MMO,8), TNSZ("pmaddwd",MMO,8), TNSZ("psadbw",MMO,8), TNSZ("maskmovq",MMOIMPL,8), 18400339a1c2SMark Johnston /* [F8] */ TNSZ("psubb",MMO,8), TNSZ("psubw",MMO,8), TNSZ("psubd",MMO,8), TNSZ("psubq",MMO,8), 18410339a1c2SMark Johnston /* [FC] */ TNSZ("paddb",MMO,8), TNSZ("paddw",MMO,8), TNSZ("paddd",MMO,8), INVALID, 18420339a1c2SMark Johnston } }; 18430339a1c2SMark Johnston 18440339a1c2SMark Johnston const instable_t dis_opAVX0F[16][16] = { 18450339a1c2SMark Johnston { 18460339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 18470339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 18480339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 18490339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 18500339a1c2SMark Johnston }, { 18510339a1c2SMark Johnston /* [10] */ TNSZ("vmovups",VEX_MX,16), TNSZ("vmovups",VEX_RM,16),TNSZ("vmovlps",VEX_RMrX,8), TNSZ("vmovlps",VEX_RM,8), 18520339a1c2SMark Johnston /* [14] */ TNSZ("vunpcklps",VEX_RMrX,16),TNSZ("vunpckhps",VEX_RMrX,16),TNSZ("vmovhps",VEX_RMrX,8),TNSZ("vmovhps",VEX_RM,8), 18530339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 18540339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 18550339a1c2SMark Johnston }, { 18560339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 18570339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 18580339a1c2SMark Johnston /* [28] */ TNSZ("vmovaps",VEX_MX,16), TNSZ("vmovaps",VEX_RX,16),INVALID, TNSZ("vmovntps",VEX_RM,16), 18590339a1c2SMark Johnston /* [2C] */ INVALID, INVALID, TNSZ("vucomiss",VEX_MX,4),TNSZ("vcomiss",VEX_MX,4), 18600339a1c2SMark Johnston }, { 18610339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 18620339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 18630339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 18640339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 18650339a1c2SMark Johnston }, { 18660339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 18670339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 18680339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 18690339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 18700339a1c2SMark Johnston }, { 18710339a1c2SMark Johnston /* [50] */ TNS("vmovmskps",VEX_MR), TNSZ("vsqrtps",VEX_MX,16), TNSZ("vrsqrtps",VEX_MX,16),TNSZ("vrcpps",VEX_MX,16), 18720339a1c2SMark Johnston /* [54] */ TNSZ("vandps",VEX_RMrX,16), TNSZ("vandnps",VEX_RMrX,16), TNSZ("vorps",VEX_RMrX,16), TNSZ("vxorps",VEX_RMrX,16), 18730339a1c2SMark Johnston /* [58] */ TNSZ("vaddps",VEX_RMrX,16), TNSZ("vmulps",VEX_RMrX,16), TNSZ("vcvtps2pd",VEX_MX,8),TNSZ("vcvtdq2ps",VEX_MX,16), 18740339a1c2SMark Johnston /* [5C] */ TNSZ("vsubps",VEX_RMrX,16), TNSZ("vminps",VEX_RMrX,16), TNSZ("vdivps",VEX_RMrX,16), TNSZ("vmaxps",VEX_RMrX,16), 18750339a1c2SMark Johnston }, { 18760339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 18770339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 18780339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 18790339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 18800339a1c2SMark Johnston }, { 18810339a1c2SMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 18820339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, TNS("vzeroupper", VEX_NONE), 18830339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 18840339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 18850339a1c2SMark Johnston }, { 18860339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 18870339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 18880339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 18890339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 18900339a1c2SMark Johnston }, { 18910339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 18920339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 18930339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 18940339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 18950339a1c2SMark Johnston }, { 18960339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 18970339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 18980339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 18990339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, TNSZ("vldmxcsr",VEX_MO,2), INVALID, 19000339a1c2SMark Johnston }, { 19010339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 19020339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 19030339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 19040339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 19050339a1c2SMark Johnston }, { 19060339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("vcmpps",VEX_RMRX,16),INVALID, 19070339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, TNSZ("vshufps",VEX_RMRX,16),INVALID, 19080339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 19090339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 19100339a1c2SMark Johnston }, { 19110339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 19120339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 19130339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 19140339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 19150339a1c2SMark Johnston }, { 19160339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 19170339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 19180339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 19190339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 19200339a1c2SMark Johnston }, { 1921*b3b5bfebSMark Johnston /* [F0] */ INVALID, INVALID, TNSZvr("andn",VEX_RMrX,5),TNSZvr("bls",BLS,5), 1922*b3b5bfebSMark Johnston /* [F4] */ INVALID, TNSZvr("bzhi",VEX_VRMrX,5),INVALID, TNSZvr("bextr",VEX_VRMrX,5), 19230339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 19240339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 19250339a1c2SMark Johnston } }; 19260339a1c2SMark Johnston 19270339a1c2SMark Johnston /* 19280339a1c2SMark Johnston * Decode table for 0x80 opcodes 19290339a1c2SMark Johnston */ 19300339a1c2SMark Johnston 19310339a1c2SMark Johnston const instable_t dis_op80[8] = { 19320339a1c2SMark Johnston 19330339a1c2SMark Johnston /* [0] */ TNS("addb",IMlw), TNS("orb",IMw), TNS("adcb",IMlw), TNS("sbbb",IMlw), 19340339a1c2SMark Johnston /* [4] */ TNS("andb",IMw), TNS("subb",IMlw), TNS("xorb",IMw), TNS("cmpb",IMlw), 19350339a1c2SMark Johnston }; 19360339a1c2SMark Johnston 19370339a1c2SMark Johnston 19380339a1c2SMark Johnston /* 19390339a1c2SMark Johnston * Decode table for 0x81 opcodes. 19400339a1c2SMark Johnston */ 19410339a1c2SMark Johnston 19420339a1c2SMark Johnston const instable_t dis_op81[8] = { 19430339a1c2SMark Johnston 19440339a1c2SMark Johnston /* [0] */ TS("add",IMlw), TS("or",IMw), TS("adc",IMlw), TS("sbb",IMlw), 19450339a1c2SMark Johnston /* [4] */ TS("and",IMw), TS("sub",IMlw), TS("xor",IMw), TS("cmp",IMlw), 19460339a1c2SMark Johnston }; 19470339a1c2SMark Johnston 19480339a1c2SMark Johnston 19490339a1c2SMark Johnston /* 19500339a1c2SMark Johnston * Decode table for 0x82 opcodes. 19510339a1c2SMark Johnston */ 19520339a1c2SMark Johnston 19530339a1c2SMark Johnston const instable_t dis_op82[8] = { 19540339a1c2SMark Johnston 19550339a1c2SMark Johnston /* [0] */ TNSx("addb",IMlw), TNSx("orb",IMlw), TNSx("adcb",IMlw), TNSx("sbbb",IMlw), 19560339a1c2SMark Johnston /* [4] */ TNSx("andb",IMlw), TNSx("subb",IMlw), TNSx("xorb",IMlw), TNSx("cmpb",IMlw), 19570339a1c2SMark Johnston }; 19580339a1c2SMark Johnston /* 19590339a1c2SMark Johnston * Decode table for 0x83 opcodes. 19600339a1c2SMark Johnston */ 19610339a1c2SMark Johnston 19620339a1c2SMark Johnston const instable_t dis_op83[8] = { 19630339a1c2SMark Johnston 19640339a1c2SMark Johnston /* [0] */ TS("add",IMlw), TS("or",IMlw), TS("adc",IMlw), TS("sbb",IMlw), 19650339a1c2SMark Johnston /* [4] */ TS("and",IMlw), TS("sub",IMlw), TS("xor",IMlw), TS("cmp",IMlw), 19660339a1c2SMark Johnston }; 19670339a1c2SMark Johnston 19680339a1c2SMark Johnston /* 19690339a1c2SMark Johnston * Decode table for 0xC0 opcodes. 19700339a1c2SMark Johnston */ 19710339a1c2SMark Johnston 19720339a1c2SMark Johnston const instable_t dis_opC0[8] = { 19730339a1c2SMark Johnston 19740339a1c2SMark Johnston /* [0] */ TNS("rolb",MvI), TNS("rorb",MvI), TNS("rclb",MvI), TNS("rcrb",MvI), 19750339a1c2SMark Johnston /* [4] */ TNS("shlb",MvI), TNS("shrb",MvI), INVALID, TNS("sarb",MvI), 19760339a1c2SMark Johnston }; 19770339a1c2SMark Johnston 19780339a1c2SMark Johnston /* 19790339a1c2SMark Johnston * Decode table for 0xD0 opcodes. 19800339a1c2SMark Johnston */ 19810339a1c2SMark Johnston 19820339a1c2SMark Johnston const instable_t dis_opD0[8] = { 19830339a1c2SMark Johnston 19840339a1c2SMark Johnston /* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv), 19850339a1c2SMark Johnston /* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv), 19860339a1c2SMark Johnston }; 19870339a1c2SMark Johnston 19880339a1c2SMark Johnston /* 19890339a1c2SMark Johnston * Decode table for 0xC1 opcodes. 19900339a1c2SMark Johnston * 186 instruction set 19910339a1c2SMark Johnston */ 19920339a1c2SMark Johnston 19930339a1c2SMark Johnston const instable_t dis_opC1[8] = { 19940339a1c2SMark Johnston 19950339a1c2SMark Johnston /* [0] */ TS("rol",MvI), TS("ror",MvI), TS("rcl",MvI), TS("rcr",MvI), 19960339a1c2SMark Johnston /* [4] */ TS("shl",MvI), TS("shr",MvI), TS("sal",MvI), TS("sar",MvI), 19970339a1c2SMark Johnston }; 19980339a1c2SMark Johnston 19990339a1c2SMark Johnston /* 20000339a1c2SMark Johnston * Decode table for 0xD1 opcodes. 20010339a1c2SMark Johnston */ 20020339a1c2SMark Johnston 20030339a1c2SMark Johnston const instable_t dis_opD1[8] = { 20040339a1c2SMark Johnston 20050339a1c2SMark Johnston /* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv), 20060339a1c2SMark Johnston /* [4] */ TS("shl",Mv), TS("shr",Mv), TS("sal",Mv), TS("sar",Mv), 20070339a1c2SMark Johnston }; 20080339a1c2SMark Johnston 20090339a1c2SMark Johnston 20100339a1c2SMark Johnston /* 20110339a1c2SMark Johnston * Decode table for 0xD2 opcodes. 20120339a1c2SMark Johnston */ 20130339a1c2SMark Johnston 20140339a1c2SMark Johnston const instable_t dis_opD2[8] = { 20150339a1c2SMark Johnston 20160339a1c2SMark Johnston /* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv), 20170339a1c2SMark Johnston /* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv), 20180339a1c2SMark Johnston }; 20190339a1c2SMark Johnston /* 20200339a1c2SMark Johnston * Decode table for 0xD3 opcodes. 20210339a1c2SMark Johnston */ 20220339a1c2SMark Johnston 20230339a1c2SMark Johnston const instable_t dis_opD3[8] = { 20240339a1c2SMark Johnston 20250339a1c2SMark Johnston /* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv), 20260339a1c2SMark Johnston /* [4] */ TS("shl",Mv), TS("shr",Mv), TS("salb",Mv), TS("sar",Mv), 20270339a1c2SMark Johnston }; 20280339a1c2SMark Johnston 20290339a1c2SMark Johnston 20300339a1c2SMark Johnston /* 20310339a1c2SMark Johnston * Decode table for 0xF6 opcodes. 20320339a1c2SMark Johnston */ 20330339a1c2SMark Johnston 20340339a1c2SMark Johnston const instable_t dis_opF6[8] = { 20350339a1c2SMark Johnston 20360339a1c2SMark Johnston /* [0] */ TNS("testb",IMw), TNS("testb",IMw), TNS("notb",Mw), TNS("negb",Mw), 20370339a1c2SMark Johnston /* [4] */ TNS("mulb",MA), TNS("imulb",MA), TNS("divb",MA), TNS("idivb",MA), 20380339a1c2SMark Johnston }; 20390339a1c2SMark Johnston 20400339a1c2SMark Johnston 20410339a1c2SMark Johnston /* 20420339a1c2SMark Johnston * Decode table for 0xF7 opcodes. 20430339a1c2SMark Johnston */ 20440339a1c2SMark Johnston 20450339a1c2SMark Johnston const instable_t dis_opF7[8] = { 20460339a1c2SMark Johnston 20470339a1c2SMark Johnston /* [0] */ TS("test",IMw), TS("test",IMw), TS("not",Mw), TS("neg",Mw), 20480339a1c2SMark Johnston /* [4] */ TS("mul",MA), TS("imul",MA), TS("div",MA), TS("idiv",MA), 20490339a1c2SMark Johnston }; 20500339a1c2SMark Johnston 20510339a1c2SMark Johnston 20520339a1c2SMark Johnston /* 20530339a1c2SMark Johnston * Decode table for 0xFE opcodes. 20540339a1c2SMark Johnston */ 20550339a1c2SMark Johnston 20560339a1c2SMark Johnston const instable_t dis_opFE[8] = { 20570339a1c2SMark Johnston 20580339a1c2SMark Johnston /* [0] */ TNS("incb",Mw), TNS("decb",Mw), INVALID, INVALID, 20590339a1c2SMark Johnston /* [4] */ INVALID, INVALID, INVALID, INVALID, 20600339a1c2SMark Johnston }; 20610339a1c2SMark Johnston /* 20620339a1c2SMark Johnston * Decode table for 0xFF opcodes. 20630339a1c2SMark Johnston */ 20640339a1c2SMark Johnston 20650339a1c2SMark Johnston const instable_t dis_opFF[8] = { 20660339a1c2SMark Johnston 20670339a1c2SMark Johnston /* [0] */ TS("inc",Mw), TS("dec",Mw), TNSyp("call",INM), TNS("lcall",INM), 20680339a1c2SMark Johnston /* [4] */ TNSy("jmp",INM), TNS("ljmp",INM), TSp("push",M), INVALID, 20690339a1c2SMark Johnston }; 20700339a1c2SMark Johnston 20710339a1c2SMark Johnston /* for 287 instructions, which are a mess to decode */ 20720339a1c2SMark Johnston 20730339a1c2SMark Johnston const instable_t dis_opFP1n2[8][8] = { 20740339a1c2SMark Johnston { 20750339a1c2SMark Johnston /* bit pattern: 1101 1xxx MODxx xR/M */ 20760339a1c2SMark Johnston /* [0,0] */ TNS("fadds",M), TNS("fmuls",M), TNS("fcoms",M), TNS("fcomps",M), 20770339a1c2SMark Johnston /* [0,4] */ TNS("fsubs",M), TNS("fsubrs",M), TNS("fdivs",M), TNS("fdivrs",M), 20780339a1c2SMark Johnston }, { 20790339a1c2SMark Johnston /* [1,0] */ TNS("flds",M), INVALID, TNS("fsts",M), TNS("fstps",M), 20800339a1c2SMark Johnston /* [1,4] */ TNSZ("fldenv",M,28), TNSZ("fldcw",M,2), TNSZ("fnstenv",M,28), TNSZ("fnstcw",M,2), 20810339a1c2SMark Johnston }, { 20820339a1c2SMark Johnston /* [2,0] */ TNS("fiaddl",M), TNS("fimull",M), TNS("ficoml",M), TNS("ficompl",M), 20830339a1c2SMark Johnston /* [2,4] */ TNS("fisubl",M), TNS("fisubrl",M), TNS("fidivl",M), TNS("fidivrl",M), 20840339a1c2SMark Johnston }, { 2085*b3b5bfebSMark Johnston /* [3,0] */ TNS("fildl",M), TNSZ("tisttpl",M,4), TNS("fistl",M), TNS("fistpl",M), 20860339a1c2SMark Johnston /* [3,4] */ INVALID, TNSZ("fldt",M,10), INVALID, TNSZ("fstpt",M,10), 20870339a1c2SMark Johnston }, { 20880339a1c2SMark Johnston /* [4,0] */ TNSZ("faddl",M,8), TNSZ("fmull",M,8), TNSZ("fcoml",M,8), TNSZ("fcompl",M,8), 20890339a1c2SMark Johnston /* [4,1] */ TNSZ("fsubl",M,8), TNSZ("fsubrl",M,8), TNSZ("fdivl",M,8), TNSZ("fdivrl",M,8), 20900339a1c2SMark Johnston }, { 2091*b3b5bfebSMark Johnston /* [5,0] */ TNSZ("fldl",M,8), TNSZ("fisttpll",M,8), TNSZ("fstl",M,8), TNSZ("fstpl",M,8), 20920339a1c2SMark Johnston /* [5,4] */ TNSZ("frstor",M,108), INVALID, TNSZ("fnsave",M,108), TNSZ("fnstsw",M,2), 20930339a1c2SMark Johnston }, { 20940339a1c2SMark Johnston /* [6,0] */ TNSZ("fiadd",M,2), TNSZ("fimul",M,2), TNSZ("ficom",M,2), TNSZ("ficomp",M,2), 20950339a1c2SMark Johnston /* [6,4] */ TNSZ("fisub",M,2), TNSZ("fisubr",M,2), TNSZ("fidiv",M,2), TNSZ("fidivr",M,2), 20960339a1c2SMark Johnston }, { 2097*b3b5bfebSMark Johnston /* [7,0] */ TNSZ("fild",M,2), TNSZ("fisttp",M,2), TNSZ("fist",M,2), TNSZ("fistp",M,2), 20980339a1c2SMark Johnston /* [7,4] */ TNSZ("fbld",M,10), TNSZ("fildll",M,8), TNSZ("fbstp",M,10), TNSZ("fistpll",M,8), 20990339a1c2SMark Johnston } }; 21000339a1c2SMark Johnston 21010339a1c2SMark Johnston const instable_t dis_opFP3[8][8] = { 21020339a1c2SMark Johnston { 21030339a1c2SMark Johnston /* bit pattern: 1101 1xxx 11xx xREG */ 21040339a1c2SMark Johnston /* [0,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F), 21050339a1c2SMark Johnston /* [0,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF), 21060339a1c2SMark Johnston }, { 21070339a1c2SMark Johnston /* [1,0] */ TNS("fld",F), TNS("fxch",F), TNS("fnop",NORM), TNS("fstp",F), 21080339a1c2SMark Johnston /* [1,4] */ INVALID, INVALID, INVALID, INVALID, 21090339a1c2SMark Johnston }, { 21100339a1c2SMark Johnston /* [2,0] */ INVALID, INVALID, INVALID, INVALID, 21110339a1c2SMark Johnston /* [2,4] */ INVALID, TNS("fucompp",NORM), INVALID, INVALID, 21120339a1c2SMark Johnston }, { 21130339a1c2SMark Johnston /* [3,0] */ INVALID, INVALID, INVALID, INVALID, 21140339a1c2SMark Johnston /* [3,4] */ INVALID, INVALID, INVALID, INVALID, 21150339a1c2SMark Johnston }, { 21160339a1c2SMark Johnston /* [4,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F), 21170339a1c2SMark Johnston /* [4,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF), 21180339a1c2SMark Johnston }, { 21190339a1c2SMark Johnston /* [5,0] */ TNS("ffree",F), TNS("fxch",F), TNS("fst",F), TNS("fstp",F), 21200339a1c2SMark Johnston /* [5,4] */ TNS("fucom",F), TNS("fucomp",F), INVALID, INVALID, 21210339a1c2SMark Johnston }, { 21220339a1c2SMark Johnston /* [6,0] */ TNS("faddp",FF), TNS("fmulp",FF), TNS("fcomp",F), TNS("fcompp",NORM), 21230339a1c2SMark Johnston /* [6,4] */ TNS("fsubp",FF), TNS("fsubrp",FF), TNS("fdivp",FF), TNS("fdivrp",FF), 21240339a1c2SMark Johnston }, { 21250339a1c2SMark Johnston /* [7,0] */ TNS("ffreep",F), TNS("fxch",F), TNS("fstp",F), TNS("fstp",F), 21260339a1c2SMark Johnston /* [7,4] */ TNS("fnstsw",M), TNS("fucomip",FFC), TNS("fcomip",FFC), INVALID, 21270339a1c2SMark Johnston } }; 21280339a1c2SMark Johnston 21290339a1c2SMark Johnston const instable_t dis_opFP4[4][8] = { 21300339a1c2SMark Johnston { 21310339a1c2SMark Johnston /* bit pattern: 1101 1001 111x xxxx */ 21320339a1c2SMark Johnston /* [0,0] */ TNS("fchs",NORM), TNS("fabs",NORM), INVALID, INVALID, 21330339a1c2SMark Johnston /* [0,4] */ TNS("ftst",NORM), TNS("fxam",NORM), TNS("ftstp",NORM), INVALID, 21340339a1c2SMark Johnston }, { 21350339a1c2SMark Johnston /* [1,0] */ TNS("fld1",NORM), TNS("fldl2t",NORM), TNS("fldl2e",NORM), TNS("fldpi",NORM), 21360339a1c2SMark Johnston /* [1,4] */ TNS("fldlg2",NORM), TNS("fldln2",NORM), TNS("fldz",NORM), INVALID, 21370339a1c2SMark Johnston }, { 21380339a1c2SMark Johnston /* [2,0] */ TNS("f2xm1",NORM), TNS("fyl2x",NORM), TNS("fptan",NORM), TNS("fpatan",NORM), 21390339a1c2SMark Johnston /* [2,4] */ TNS("fxtract",NORM), TNS("fprem1",NORM), TNS("fdecstp",NORM), TNS("fincstp",NORM), 21400339a1c2SMark Johnston }, { 21410339a1c2SMark Johnston /* [3,0] */ TNS("fprem",NORM), TNS("fyl2xp1",NORM), TNS("fsqrt",NORM), TNS("fsincos",NORM), 21420339a1c2SMark Johnston /* [3,4] */ TNS("frndint",NORM), TNS("fscale",NORM), TNS("fsin",NORM), TNS("fcos",NORM), 21430339a1c2SMark Johnston } }; 21440339a1c2SMark Johnston 21450339a1c2SMark Johnston const instable_t dis_opFP5[8] = { 21460339a1c2SMark Johnston /* bit pattern: 1101 1011 111x xxxx */ 21470339a1c2SMark Johnston /* [0] */ TNS("feni",NORM), TNS("fdisi",NORM), TNS("fnclex",NORM), TNS("fninit",NORM), 21480339a1c2SMark Johnston /* [4] */ TNS("fsetpm",NORM), TNS("frstpm",NORM), INVALID, INVALID, 21490339a1c2SMark Johnston }; 21500339a1c2SMark Johnston 21510339a1c2SMark Johnston const instable_t dis_opFP6[8] = { 21520339a1c2SMark Johnston /* bit pattern: 1101 1011 11yy yxxx */ 21530339a1c2SMark Johnston /* [00] */ TNS("fcmov.nb",FF), TNS("fcmov.ne",FF), TNS("fcmov.nbe",FF), TNS("fcmov.nu",FF), 21540339a1c2SMark Johnston /* [04] */ INVALID, TNS("fucomi",F), TNS("fcomi",F), INVALID, 21550339a1c2SMark Johnston }; 21560339a1c2SMark Johnston 21570339a1c2SMark Johnston const instable_t dis_opFP7[8] = { 21580339a1c2SMark Johnston /* bit pattern: 1101 1010 11yy yxxx */ 21590339a1c2SMark Johnston /* [00] */ TNS("fcmov.b",FF), TNS("fcmov.e",FF), TNS("fcmov.be",FF), TNS("fcmov.u",FF), 21600339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 21610339a1c2SMark Johnston }; 21620339a1c2SMark Johnston 21630339a1c2SMark Johnston /* 21640339a1c2SMark Johnston * Main decode table for the op codes. The first two nibbles 21650339a1c2SMark Johnston * will be used as an index into the table. If there is a 21660339a1c2SMark Johnston * a need to further decode an instruction, the array to be 21670339a1c2SMark Johnston * referenced is indicated with the other two entries being 21680339a1c2SMark Johnston * empty. 21690339a1c2SMark Johnston */ 21700339a1c2SMark Johnston 21710339a1c2SMark Johnston const instable_t dis_distable[16][16] = { 21720339a1c2SMark Johnston { 21730339a1c2SMark Johnston /* [0,0] */ TNS("addb",RMw), TS("add",RMw), TNS("addb",MRw), TS("add",MRw), 21740339a1c2SMark Johnston /* [0,4] */ TNS("addb",IA), TS("add",IA), TSx("push",SEG), TSx("pop",SEG), 21750339a1c2SMark Johnston /* [0,8] */ TNS("orb",RMw), TS("or",RMw), TNS("orb",MRw), TS("or",MRw), 21760339a1c2SMark Johnston /* [0,C] */ TNS("orb",IA), TS("or",IA), TSx("push",SEG), IND(dis_op0F), 21770339a1c2SMark Johnston }, { 21780339a1c2SMark Johnston /* [1,0] */ TNS("adcb",RMw), TS("adc",RMw), TNS("adcb",MRw), TS("adc",MRw), 21790339a1c2SMark Johnston /* [1,4] */ TNS("adcb",IA), TS("adc",IA), TSx("push",SEG), TSx("pop",SEG), 21800339a1c2SMark Johnston /* [1,8] */ TNS("sbbb",RMw), TS("sbb",RMw), TNS("sbbb",MRw), TS("sbb",MRw), 21810339a1c2SMark Johnston /* [1,C] */ TNS("sbbb",IA), TS("sbb",IA), TSx("push",SEG), TSx("pop",SEG), 21820339a1c2SMark Johnston }, { 21830339a1c2SMark Johnston /* [2,0] */ TNS("andb",RMw), TS("and",RMw), TNS("andb",MRw), TS("and",MRw), 2184c3ddb60eSPeter Grehan /* [2,4] */ TNS("andb",IA), TS("and",IA), TNSx("%es:",OVERRIDE), TNSx("daa",NORM), 21850339a1c2SMark Johnston /* [2,8] */ TNS("subb",RMw), TS("sub",RMw), TNS("subb",MRw), TS("sub",MRw), 21860339a1c2SMark Johnston /* [2,C] */ TNS("subb",IA), TS("sub",IA), TNS("%cs:",OVERRIDE), TNSx("das",NORM), 21870339a1c2SMark Johnston }, { 21880339a1c2SMark Johnston /* [3,0] */ TNS("xorb",RMw), TS("xor",RMw), TNS("xorb",MRw), TS("xor",MRw), 2189c3ddb60eSPeter Grehan /* [3,4] */ TNS("xorb",IA), TS("xor",IA), TNSx("%ss:",OVERRIDE), TNSx("aaa",NORM), 21900339a1c2SMark Johnston /* [3,8] */ TNS("cmpb",RMw), TS("cmp",RMw), TNS("cmpb",MRw), TS("cmp",MRw), 2191c3ddb60eSPeter Grehan /* [3,C] */ TNS("cmpb",IA), TS("cmp",IA), TNSx("%ds:",OVERRIDE), TNSx("aas",NORM), 21920339a1c2SMark Johnston }, { 21930339a1c2SMark Johnston /* [4,0] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R), 21940339a1c2SMark Johnston /* [4,4] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R), 21950339a1c2SMark Johnston /* [4,8] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R), 21960339a1c2SMark Johnston /* [4,C] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R), 21970339a1c2SMark Johnston }, { 21980339a1c2SMark Johnston /* [5,0] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R), 21990339a1c2SMark Johnston /* [5,4] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R), 22000339a1c2SMark Johnston /* [5,8] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R), 22010339a1c2SMark Johnston /* [5,C] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R), 22020339a1c2SMark Johnston }, { 22030339a1c2SMark Johnston /* [6,0] */ TSZx("pusha",IMPLMEM,28),TSZx("popa",IMPLMEM,28), TSx("bound",MR), TNS("arpl",RMw), 22040339a1c2SMark Johnston /* [6,4] */ TNS("%fs:",OVERRIDE), TNS("%gs:",OVERRIDE), TNS("data16",DM), TNS("addr16",AM), 22050339a1c2SMark Johnston /* [6,8] */ TSp("push",I), TS("imul",IMUL), TSp("push",Ib), TS("imul",IMUL), 22060339a1c2SMark Johnston /* [6,C] */ TNSZ("insb",IMPLMEM,1), TSZ("ins",IMPLMEM,4), TNSZ("outsb",IMPLMEM,1),TSZ("outs",IMPLMEM,4), 22070339a1c2SMark Johnston }, { 22080339a1c2SMark Johnston /* [7,0] */ TNSy("jo",BD), TNSy("jno",BD), TNSy("jb",BD), TNSy("jae",BD), 22090339a1c2SMark Johnston /* [7,4] */ TNSy("je",BD), TNSy("jne",BD), TNSy("jbe",BD), TNSy("ja",BD), 22100339a1c2SMark Johnston /* [7,8] */ TNSy("js",BD), TNSy("jns",BD), TNSy("jp",BD), TNSy("jnp",BD), 22110339a1c2SMark Johnston /* [7,C] */ TNSy("jl",BD), TNSy("jge",BD), TNSy("jle",BD), TNSy("jg",BD), 22120339a1c2SMark Johnston }, { 22130339a1c2SMark Johnston /* [8,0] */ IND(dis_op80), IND(dis_op81), INDx(dis_op82), IND(dis_op83), 22140339a1c2SMark Johnston /* [8,4] */ TNS("testb",RMw), TS("test",RMw), TNS("xchgb",RMw), TS("xchg",RMw), 22150339a1c2SMark Johnston /* [8,8] */ TNS("movb",RMw), TS("mov",RMw), TNS("movb",MRw), TS("mov",MRw), 22160339a1c2SMark Johnston /* [8,C] */ TNS("movw",SM), TS("lea",MR), TNS("movw",MS), TSp("pop",M), 22170339a1c2SMark Johnston }, { 22180339a1c2SMark Johnston /* [9,0] */ TNS("nop",NORM), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), 22190339a1c2SMark Johnston /* [9,4] */ TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), 22200339a1c2SMark Johnston /* [9,8] */ TNS("cXtX",CBW), TNS("cXtX",CWD), TNSx("lcall",SO), TNS("fwait",NORM), 22212d69831bSAndriy Gapon /* [9,C] */ TSZy("pushf",IMPLMEM,4),TSZy("popf",IMPLMEM,4), TNS("sahf",NORM), TNS("lahf",NORM), 22220339a1c2SMark Johnston }, { 22230339a1c2SMark Johnston /* [A,0] */ TNS("movb",OA), TS("mov",OA), TNS("movb",AO), TS("mov",AO), 22240339a1c2SMark Johnston /* [A,4] */ TNSZ("movsb",SD,1), TS("movs",SD), TNSZ("cmpsb",SD,1), TS("cmps",SD), 22250339a1c2SMark Johnston /* [A,8] */ TNS("testb",IA), TS("test",IA), TNS("stosb",AD), TS("stos",AD), 22260339a1c2SMark Johnston /* [A,C] */ TNS("lodsb",SA), TS("lods",SA), TNS("scasb",AD), TS("scas",AD), 22270339a1c2SMark Johnston }, { 22280339a1c2SMark Johnston /* [B,0] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), 22290339a1c2SMark Johnston /* [B,4] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), 22300339a1c2SMark Johnston /* [B,8] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR), 22310339a1c2SMark Johnston /* [B,C] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR), 22320339a1c2SMark Johnston }, { 22330339a1c2SMark Johnston /* [C,0] */ IND(dis_opC0), IND(dis_opC1), TNSyp("ret",RET), TNSyp("ret",NORM), 22340339a1c2SMark Johnston /* [C,4] */ TNSx("les",MR), TNSx("lds",MR), TNS("movb",IMw), TS("mov",IMw), 22350339a1c2SMark Johnston /* [C,8] */ TNSyp("enter",ENTER), TNSyp("leave",NORM), TNS("lret",RET), TNS("lret",NORM), 22360339a1c2SMark Johnston /* [C,C] */ TNS("int",INT3), TNS("int",INTx), TNSx("into",NORM), TNS("iret",NORM), 22370339a1c2SMark Johnston }, { 22380339a1c2SMark Johnston /* [D,0] */ IND(dis_opD0), IND(dis_opD1), IND(dis_opD2), IND(dis_opD3), 22390339a1c2SMark Johnston /* [D,4] */ TNSx("aam",U), TNSx("aad",U), TNSx("falc",NORM), TNSZ("xlat",IMPLMEM,1), 22400339a1c2SMark Johnston 22410339a1c2SMark Johnston /* 287 instructions. Note that although the indirect field */ 22420339a1c2SMark Johnston /* indicates opFP1n2 for further decoding, this is not necessarily */ 22430339a1c2SMark Johnston /* the case since the opFP arrays are not partitioned according to key1 */ 22440339a1c2SMark Johnston /* and key2. opFP1n2 is given only to indicate that we haven't */ 22450339a1c2SMark Johnston /* finished decoding the instruction. */ 22460339a1c2SMark Johnston /* [D,8] */ IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), 22470339a1c2SMark Johnston /* [D,C] */ IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), 22480339a1c2SMark Johnston }, { 22490339a1c2SMark Johnston /* [E,0] */ TNSy("loopnz",BD), TNSy("loopz",BD), TNSy("loop",BD), TNSy("jcxz",BD), 22500339a1c2SMark Johnston /* [E,4] */ TNS("inb",P), TS("in",P), TNS("outb",P), TS("out",P), 22510339a1c2SMark Johnston /* [E,8] */ TNSyp("call",D), TNSy("jmp",D), TNSx("ljmp",SO), TNSy("jmp",BD), 22520339a1c2SMark Johnston /* [E,C] */ TNS("inb",V), TS("in",V), TNS("outb",V), TS("out",V), 22530339a1c2SMark Johnston }, { 22540339a1c2SMark Johnston /* [F,0] */ TNS("lock",LOCK), TNS("icebp", NORM), TNS("repnz",PREFIX), TNS("repz",PREFIX), 22550339a1c2SMark Johnston /* [F,4] */ TNS("hlt",NORM), TNS("cmc",NORM), IND(dis_opF6), IND(dis_opF7), 22560339a1c2SMark Johnston /* [F,8] */ TNS("clc",NORM), TNS("stc",NORM), TNS("cli",NORM), TNS("sti",NORM), 22570339a1c2SMark Johnston /* [F,C] */ TNS("cld",NORM), TNS("std",NORM), IND(dis_opFE), IND(dis_opFF), 22580339a1c2SMark Johnston } }; 22590339a1c2SMark Johnston 22600339a1c2SMark Johnston /* END CSTYLED */ 22610339a1c2SMark Johnston 22620339a1c2SMark Johnston /* 22630339a1c2SMark Johnston * common functions to decode and disassemble an x86 or amd64 instruction 22640339a1c2SMark Johnston */ 22650339a1c2SMark Johnston 22660339a1c2SMark Johnston /* 22670339a1c2SMark Johnston * These are the individual fields of a REX prefix. Note that a REX 22680339a1c2SMark Johnston * prefix with none of these set is still needed to: 22690339a1c2SMark Johnston * - use the MOVSXD (sign extend 32 to 64 bits) instruction 22700339a1c2SMark Johnston * - access the %sil, %dil, %bpl, %spl registers 22710339a1c2SMark Johnston */ 22720339a1c2SMark Johnston #define REX_W 0x08 /* 64 bit operand size when set */ 22730339a1c2SMark Johnston #define REX_R 0x04 /* high order bit extension of ModRM reg field */ 22740339a1c2SMark Johnston #define REX_X 0x02 /* high order bit extension of SIB index field */ 22750339a1c2SMark Johnston #define REX_B 0x01 /* extends ModRM r_m, SIB base, or opcode reg */ 22760339a1c2SMark Johnston 22770339a1c2SMark Johnston /* 22780339a1c2SMark Johnston * These are the individual fields of a VEX prefix. 22790339a1c2SMark Johnston */ 22800339a1c2SMark Johnston #define VEX_R 0x08 /* REX.R in 1's complement form */ 22810339a1c2SMark Johnston #define VEX_X 0x04 /* REX.X in 1's complement form */ 22820339a1c2SMark Johnston #define VEX_B 0x02 /* REX.B in 1's complement form */ 22830339a1c2SMark Johnston /* Vector Length, 0: scalar or 128-bit vector, 1: 256-bit vector */ 22840339a1c2SMark Johnston #define VEX_L 0x04 22850339a1c2SMark Johnston #define VEX_W 0x08 /* opcode specific, use like REX.W */ 22860339a1c2SMark Johnston #define VEX_m 0x1F /* VEX m-mmmm field */ 22870339a1c2SMark Johnston #define VEX_v 0x78 /* VEX register specifier */ 22880339a1c2SMark Johnston #define VEX_p 0x03 /* VEX pp field, opcode extension */ 22890339a1c2SMark Johnston 22900339a1c2SMark Johnston /* VEX m-mmmm field, only used by three bytes prefix */ 22910339a1c2SMark Johnston #define VEX_m_0F 0x01 /* implied 0F leading opcode byte */ 22920339a1c2SMark Johnston #define VEX_m_0F38 0x02 /* implied 0F 38 leading opcode byte */ 22930339a1c2SMark Johnston #define VEX_m_0F3A 0x03 /* implied 0F 3A leading opcode byte */ 22940339a1c2SMark Johnston 22950339a1c2SMark Johnston /* VEX pp field, providing equivalent functionality of a SIMD prefix */ 22960339a1c2SMark Johnston #define VEX_p_66 0x01 22970339a1c2SMark Johnston #define VEX_p_F3 0x02 22980339a1c2SMark Johnston #define VEX_p_F2 0x03 22990339a1c2SMark Johnston 23000339a1c2SMark Johnston /* 23010339a1c2SMark Johnston * Even in 64 bit mode, usually only 4 byte immediate operands are supported. 23020339a1c2SMark Johnston */ 23030339a1c2SMark Johnston static int isize[] = {1, 2, 4, 4}; 23040339a1c2SMark Johnston static int isize64[] = {1, 2, 4, 8}; 23050339a1c2SMark Johnston 23060339a1c2SMark Johnston /* 23070339a1c2SMark Johnston * Just a bunch of useful macros. 23080339a1c2SMark Johnston */ 23090339a1c2SMark Johnston #define WBIT(x) (x & 0x1) /* to get w bit */ 23100339a1c2SMark Johnston #define REGNO(x) (x & 0x7) /* to get 3 bit register */ 23110339a1c2SMark Johnston #define VBIT(x) ((x)>>1 & 0x1) /* to get 'v' bit */ 23120339a1c2SMark Johnston #define OPSIZE(osize, wbit) ((wbit) ? isize[osize] : 1) 23130339a1c2SMark Johnston #define OPSIZE64(osize, wbit) ((wbit) ? isize64[osize] : 1) 23140339a1c2SMark Johnston 23150339a1c2SMark Johnston #define REG_ONLY 3 /* mode to indicate a register operand (not memory) */ 23160339a1c2SMark Johnston 23170339a1c2SMark Johnston #define BYTE_OPND 0 /* w-bit value indicating byte register */ 23180339a1c2SMark Johnston #define LONG_OPND 1 /* w-bit value indicating opnd_size register */ 23190339a1c2SMark Johnston #define MM_OPND 2 /* "value" used to indicate a mmx reg */ 23200339a1c2SMark Johnston #define XMM_OPND 3 /* "value" used to indicate a xmm reg */ 23210339a1c2SMark Johnston #define SEG_OPND 4 /* "value" used to indicate a segment reg */ 23220339a1c2SMark Johnston #define CONTROL_OPND 5 /* "value" used to indicate a control reg */ 23230339a1c2SMark Johnston #define DEBUG_OPND 6 /* "value" used to indicate a debug reg */ 23240339a1c2SMark Johnston #define TEST_OPND 7 /* "value" used to indicate a test reg */ 23250339a1c2SMark Johnston #define WORD_OPND 8 /* w-bit value indicating word size reg */ 23260339a1c2SMark Johnston #define YMM_OPND 9 /* "value" used to indicate a ymm reg */ 23270339a1c2SMark Johnston 23280339a1c2SMark Johnston /* 2329*b3b5bfebSMark Johnston * The AVX2 gather instructions are a bit of a mess. While there's a pattern, 2330*b3b5bfebSMark Johnston * there's not really a consistent scheme that we can use to know what the mode 2331*b3b5bfebSMark Johnston * is supposed to be for a given type. Various instructions, like VPGATHERDD, 2332*b3b5bfebSMark Johnston * always match the value of VEX_L. Other instructions like VPGATHERDQ, have 2333*b3b5bfebSMark Johnston * some registers match VEX_L, but the VSIB is always XMM. 2334*b3b5bfebSMark Johnston * 2335*b3b5bfebSMark Johnston * The simplest way to deal with this is to just define a table based on the 2336*b3b5bfebSMark Johnston * instruction opcodes, which are 0x90-0x93, so we subtract 0x90 to index into 2337*b3b5bfebSMark Johnston * them. 2338*b3b5bfebSMark Johnston * 2339*b3b5bfebSMark Johnston * We further have to subdivide this based on the value of VEX_W and the value 2340*b3b5bfebSMark Johnston * of VEX_L. The array is constructed to be indexed as: 2341*b3b5bfebSMark Johnston * [opcode - 0x90][VEX_W][VEX_L]. 2342*b3b5bfebSMark Johnston */ 2343*b3b5bfebSMark Johnston /* w = 0, 0x90 */ 2344*b3b5bfebSMark Johnston typedef struct dis_gather_regs { 2345*b3b5bfebSMark Johnston uint_t dgr_arg0; /* src reg */ 2346*b3b5bfebSMark Johnston uint_t dgr_arg1; /* vsib reg */ 2347*b3b5bfebSMark Johnston uint_t dgr_arg2; /* dst reg */ 2348*b3b5bfebSMark Johnston char *dgr_suffix; /* suffix to append */ 2349*b3b5bfebSMark Johnston } dis_gather_regs_t; 2350*b3b5bfebSMark Johnston 2351*b3b5bfebSMark Johnston static dis_gather_regs_t dis_vgather[4][2][2] = { 2352*b3b5bfebSMark Johnston { 2353*b3b5bfebSMark Johnston /* op 0x90, W.0 */ 2354*b3b5bfebSMark Johnston { 2355*b3b5bfebSMark Johnston { XMM_OPND, XMM_OPND, XMM_OPND, "d" }, 2356*b3b5bfebSMark Johnston { YMM_OPND, YMM_OPND, YMM_OPND, "d" } 2357*b3b5bfebSMark Johnston }, 2358*b3b5bfebSMark Johnston /* op 0x90, W.1 */ 2359*b3b5bfebSMark Johnston { 2360*b3b5bfebSMark Johnston { XMM_OPND, XMM_OPND, XMM_OPND, "q" }, 2361*b3b5bfebSMark Johnston { YMM_OPND, XMM_OPND, YMM_OPND, "q" } 2362*b3b5bfebSMark Johnston } 2363*b3b5bfebSMark Johnston }, 2364*b3b5bfebSMark Johnston { 2365*b3b5bfebSMark Johnston /* op 0x91, W.0 */ 2366*b3b5bfebSMark Johnston { 2367*b3b5bfebSMark Johnston { XMM_OPND, XMM_OPND, XMM_OPND, "d" }, 2368*b3b5bfebSMark Johnston { XMM_OPND, YMM_OPND, XMM_OPND, "d" }, 2369*b3b5bfebSMark Johnston }, 2370*b3b5bfebSMark Johnston /* op 0x91, W.1 */ 2371*b3b5bfebSMark Johnston { 2372*b3b5bfebSMark Johnston { XMM_OPND, XMM_OPND, XMM_OPND, "q" }, 2373*b3b5bfebSMark Johnston { YMM_OPND, YMM_OPND, YMM_OPND, "q" }, 2374*b3b5bfebSMark Johnston } 2375*b3b5bfebSMark Johnston }, 2376*b3b5bfebSMark Johnston { 2377*b3b5bfebSMark Johnston /* op 0x92, W.0 */ 2378*b3b5bfebSMark Johnston { 2379*b3b5bfebSMark Johnston { XMM_OPND, XMM_OPND, XMM_OPND, "s" }, 2380*b3b5bfebSMark Johnston { YMM_OPND, YMM_OPND, YMM_OPND, "s" } 2381*b3b5bfebSMark Johnston }, 2382*b3b5bfebSMark Johnston /* op 0x92, W.1 */ 2383*b3b5bfebSMark Johnston { 2384*b3b5bfebSMark Johnston { XMM_OPND, XMM_OPND, XMM_OPND, "d" }, 2385*b3b5bfebSMark Johnston { YMM_OPND, XMM_OPND, YMM_OPND, "d" } 2386*b3b5bfebSMark Johnston } 2387*b3b5bfebSMark Johnston }, 2388*b3b5bfebSMark Johnston { 2389*b3b5bfebSMark Johnston /* op 0x93, W.0 */ 2390*b3b5bfebSMark Johnston { 2391*b3b5bfebSMark Johnston { XMM_OPND, XMM_OPND, XMM_OPND, "s" }, 2392*b3b5bfebSMark Johnston { XMM_OPND, YMM_OPND, XMM_OPND, "s" } 2393*b3b5bfebSMark Johnston }, 2394*b3b5bfebSMark Johnston /* op 0x93, W.1 */ 2395*b3b5bfebSMark Johnston { 2396*b3b5bfebSMark Johnston { XMM_OPND, XMM_OPND, XMM_OPND, "d" }, 2397*b3b5bfebSMark Johnston { YMM_OPND, YMM_OPND, YMM_OPND, "d" } 2398*b3b5bfebSMark Johnston } 2399*b3b5bfebSMark Johnston } 2400*b3b5bfebSMark Johnston }; 2401*b3b5bfebSMark Johnston 2402*b3b5bfebSMark Johnston /* 24030339a1c2SMark Johnston * Get the next byte and separate the op code into the high and low nibbles. 24040339a1c2SMark Johnston */ 24050339a1c2SMark Johnston static int 24060339a1c2SMark Johnston dtrace_get_opcode(dis86_t *x, uint_t *high, uint_t *low) 24070339a1c2SMark Johnston { 24080339a1c2SMark Johnston int byte; 24090339a1c2SMark Johnston 24100339a1c2SMark Johnston /* 24110339a1c2SMark Johnston * x86 instructions have a maximum length of 15 bytes. Bail out if 24120339a1c2SMark Johnston * we try to read more. 24130339a1c2SMark Johnston */ 24140339a1c2SMark Johnston if (x->d86_len >= 15) 24150339a1c2SMark Johnston return (x->d86_error = 1); 24160339a1c2SMark Johnston 24170339a1c2SMark Johnston if (x->d86_error) 24180339a1c2SMark Johnston return (1); 24190339a1c2SMark Johnston byte = x->d86_get_byte(x->d86_data); 24200339a1c2SMark Johnston if (byte < 0) 24210339a1c2SMark Johnston return (x->d86_error = 1); 24220339a1c2SMark Johnston x->d86_bytes[x->d86_len++] = byte; 24230339a1c2SMark Johnston *low = byte & 0xf; /* ----xxxx low 4 bits */ 24240339a1c2SMark Johnston *high = byte >> 4 & 0xf; /* xxxx---- bits 7 to 4 */ 24250339a1c2SMark Johnston return (0); 24260339a1c2SMark Johnston } 24270339a1c2SMark Johnston 24280339a1c2SMark Johnston /* 24290339a1c2SMark Johnston * Get and decode an SIB (scaled index base) byte 24300339a1c2SMark Johnston */ 24310339a1c2SMark Johnston static void 24320339a1c2SMark Johnston dtrace_get_SIB(dis86_t *x, uint_t *ss, uint_t *index, uint_t *base) 24330339a1c2SMark Johnston { 24340339a1c2SMark Johnston int byte; 24350339a1c2SMark Johnston 24360339a1c2SMark Johnston if (x->d86_error) 24370339a1c2SMark Johnston return; 24380339a1c2SMark Johnston 24390339a1c2SMark Johnston byte = x->d86_get_byte(x->d86_data); 24400339a1c2SMark Johnston if (byte < 0) { 24410339a1c2SMark Johnston x->d86_error = 1; 24420339a1c2SMark Johnston return; 24430339a1c2SMark Johnston } 24440339a1c2SMark Johnston x->d86_bytes[x->d86_len++] = byte; 24450339a1c2SMark Johnston 24460339a1c2SMark Johnston *base = byte & 0x7; 24470339a1c2SMark Johnston *index = (byte >> 3) & 0x7; 24480339a1c2SMark Johnston *ss = (byte >> 6) & 0x3; 24490339a1c2SMark Johnston } 24500339a1c2SMark Johnston 24510339a1c2SMark Johnston /* 24520339a1c2SMark Johnston * Get the byte following the op code and separate it into the 24530339a1c2SMark Johnston * mode, register, and r/m fields. 24540339a1c2SMark Johnston */ 24550339a1c2SMark Johnston static void 24560339a1c2SMark Johnston dtrace_get_modrm(dis86_t *x, uint_t *mode, uint_t *reg, uint_t *r_m) 24570339a1c2SMark Johnston { 24580339a1c2SMark Johnston if (x->d86_got_modrm == 0) { 24590339a1c2SMark Johnston if (x->d86_rmindex == -1) 24600339a1c2SMark Johnston x->d86_rmindex = x->d86_len; 24610339a1c2SMark Johnston dtrace_get_SIB(x, mode, reg, r_m); 24620339a1c2SMark Johnston x->d86_got_modrm = 1; 24630339a1c2SMark Johnston } 24640339a1c2SMark Johnston } 24650339a1c2SMark Johnston 24660339a1c2SMark Johnston /* 24670339a1c2SMark Johnston * Adjust register selection based on any REX prefix bits present. 24680339a1c2SMark Johnston */ 24690339a1c2SMark Johnston /*ARGSUSED*/ 24700339a1c2SMark Johnston static void 24710339a1c2SMark Johnston dtrace_rex_adjust(uint_t rex_prefix, uint_t mode, uint_t *reg, uint_t *r_m) 24720339a1c2SMark Johnston { 24730339a1c2SMark Johnston if (reg != NULL && r_m == NULL) { 24740339a1c2SMark Johnston if (rex_prefix & REX_B) 24750339a1c2SMark Johnston *reg += 8; 24760339a1c2SMark Johnston } else { 24770339a1c2SMark Johnston if (reg != NULL && (REX_R & rex_prefix) != 0) 24780339a1c2SMark Johnston *reg += 8; 24790339a1c2SMark Johnston if (r_m != NULL && (REX_B & rex_prefix) != 0) 24800339a1c2SMark Johnston *r_m += 8; 24810339a1c2SMark Johnston } 24820339a1c2SMark Johnston } 24830339a1c2SMark Johnston 24840339a1c2SMark Johnston /* 24850339a1c2SMark Johnston * Adjust register selection based on any VEX prefix bits present. 24860339a1c2SMark Johnston * Notes: VEX.R, VEX.X and VEX.B use the inverted form compared with REX prefix 24870339a1c2SMark Johnston */ 24880339a1c2SMark Johnston /*ARGSUSED*/ 24890339a1c2SMark Johnston static void 24900339a1c2SMark Johnston dtrace_vex_adjust(uint_t vex_byte1, uint_t mode, uint_t *reg, uint_t *r_m) 24910339a1c2SMark Johnston { 24920339a1c2SMark Johnston if (reg != NULL && r_m == NULL) { 24930339a1c2SMark Johnston if (!(vex_byte1 & VEX_B)) 24940339a1c2SMark Johnston *reg += 8; 24950339a1c2SMark Johnston } else { 24960339a1c2SMark Johnston if (reg != NULL && ((VEX_R & vex_byte1) == 0)) 24970339a1c2SMark Johnston *reg += 8; 24980339a1c2SMark Johnston if (r_m != NULL && ((VEX_B & vex_byte1) == 0)) 24990339a1c2SMark Johnston *r_m += 8; 25000339a1c2SMark Johnston } 25010339a1c2SMark Johnston } 25020339a1c2SMark Johnston 25030339a1c2SMark Johnston /* 25040339a1c2SMark Johnston * Get an immediate operand of the given size, with sign extension. 25050339a1c2SMark Johnston */ 25060339a1c2SMark Johnston static void 25070339a1c2SMark Johnston dtrace_imm_opnd(dis86_t *x, int wbit, int size, int opindex) 25080339a1c2SMark Johnston { 25090339a1c2SMark Johnston int i; 25100339a1c2SMark Johnston int byte; 25110339a1c2SMark Johnston int valsize; 25120339a1c2SMark Johnston 25130339a1c2SMark Johnston if (x->d86_numopnds < opindex + 1) 25140339a1c2SMark Johnston x->d86_numopnds = opindex + 1; 25150339a1c2SMark Johnston 25160339a1c2SMark Johnston switch (wbit) { 25170339a1c2SMark Johnston case BYTE_OPND: 25180339a1c2SMark Johnston valsize = 1; 25190339a1c2SMark Johnston break; 25200339a1c2SMark Johnston case LONG_OPND: 25210339a1c2SMark Johnston if (x->d86_opnd_size == SIZE16) 25220339a1c2SMark Johnston valsize = 2; 25230339a1c2SMark Johnston else if (x->d86_opnd_size == SIZE32) 25240339a1c2SMark Johnston valsize = 4; 25250339a1c2SMark Johnston else 25260339a1c2SMark Johnston valsize = 8; 25270339a1c2SMark Johnston break; 25280339a1c2SMark Johnston case MM_OPND: 25290339a1c2SMark Johnston case XMM_OPND: 25300339a1c2SMark Johnston case YMM_OPND: 25310339a1c2SMark Johnston case SEG_OPND: 25320339a1c2SMark Johnston case CONTROL_OPND: 25330339a1c2SMark Johnston case DEBUG_OPND: 25340339a1c2SMark Johnston case TEST_OPND: 25350339a1c2SMark Johnston valsize = size; 25360339a1c2SMark Johnston break; 25370339a1c2SMark Johnston case WORD_OPND: 25380339a1c2SMark Johnston valsize = 2; 25390339a1c2SMark Johnston break; 25400339a1c2SMark Johnston } 25410339a1c2SMark Johnston if (valsize < size) 25420339a1c2SMark Johnston valsize = size; 25430339a1c2SMark Johnston 25440339a1c2SMark Johnston if (x->d86_error) 25450339a1c2SMark Johnston return; 25460339a1c2SMark Johnston x->d86_opnd[opindex].d86_value = 0; 25470339a1c2SMark Johnston for (i = 0; i < size; ++i) { 25480339a1c2SMark Johnston byte = x->d86_get_byte(x->d86_data); 25490339a1c2SMark Johnston if (byte < 0) { 25500339a1c2SMark Johnston x->d86_error = 1; 25510339a1c2SMark Johnston return; 25520339a1c2SMark Johnston } 25530339a1c2SMark Johnston x->d86_bytes[x->d86_len++] = byte; 25540339a1c2SMark Johnston x->d86_opnd[opindex].d86_value |= (uint64_t)byte << (i * 8); 25550339a1c2SMark Johnston } 25560339a1c2SMark Johnston /* Do sign extension */ 25570339a1c2SMark Johnston if (x->d86_bytes[x->d86_len - 1] & 0x80) { 25580339a1c2SMark Johnston for (; i < sizeof (uint64_t); i++) 25590339a1c2SMark Johnston x->d86_opnd[opindex].d86_value |= 25600339a1c2SMark Johnston (uint64_t)0xff << (i * 8); 25610339a1c2SMark Johnston } 25620339a1c2SMark Johnston #ifdef DIS_TEXT 25630339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = MODE_SIGNED; 25640339a1c2SMark Johnston x->d86_opnd[opindex].d86_value_size = valsize; 25650339a1c2SMark Johnston x->d86_imm_bytes += size; 25660339a1c2SMark Johnston #endif 25670339a1c2SMark Johnston } 25680339a1c2SMark Johnston 25690339a1c2SMark Johnston /* 25700339a1c2SMark Johnston * Get an ip relative operand of the given size, with sign extension. 25710339a1c2SMark Johnston */ 25720339a1c2SMark Johnston static void 25730339a1c2SMark Johnston dtrace_disp_opnd(dis86_t *x, int wbit, int size, int opindex) 25740339a1c2SMark Johnston { 25750339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, size, opindex); 25760339a1c2SMark Johnston #ifdef DIS_TEXT 25770339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = MODE_IPREL; 25780339a1c2SMark Johnston #endif 25790339a1c2SMark Johnston } 25800339a1c2SMark Johnston 25810339a1c2SMark Johnston /* 25820339a1c2SMark Johnston * Check to see if there is a segment override prefix pending. 25830339a1c2SMark Johnston * If so, print it in the current 'operand' location and set 25840339a1c2SMark Johnston * the override flag back to false. 25850339a1c2SMark Johnston */ 25860339a1c2SMark Johnston /*ARGSUSED*/ 25870339a1c2SMark Johnston static void 25880339a1c2SMark Johnston dtrace_check_override(dis86_t *x, int opindex) 25890339a1c2SMark Johnston { 25900339a1c2SMark Johnston #ifdef DIS_TEXT 25910339a1c2SMark Johnston if (x->d86_seg_prefix) { 25920339a1c2SMark Johnston (void) strlcat(x->d86_opnd[opindex].d86_prefix, 25930339a1c2SMark Johnston x->d86_seg_prefix, PFIXLEN); 25940339a1c2SMark Johnston } 25950339a1c2SMark Johnston #endif 25960339a1c2SMark Johnston x->d86_seg_prefix = NULL; 25970339a1c2SMark Johnston } 25980339a1c2SMark Johnston 25990339a1c2SMark Johnston 26000339a1c2SMark Johnston /* 26010339a1c2SMark Johnston * Process a single instruction Register or Memory operand. 26020339a1c2SMark Johnston * 26030339a1c2SMark Johnston * mode = addressing mode from ModRM byte 26040339a1c2SMark Johnston * r_m = r_m (or reg if mode == 3) field from ModRM byte 26050339a1c2SMark Johnston * wbit = indicates which register (8bit, 16bit, ... MMX, etc.) set to use. 26060339a1c2SMark Johnston * o = index of operand that we are processing (0, 1 or 2) 26070339a1c2SMark Johnston * 26080339a1c2SMark Johnston * the value of reg or r_m must have already been adjusted for any REX prefix. 26090339a1c2SMark Johnston */ 26100339a1c2SMark Johnston /*ARGSUSED*/ 26110339a1c2SMark Johnston static void 26120339a1c2SMark Johnston dtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex) 26130339a1c2SMark Johnston { 26140339a1c2SMark Johnston int have_SIB = 0; /* flag presence of scale-index-byte */ 26150339a1c2SMark Johnston uint_t ss; /* scale-factor from opcode */ 26160339a1c2SMark Johnston uint_t index; /* index register number */ 26170339a1c2SMark Johnston uint_t base; /* base register number */ 26180339a1c2SMark Johnston int dispsize; /* size of displacement in bytes */ 26190339a1c2SMark Johnston #ifdef DIS_TEXT 26200339a1c2SMark Johnston char *opnd = x->d86_opnd[opindex].d86_opnd; 26210339a1c2SMark Johnston #endif 26220339a1c2SMark Johnston 26230339a1c2SMark Johnston if (x->d86_numopnds < opindex + 1) 26240339a1c2SMark Johnston x->d86_numopnds = opindex + 1; 26250339a1c2SMark Johnston 26260339a1c2SMark Johnston if (x->d86_error) 26270339a1c2SMark Johnston return; 26280339a1c2SMark Johnston 26290339a1c2SMark Johnston /* 26300339a1c2SMark Johnston * first handle a simple register 26310339a1c2SMark Johnston */ 26320339a1c2SMark Johnston if (mode == REG_ONLY) { 26330339a1c2SMark Johnston #ifdef DIS_TEXT 26340339a1c2SMark Johnston switch (wbit) { 26350339a1c2SMark Johnston case MM_OPND: 26360339a1c2SMark Johnston (void) strlcat(opnd, dis_MMREG[r_m], OPLEN); 26370339a1c2SMark Johnston break; 26380339a1c2SMark Johnston case XMM_OPND: 26390339a1c2SMark Johnston (void) strlcat(opnd, dis_XMMREG[r_m], OPLEN); 26400339a1c2SMark Johnston break; 26410339a1c2SMark Johnston case YMM_OPND: 26420339a1c2SMark Johnston (void) strlcat(opnd, dis_YMMREG[r_m], OPLEN); 26430339a1c2SMark Johnston break; 26440339a1c2SMark Johnston case SEG_OPND: 26450339a1c2SMark Johnston (void) strlcat(opnd, dis_SEGREG[r_m], OPLEN); 26460339a1c2SMark Johnston break; 26470339a1c2SMark Johnston case CONTROL_OPND: 26480339a1c2SMark Johnston (void) strlcat(opnd, dis_CONTROLREG[r_m], OPLEN); 26490339a1c2SMark Johnston break; 26500339a1c2SMark Johnston case DEBUG_OPND: 26510339a1c2SMark Johnston (void) strlcat(opnd, dis_DEBUGREG[r_m], OPLEN); 26520339a1c2SMark Johnston break; 26530339a1c2SMark Johnston case TEST_OPND: 26540339a1c2SMark Johnston (void) strlcat(opnd, dis_TESTREG[r_m], OPLEN); 26550339a1c2SMark Johnston break; 26560339a1c2SMark Johnston case BYTE_OPND: 26570339a1c2SMark Johnston if (x->d86_rex_prefix == 0) 26580339a1c2SMark Johnston (void) strlcat(opnd, dis_REG8[r_m], OPLEN); 26590339a1c2SMark Johnston else 26600339a1c2SMark Johnston (void) strlcat(opnd, dis_REG8_REX[r_m], OPLEN); 26610339a1c2SMark Johnston break; 26620339a1c2SMark Johnston case WORD_OPND: 26630339a1c2SMark Johnston (void) strlcat(opnd, dis_REG16[r_m], OPLEN); 26640339a1c2SMark Johnston break; 26650339a1c2SMark Johnston case LONG_OPND: 26660339a1c2SMark Johnston if (x->d86_opnd_size == SIZE16) 26670339a1c2SMark Johnston (void) strlcat(opnd, dis_REG16[r_m], OPLEN); 26680339a1c2SMark Johnston else if (x->d86_opnd_size == SIZE32) 26690339a1c2SMark Johnston (void) strlcat(opnd, dis_REG32[r_m], OPLEN); 26700339a1c2SMark Johnston else 26710339a1c2SMark Johnston (void) strlcat(opnd, dis_REG64[r_m], OPLEN); 26720339a1c2SMark Johnston break; 26730339a1c2SMark Johnston } 26740339a1c2SMark Johnston #endif /* DIS_TEXT */ 26750339a1c2SMark Johnston return; 26760339a1c2SMark Johnston } 26770339a1c2SMark Johnston 26780339a1c2SMark Johnston /* 26790339a1c2SMark Johnston * if symbolic representation, skip override prefix, if any 26800339a1c2SMark Johnston */ 26810339a1c2SMark Johnston dtrace_check_override(x, opindex); 26820339a1c2SMark Johnston 26830339a1c2SMark Johnston /* 26840339a1c2SMark Johnston * Handle 16 bit memory references first, since they decode 26850339a1c2SMark Johnston * the mode values more simply. 26860339a1c2SMark Johnston * mode 1 is r_m + 8 bit displacement 26870339a1c2SMark Johnston * mode 2 is r_m + 16 bit displacement 26880339a1c2SMark Johnston * mode 0 is just r_m, unless r_m is 6 which is 16 bit disp 26890339a1c2SMark Johnston */ 26900339a1c2SMark Johnston if (x->d86_addr_size == SIZE16) { 26910339a1c2SMark Johnston if ((mode == 0 && r_m == 6) || mode == 2) 26920339a1c2SMark Johnston dtrace_imm_opnd(x, WORD_OPND, 2, opindex); 26930339a1c2SMark Johnston else if (mode == 1) 26940339a1c2SMark Johnston dtrace_imm_opnd(x, BYTE_OPND, 1, opindex); 26950339a1c2SMark Johnston #ifdef DIS_TEXT 26960339a1c2SMark Johnston if (mode == 0 && r_m == 6) 26970339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = MODE_SIGNED; 26980339a1c2SMark Johnston else if (mode == 0) 26990339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = MODE_NONE; 27000339a1c2SMark Johnston else 27010339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = MODE_OFFSET; 27020339a1c2SMark Johnston (void) strlcat(opnd, dis_addr16[mode][r_m], OPLEN); 27030339a1c2SMark Johnston #endif 27040339a1c2SMark Johnston return; 27050339a1c2SMark Johnston } 27060339a1c2SMark Johnston 27070339a1c2SMark Johnston /* 27080339a1c2SMark Johnston * 32 and 64 bit addressing modes are more complex since they 27090339a1c2SMark Johnston * can involve an SIB (scaled index and base) byte to decode. 27100339a1c2SMark Johnston */ 27110339a1c2SMark Johnston if (r_m == ESP_REGNO || r_m == ESP_REGNO + 8) { 27120339a1c2SMark Johnston have_SIB = 1; 27130339a1c2SMark Johnston dtrace_get_SIB(x, &ss, &index, &base); 27140339a1c2SMark Johnston if (x->d86_error) 27150339a1c2SMark Johnston return; 27160339a1c2SMark Johnston if (base != 5 || mode != 0) 27170339a1c2SMark Johnston if (x->d86_rex_prefix & REX_B) 27180339a1c2SMark Johnston base += 8; 27190339a1c2SMark Johnston if (x->d86_rex_prefix & REX_X) 27200339a1c2SMark Johnston index += 8; 27210339a1c2SMark Johnston } else { 27220339a1c2SMark Johnston base = r_m; 27230339a1c2SMark Johnston } 27240339a1c2SMark Johnston 27250339a1c2SMark Johnston /* 27260339a1c2SMark Johnston * Compute the displacement size and get its bytes 27270339a1c2SMark Johnston */ 27280339a1c2SMark Johnston dispsize = 0; 27290339a1c2SMark Johnston 27300339a1c2SMark Johnston if (mode == 1) 27310339a1c2SMark Johnston dispsize = 1; 27320339a1c2SMark Johnston else if (mode == 2) 27330339a1c2SMark Johnston dispsize = 4; 27340339a1c2SMark Johnston else if ((r_m & 7) == EBP_REGNO || 27350339a1c2SMark Johnston (have_SIB && (base & 7) == EBP_REGNO)) 27360339a1c2SMark Johnston dispsize = 4; 27370339a1c2SMark Johnston 27380339a1c2SMark Johnston if (dispsize > 0) { 27390339a1c2SMark Johnston dtrace_imm_opnd(x, dispsize == 4 ? LONG_OPND : BYTE_OPND, 27400339a1c2SMark Johnston dispsize, opindex); 27410339a1c2SMark Johnston if (x->d86_error) 27420339a1c2SMark Johnston return; 27430339a1c2SMark Johnston } 27440339a1c2SMark Johnston 27450339a1c2SMark Johnston #ifdef DIS_TEXT 27460339a1c2SMark Johnston if (dispsize > 0) 27470339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = MODE_OFFSET; 27480339a1c2SMark Johnston 27490339a1c2SMark Johnston if (have_SIB == 0) { 27500339a1c2SMark Johnston if (x->d86_mode == SIZE32) { 27510339a1c2SMark Johnston if (mode == 0) 27520339a1c2SMark Johnston (void) strlcat(opnd, dis_addr32_mode0[r_m], 27530339a1c2SMark Johnston OPLEN); 27540339a1c2SMark Johnston else 27550339a1c2SMark Johnston (void) strlcat(opnd, dis_addr32_mode12[r_m], 27560339a1c2SMark Johnston OPLEN); 27570339a1c2SMark Johnston } else { 27580339a1c2SMark Johnston if (mode == 0) { 27590339a1c2SMark Johnston (void) strlcat(opnd, dis_addr64_mode0[r_m], 27600339a1c2SMark Johnston OPLEN); 27610339a1c2SMark Johnston if (r_m == 5) { 27620339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = 27630339a1c2SMark Johnston MODE_RIPREL; 27640339a1c2SMark Johnston } 27650339a1c2SMark Johnston } else { 27660339a1c2SMark Johnston (void) strlcat(opnd, dis_addr64_mode12[r_m], 27670339a1c2SMark Johnston OPLEN); 27680339a1c2SMark Johnston } 27690339a1c2SMark Johnston } 27700339a1c2SMark Johnston } else { 27710339a1c2SMark Johnston uint_t need_paren = 0; 27720339a1c2SMark Johnston char **regs; 2773*b3b5bfebSMark Johnston char **bregs; 2774*b3b5bfebSMark Johnston const char *const *sf; 27750339a1c2SMark Johnston if (x->d86_mode == SIZE32) /* NOTE this is not addr_size! */ 27760339a1c2SMark Johnston regs = (char **)dis_REG32; 27770339a1c2SMark Johnston else 27780339a1c2SMark Johnston regs = (char **)dis_REG64; 27790339a1c2SMark Johnston 2780*b3b5bfebSMark Johnston if (x->d86_vsib != 0) { 2781*b3b5bfebSMark Johnston if (wbit == YMM_OPND) /* NOTE this is not addr_size! */ 2782*b3b5bfebSMark Johnston bregs = (char **)dis_YMMREG; 2783*b3b5bfebSMark Johnston else 2784*b3b5bfebSMark Johnston bregs = (char **)dis_XMMREG; 2785*b3b5bfebSMark Johnston sf = dis_vscale_factor; 2786*b3b5bfebSMark Johnston } else { 2787*b3b5bfebSMark Johnston bregs = regs; 2788*b3b5bfebSMark Johnston sf = dis_scale_factor; 2789*b3b5bfebSMark Johnston } 2790*b3b5bfebSMark Johnston 27910339a1c2SMark Johnston /* 27920339a1c2SMark Johnston * print the base (if any) 27930339a1c2SMark Johnston */ 27940339a1c2SMark Johnston if (base == EBP_REGNO && mode == 0) { 2795*b3b5bfebSMark Johnston if (index != ESP_REGNO || x->d86_vsib != 0) { 27960339a1c2SMark Johnston (void) strlcat(opnd, "(", OPLEN); 27970339a1c2SMark Johnston need_paren = 1; 27980339a1c2SMark Johnston } 27990339a1c2SMark Johnston } else { 28000339a1c2SMark Johnston (void) strlcat(opnd, "(", OPLEN); 28010339a1c2SMark Johnston (void) strlcat(opnd, regs[base], OPLEN); 28020339a1c2SMark Johnston need_paren = 1; 28030339a1c2SMark Johnston } 28040339a1c2SMark Johnston 28050339a1c2SMark Johnston /* 28060339a1c2SMark Johnston * print the index (if any) 28070339a1c2SMark Johnston */ 2808*b3b5bfebSMark Johnston if (index != ESP_REGNO || x->d86_vsib) { 28090339a1c2SMark Johnston (void) strlcat(opnd, ",", OPLEN); 2810*b3b5bfebSMark Johnston (void) strlcat(opnd, bregs[index], OPLEN); 2811*b3b5bfebSMark Johnston (void) strlcat(opnd, sf[ss], OPLEN); 28120339a1c2SMark Johnston } else 28130339a1c2SMark Johnston if (need_paren) 28140339a1c2SMark Johnston (void) strlcat(opnd, ")", OPLEN); 28150339a1c2SMark Johnston } 28160339a1c2SMark Johnston #endif 28170339a1c2SMark Johnston } 28180339a1c2SMark Johnston 28190339a1c2SMark Johnston /* 28200339a1c2SMark Johnston * Operand sequence for standard instruction involving one register 28210339a1c2SMark Johnston * and one register/memory operand. 28220339a1c2SMark Johnston * wbit indicates a byte(0) or opnd_size(1) operation 28230339a1c2SMark Johnston * vbit indicates direction (0 for "opcode r,r_m") or (1 for "opcode r_m, r") 28240339a1c2SMark Johnston */ 28250339a1c2SMark Johnston #define STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, vbit) { \ 28260339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); \ 28270339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 28280339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, vbit); \ 28290339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1 - vbit); \ 28300339a1c2SMark Johnston } 28310339a1c2SMark Johnston 28320339a1c2SMark Johnston /* 28330339a1c2SMark Johnston * Similar to above, but allows for the two operands to be of different 28340339a1c2SMark Johnston * classes (ie. wbit). 28350339a1c2SMark Johnston * wbit is for the r_m operand 28360339a1c2SMark Johnston * w2 is for the reg operand 28370339a1c2SMark Johnston */ 28380339a1c2SMark Johnston #define MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, w2, vbit) { \ 28390339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); \ 28400339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 28410339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, vbit); \ 28420339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, w2, 1 - vbit); \ 28430339a1c2SMark Johnston } 28440339a1c2SMark Johnston 28450339a1c2SMark Johnston /* 28460339a1c2SMark Johnston * Similar, but for 2 operands plus an immediate. 28470339a1c2SMark Johnston * vbit indicates direction 28480339a1c2SMark Johnston * 0 for "opcode imm, r, r_m" or 28490339a1c2SMark Johnston * 1 for "opcode imm, r_m, r" 28500339a1c2SMark Johnston */ 28510339a1c2SMark Johnston #define THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize, vbit) { \ 28520339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); \ 28530339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 28540339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 2-vbit); \ 28550339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, w2, 1+vbit); \ 28560339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, immsize, 0); \ 28570339a1c2SMark Johnston } 28580339a1c2SMark Johnston 28590339a1c2SMark Johnston /* 28600339a1c2SMark Johnston * Similar, but for 2 operands plus two immediates. 28610339a1c2SMark Johnston */ 28620339a1c2SMark Johnston #define FOUROPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize) { \ 28630339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); \ 28640339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 28650339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 2); \ 28660339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, w2, 3); \ 28670339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, immsize, 1); \ 28680339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, immsize, 0); \ 28690339a1c2SMark Johnston } 28700339a1c2SMark Johnston 28710339a1c2SMark Johnston /* 28720339a1c2SMark Johnston * 1 operands plus two immediates. 28730339a1c2SMark Johnston */ 28740339a1c2SMark Johnston #define ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, wbit, immsize) { \ 28750339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); \ 28760339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 28770339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 2); \ 28780339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, immsize, 1); \ 28790339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, immsize, 0); \ 28800339a1c2SMark Johnston } 28810339a1c2SMark Johnston 28820339a1c2SMark Johnston /* 28830339a1c2SMark Johnston * Dissassemble a single x86 or amd64 instruction. 28840339a1c2SMark Johnston * 28850339a1c2SMark Johnston * Mode determines the default operating mode (SIZE16, SIZE32 or SIZE64) 28860339a1c2SMark Johnston * for interpreting instructions. 28870339a1c2SMark Johnston * 28880339a1c2SMark Johnston * returns non-zero for bad opcode 28890339a1c2SMark Johnston */ 28900339a1c2SMark Johnston int 28910339a1c2SMark Johnston dtrace_disx86(dis86_t *x, uint_t cpu_mode) 28920339a1c2SMark Johnston { 28930339a1c2SMark Johnston instable_t *dp; /* decode table being used */ 28940339a1c2SMark Johnston #ifdef DIS_TEXT 28950339a1c2SMark Johnston uint_t i; 28960339a1c2SMark Johnston #endif 28970339a1c2SMark Johnston #ifdef DIS_MEM 28980339a1c2SMark Johnston uint_t nomem = 0; 28990339a1c2SMark Johnston #define NOMEM (nomem = 1) 29000339a1c2SMark Johnston #else 29010339a1c2SMark Johnston #define NOMEM /* nothing */ 29020339a1c2SMark Johnston #endif 29030339a1c2SMark Johnston uint_t opnd_size; /* SIZE16, SIZE32 or SIZE64 */ 29040339a1c2SMark Johnston uint_t addr_size; /* SIZE16, SIZE32 or SIZE64 */ 29050339a1c2SMark Johnston uint_t wbit; /* opcode wbit, 0 is 8 bit, !0 for opnd_size */ 29060339a1c2SMark Johnston uint_t w2; /* wbit value for second operand */ 29070339a1c2SMark Johnston uint_t vbit; 29080339a1c2SMark Johnston uint_t mode = 0; /* mode value from ModRM byte */ 29090339a1c2SMark Johnston uint_t reg; /* reg value from ModRM byte */ 29100339a1c2SMark Johnston uint_t r_m; /* r_m value from ModRM byte */ 29110339a1c2SMark Johnston 29120339a1c2SMark Johnston uint_t opcode1; /* high nibble of 1st byte */ 29130339a1c2SMark Johnston uint_t opcode2; /* low nibble of 1st byte */ 29140339a1c2SMark Johnston uint_t opcode3; /* extra opcode bits usually from ModRM byte */ 29150339a1c2SMark Johnston uint_t opcode4; /* high nibble of 2nd byte */ 29160339a1c2SMark Johnston uint_t opcode5; /* low nibble of 2nd byte */ 29170339a1c2SMark Johnston uint_t opcode6; /* high nibble of 3rd byte */ 29180339a1c2SMark Johnston uint_t opcode7; /* low nibble of 3rd byte */ 29190339a1c2SMark Johnston uint_t opcode_bytes = 1; 29200339a1c2SMark Johnston 29210339a1c2SMark Johnston /* 29220339a1c2SMark Johnston * legacy prefixes come in 5 flavors, you should have only one of each 29230339a1c2SMark Johnston */ 29240339a1c2SMark Johnston uint_t opnd_size_prefix = 0; 29250339a1c2SMark Johnston uint_t addr_size_prefix = 0; 29260339a1c2SMark Johnston uint_t segment_prefix = 0; 29270339a1c2SMark Johnston uint_t lock_prefix = 0; 29280339a1c2SMark Johnston uint_t rep_prefix = 0; 29290339a1c2SMark Johnston uint_t rex_prefix = 0; /* amd64 register extension prefix */ 29300339a1c2SMark Johnston 29310339a1c2SMark Johnston /* 29320339a1c2SMark Johnston * Intel VEX instruction encoding prefix and fields 29330339a1c2SMark Johnston */ 29340339a1c2SMark Johnston 29350339a1c2SMark Johnston /* 0xC4 means 3 bytes prefix, 0xC5 means 2 bytes prefix */ 29360339a1c2SMark Johnston uint_t vex_prefix = 0; 29370339a1c2SMark Johnston 29380339a1c2SMark Johnston /* 29390339a1c2SMark Johnston * VEX prefix byte 1, includes vex.r, vex.x and vex.b 29400339a1c2SMark Johnston * (for 3 bytes prefix) 29410339a1c2SMark Johnston */ 29420339a1c2SMark Johnston uint_t vex_byte1 = 0; 29430339a1c2SMark Johnston 29440339a1c2SMark Johnston /* 29450339a1c2SMark Johnston * For 32-bit mode, it should prefetch the next byte to 29460339a1c2SMark Johnston * distinguish between AVX and les/lds 29470339a1c2SMark Johnston */ 29480339a1c2SMark Johnston uint_t vex_prefetch = 0; 29490339a1c2SMark Johnston 29500339a1c2SMark Johnston uint_t vex_m = 0; 29510339a1c2SMark Johnston uint_t vex_v = 0; 29520339a1c2SMark Johnston uint_t vex_p = 0; 29530339a1c2SMark Johnston uint_t vex_R = 1; 29540339a1c2SMark Johnston uint_t vex_X = 1; 29550339a1c2SMark Johnston uint_t vex_B = 1; 29560339a1c2SMark Johnston uint_t vex_W = 0; 29570339a1c2SMark Johnston uint_t vex_L; 2958*b3b5bfebSMark Johnston dis_gather_regs_t *vreg; 29590339a1c2SMark Johnston 2960*b3b5bfebSMark Johnston #ifdef DIS_TEXT 2961*b3b5bfebSMark Johnston /* Instruction name for BLS* family of instructions */ 2962*b3b5bfebSMark Johnston char *blsinstr; 2963*b3b5bfebSMark Johnston #endif 29640339a1c2SMark Johnston 29650339a1c2SMark Johnston size_t off; 29660339a1c2SMark Johnston 29670339a1c2SMark Johnston instable_t dp_mmx; 29680339a1c2SMark Johnston 29690339a1c2SMark Johnston x->d86_len = 0; 29700339a1c2SMark Johnston x->d86_rmindex = -1; 29710339a1c2SMark Johnston x->d86_error = 0; 29720339a1c2SMark Johnston #ifdef DIS_TEXT 29730339a1c2SMark Johnston x->d86_numopnds = 0; 29740339a1c2SMark Johnston x->d86_seg_prefix = NULL; 29750339a1c2SMark Johnston x->d86_mnem[0] = 0; 29760339a1c2SMark Johnston for (i = 0; i < 4; ++i) { 29770339a1c2SMark Johnston x->d86_opnd[i].d86_opnd[0] = 0; 29780339a1c2SMark Johnston x->d86_opnd[i].d86_prefix[0] = 0; 29790339a1c2SMark Johnston x->d86_opnd[i].d86_value_size = 0; 29800339a1c2SMark Johnston x->d86_opnd[i].d86_value = 0; 29810339a1c2SMark Johnston x->d86_opnd[i].d86_mode = MODE_NONE; 29820339a1c2SMark Johnston } 29830339a1c2SMark Johnston #endif 29840339a1c2SMark Johnston x->d86_rex_prefix = 0; 29850339a1c2SMark Johnston x->d86_got_modrm = 0; 29860339a1c2SMark Johnston x->d86_memsize = 0; 2987*b3b5bfebSMark Johnston x->d86_vsib = 0; 29880339a1c2SMark Johnston 29890339a1c2SMark Johnston if (cpu_mode == SIZE16) { 29900339a1c2SMark Johnston opnd_size = SIZE16; 29910339a1c2SMark Johnston addr_size = SIZE16; 29920339a1c2SMark Johnston } else if (cpu_mode == SIZE32) { 29930339a1c2SMark Johnston opnd_size = SIZE32; 29940339a1c2SMark Johnston addr_size = SIZE32; 29950339a1c2SMark Johnston } else { 29960339a1c2SMark Johnston opnd_size = SIZE32; 29970339a1c2SMark Johnston addr_size = SIZE64; 29980339a1c2SMark Johnston } 29990339a1c2SMark Johnston 30000339a1c2SMark Johnston /* 30010339a1c2SMark Johnston * Get one opcode byte and check for zero padding that follows 30020339a1c2SMark Johnston * jump tables. 30030339a1c2SMark Johnston */ 30040339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 30050339a1c2SMark Johnston goto error; 30060339a1c2SMark Johnston 30070339a1c2SMark Johnston if (opcode1 == 0 && opcode2 == 0 && 30080339a1c2SMark Johnston x->d86_check_func != NULL && x->d86_check_func(x->d86_data)) { 30090339a1c2SMark Johnston #ifdef DIS_TEXT 30100339a1c2SMark Johnston (void) strncpy(x->d86_mnem, ".byte\t0", OPLEN); 30110339a1c2SMark Johnston #endif 30120339a1c2SMark Johnston goto done; 30130339a1c2SMark Johnston } 30140339a1c2SMark Johnston 30150339a1c2SMark Johnston /* 30160339a1c2SMark Johnston * Gather up legacy x86 prefix bytes. 30170339a1c2SMark Johnston */ 30180339a1c2SMark Johnston for (;;) { 30190339a1c2SMark Johnston uint_t *which_prefix = NULL; 30200339a1c2SMark Johnston 30210339a1c2SMark Johnston dp = (instable_t *)&dis_distable[opcode1][opcode2]; 30220339a1c2SMark Johnston 30230339a1c2SMark Johnston switch (dp->it_adrmode) { 30240339a1c2SMark Johnston case PREFIX: 30250339a1c2SMark Johnston which_prefix = &rep_prefix; 30260339a1c2SMark Johnston break; 30270339a1c2SMark Johnston case LOCK: 30280339a1c2SMark Johnston which_prefix = &lock_prefix; 30290339a1c2SMark Johnston break; 30300339a1c2SMark Johnston case OVERRIDE: 30310339a1c2SMark Johnston which_prefix = &segment_prefix; 30320339a1c2SMark Johnston #ifdef DIS_TEXT 30330339a1c2SMark Johnston x->d86_seg_prefix = (char *)dp->it_name; 30340339a1c2SMark Johnston #endif 30350339a1c2SMark Johnston if (dp->it_invalid64 && cpu_mode == SIZE64) 30360339a1c2SMark Johnston goto error; 30370339a1c2SMark Johnston break; 30380339a1c2SMark Johnston case AM: 30390339a1c2SMark Johnston which_prefix = &addr_size_prefix; 30400339a1c2SMark Johnston break; 30410339a1c2SMark Johnston case DM: 30420339a1c2SMark Johnston which_prefix = &opnd_size_prefix; 30430339a1c2SMark Johnston break; 30440339a1c2SMark Johnston } 30450339a1c2SMark Johnston if (which_prefix == NULL) 30460339a1c2SMark Johnston break; 30470339a1c2SMark Johnston *which_prefix = (opcode1 << 4) | opcode2; 30480339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 30490339a1c2SMark Johnston goto error; 30500339a1c2SMark Johnston } 30510339a1c2SMark Johnston 30520339a1c2SMark Johnston /* 30530339a1c2SMark Johnston * Handle amd64 mode PREFIX values. 30540339a1c2SMark Johnston * Some of the segment prefixes are no-ops. (only FS/GS actually work) 30550339a1c2SMark Johnston * We might have a REX prefix (opcodes 0x40-0x4f) 30560339a1c2SMark Johnston */ 30570339a1c2SMark Johnston if (cpu_mode == SIZE64) { 30580339a1c2SMark Johnston if (segment_prefix != 0x64 && segment_prefix != 0x65) 30590339a1c2SMark Johnston segment_prefix = 0; 30600339a1c2SMark Johnston 30610339a1c2SMark Johnston if (opcode1 == 0x4) { 30620339a1c2SMark Johnston rex_prefix = (opcode1 << 4) | opcode2; 30630339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 30640339a1c2SMark Johnston goto error; 30650339a1c2SMark Johnston dp = (instable_t *)&dis_distable[opcode1][opcode2]; 30660339a1c2SMark Johnston } else if (opcode1 == 0xC && 30670339a1c2SMark Johnston (opcode2 == 0x4 || opcode2 == 0x5)) { 30680339a1c2SMark Johnston /* AVX instructions */ 30690339a1c2SMark Johnston vex_prefix = (opcode1 << 4) | opcode2; 30700339a1c2SMark Johnston x->d86_rex_prefix = 0x40; 30710339a1c2SMark Johnston } 30720339a1c2SMark Johnston } else if (opcode1 == 0xC && (opcode2 == 0x4 || opcode2 == 0x5)) { 30730339a1c2SMark Johnston /* LDS, LES or AVX */ 30740339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 30750339a1c2SMark Johnston vex_prefetch = 1; 30760339a1c2SMark Johnston 30770339a1c2SMark Johnston if (mode == REG_ONLY) { 30780339a1c2SMark Johnston /* AVX */ 30790339a1c2SMark Johnston vex_prefix = (opcode1 << 4) | opcode2; 30800339a1c2SMark Johnston x->d86_rex_prefix = 0x40; 30810339a1c2SMark Johnston opcode3 = (((mode << 3) | reg)>>1) & 0x0F; 30820339a1c2SMark Johnston opcode4 = ((reg << 3) | r_m) & 0x0F; 30830339a1c2SMark Johnston } 30840339a1c2SMark Johnston } 30850339a1c2SMark Johnston 30860339a1c2SMark Johnston if (vex_prefix == VEX_2bytes) { 30870339a1c2SMark Johnston if (!vex_prefetch) { 30880339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode3, &opcode4) != 0) 30890339a1c2SMark Johnston goto error; 30900339a1c2SMark Johnston } 30910339a1c2SMark Johnston vex_R = ((opcode3 & VEX_R) & 0x0F) >> 3; 30920339a1c2SMark Johnston vex_L = ((opcode4 & VEX_L) & 0x0F) >> 2; 30930339a1c2SMark Johnston vex_v = (((opcode3 << 4) | opcode4) & VEX_v) >> 3; 30940339a1c2SMark Johnston vex_p = opcode4 & VEX_p; 30950339a1c2SMark Johnston /* 30960339a1c2SMark Johnston * The vex.x and vex.b bits are not defined in two bytes 30970339a1c2SMark Johnston * mode vex prefix, their default values are 1 30980339a1c2SMark Johnston */ 30990339a1c2SMark Johnston vex_byte1 = (opcode3 & VEX_R) | VEX_X | VEX_B; 31000339a1c2SMark Johnston 31010339a1c2SMark Johnston if (vex_R == 0) 31020339a1c2SMark Johnston x->d86_rex_prefix |= REX_R; 31030339a1c2SMark Johnston 31040339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 31050339a1c2SMark Johnston goto error; 31060339a1c2SMark Johnston 31070339a1c2SMark Johnston switch (vex_p) { 31080339a1c2SMark Johnston case VEX_p_66: 31090339a1c2SMark Johnston dp = (instable_t *) 31100339a1c2SMark Johnston &dis_opAVX660F[(opcode1 << 4) | opcode2]; 31110339a1c2SMark Johnston break; 31120339a1c2SMark Johnston case VEX_p_F3: 31130339a1c2SMark Johnston dp = (instable_t *) 31140339a1c2SMark Johnston &dis_opAVXF30F[(opcode1 << 4) | opcode2]; 31150339a1c2SMark Johnston break; 31160339a1c2SMark Johnston case VEX_p_F2: 31170339a1c2SMark Johnston dp = (instable_t *) 31180339a1c2SMark Johnston &dis_opAVXF20F [(opcode1 << 4) | opcode2]; 31190339a1c2SMark Johnston break; 31200339a1c2SMark Johnston default: 31210339a1c2SMark Johnston dp = (instable_t *) 31220339a1c2SMark Johnston &dis_opAVX0F[opcode1][opcode2]; 31230339a1c2SMark Johnston 31240339a1c2SMark Johnston } 31250339a1c2SMark Johnston 31260339a1c2SMark Johnston } else if (vex_prefix == VEX_3bytes) { 31270339a1c2SMark Johnston if (!vex_prefetch) { 31280339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode3, &opcode4) != 0) 31290339a1c2SMark Johnston goto error; 31300339a1c2SMark Johnston } 31310339a1c2SMark Johnston vex_R = (opcode3 & VEX_R) >> 3; 31320339a1c2SMark Johnston vex_X = (opcode3 & VEX_X) >> 2; 31330339a1c2SMark Johnston vex_B = (opcode3 & VEX_B) >> 1; 31340339a1c2SMark Johnston vex_m = (((opcode3 << 4) | opcode4) & VEX_m); 31350339a1c2SMark Johnston vex_byte1 = opcode3 & (VEX_R | VEX_X | VEX_B); 31360339a1c2SMark Johnston 31370339a1c2SMark Johnston if (vex_R == 0) 31380339a1c2SMark Johnston x->d86_rex_prefix |= REX_R; 31390339a1c2SMark Johnston if (vex_X == 0) 31400339a1c2SMark Johnston x->d86_rex_prefix |= REX_X; 31410339a1c2SMark Johnston if (vex_B == 0) 31420339a1c2SMark Johnston x->d86_rex_prefix |= REX_B; 31430339a1c2SMark Johnston 31440339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode5, &opcode6) != 0) 31450339a1c2SMark Johnston goto error; 31460339a1c2SMark Johnston vex_W = (opcode5 & VEX_W) >> 3; 31470339a1c2SMark Johnston vex_L = (opcode6 & VEX_L) >> 2; 31480339a1c2SMark Johnston vex_v = (((opcode5 << 4) | opcode6) & VEX_v) >> 3; 31490339a1c2SMark Johnston vex_p = opcode6 & VEX_p; 31500339a1c2SMark Johnston 31510339a1c2SMark Johnston if (vex_W) 31520339a1c2SMark Johnston x->d86_rex_prefix |= REX_W; 31530339a1c2SMark Johnston 31540339a1c2SMark Johnston /* Only these three vex_m values valid; others are reserved */ 31550339a1c2SMark Johnston if ((vex_m != VEX_m_0F) && (vex_m != VEX_m_0F38) && 31560339a1c2SMark Johnston (vex_m != VEX_m_0F3A)) 31570339a1c2SMark Johnston goto error; 31580339a1c2SMark Johnston 31590339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 31600339a1c2SMark Johnston goto error; 31610339a1c2SMark Johnston 31620339a1c2SMark Johnston switch (vex_p) { 31630339a1c2SMark Johnston case VEX_p_66: 31640339a1c2SMark Johnston if (vex_m == VEX_m_0F) { 31650339a1c2SMark Johnston dp = (instable_t *) 31660339a1c2SMark Johnston &dis_opAVX660F 31670339a1c2SMark Johnston [(opcode1 << 4) | opcode2]; 31680339a1c2SMark Johnston } else if (vex_m == VEX_m_0F38) { 31690339a1c2SMark Johnston dp = (instable_t *) 31700339a1c2SMark Johnston &dis_opAVX660F38 31710339a1c2SMark Johnston [(opcode1 << 4) | opcode2]; 31720339a1c2SMark Johnston } else if (vex_m == VEX_m_0F3A) { 31730339a1c2SMark Johnston dp = (instable_t *) 31740339a1c2SMark Johnston &dis_opAVX660F3A 31750339a1c2SMark Johnston [(opcode1 << 4) | opcode2]; 31760339a1c2SMark Johnston } else { 31770339a1c2SMark Johnston goto error; 31780339a1c2SMark Johnston } 31790339a1c2SMark Johnston break; 31800339a1c2SMark Johnston case VEX_p_F3: 31810339a1c2SMark Johnston if (vex_m == VEX_m_0F) { 31820339a1c2SMark Johnston dp = (instable_t *) 31830339a1c2SMark Johnston &dis_opAVXF30F 31840339a1c2SMark Johnston [(opcode1 << 4) | opcode2]; 3185*b3b5bfebSMark Johnston } else if (vex_m == VEX_m_0F38) { 3186*b3b5bfebSMark Johnston dp = (instable_t *) 3187*b3b5bfebSMark Johnston &dis_opAVXF30F38 3188*b3b5bfebSMark Johnston [(opcode1 << 4) | opcode2]; 31890339a1c2SMark Johnston } else { 31900339a1c2SMark Johnston goto error; 31910339a1c2SMark Johnston } 31920339a1c2SMark Johnston break; 31930339a1c2SMark Johnston case VEX_p_F2: 31940339a1c2SMark Johnston if (vex_m == VEX_m_0F) { 31950339a1c2SMark Johnston dp = (instable_t *) 31960339a1c2SMark Johnston &dis_opAVXF20F 31970339a1c2SMark Johnston [(opcode1 << 4) | opcode2]; 3198*b3b5bfebSMark Johnston } else if (vex_m == VEX_m_0F3A) { 3199*b3b5bfebSMark Johnston dp = (instable_t *) 3200*b3b5bfebSMark Johnston &dis_opAVXF20F3A 3201*b3b5bfebSMark Johnston [(opcode1 << 4) | opcode2]; 3202*b3b5bfebSMark Johnston } else if (vex_m == VEX_m_0F38) { 3203*b3b5bfebSMark Johnston dp = (instable_t *) 3204*b3b5bfebSMark Johnston &dis_opAVXF20F38 3205*b3b5bfebSMark Johnston [(opcode1 << 4) | opcode2]; 32060339a1c2SMark Johnston } else { 32070339a1c2SMark Johnston goto error; 32080339a1c2SMark Johnston } 32090339a1c2SMark Johnston break; 32100339a1c2SMark Johnston default: 32110339a1c2SMark Johnston dp = (instable_t *) 32120339a1c2SMark Johnston &dis_opAVX0F[opcode1][opcode2]; 32130339a1c2SMark Johnston 32140339a1c2SMark Johnston } 32150339a1c2SMark Johnston } 32160339a1c2SMark Johnston if (vex_prefix) { 3217*b3b5bfebSMark Johnston if (dp->it_vexwoxmm) { 3218*b3b5bfebSMark Johnston wbit = LONG_OPND; 3219*b3b5bfebSMark Johnston } else { 32200339a1c2SMark Johnston if (vex_L) 32210339a1c2SMark Johnston wbit = YMM_OPND; 32220339a1c2SMark Johnston else 32230339a1c2SMark Johnston wbit = XMM_OPND; 32240339a1c2SMark Johnston } 3225*b3b5bfebSMark Johnston } 32260339a1c2SMark Johnston 32270339a1c2SMark Johnston /* 32280339a1c2SMark Johnston * Deal with selection of operand and address size now. 32290339a1c2SMark Johnston * Note that the REX.W bit being set causes opnd_size_prefix to be 32300339a1c2SMark Johnston * ignored. 32310339a1c2SMark Johnston */ 32320339a1c2SMark Johnston if (cpu_mode == SIZE64) { 32330339a1c2SMark Johnston if ((rex_prefix & REX_W) || vex_W) 32340339a1c2SMark Johnston opnd_size = SIZE64; 32350339a1c2SMark Johnston else if (opnd_size_prefix) 32360339a1c2SMark Johnston opnd_size = SIZE16; 32370339a1c2SMark Johnston 32380339a1c2SMark Johnston if (addr_size_prefix) 32390339a1c2SMark Johnston addr_size = SIZE32; 32400339a1c2SMark Johnston } else if (cpu_mode == SIZE32) { 32410339a1c2SMark Johnston if (opnd_size_prefix) 32420339a1c2SMark Johnston opnd_size = SIZE16; 32430339a1c2SMark Johnston if (addr_size_prefix) 32440339a1c2SMark Johnston addr_size = SIZE16; 32450339a1c2SMark Johnston } else { 32460339a1c2SMark Johnston if (opnd_size_prefix) 32470339a1c2SMark Johnston opnd_size = SIZE32; 32480339a1c2SMark Johnston if (addr_size_prefix) 32490339a1c2SMark Johnston addr_size = SIZE32; 32500339a1c2SMark Johnston } 32510339a1c2SMark Johnston /* 32520339a1c2SMark Johnston * The pause instruction - a repz'd nop. This doesn't fit 32530339a1c2SMark Johnston * with any of the other prefix goop added for SSE, so we'll 32540339a1c2SMark Johnston * special-case it here. 32550339a1c2SMark Johnston */ 32560339a1c2SMark Johnston if (rep_prefix == 0xf3 && opcode1 == 0x9 && opcode2 == 0x0) { 32570339a1c2SMark Johnston rep_prefix = 0; 32580339a1c2SMark Johnston dp = (instable_t *)&dis_opPause; 32590339a1c2SMark Johnston } 32600339a1c2SMark Johnston 32610339a1c2SMark Johnston /* 32620339a1c2SMark Johnston * Some 386 instructions have 2 bytes of opcode before the mod_r/m 32630339a1c2SMark Johnston * byte so we may need to perform a table indirection. 32640339a1c2SMark Johnston */ 32650339a1c2SMark Johnston if (dp->it_indirect == (instable_t *)dis_op0F) { 32660339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode4, &opcode5) != 0) 32670339a1c2SMark Johnston goto error; 32680339a1c2SMark Johnston opcode_bytes = 2; 32690339a1c2SMark Johnston if (opcode4 == 0x7 && opcode5 >= 0x1 && opcode5 <= 0x3) { 32700339a1c2SMark Johnston uint_t subcode; 32710339a1c2SMark Johnston 32720339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 32730339a1c2SMark Johnston goto error; 32740339a1c2SMark Johnston opcode_bytes = 3; 32750339a1c2SMark Johnston subcode = ((opcode6 & 0x3) << 1) | 32760339a1c2SMark Johnston ((opcode7 & 0x8) >> 3); 32770339a1c2SMark Johnston dp = (instable_t *)&dis_op0F7123[opcode5][subcode]; 32780339a1c2SMark Johnston } else if ((opcode4 == 0xc) && (opcode5 >= 0x8)) { 32790339a1c2SMark Johnston dp = (instable_t *)&dis_op0FC8[0]; 32800339a1c2SMark Johnston } else if ((opcode4 == 0x3) && (opcode5 == 0xA)) { 32810339a1c2SMark Johnston opcode_bytes = 3; 32820339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 32830339a1c2SMark Johnston goto error; 32840339a1c2SMark Johnston if (opnd_size == SIZE16) 32850339a1c2SMark Johnston opnd_size = SIZE32; 32860339a1c2SMark Johnston 32870339a1c2SMark Johnston dp = (instable_t *)&dis_op0F3A[(opcode6<<4)|opcode7]; 32880339a1c2SMark Johnston #ifdef DIS_TEXT 32890339a1c2SMark Johnston if (strcmp(dp->it_name, "INVALID") == 0) 32900339a1c2SMark Johnston goto error; 32910339a1c2SMark Johnston #endif 32920339a1c2SMark Johnston switch (dp->it_adrmode) { 3293*b3b5bfebSMark Johnston case XMMP: 3294*b3b5bfebSMark Johnston break; 32950339a1c2SMark Johnston case XMMP_66r: 32960339a1c2SMark Johnston case XMMPRM_66r: 32970339a1c2SMark Johnston case XMM3PM_66r: 32980339a1c2SMark Johnston if (opnd_size_prefix == 0) { 32990339a1c2SMark Johnston goto error; 33000339a1c2SMark Johnston } 33010339a1c2SMark Johnston break; 33020339a1c2SMark Johnston case XMMP_66o: 33030339a1c2SMark Johnston if (opnd_size_prefix == 0) { 33040339a1c2SMark Johnston /* SSSE3 MMX instructions */ 33050339a1c2SMark Johnston dp_mmx = *dp; 33060339a1c2SMark Johnston dp = &dp_mmx; 33070339a1c2SMark Johnston dp->it_adrmode = MMOPM_66o; 33080339a1c2SMark Johnston #ifdef DIS_MEM 33090339a1c2SMark Johnston dp->it_size = 8; 33100339a1c2SMark Johnston #endif 33110339a1c2SMark Johnston } 33120339a1c2SMark Johnston break; 33130339a1c2SMark Johnston default: 33140339a1c2SMark Johnston goto error; 33150339a1c2SMark Johnston } 33160339a1c2SMark Johnston } else if ((opcode4 == 0x3) && (opcode5 == 0x8)) { 33170339a1c2SMark Johnston opcode_bytes = 3; 33180339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 33190339a1c2SMark Johnston goto error; 33200339a1c2SMark Johnston dp = (instable_t *)&dis_op0F38[(opcode6<<4)|opcode7]; 33210339a1c2SMark Johnston 33220339a1c2SMark Johnston /* 33230339a1c2SMark Johnston * Both crc32 and movbe have the same 3rd opcode 33240339a1c2SMark Johnston * byte of either 0xF0 or 0xF1, so we use another 33250339a1c2SMark Johnston * indirection to distinguish between the two. 33260339a1c2SMark Johnston */ 33270339a1c2SMark Johnston if (dp->it_indirect == (instable_t *)dis_op0F38F0 || 33280339a1c2SMark Johnston dp->it_indirect == (instable_t *)dis_op0F38F1) { 33290339a1c2SMark Johnston 33300339a1c2SMark Johnston dp = dp->it_indirect; 33310339a1c2SMark Johnston if (rep_prefix != 0xF2) { 33320339a1c2SMark Johnston /* It is movbe */ 33330339a1c2SMark Johnston dp++; 33340339a1c2SMark Johnston } 33350339a1c2SMark Johnston } 3336*b3b5bfebSMark Johnston 3337*b3b5bfebSMark Johnston /* 3338*b3b5bfebSMark Johnston * The adx family of instructions (adcx and adox) 3339*b3b5bfebSMark Johnston * continue the classic Intel tradition of abusing 3340*b3b5bfebSMark Johnston * arbitrary prefixes without actually meaning the 3341*b3b5bfebSMark Johnston * prefix bit. Therefore, if we find either the 3342*b3b5bfebSMark Johnston * opnd_size_prefix or rep_prefix we end up zeroing it 3343*b3b5bfebSMark Johnston * out after making our determination so as to ensure 3344*b3b5bfebSMark Johnston * that we don't get confused and accidentally print 3345*b3b5bfebSMark Johnston * repz prefixes and the like on these instructions. 3346*b3b5bfebSMark Johnston * 3347*b3b5bfebSMark Johnston * In addition, these instructions are actually much 3348*b3b5bfebSMark Johnston * closer to AVX instructions in semantics. Importantly, 3349*b3b5bfebSMark Johnston * they always default to having 32-bit operands. 3350*b3b5bfebSMark Johnston * However, if the CPU is in 64-bit mode, then and only 3351*b3b5bfebSMark Johnston * then, does it use REX.w promotes things to 64-bits 3352*b3b5bfebSMark Johnston * and REX.r allows 64-bit mode to use register r8-r15. 3353*b3b5bfebSMark Johnston */ 3354*b3b5bfebSMark Johnston if (dp->it_indirect == (instable_t *)dis_op0F38F6) { 3355*b3b5bfebSMark Johnston dp = dp->it_indirect; 3356*b3b5bfebSMark Johnston if (opnd_size_prefix == 0 && 3357*b3b5bfebSMark Johnston rep_prefix == 0xf3) { 3358*b3b5bfebSMark Johnston /* It is adox */ 3359*b3b5bfebSMark Johnston dp++; 3360*b3b5bfebSMark Johnston } else if (opnd_size_prefix != 0x66 && 3361*b3b5bfebSMark Johnston rep_prefix != 0) { 3362*b3b5bfebSMark Johnston /* It isn't adcx */ 3363*b3b5bfebSMark Johnston goto error; 3364*b3b5bfebSMark Johnston } 3365*b3b5bfebSMark Johnston opnd_size_prefix = 0; 3366*b3b5bfebSMark Johnston rep_prefix = 0; 3367*b3b5bfebSMark Johnston opnd_size = SIZE32; 3368*b3b5bfebSMark Johnston if (rex_prefix & REX_W) 3369*b3b5bfebSMark Johnston opnd_size = SIZE64; 3370*b3b5bfebSMark Johnston } 3371*b3b5bfebSMark Johnston 33720339a1c2SMark Johnston #ifdef DIS_TEXT 33730339a1c2SMark Johnston if (strcmp(dp->it_name, "INVALID") == 0) 33740339a1c2SMark Johnston goto error; 33750339a1c2SMark Johnston #endif 33760339a1c2SMark Johnston switch (dp->it_adrmode) { 3377*b3b5bfebSMark Johnston case ADX: 3378*b3b5bfebSMark Johnston case XMM: 3379*b3b5bfebSMark Johnston break; 3380c3ddb60eSPeter Grehan case RM_66r: 33810339a1c2SMark Johnston case XMM_66r: 33820339a1c2SMark Johnston case XMMM_66r: 33830339a1c2SMark Johnston if (opnd_size_prefix == 0) { 33840339a1c2SMark Johnston goto error; 33850339a1c2SMark Johnston } 33860339a1c2SMark Johnston break; 33870339a1c2SMark Johnston case XMM_66o: 33880339a1c2SMark Johnston if (opnd_size_prefix == 0) { 33890339a1c2SMark Johnston /* SSSE3 MMX instructions */ 33900339a1c2SMark Johnston dp_mmx = *dp; 33910339a1c2SMark Johnston dp = &dp_mmx; 33920339a1c2SMark Johnston dp->it_adrmode = MM; 33930339a1c2SMark Johnston #ifdef DIS_MEM 33940339a1c2SMark Johnston dp->it_size = 8; 33950339a1c2SMark Johnston #endif 33960339a1c2SMark Johnston } 33970339a1c2SMark Johnston break; 33980339a1c2SMark Johnston case CRC32: 33990339a1c2SMark Johnston if (rep_prefix != 0xF2) { 34000339a1c2SMark Johnston goto error; 34010339a1c2SMark Johnston } 34020339a1c2SMark Johnston rep_prefix = 0; 34030339a1c2SMark Johnston break; 34040339a1c2SMark Johnston case MOVBE: 34050339a1c2SMark Johnston if (rep_prefix != 0x0) { 34060339a1c2SMark Johnston goto error; 34070339a1c2SMark Johnston } 34080339a1c2SMark Johnston break; 34090339a1c2SMark Johnston default: 34100339a1c2SMark Johnston goto error; 34110339a1c2SMark Johnston } 34120339a1c2SMark Johnston } else { 34130339a1c2SMark Johnston dp = (instable_t *)&dis_op0F[opcode4][opcode5]; 34140339a1c2SMark Johnston } 34150339a1c2SMark Johnston } 34160339a1c2SMark Johnston 34170339a1c2SMark Johnston /* 34180339a1c2SMark Johnston * If still not at a TERM decode entry, then a ModRM byte 34190339a1c2SMark Johnston * exists and its fields further decode the instruction. 34200339a1c2SMark Johnston */ 34210339a1c2SMark Johnston x->d86_got_modrm = 0; 34220339a1c2SMark Johnston if (dp->it_indirect != TERM) { 34230339a1c2SMark Johnston dtrace_get_modrm(x, &mode, &opcode3, &r_m); 34240339a1c2SMark Johnston if (x->d86_error) 34250339a1c2SMark Johnston goto error; 34260339a1c2SMark Johnston reg = opcode3; 34270339a1c2SMark Johnston 34280339a1c2SMark Johnston /* 34290339a1c2SMark Johnston * decode 287 instructions (D8-DF) from opcodeN 34300339a1c2SMark Johnston */ 34310339a1c2SMark Johnston if (opcode1 == 0xD && opcode2 >= 0x8) { 34320339a1c2SMark Johnston if (opcode2 == 0xB && mode == 0x3 && opcode3 == 4) 34330339a1c2SMark Johnston dp = (instable_t *)&dis_opFP5[r_m]; 34340339a1c2SMark Johnston else if (opcode2 == 0xA && mode == 0x3 && opcode3 < 4) 34350339a1c2SMark Johnston dp = (instable_t *)&dis_opFP7[opcode3]; 34360339a1c2SMark Johnston else if (opcode2 == 0xB && mode == 0x3) 34370339a1c2SMark Johnston dp = (instable_t *)&dis_opFP6[opcode3]; 34380339a1c2SMark Johnston else if (opcode2 == 0x9 && mode == 0x3 && opcode3 >= 4) 34390339a1c2SMark Johnston dp = (instable_t *)&dis_opFP4[opcode3 - 4][r_m]; 34400339a1c2SMark Johnston else if (mode == 0x3) 34410339a1c2SMark Johnston dp = (instable_t *) 34420339a1c2SMark Johnston &dis_opFP3[opcode2 - 8][opcode3]; 34430339a1c2SMark Johnston else 34440339a1c2SMark Johnston dp = (instable_t *) 34450339a1c2SMark Johnston &dis_opFP1n2[opcode2 - 8][opcode3]; 34460339a1c2SMark Johnston } else { 34470339a1c2SMark Johnston dp = (instable_t *)dp->it_indirect + opcode3; 34480339a1c2SMark Johnston } 34490339a1c2SMark Johnston } 34500339a1c2SMark Johnston 34510339a1c2SMark Johnston /* 34520339a1c2SMark Johnston * In amd64 bit mode, ARPL opcode is changed to MOVSXD 34530339a1c2SMark Johnston * (sign extend 32bit to 64 bit) 34540339a1c2SMark Johnston */ 34550339a1c2SMark Johnston if ((vex_prefix == 0) && cpu_mode == SIZE64 && 34560339a1c2SMark Johnston opcode1 == 0x6 && opcode2 == 0x3) 34570339a1c2SMark Johnston dp = (instable_t *)&dis_opMOVSLD; 34580339a1c2SMark Johnston 34590339a1c2SMark Johnston /* 34600339a1c2SMark Johnston * at this point we should have a correct (or invalid) opcode 34610339a1c2SMark Johnston */ 34620339a1c2SMark Johnston if (cpu_mode == SIZE64 && dp->it_invalid64 || 34630339a1c2SMark Johnston cpu_mode != SIZE64 && dp->it_invalid32) 34640339a1c2SMark Johnston goto error; 34650339a1c2SMark Johnston if (dp->it_indirect != TERM) 34660339a1c2SMark Johnston goto error; 34670339a1c2SMark Johnston 34680339a1c2SMark Johnston /* 3469*b3b5bfebSMark Johnston * Deal with MMX/SSE opcodes which are changed by prefixes. Note, we do 3470*b3b5bfebSMark Johnston * need to include UNKNOWN below, as we may have instructions that 3471*b3b5bfebSMark Johnston * actually have a prefix, but don't exist in any other form. 34720339a1c2SMark Johnston */ 34730339a1c2SMark Johnston switch (dp->it_adrmode) { 3474*b3b5bfebSMark Johnston case UNKNOWN: 34750339a1c2SMark Johnston case MMO: 34760339a1c2SMark Johnston case MMOIMPL: 34770339a1c2SMark Johnston case MMO3P: 34780339a1c2SMark Johnston case MMOM3: 34790339a1c2SMark Johnston case MMOMS: 34800339a1c2SMark Johnston case MMOPM: 34810339a1c2SMark Johnston case MMOPRM: 34820339a1c2SMark Johnston case MMOS: 34830339a1c2SMark Johnston case XMMO: 34840339a1c2SMark Johnston case XMMOM: 34850339a1c2SMark Johnston case XMMOMS: 34860339a1c2SMark Johnston case XMMOPM: 34870339a1c2SMark Johnston case XMMOS: 34880339a1c2SMark Johnston case XMMOMX: 34890339a1c2SMark Johnston case XMMOX3: 34900339a1c2SMark Johnston case XMMOXMM: 34910339a1c2SMark Johnston /* 34920339a1c2SMark Johnston * This is horrible. Some SIMD instructions take the 34930339a1c2SMark Johnston * form 0x0F 0x?? ..., which is easily decoded using the 34940339a1c2SMark Johnston * existing tables. Other SIMD instructions use various 34950339a1c2SMark Johnston * prefix bytes to overload existing instructions. For 34960339a1c2SMark Johnston * Example, addps is F0, 58, whereas addss is F3 (repz), 34970339a1c2SMark Johnston * F0, 58. Presumably someone got a raise for this. 34980339a1c2SMark Johnston * 34990339a1c2SMark Johnston * If we see one of the instructions which can be 35000339a1c2SMark Johnston * modified in this way (if we've got one of the SIMDO* 35010339a1c2SMark Johnston * address modes), we'll check to see if the last prefix 35020339a1c2SMark Johnston * was a repz. If it was, we strip the prefix from the 35030339a1c2SMark Johnston * mnemonic, and we indirect using the dis_opSIMDrepz 35040339a1c2SMark Johnston * table. 35050339a1c2SMark Johnston */ 35060339a1c2SMark Johnston 35070339a1c2SMark Johnston /* 35080339a1c2SMark Johnston * Calculate our offset in dis_op0F 35090339a1c2SMark Johnston */ 35100339a1c2SMark Johnston if ((uintptr_t)dp - (uintptr_t)dis_op0F > sizeof (dis_op0F)) 35110339a1c2SMark Johnston goto error; 35120339a1c2SMark Johnston 35130339a1c2SMark Johnston off = ((uintptr_t)dp - (uintptr_t)dis_op0F) / 35140339a1c2SMark Johnston sizeof (instable_t); 35150339a1c2SMark Johnston 35160339a1c2SMark Johnston /* 35170339a1c2SMark Johnston * Rewrite if this instruction used one of the magic prefixes. 35180339a1c2SMark Johnston */ 35190339a1c2SMark Johnston if (rep_prefix) { 35200339a1c2SMark Johnston if (rep_prefix == 0xf2) 35210339a1c2SMark Johnston dp = (instable_t *)&dis_opSIMDrepnz[off]; 35220339a1c2SMark Johnston else 35230339a1c2SMark Johnston dp = (instable_t *)&dis_opSIMDrepz[off]; 35240339a1c2SMark Johnston rep_prefix = 0; 35250339a1c2SMark Johnston } else if (opnd_size_prefix) { 35260339a1c2SMark Johnston dp = (instable_t *)&dis_opSIMDdata16[off]; 35270339a1c2SMark Johnston opnd_size_prefix = 0; 35280339a1c2SMark Johnston if (opnd_size == SIZE16) 35290339a1c2SMark Johnston opnd_size = SIZE32; 35300339a1c2SMark Johnston } 35310339a1c2SMark Johnston break; 35320339a1c2SMark Johnston 3533c3ddb60eSPeter Grehan case MG9: 3534c3ddb60eSPeter Grehan /* 3535c3ddb60eSPeter Grehan * More horribleness: the group 9 (0xF0 0xC7) instructions are 3536c3ddb60eSPeter Grehan * allowed an optional prefix of 0x66 or 0xF3. This is similar 3537c3ddb60eSPeter Grehan * to the SIMD business described above, but with a different 3538c3ddb60eSPeter Grehan * addressing mode (and an indirect table), so we deal with it 3539c3ddb60eSPeter Grehan * separately (if similarly). 3540c3ddb60eSPeter Grehan * 3541c3ddb60eSPeter Grehan * Intel further complicated this with the release of Ivy Bridge 3542c3ddb60eSPeter Grehan * where they overloaded these instructions based on the ModR/M 3543c3ddb60eSPeter Grehan * bytes. The VMX instructions have a mode of 0 since they are 3544c3ddb60eSPeter Grehan * memory instructions but rdrand instructions have a mode of 3545c3ddb60eSPeter Grehan * 0b11 (REG_ONLY) because they only operate on registers. While 3546c3ddb60eSPeter Grehan * there are different prefix formats, for now it is sufficient 3547c3ddb60eSPeter Grehan * to use a single different table. 3548c3ddb60eSPeter Grehan */ 3549c3ddb60eSPeter Grehan 3550c3ddb60eSPeter Grehan /* 3551c3ddb60eSPeter Grehan * Calculate our offset in dis_op0FC7 (the group 9 table) 3552c3ddb60eSPeter Grehan */ 3553c3ddb60eSPeter Grehan if ((uintptr_t)dp - (uintptr_t)dis_op0FC7 > sizeof (dis_op0FC7)) 3554c3ddb60eSPeter Grehan goto error; 3555c3ddb60eSPeter Grehan 3556c3ddb60eSPeter Grehan off = ((uintptr_t)dp - (uintptr_t)dis_op0FC7) / 3557c3ddb60eSPeter Grehan sizeof (instable_t); 3558c3ddb60eSPeter Grehan 3559c3ddb60eSPeter Grehan /* 3560c3ddb60eSPeter Grehan * If we have a mode of 0b11 then we have to rewrite this. 3561c3ddb60eSPeter Grehan */ 3562c3ddb60eSPeter Grehan dtrace_get_modrm(x, &mode, ®, &r_m); 3563c3ddb60eSPeter Grehan if (mode == REG_ONLY) { 3564c3ddb60eSPeter Grehan dp = (instable_t *)&dis_op0FC7m3[off]; 3565c3ddb60eSPeter Grehan break; 3566c3ddb60eSPeter Grehan } 3567c3ddb60eSPeter Grehan 3568c3ddb60eSPeter Grehan /* 3569c3ddb60eSPeter Grehan * Rewrite if this instruction used one of the magic prefixes. 3570c3ddb60eSPeter Grehan */ 3571c3ddb60eSPeter Grehan if (rep_prefix) { 3572c3ddb60eSPeter Grehan if (rep_prefix == 0xf3) 3573c3ddb60eSPeter Grehan dp = (instable_t *)&dis_opF30FC7[off]; 3574c3ddb60eSPeter Grehan else 3575c3ddb60eSPeter Grehan goto error; 3576c3ddb60eSPeter Grehan rep_prefix = 0; 3577c3ddb60eSPeter Grehan } else if (opnd_size_prefix) { 3578c3ddb60eSPeter Grehan dp = (instable_t *)&dis_op660FC7[off]; 3579c3ddb60eSPeter Grehan opnd_size_prefix = 0; 3580c3ddb60eSPeter Grehan if (opnd_size == SIZE16) 3581c3ddb60eSPeter Grehan opnd_size = SIZE32; 3582c3ddb60eSPeter Grehan } 3583c3ddb60eSPeter Grehan break; 3584c3ddb60eSPeter Grehan 3585c3ddb60eSPeter Grehan 35860339a1c2SMark Johnston case MMOSH: 35870339a1c2SMark Johnston /* 35880339a1c2SMark Johnston * As with the "normal" SIMD instructions, the MMX 35890339a1c2SMark Johnston * shuffle instructions are overloaded. These 35900339a1c2SMark Johnston * instructions, however, are special in that they use 35910339a1c2SMark Johnston * an extra byte, and thus an extra table. As of this 35920339a1c2SMark Johnston * writing, they only use the opnd_size prefix. 35930339a1c2SMark Johnston */ 35940339a1c2SMark Johnston 35950339a1c2SMark Johnston /* 35960339a1c2SMark Johnston * Calculate our offset in dis_op0F7123 35970339a1c2SMark Johnston */ 35980339a1c2SMark Johnston if ((uintptr_t)dp - (uintptr_t)dis_op0F7123 > 35990339a1c2SMark Johnston sizeof (dis_op0F7123)) 36000339a1c2SMark Johnston goto error; 36010339a1c2SMark Johnston 36020339a1c2SMark Johnston if (opnd_size_prefix) { 36030339a1c2SMark Johnston off = ((uintptr_t)dp - (uintptr_t)dis_op0F7123) / 36040339a1c2SMark Johnston sizeof (instable_t); 36050339a1c2SMark Johnston dp = (instable_t *)&dis_opSIMD7123[off]; 36060339a1c2SMark Johnston opnd_size_prefix = 0; 36070339a1c2SMark Johnston if (opnd_size == SIZE16) 36080339a1c2SMark Johnston opnd_size = SIZE32; 36090339a1c2SMark Johnston } 36100339a1c2SMark Johnston break; 36110339a1c2SMark Johnston case MRw: 36120339a1c2SMark Johnston if (rep_prefix) { 36130339a1c2SMark Johnston if (rep_prefix == 0xf3) { 36140339a1c2SMark Johnston 36150339a1c2SMark Johnston /* 36160339a1c2SMark Johnston * Calculate our offset in dis_op0F 36170339a1c2SMark Johnston */ 36180339a1c2SMark Johnston if ((uintptr_t)dp - (uintptr_t)dis_op0F 36190339a1c2SMark Johnston > sizeof (dis_op0F)) 36200339a1c2SMark Johnston goto error; 36210339a1c2SMark Johnston 36220339a1c2SMark Johnston off = ((uintptr_t)dp - (uintptr_t)dis_op0F) / 36230339a1c2SMark Johnston sizeof (instable_t); 36240339a1c2SMark Johnston 36250339a1c2SMark Johnston dp = (instable_t *)&dis_opSIMDrepz[off]; 36260339a1c2SMark Johnston rep_prefix = 0; 36270339a1c2SMark Johnston } else { 36280339a1c2SMark Johnston goto error; 36290339a1c2SMark Johnston } 36300339a1c2SMark Johnston } 36310339a1c2SMark Johnston break; 36320339a1c2SMark Johnston } 36330339a1c2SMark Johnston 36340339a1c2SMark Johnston /* 36350339a1c2SMark Johnston * In 64 bit mode, some opcodes automatically use opnd_size == SIZE64. 36360339a1c2SMark Johnston */ 36370339a1c2SMark Johnston if (cpu_mode == SIZE64) 36380339a1c2SMark Johnston if (dp->it_always64 || (opnd_size == SIZE32 && dp->it_stackop)) 36390339a1c2SMark Johnston opnd_size = SIZE64; 36400339a1c2SMark Johnston 36410339a1c2SMark Johnston #ifdef DIS_TEXT 36420339a1c2SMark Johnston /* 36430339a1c2SMark Johnston * At this point most instructions can format the opcode mnemonic 36440339a1c2SMark Johnston * including the prefixes. 36450339a1c2SMark Johnston */ 36460339a1c2SMark Johnston if (lock_prefix) 36470339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "lock ", OPLEN); 36480339a1c2SMark Johnston 36490339a1c2SMark Johnston if (rep_prefix == 0xf2) 36500339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "repnz ", OPLEN); 36510339a1c2SMark Johnston else if (rep_prefix == 0xf3) 36520339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "repz ", OPLEN); 36530339a1c2SMark Johnston 36540339a1c2SMark Johnston if (cpu_mode == SIZE64 && addr_size_prefix) 36550339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "addr32 ", OPLEN); 36560339a1c2SMark Johnston 36570339a1c2SMark Johnston if (dp->it_adrmode != CBW && 36580339a1c2SMark Johnston dp->it_adrmode != CWD && 36590339a1c2SMark Johnston dp->it_adrmode != XMMSFNC) { 36600339a1c2SMark Johnston if (strcmp(dp->it_name, "INVALID") == 0) 36610339a1c2SMark Johnston goto error; 36620339a1c2SMark Johnston (void) strlcat(x->d86_mnem, dp->it_name, OPLEN); 3663*b3b5bfebSMark Johnston if (dp->it_avxsuf && dp->it_suffix) { 3664*b3b5bfebSMark Johnston (void) strlcat(x->d86_mnem, vex_W != 0 ? "q" : "d", 3665*b3b5bfebSMark Johnston OPLEN); 3666*b3b5bfebSMark Johnston } else if (dp->it_suffix) { 36670339a1c2SMark Johnston char *types[] = {"", "w", "l", "q"}; 36680339a1c2SMark Johnston if (opcode_bytes == 2 && opcode4 == 4) { 36690339a1c2SMark Johnston /* It's a cmovx.yy. Replace the suffix x */ 36700339a1c2SMark Johnston for (i = 5; i < OPLEN; i++) { 36710339a1c2SMark Johnston if (x->d86_mnem[i] == '.') 36720339a1c2SMark Johnston break; 36730339a1c2SMark Johnston } 36740339a1c2SMark Johnston x->d86_mnem[i - 1] = *types[opnd_size]; 36750339a1c2SMark Johnston } else if ((opnd_size == 2) && (opcode_bytes == 3) && 36760339a1c2SMark Johnston ((opcode6 == 1 && opcode7 == 6) || 36770339a1c2SMark Johnston (opcode6 == 2 && opcode7 == 2))) { 36780339a1c2SMark Johnston /* 36790339a1c2SMark Johnston * To handle PINSRD and PEXTRD 36800339a1c2SMark Johnston */ 36810339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "d", OPLEN); 36820339a1c2SMark Johnston } else { 36830339a1c2SMark Johnston (void) strlcat(x->d86_mnem, types[opnd_size], 36840339a1c2SMark Johnston OPLEN); 36850339a1c2SMark Johnston } 36860339a1c2SMark Johnston } 36870339a1c2SMark Johnston } 36880339a1c2SMark Johnston #endif 36890339a1c2SMark Johnston 36900339a1c2SMark Johnston /* 36910339a1c2SMark Johnston * Process operands based on the addressing modes. 36920339a1c2SMark Johnston */ 36930339a1c2SMark Johnston x->d86_mode = cpu_mode; 36940339a1c2SMark Johnston /* 36950339a1c2SMark Johnston * In vex mode the rex_prefix has no meaning 36960339a1c2SMark Johnston */ 36970339a1c2SMark Johnston if (!vex_prefix) 36980339a1c2SMark Johnston x->d86_rex_prefix = rex_prefix; 36990339a1c2SMark Johnston x->d86_opnd_size = opnd_size; 37000339a1c2SMark Johnston x->d86_addr_size = addr_size; 37010339a1c2SMark Johnston vbit = 0; /* initialize for mem/reg -> reg */ 37020339a1c2SMark Johnston switch (dp->it_adrmode) { 37030339a1c2SMark Johnston /* 37040339a1c2SMark Johnston * amd64 instruction to sign extend 32 bit reg/mem operands 37050339a1c2SMark Johnston * into 64 bit register values 37060339a1c2SMark Johnston */ 37070339a1c2SMark Johnston case MOVSXZ: 37080339a1c2SMark Johnston #ifdef DIS_TEXT 37090339a1c2SMark Johnston if (rex_prefix == 0) 37100339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "movzld", OPLEN); 37110339a1c2SMark Johnston #endif 37120339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 37130339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 37140339a1c2SMark Johnston x->d86_opnd_size = SIZE64; 37150339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 37160339a1c2SMark Johnston x->d86_opnd_size = opnd_size = SIZE32; 37170339a1c2SMark Johnston wbit = LONG_OPND; 37180339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 37190339a1c2SMark Johnston break; 37200339a1c2SMark Johnston 37210339a1c2SMark Johnston /* 37220339a1c2SMark Johnston * movsbl movsbw movsbq (0x0FBE) or movswl movswq (0x0FBF) 37230339a1c2SMark Johnston * movzbl movzbw movzbq (0x0FB6) or movzwl movzwq (0x0FB7) 37240339a1c2SMark Johnston * wbit lives in 2nd byte, note that operands 37250339a1c2SMark Johnston * are different sized 37260339a1c2SMark Johnston */ 37270339a1c2SMark Johnston case MOVZ: 37280339a1c2SMark Johnston if (rex_prefix & REX_W) { 37290339a1c2SMark Johnston /* target register size = 64 bit */ 37300339a1c2SMark Johnston x->d86_mnem[5] = 'q'; 37310339a1c2SMark Johnston } 37320339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 37330339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 37340339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 37350339a1c2SMark Johnston x->d86_opnd_size = opnd_size = SIZE16; 37360339a1c2SMark Johnston wbit = WBIT(opcode5); 37370339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 37380339a1c2SMark Johnston break; 37390339a1c2SMark Johnston case CRC32: 37400339a1c2SMark Johnston opnd_size = SIZE32; 37410339a1c2SMark Johnston if (rex_prefix & REX_W) 37420339a1c2SMark Johnston opnd_size = SIZE64; 37430339a1c2SMark Johnston x->d86_opnd_size = opnd_size; 37440339a1c2SMark Johnston 37450339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 37460339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 37470339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 37480339a1c2SMark Johnston wbit = WBIT(opcode7); 37490339a1c2SMark Johnston if (opnd_size_prefix) 37500339a1c2SMark Johnston x->d86_opnd_size = opnd_size = SIZE16; 37510339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 37520339a1c2SMark Johnston break; 37530339a1c2SMark Johnston case MOVBE: 37540339a1c2SMark Johnston opnd_size = SIZE32; 37550339a1c2SMark Johnston if (rex_prefix & REX_W) 37560339a1c2SMark Johnston opnd_size = SIZE64; 37570339a1c2SMark Johnston x->d86_opnd_size = opnd_size; 37580339a1c2SMark Johnston 37590339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 37600339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 37610339a1c2SMark Johnston wbit = WBIT(opcode7); 37620339a1c2SMark Johnston if (opnd_size_prefix) 37630339a1c2SMark Johnston x->d86_opnd_size = opnd_size = SIZE16; 37640339a1c2SMark Johnston if (wbit) { 37650339a1c2SMark Johnston /* reg -> mem */ 37660339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 37670339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 37680339a1c2SMark Johnston } else { 37690339a1c2SMark Johnston /* mem -> reg */ 37700339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 37710339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 37720339a1c2SMark Johnston } 37730339a1c2SMark Johnston break; 37740339a1c2SMark Johnston 37750339a1c2SMark Johnston /* 37760339a1c2SMark Johnston * imul instruction, with either 8-bit or longer immediate 37770339a1c2SMark Johnston * opcode 0x6B for byte, sign-extended displacement, 0x69 for word(s) 37780339a1c2SMark Johnston */ 37790339a1c2SMark Johnston case IMUL: 37800339a1c2SMark Johnston wbit = LONG_OPND; 37810339a1c2SMark Johnston THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 37820339a1c2SMark Johnston OPSIZE(opnd_size, opcode2 == 0x9), 1); 37830339a1c2SMark Johnston break; 37840339a1c2SMark Johnston 37850339a1c2SMark Johnston /* memory or register operand to register, with 'w' bit */ 37860339a1c2SMark Johnston case MRw: 3787*b3b5bfebSMark Johnston case ADX: 37880339a1c2SMark Johnston wbit = WBIT(opcode2); 37890339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 37900339a1c2SMark Johnston break; 37910339a1c2SMark Johnston 37920339a1c2SMark Johnston /* register to memory or register operand, with 'w' bit */ 37930339a1c2SMark Johnston /* arpl happens to fit here also because it is odd */ 37940339a1c2SMark Johnston case RMw: 37950339a1c2SMark Johnston if (opcode_bytes == 2) 37960339a1c2SMark Johnston wbit = WBIT(opcode5); 37970339a1c2SMark Johnston else 37980339a1c2SMark Johnston wbit = WBIT(opcode2); 37990339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 38000339a1c2SMark Johnston break; 38010339a1c2SMark Johnston 38020339a1c2SMark Johnston /* xaddb instruction */ 38030339a1c2SMark Johnston case XADDB: 38040339a1c2SMark Johnston wbit = 0; 38050339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 38060339a1c2SMark Johnston break; 38070339a1c2SMark Johnston 38080339a1c2SMark Johnston /* MMX register to memory or register operand */ 38090339a1c2SMark Johnston case MMS: 38100339a1c2SMark Johnston case MMOS: 38110339a1c2SMark Johnston #ifdef DIS_TEXT 38120339a1c2SMark Johnston wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 38130339a1c2SMark Johnston #else 38140339a1c2SMark Johnston wbit = LONG_OPND; 38150339a1c2SMark Johnston #endif 38160339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1); 38170339a1c2SMark Johnston break; 38180339a1c2SMark Johnston 38190339a1c2SMark Johnston /* MMX register to memory */ 38200339a1c2SMark Johnston case MMOMS: 38210339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 38220339a1c2SMark Johnston if (mode == REG_ONLY) 38230339a1c2SMark Johnston goto error; 38240339a1c2SMark Johnston wbit = MM_OPND; 38250339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1); 38260339a1c2SMark Johnston break; 38270339a1c2SMark Johnston 38280339a1c2SMark Johnston /* Double shift. Has immediate operand specifying the shift. */ 38290339a1c2SMark Johnston case DSHIFT: 38300339a1c2SMark Johnston wbit = LONG_OPND; 38310339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 38320339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 38330339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 2); 38340339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 38350339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 38360339a1c2SMark Johnston break; 38370339a1c2SMark Johnston 38380339a1c2SMark Johnston /* 38390339a1c2SMark Johnston * Double shift. With no immediate operand, specifies using %cl. 38400339a1c2SMark Johnston */ 38410339a1c2SMark Johnston case DSHIFTcl: 38420339a1c2SMark Johnston wbit = LONG_OPND; 38430339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 38440339a1c2SMark Johnston break; 38450339a1c2SMark Johnston 38460339a1c2SMark Johnston /* immediate to memory or register operand */ 38470339a1c2SMark Johnston case IMlw: 38480339a1c2SMark Johnston wbit = WBIT(opcode2); 38490339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 38500339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 38510339a1c2SMark Johnston /* 38520339a1c2SMark Johnston * Have long immediate for opcode 0x81, but not 0x80 nor 0x83 38530339a1c2SMark Johnston */ 38540339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, opcode2 == 1), 0); 38550339a1c2SMark Johnston break; 38560339a1c2SMark Johnston 38570339a1c2SMark Johnston /* immediate to memory or register operand with the */ 38580339a1c2SMark Johnston /* 'w' bit present */ 38590339a1c2SMark Johnston case IMw: 38600339a1c2SMark Johnston wbit = WBIT(opcode2); 38610339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 38620339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 38630339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 38640339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0); 38650339a1c2SMark Johnston break; 38660339a1c2SMark Johnston 38670339a1c2SMark Johnston /* immediate to register with register in low 3 bits */ 38680339a1c2SMark Johnston /* of op code */ 38690339a1c2SMark Johnston case IR: 38700339a1c2SMark Johnston /* w-bit here (with regs) is bit 3 */ 38710339a1c2SMark Johnston wbit = opcode2 >>3 & 0x1; 38720339a1c2SMark Johnston reg = REGNO(opcode2); 38730339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 38740339a1c2SMark Johnston mode = REG_ONLY; 38750339a1c2SMark Johnston r_m = reg; 38760339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 38770339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE64(opnd_size, wbit), 0); 38780339a1c2SMark Johnston break; 38790339a1c2SMark Johnston 38800339a1c2SMark Johnston /* MMX immediate shift of register */ 38810339a1c2SMark Johnston case MMSH: 38820339a1c2SMark Johnston case MMOSH: 38830339a1c2SMark Johnston wbit = MM_OPND; 38840339a1c2SMark Johnston goto mm_shift; /* in next case */ 38850339a1c2SMark Johnston 38860339a1c2SMark Johnston /* SIMD immediate shift of register */ 38870339a1c2SMark Johnston case XMMSH: 38880339a1c2SMark Johnston wbit = XMM_OPND; 38890339a1c2SMark Johnston mm_shift: 38900339a1c2SMark Johnston reg = REGNO(opcode7); 38910339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 38920339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 38930339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 38940339a1c2SMark Johnston NOMEM; 38950339a1c2SMark Johnston break; 38960339a1c2SMark Johnston 38970339a1c2SMark Johnston /* accumulator to memory operand */ 38980339a1c2SMark Johnston case AO: 38990339a1c2SMark Johnston vbit = 1; 39000339a1c2SMark Johnston /*FALLTHROUGH*/ 39010339a1c2SMark Johnston 39020339a1c2SMark Johnston /* memory operand to accumulator */ 39030339a1c2SMark Johnston case OA: 39040339a1c2SMark Johnston wbit = WBIT(opcode2); 39050339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1 - vbit); 39060339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE64(addr_size, LONG_OPND), vbit); 39070339a1c2SMark Johnston #ifdef DIS_TEXT 39080339a1c2SMark Johnston x->d86_opnd[vbit].d86_mode = MODE_OFFSET; 39090339a1c2SMark Johnston #endif 39100339a1c2SMark Johnston break; 39110339a1c2SMark Johnston 39120339a1c2SMark Johnston 39130339a1c2SMark Johnston /* segment register to memory or register operand */ 39140339a1c2SMark Johnston case SM: 39150339a1c2SMark Johnston vbit = 1; 39160339a1c2SMark Johnston /*FALLTHROUGH*/ 39170339a1c2SMark Johnston 39180339a1c2SMark Johnston /* memory or register operand to segment register */ 39190339a1c2SMark Johnston case MS: 39200339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 39210339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 39220339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, vbit); 39230339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 1 - vbit); 39240339a1c2SMark Johnston break; 39250339a1c2SMark Johnston 39260339a1c2SMark Johnston /* 39270339a1c2SMark Johnston * rotate or shift instructions, which may shift by 1 or 39280339a1c2SMark Johnston * consult the cl register, depending on the 'v' bit 39290339a1c2SMark Johnston */ 39300339a1c2SMark Johnston case Mv: 39310339a1c2SMark Johnston vbit = VBIT(opcode2); 39320339a1c2SMark Johnston wbit = WBIT(opcode2); 39330339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 39340339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 39350339a1c2SMark Johnston #ifdef DIS_TEXT 39360339a1c2SMark Johnston if (vbit) { 39370339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "%cl", OPLEN); 39380339a1c2SMark Johnston } else { 39390339a1c2SMark Johnston x->d86_opnd[0].d86_mode = MODE_SIGNED; 39400339a1c2SMark Johnston x->d86_opnd[0].d86_value_size = 1; 39410339a1c2SMark Johnston x->d86_opnd[0].d86_value = 1; 39420339a1c2SMark Johnston } 39430339a1c2SMark Johnston #endif 39440339a1c2SMark Johnston break; 39450339a1c2SMark Johnston /* 39460339a1c2SMark Johnston * immediate rotate or shift instructions 39470339a1c2SMark Johnston */ 39480339a1c2SMark Johnston case MvI: 39490339a1c2SMark Johnston wbit = WBIT(opcode2); 39500339a1c2SMark Johnston normal_imm_mem: 39510339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 39520339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 39530339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 39540339a1c2SMark Johnston break; 39550339a1c2SMark Johnston 39560339a1c2SMark Johnston /* bit test instructions */ 39570339a1c2SMark Johnston case MIb: 39580339a1c2SMark Johnston wbit = LONG_OPND; 39590339a1c2SMark Johnston goto normal_imm_mem; 39600339a1c2SMark Johnston 39610339a1c2SMark Johnston /* single memory or register operand with 'w' bit present */ 39620339a1c2SMark Johnston case Mw: 39630339a1c2SMark Johnston wbit = WBIT(opcode2); 39640339a1c2SMark Johnston just_mem: 39650339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 39660339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 39670339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 39680339a1c2SMark Johnston break; 39690339a1c2SMark Johnston 3970c3ddb60eSPeter Grehan case SWAPGS_RDTSCP: 39710339a1c2SMark Johnston if (cpu_mode == SIZE64 && mode == 3 && r_m == 0) { 39720339a1c2SMark Johnston #ifdef DIS_TEXT 39730339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "swapgs", OPLEN); 39740339a1c2SMark Johnston #endif 39750339a1c2SMark Johnston NOMEM; 39760339a1c2SMark Johnston break; 3977c3ddb60eSPeter Grehan } else if (mode == 3 && r_m == 1) { 3978c3ddb60eSPeter Grehan #ifdef DIS_TEXT 3979c3ddb60eSPeter Grehan (void) strncpy(x->d86_mnem, "rdtscp", OPLEN); 3980c3ddb60eSPeter Grehan #endif 3981c3ddb60eSPeter Grehan NOMEM; 3982c3ddb60eSPeter Grehan break; 39830339a1c2SMark Johnston } 3984c3ddb60eSPeter Grehan 39850339a1c2SMark Johnston /*FALLTHROUGH*/ 39860339a1c2SMark Johnston 39870339a1c2SMark Johnston /* prefetch instruction - memory operand, but no memory acess */ 39880339a1c2SMark Johnston case PREF: 39890339a1c2SMark Johnston NOMEM; 39900339a1c2SMark Johnston /*FALLTHROUGH*/ 39910339a1c2SMark Johnston 39920339a1c2SMark Johnston /* single memory or register operand */ 39930339a1c2SMark Johnston case M: 3994c3ddb60eSPeter Grehan case MG9: 39950339a1c2SMark Johnston wbit = LONG_OPND; 39960339a1c2SMark Johnston goto just_mem; 39970339a1c2SMark Johnston 39980339a1c2SMark Johnston /* single memory or register byte operand */ 39990339a1c2SMark Johnston case Mb: 40000339a1c2SMark Johnston wbit = BYTE_OPND; 40010339a1c2SMark Johnston goto just_mem; 40020339a1c2SMark Johnston 4003c3ddb60eSPeter Grehan case VMx: 4004c3ddb60eSPeter Grehan if (mode == 3) { 4005c3ddb60eSPeter Grehan #ifdef DIS_TEXT 4006c3ddb60eSPeter Grehan char *vminstr; 4007c3ddb60eSPeter Grehan 4008c3ddb60eSPeter Grehan switch (r_m) { 4009c3ddb60eSPeter Grehan case 1: 4010c3ddb60eSPeter Grehan vminstr = "vmcall"; 4011c3ddb60eSPeter Grehan break; 4012c3ddb60eSPeter Grehan case 2: 4013c3ddb60eSPeter Grehan vminstr = "vmlaunch"; 4014c3ddb60eSPeter Grehan break; 4015c3ddb60eSPeter Grehan case 3: 4016c3ddb60eSPeter Grehan vminstr = "vmresume"; 4017c3ddb60eSPeter Grehan break; 4018c3ddb60eSPeter Grehan case 4: 4019c3ddb60eSPeter Grehan vminstr = "vmxoff"; 4020c3ddb60eSPeter Grehan break; 4021c3ddb60eSPeter Grehan default: 4022c3ddb60eSPeter Grehan goto error; 4023c3ddb60eSPeter Grehan } 4024c3ddb60eSPeter Grehan 4025c3ddb60eSPeter Grehan (void) strncpy(x->d86_mnem, vminstr, OPLEN); 4026c3ddb60eSPeter Grehan #else 4027c3ddb60eSPeter Grehan if (r_m < 1 || r_m > 4) 4028c3ddb60eSPeter Grehan goto error; 4029c3ddb60eSPeter Grehan #endif 4030c3ddb60eSPeter Grehan 4031c3ddb60eSPeter Grehan NOMEM; 4032c3ddb60eSPeter Grehan break; 4033c3ddb60eSPeter Grehan } 4034c3ddb60eSPeter Grehan /*FALLTHROUGH*/ 4035c3ddb60eSPeter Grehan case SVM: 4036c3ddb60eSPeter Grehan if (mode == 3) { 4037c3ddb60eSPeter Grehan #ifdef DIS_TEXT 4038c3ddb60eSPeter Grehan char *vinstr; 4039c3ddb60eSPeter Grehan 4040c3ddb60eSPeter Grehan switch (r_m) { 4041c3ddb60eSPeter Grehan case 0: 4042c3ddb60eSPeter Grehan vinstr = "vmrun"; 4043c3ddb60eSPeter Grehan break; 4044c3ddb60eSPeter Grehan case 1: 4045c3ddb60eSPeter Grehan vinstr = "vmmcall"; 4046c3ddb60eSPeter Grehan break; 4047c3ddb60eSPeter Grehan case 2: 4048c3ddb60eSPeter Grehan vinstr = "vmload"; 4049c3ddb60eSPeter Grehan break; 4050c3ddb60eSPeter Grehan case 3: 4051c3ddb60eSPeter Grehan vinstr = "vmsave"; 4052c3ddb60eSPeter Grehan break; 4053c3ddb60eSPeter Grehan case 4: 4054c3ddb60eSPeter Grehan vinstr = "stgi"; 4055c3ddb60eSPeter Grehan break; 4056c3ddb60eSPeter Grehan case 5: 4057c3ddb60eSPeter Grehan vinstr = "clgi"; 4058c3ddb60eSPeter Grehan break; 4059c3ddb60eSPeter Grehan case 6: 4060c3ddb60eSPeter Grehan vinstr = "skinit"; 4061c3ddb60eSPeter Grehan break; 4062c3ddb60eSPeter Grehan case 7: 4063c3ddb60eSPeter Grehan vinstr = "invlpga"; 4064c3ddb60eSPeter Grehan break; 4065c3ddb60eSPeter Grehan } 4066c3ddb60eSPeter Grehan 4067c3ddb60eSPeter Grehan (void) strncpy(x->d86_mnem, vinstr, OPLEN); 4068c3ddb60eSPeter Grehan #endif 4069c3ddb60eSPeter Grehan NOMEM; 4070c3ddb60eSPeter Grehan break; 4071c3ddb60eSPeter Grehan } 4072c3ddb60eSPeter Grehan /*FALLTHROUGH*/ 40730339a1c2SMark Johnston case MONITOR_MWAIT: 40740339a1c2SMark Johnston if (mode == 3) { 40750339a1c2SMark Johnston if (r_m == 0) { 40760339a1c2SMark Johnston #ifdef DIS_TEXT 40770339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "monitor", OPLEN); 40780339a1c2SMark Johnston #endif 40790339a1c2SMark Johnston NOMEM; 40800339a1c2SMark Johnston break; 40810339a1c2SMark Johnston } else if (r_m == 1) { 40820339a1c2SMark Johnston #ifdef DIS_TEXT 40830339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "mwait", OPLEN); 40840339a1c2SMark Johnston #endif 40850339a1c2SMark Johnston NOMEM; 40860339a1c2SMark Johnston break; 4087*b3b5bfebSMark Johnston } else if (r_m == 2) { 4088*b3b5bfebSMark Johnston #ifdef DIS_TEXT 4089*b3b5bfebSMark Johnston (void) strncpy(x->d86_mnem, "clac", OPLEN); 4090*b3b5bfebSMark Johnston #endif 4091*b3b5bfebSMark Johnston NOMEM; 4092*b3b5bfebSMark Johnston break; 4093*b3b5bfebSMark Johnston } else if (r_m == 3) { 4094*b3b5bfebSMark Johnston #ifdef DIS_TEXT 4095*b3b5bfebSMark Johnston (void) strncpy(x->d86_mnem, "stac", OPLEN); 4096*b3b5bfebSMark Johnston #endif 4097*b3b5bfebSMark Johnston NOMEM; 4098*b3b5bfebSMark Johnston break; 40990339a1c2SMark Johnston } else { 41000339a1c2SMark Johnston goto error; 41010339a1c2SMark Johnston } 41020339a1c2SMark Johnston } 41030339a1c2SMark Johnston /*FALLTHROUGH*/ 41040339a1c2SMark Johnston case XGETBV_XSETBV: 41050339a1c2SMark Johnston if (mode == 3) { 41060339a1c2SMark Johnston if (r_m == 0) { 41070339a1c2SMark Johnston #ifdef DIS_TEXT 41080339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "xgetbv", OPLEN); 41090339a1c2SMark Johnston #endif 41100339a1c2SMark Johnston NOMEM; 41110339a1c2SMark Johnston break; 41120339a1c2SMark Johnston } else if (r_m == 1) { 41130339a1c2SMark Johnston #ifdef DIS_TEXT 41140339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "xsetbv", OPLEN); 41150339a1c2SMark Johnston #endif 41160339a1c2SMark Johnston NOMEM; 41170339a1c2SMark Johnston break; 41180339a1c2SMark Johnston } else { 41190339a1c2SMark Johnston goto error; 41200339a1c2SMark Johnston } 41210339a1c2SMark Johnston 41220339a1c2SMark Johnston } 41230339a1c2SMark Johnston /*FALLTHROUGH*/ 41240339a1c2SMark Johnston case MO: 41250339a1c2SMark Johnston /* Similar to M, but only memory (no direct registers) */ 41260339a1c2SMark Johnston wbit = LONG_OPND; 41270339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 41280339a1c2SMark Johnston if (mode == 3) 41290339a1c2SMark Johnston goto error; 41300339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 41310339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 41320339a1c2SMark Johnston break; 41330339a1c2SMark Johnston 41340339a1c2SMark Johnston /* move special register to register or reverse if vbit */ 41350339a1c2SMark Johnston case SREG: 41360339a1c2SMark Johnston switch (opcode5) { 41370339a1c2SMark Johnston 41380339a1c2SMark Johnston case 2: 41390339a1c2SMark Johnston vbit = 1; 41400339a1c2SMark Johnston /*FALLTHROUGH*/ 41410339a1c2SMark Johnston case 0: 41420339a1c2SMark Johnston wbit = CONTROL_OPND; 41430339a1c2SMark Johnston break; 41440339a1c2SMark Johnston 41450339a1c2SMark Johnston case 3: 41460339a1c2SMark Johnston vbit = 1; 41470339a1c2SMark Johnston /*FALLTHROUGH*/ 41480339a1c2SMark Johnston case 1: 41490339a1c2SMark Johnston wbit = DEBUG_OPND; 41500339a1c2SMark Johnston break; 41510339a1c2SMark Johnston 41520339a1c2SMark Johnston case 6: 41530339a1c2SMark Johnston vbit = 1; 41540339a1c2SMark Johnston /*FALLTHROUGH*/ 41550339a1c2SMark Johnston case 4: 41560339a1c2SMark Johnston wbit = TEST_OPND; 41570339a1c2SMark Johnston break; 41580339a1c2SMark Johnston 41590339a1c2SMark Johnston } 41600339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 41610339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 41620339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit); 41630339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, r_m, LONG_OPND, 1 - vbit); 41640339a1c2SMark Johnston NOMEM; 41650339a1c2SMark Johnston break; 41660339a1c2SMark Johnston 41670339a1c2SMark Johnston /* 41680339a1c2SMark Johnston * single register operand with register in the low 3 41690339a1c2SMark Johnston * bits of op code 41700339a1c2SMark Johnston */ 41710339a1c2SMark Johnston case R: 41720339a1c2SMark Johnston if (opcode_bytes == 2) 41730339a1c2SMark Johnston reg = REGNO(opcode5); 41740339a1c2SMark Johnston else 41750339a1c2SMark Johnston reg = REGNO(opcode2); 41760339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 41770339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 41780339a1c2SMark Johnston NOMEM; 41790339a1c2SMark Johnston break; 41800339a1c2SMark Johnston 41810339a1c2SMark Johnston /* 41820339a1c2SMark Johnston * register to accumulator with register in the low 3 41830339a1c2SMark Johnston * bits of op code, xchg instructions 41840339a1c2SMark Johnston */ 41850339a1c2SMark Johnston case RA: 41860339a1c2SMark Johnston NOMEM; 41870339a1c2SMark Johnston reg = REGNO(opcode2); 41880339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 41890339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 41900339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, EAX_REGNO, LONG_OPND, 1); 41910339a1c2SMark Johnston break; 41920339a1c2SMark Johnston 41930339a1c2SMark Johnston /* 41940339a1c2SMark Johnston * single segment register operand, with register in 41950339a1c2SMark Johnston * bits 3-4 of op code byte 41960339a1c2SMark Johnston */ 41970339a1c2SMark Johnston case SEG: 41980339a1c2SMark Johnston NOMEM; 41990339a1c2SMark Johnston reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x3; 42000339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0); 42010339a1c2SMark Johnston break; 42020339a1c2SMark Johnston 42030339a1c2SMark Johnston /* 42040339a1c2SMark Johnston * single segment register operand, with register in 42050339a1c2SMark Johnston * bits 3-5 of op code 42060339a1c2SMark Johnston */ 42070339a1c2SMark Johnston case LSEG: 42080339a1c2SMark Johnston NOMEM; 42090339a1c2SMark Johnston /* long seg reg from opcode */ 42100339a1c2SMark Johnston reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x7; 42110339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0); 42120339a1c2SMark Johnston break; 42130339a1c2SMark Johnston 42140339a1c2SMark Johnston /* memory or register operand to register */ 42150339a1c2SMark Johnston case MR: 42160339a1c2SMark Johnston if (vex_prefetch) 42170339a1c2SMark Johnston x->d86_got_modrm = 1; 42180339a1c2SMark Johnston wbit = LONG_OPND; 42190339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 42200339a1c2SMark Johnston break; 42210339a1c2SMark Johnston 42220339a1c2SMark Johnston case RM: 4223c3ddb60eSPeter Grehan case RM_66r: 42240339a1c2SMark Johnston wbit = LONG_OPND; 42250339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 42260339a1c2SMark Johnston break; 42270339a1c2SMark Johnston 42280339a1c2SMark Johnston /* MMX/SIMD-Int memory or mm reg to mm reg */ 42290339a1c2SMark Johnston case MM: 42300339a1c2SMark Johnston case MMO: 42310339a1c2SMark Johnston #ifdef DIS_TEXT 42320339a1c2SMark Johnston wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 42330339a1c2SMark Johnston #else 42340339a1c2SMark Johnston wbit = LONG_OPND; 42350339a1c2SMark Johnston #endif 42360339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0); 42370339a1c2SMark Johnston break; 42380339a1c2SMark Johnston 42390339a1c2SMark Johnston case MMOIMPL: 42400339a1c2SMark Johnston #ifdef DIS_TEXT 42410339a1c2SMark Johnston wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 42420339a1c2SMark Johnston #else 42430339a1c2SMark Johnston wbit = LONG_OPND; 42440339a1c2SMark Johnston #endif 42450339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 42460339a1c2SMark Johnston if (mode != REG_ONLY) 42470339a1c2SMark Johnston goto error; 42480339a1c2SMark Johnston 42490339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 42500339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 42510339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, MM_OPND, 1); 42520339a1c2SMark Johnston mode = 0; /* change for memory access size... */ 42530339a1c2SMark Johnston break; 42540339a1c2SMark Johnston 42550339a1c2SMark Johnston /* MMX/SIMD-Int and SIMD-FP predicated mm reg to r32 */ 42560339a1c2SMark Johnston case MMO3P: 42570339a1c2SMark Johnston wbit = MM_OPND; 42580339a1c2SMark Johnston goto xmm3p; 42590339a1c2SMark Johnston case XMM3P: 42600339a1c2SMark Johnston wbit = XMM_OPND; 42610339a1c2SMark Johnston xmm3p: 42620339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 42630339a1c2SMark Johnston if (mode != REG_ONLY) 42640339a1c2SMark Johnston goto error; 42650339a1c2SMark Johnston 42660339a1c2SMark Johnston THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 1, 42670339a1c2SMark Johnston 1); 42680339a1c2SMark Johnston NOMEM; 42690339a1c2SMark Johnston break; 42700339a1c2SMark Johnston 42710339a1c2SMark Johnston case XMM3PM_66r: 42720339a1c2SMark Johnston THREEOPERAND(x, mode, reg, r_m, rex_prefix, LONG_OPND, XMM_OPND, 42730339a1c2SMark Johnston 1, 0); 42740339a1c2SMark Johnston break; 42750339a1c2SMark Johnston 42760339a1c2SMark Johnston /* MMX/SIMD-Int predicated r32/mem to mm reg */ 42770339a1c2SMark Johnston case MMOPRM: 42780339a1c2SMark Johnston wbit = LONG_OPND; 42790339a1c2SMark Johnston w2 = MM_OPND; 42800339a1c2SMark Johnston goto xmmprm; 42810339a1c2SMark Johnston case XMMPRM: 42820339a1c2SMark Johnston case XMMPRM_66r: 42830339a1c2SMark Johnston wbit = LONG_OPND; 42840339a1c2SMark Johnston w2 = XMM_OPND; 42850339a1c2SMark Johnston xmmprm: 42860339a1c2SMark Johnston THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, 1, 1); 42870339a1c2SMark Johnston break; 42880339a1c2SMark Johnston 42890339a1c2SMark Johnston /* MMX/SIMD-Int predicated mm/mem to mm reg */ 42900339a1c2SMark Johnston case MMOPM: 42910339a1c2SMark Johnston case MMOPM_66o: 42920339a1c2SMark Johnston wbit = w2 = MM_OPND; 42930339a1c2SMark Johnston goto xmmprm; 42940339a1c2SMark Johnston 42950339a1c2SMark Johnston /* MMX/SIMD-Int mm reg to r32 */ 42960339a1c2SMark Johnston case MMOM3: 42970339a1c2SMark Johnston NOMEM; 42980339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 42990339a1c2SMark Johnston if (mode != REG_ONLY) 43000339a1c2SMark Johnston goto error; 43010339a1c2SMark Johnston wbit = MM_OPND; 43020339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0); 43030339a1c2SMark Johnston break; 43040339a1c2SMark Johnston 43050339a1c2SMark Johnston /* SIMD memory or xmm reg operand to xmm reg */ 43060339a1c2SMark Johnston case XMM: 43070339a1c2SMark Johnston case XMM_66o: 43080339a1c2SMark Johnston case XMM_66r: 43090339a1c2SMark Johnston case XMMO: 43100339a1c2SMark Johnston case XMMXIMPL: 43110339a1c2SMark Johnston wbit = XMM_OPND; 43120339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 43130339a1c2SMark Johnston 43140339a1c2SMark Johnston if (dp->it_adrmode == XMMXIMPL && mode != REG_ONLY) 43150339a1c2SMark Johnston goto error; 43160339a1c2SMark Johnston 43170339a1c2SMark Johnston #ifdef DIS_TEXT 43180339a1c2SMark Johnston /* 43190339a1c2SMark Johnston * movlps and movhlps share opcodes. They differ in the 43200339a1c2SMark Johnston * addressing modes allowed for their operands. 43210339a1c2SMark Johnston * movhps and movlhps behave similarly. 43220339a1c2SMark Johnston */ 43230339a1c2SMark Johnston if (mode == REG_ONLY) { 43240339a1c2SMark Johnston if (strcmp(dp->it_name, "movlps") == 0) 43250339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "movhlps", OPLEN); 43260339a1c2SMark Johnston else if (strcmp(dp->it_name, "movhps") == 0) 43270339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "movlhps", OPLEN); 43280339a1c2SMark Johnston } 43290339a1c2SMark Johnston #endif 43300339a1c2SMark Johnston if (dp->it_adrmode == XMMXIMPL) 43310339a1c2SMark Johnston mode = 0; /* change for memory access size... */ 43320339a1c2SMark Johnston break; 43330339a1c2SMark Johnston 43340339a1c2SMark Johnston /* SIMD xmm reg to memory or xmm reg */ 43350339a1c2SMark Johnston case XMMS: 43360339a1c2SMark Johnston case XMMOS: 43370339a1c2SMark Johnston case XMMMS: 43380339a1c2SMark Johnston case XMMOMS: 43390339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 43400339a1c2SMark Johnston #ifdef DIS_TEXT 43410339a1c2SMark Johnston if ((strcmp(dp->it_name, "movlps") == 0 || 43420339a1c2SMark Johnston strcmp(dp->it_name, "movhps") == 0 || 43430339a1c2SMark Johnston strcmp(dp->it_name, "movntps") == 0) && 43440339a1c2SMark Johnston mode == REG_ONLY) 43450339a1c2SMark Johnston goto error; 43460339a1c2SMark Johnston #endif 43470339a1c2SMark Johnston wbit = XMM_OPND; 43480339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1); 43490339a1c2SMark Johnston break; 43500339a1c2SMark Johnston 43510339a1c2SMark Johnston /* SIMD memory to xmm reg */ 43520339a1c2SMark Johnston case XMMM: 43530339a1c2SMark Johnston case XMMM_66r: 43540339a1c2SMark Johnston case XMMOM: 43550339a1c2SMark Johnston wbit = XMM_OPND; 43560339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 43570339a1c2SMark Johnston #ifdef DIS_TEXT 43580339a1c2SMark Johnston if (mode == REG_ONLY) { 43590339a1c2SMark Johnston if (strcmp(dp->it_name, "movhps") == 0) 43600339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "movlhps", OPLEN); 43610339a1c2SMark Johnston else 43620339a1c2SMark Johnston goto error; 43630339a1c2SMark Johnston } 43640339a1c2SMark Johnston #endif 43650339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 43660339a1c2SMark Johnston break; 43670339a1c2SMark Johnston 43680339a1c2SMark Johnston /* SIMD memory or r32 to xmm reg */ 43690339a1c2SMark Johnston case XMM3MX: 43700339a1c2SMark Johnston wbit = LONG_OPND; 43710339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 43720339a1c2SMark Johnston break; 43730339a1c2SMark Johnston 43740339a1c2SMark Johnston case XMM3MXS: 43750339a1c2SMark Johnston wbit = LONG_OPND; 43760339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1); 43770339a1c2SMark Johnston break; 43780339a1c2SMark Johnston 43790339a1c2SMark Johnston /* SIMD memory or mm reg to xmm reg */ 43800339a1c2SMark Johnston case XMMOMX: 43810339a1c2SMark Johnston /* SIMD mm to xmm */ 43820339a1c2SMark Johnston case XMMMX: 43830339a1c2SMark Johnston wbit = MM_OPND; 43840339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 43850339a1c2SMark Johnston break; 43860339a1c2SMark Johnston 43870339a1c2SMark Johnston /* SIMD memory or xmm reg to mm reg */ 43880339a1c2SMark Johnston case XMMXMM: 43890339a1c2SMark Johnston case XMMOXMM: 43900339a1c2SMark Johnston case XMMXM: 43910339a1c2SMark Johnston wbit = XMM_OPND; 43920339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0); 43930339a1c2SMark Johnston break; 43940339a1c2SMark Johnston 43950339a1c2SMark Johnston 43960339a1c2SMark Johnston /* SIMD memory or xmm reg to r32 */ 43970339a1c2SMark Johnston case XMMXM3: 43980339a1c2SMark Johnston wbit = XMM_OPND; 43990339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0); 44000339a1c2SMark Johnston break; 44010339a1c2SMark Johnston 44020339a1c2SMark Johnston /* SIMD xmm to r32 */ 44030339a1c2SMark Johnston case XMMX3: 44040339a1c2SMark Johnston case XMMOX3: 44050339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 44060339a1c2SMark Johnston if (mode != REG_ONLY) 44070339a1c2SMark Johnston goto error; 44080339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 44090339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, XMM_OPND, 0); 44100339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 44110339a1c2SMark Johnston NOMEM; 44120339a1c2SMark Johnston break; 44130339a1c2SMark Johnston 44140339a1c2SMark Johnston /* SIMD predicated memory or xmm reg with/to xmm reg */ 44150339a1c2SMark Johnston case XMMP: 44160339a1c2SMark Johnston case XMMP_66r: 44170339a1c2SMark Johnston case XMMP_66o: 44180339a1c2SMark Johnston case XMMOPM: 44190339a1c2SMark Johnston wbit = XMM_OPND; 44200339a1c2SMark Johnston THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1, 44210339a1c2SMark Johnston 1); 44220339a1c2SMark Johnston 44230339a1c2SMark Johnston #ifdef DIS_TEXT 44240339a1c2SMark Johnston /* 44250339a1c2SMark Johnston * cmpps and cmpss vary their instruction name based 44260339a1c2SMark Johnston * on the value of imm8. Other XMMP instructions, 44270339a1c2SMark Johnston * such as shufps, require explicit specification of 44280339a1c2SMark Johnston * the predicate. 44290339a1c2SMark Johnston */ 44300339a1c2SMark Johnston if (dp->it_name[0] == 'c' && 44310339a1c2SMark Johnston dp->it_name[1] == 'm' && 44320339a1c2SMark Johnston dp->it_name[2] == 'p' && 44330339a1c2SMark Johnston strlen(dp->it_name) == 5) { 44340339a1c2SMark Johnston uchar_t pred = x->d86_opnd[0].d86_value & 0xff; 44350339a1c2SMark Johnston 44360339a1c2SMark Johnston if (pred >= (sizeof (dis_PREDSUFFIX) / sizeof (char *))) 44370339a1c2SMark Johnston goto error; 44380339a1c2SMark Johnston 44390339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "cmp", OPLEN); 44400339a1c2SMark Johnston (void) strlcat(x->d86_mnem, dis_PREDSUFFIX[pred], 44410339a1c2SMark Johnston OPLEN); 44420339a1c2SMark Johnston (void) strlcat(x->d86_mnem, 44430339a1c2SMark Johnston dp->it_name + strlen(dp->it_name) - 2, 44440339a1c2SMark Johnston OPLEN); 44450339a1c2SMark Johnston x->d86_opnd[0] = x->d86_opnd[1]; 44460339a1c2SMark Johnston x->d86_opnd[1] = x->d86_opnd[2]; 44470339a1c2SMark Johnston x->d86_numopnds = 2; 44480339a1c2SMark Johnston } 44490339a1c2SMark Johnston #endif 44500339a1c2SMark Johnston break; 44510339a1c2SMark Johnston 44520339a1c2SMark Johnston case XMMX2I: 44530339a1c2SMark Johnston FOUROPERAND(x, mode, reg, r_m, rex_prefix, XMM_OPND, XMM_OPND, 44540339a1c2SMark Johnston 1); 44550339a1c2SMark Johnston NOMEM; 44560339a1c2SMark Johnston break; 44570339a1c2SMark Johnston 44580339a1c2SMark Johnston case XMM2I: 44590339a1c2SMark Johnston ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, XMM_OPND, 1); 44600339a1c2SMark Johnston NOMEM; 44610339a1c2SMark Johnston break; 44620339a1c2SMark Johnston 44630339a1c2SMark Johnston /* immediate operand to accumulator */ 44640339a1c2SMark Johnston case IA: 44650339a1c2SMark Johnston wbit = WBIT(opcode2); 44660339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1); 44670339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0); 44680339a1c2SMark Johnston NOMEM; 44690339a1c2SMark Johnston break; 44700339a1c2SMark Johnston 44710339a1c2SMark Johnston /* memory or register operand to accumulator */ 44720339a1c2SMark Johnston case MA: 44730339a1c2SMark Johnston wbit = WBIT(opcode2); 44740339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 44750339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 44760339a1c2SMark Johnston break; 44770339a1c2SMark Johnston 44780339a1c2SMark Johnston /* si register to di register used to reference memory */ 44790339a1c2SMark Johnston case SD: 44800339a1c2SMark Johnston #ifdef DIS_TEXT 44810339a1c2SMark Johnston dtrace_check_override(x, 0); 44820339a1c2SMark Johnston x->d86_numopnds = 2; 44830339a1c2SMark Johnston if (addr_size == SIZE64) { 44840339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", 44850339a1c2SMark Johnston OPLEN); 44860339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", 44870339a1c2SMark Johnston OPLEN); 44880339a1c2SMark Johnston } else if (addr_size == SIZE32) { 44890339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", 44900339a1c2SMark Johnston OPLEN); 44910339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", 44920339a1c2SMark Johnston OPLEN); 44930339a1c2SMark Johnston } else { 44940339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)", 44950339a1c2SMark Johnston OPLEN); 44960339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)", 44970339a1c2SMark Johnston OPLEN); 44980339a1c2SMark Johnston } 44990339a1c2SMark Johnston #endif 45000339a1c2SMark Johnston wbit = LONG_OPND; 45010339a1c2SMark Johnston break; 45020339a1c2SMark Johnston 45030339a1c2SMark Johnston /* accumulator to di register */ 45040339a1c2SMark Johnston case AD: 45050339a1c2SMark Johnston wbit = WBIT(opcode2); 45060339a1c2SMark Johnston #ifdef DIS_TEXT 45070339a1c2SMark Johnston dtrace_check_override(x, 1); 45080339a1c2SMark Johnston x->d86_numopnds = 2; 45090339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 0); 45100339a1c2SMark Johnston if (addr_size == SIZE64) 45110339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", 45120339a1c2SMark Johnston OPLEN); 45130339a1c2SMark Johnston else if (addr_size == SIZE32) 45140339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", 45150339a1c2SMark Johnston OPLEN); 45160339a1c2SMark Johnston else 45170339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)", 45180339a1c2SMark Johnston OPLEN); 45190339a1c2SMark Johnston #endif 45200339a1c2SMark Johnston break; 45210339a1c2SMark Johnston 45220339a1c2SMark Johnston /* si register to accumulator */ 45230339a1c2SMark Johnston case SA: 45240339a1c2SMark Johnston wbit = WBIT(opcode2); 45250339a1c2SMark Johnston #ifdef DIS_TEXT 45260339a1c2SMark Johnston dtrace_check_override(x, 0); 45270339a1c2SMark Johnston x->d86_numopnds = 2; 45280339a1c2SMark Johnston if (addr_size == SIZE64) 45290339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", 45300339a1c2SMark Johnston OPLEN); 45310339a1c2SMark Johnston else if (addr_size == SIZE32) 45320339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", 45330339a1c2SMark Johnston OPLEN); 45340339a1c2SMark Johnston else 45350339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)", 45360339a1c2SMark Johnston OPLEN); 45370339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1); 45380339a1c2SMark Johnston #endif 45390339a1c2SMark Johnston break; 45400339a1c2SMark Johnston 45410339a1c2SMark Johnston /* 45420339a1c2SMark Johnston * single operand, a 16/32 bit displacement 45430339a1c2SMark Johnston */ 45440339a1c2SMark Johnston case D: 45450339a1c2SMark Johnston wbit = LONG_OPND; 45460339a1c2SMark Johnston dtrace_disp_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0); 45470339a1c2SMark Johnston NOMEM; 45480339a1c2SMark Johnston break; 45490339a1c2SMark Johnston 45500339a1c2SMark Johnston /* jmp/call indirect to memory or register operand */ 45510339a1c2SMark Johnston case INM: 45520339a1c2SMark Johnston #ifdef DIS_TEXT 45530339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_prefix, "*", OPLEN); 45540339a1c2SMark Johnston #endif 45550339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 45560339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 0); 45570339a1c2SMark Johnston wbit = LONG_OPND; 45580339a1c2SMark Johnston break; 45590339a1c2SMark Johnston 45600339a1c2SMark Johnston /* 45610339a1c2SMark Johnston * for long jumps and long calls -- a new code segment 45620339a1c2SMark Johnston * register and an offset in IP -- stored in object 45630339a1c2SMark Johnston * code in reverse order. Note - not valid in amd64 45640339a1c2SMark Johnston */ 45650339a1c2SMark Johnston case SO: 45660339a1c2SMark Johnston dtrace_check_override(x, 1); 45670339a1c2SMark Johnston wbit = LONG_OPND; 45680339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 1); 45690339a1c2SMark Johnston #ifdef DIS_TEXT 45700339a1c2SMark Johnston x->d86_opnd[1].d86_mode = MODE_SIGNED; 45710339a1c2SMark Johnston #endif 45720339a1c2SMark Johnston /* will now get segment operand */ 45730339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 2, 0); 45740339a1c2SMark Johnston break; 45750339a1c2SMark Johnston 45760339a1c2SMark Johnston /* 45770339a1c2SMark Johnston * jmp/call. single operand, 8 bit displacement. 45780339a1c2SMark Johnston * added to current EIP in 'compofff' 45790339a1c2SMark Johnston */ 45800339a1c2SMark Johnston case BD: 45810339a1c2SMark Johnston dtrace_disp_opnd(x, BYTE_OPND, 1, 0); 45820339a1c2SMark Johnston NOMEM; 45830339a1c2SMark Johnston break; 45840339a1c2SMark Johnston 45850339a1c2SMark Johnston /* single 32/16 bit immediate operand */ 45860339a1c2SMark Johnston case I: 45870339a1c2SMark Johnston wbit = LONG_OPND; 45880339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0); 45890339a1c2SMark Johnston break; 45900339a1c2SMark Johnston 45910339a1c2SMark Johnston /* single 8 bit immediate operand */ 45920339a1c2SMark Johnston case Ib: 45930339a1c2SMark Johnston wbit = LONG_OPND; 45940339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 45950339a1c2SMark Johnston break; 45960339a1c2SMark Johnston 45970339a1c2SMark Johnston case ENTER: 45980339a1c2SMark Johnston wbit = LONG_OPND; 45990339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 2, 0); 46000339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 1); 46010339a1c2SMark Johnston switch (opnd_size) { 46020339a1c2SMark Johnston case SIZE64: 46030339a1c2SMark Johnston x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 8; 46040339a1c2SMark Johnston break; 46050339a1c2SMark Johnston case SIZE32: 46060339a1c2SMark Johnston x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 4; 46070339a1c2SMark Johnston break; 46080339a1c2SMark Johnston case SIZE16: 46090339a1c2SMark Johnston x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 2; 46100339a1c2SMark Johnston break; 46110339a1c2SMark Johnston } 46120339a1c2SMark Johnston 46130339a1c2SMark Johnston break; 46140339a1c2SMark Johnston 46150339a1c2SMark Johnston /* 16-bit immediate operand */ 46160339a1c2SMark Johnston case RET: 46170339a1c2SMark Johnston wbit = LONG_OPND; 46180339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 2, 0); 46190339a1c2SMark Johnston break; 46200339a1c2SMark Johnston 46210339a1c2SMark Johnston /* single 8 bit port operand */ 46220339a1c2SMark Johnston case P: 46230339a1c2SMark Johnston dtrace_check_override(x, 0); 46240339a1c2SMark Johnston dtrace_imm_opnd(x, BYTE_OPND, 1, 0); 46250339a1c2SMark Johnston NOMEM; 46260339a1c2SMark Johnston break; 46270339a1c2SMark Johnston 46280339a1c2SMark Johnston /* single operand, dx register (variable port instruction) */ 46290339a1c2SMark Johnston case V: 46300339a1c2SMark Johnston x->d86_numopnds = 1; 46310339a1c2SMark Johnston dtrace_check_override(x, 0); 46320339a1c2SMark Johnston #ifdef DIS_TEXT 46330339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%dx)", OPLEN); 46340339a1c2SMark Johnston #endif 46350339a1c2SMark Johnston NOMEM; 46360339a1c2SMark Johnston break; 46370339a1c2SMark Johnston 46380339a1c2SMark Johnston /* 46390339a1c2SMark Johnston * The int instruction, which has two forms: 46400339a1c2SMark Johnston * int 3 (breakpoint) or 46410339a1c2SMark Johnston * int n, where n is indicated in the subsequent 46420339a1c2SMark Johnston * byte (format Ib). The int 3 instruction (opcode 0xCC), 46430339a1c2SMark Johnston * where, although the 3 looks like an operand, 46440339a1c2SMark Johnston * it is implied by the opcode. It must be converted 46450339a1c2SMark Johnston * to the correct base and output. 46460339a1c2SMark Johnston */ 46470339a1c2SMark Johnston case INT3: 46480339a1c2SMark Johnston #ifdef DIS_TEXT 46490339a1c2SMark Johnston x->d86_numopnds = 1; 46500339a1c2SMark Johnston x->d86_opnd[0].d86_mode = MODE_SIGNED; 46510339a1c2SMark Johnston x->d86_opnd[0].d86_value_size = 1; 46520339a1c2SMark Johnston x->d86_opnd[0].d86_value = 3; 46530339a1c2SMark Johnston #endif 46540339a1c2SMark Johnston NOMEM; 46550339a1c2SMark Johnston break; 46560339a1c2SMark Johnston 46570339a1c2SMark Johnston /* single 8 bit immediate operand */ 46580339a1c2SMark Johnston case INTx: 46590339a1c2SMark Johnston dtrace_imm_opnd(x, BYTE_OPND, 1, 0); 46600339a1c2SMark Johnston NOMEM; 46610339a1c2SMark Johnston break; 46620339a1c2SMark Johnston 46630339a1c2SMark Johnston /* an unused byte must be discarded */ 46640339a1c2SMark Johnston case U: 46650339a1c2SMark Johnston if (x->d86_get_byte(x->d86_data) < 0) 46660339a1c2SMark Johnston goto error; 46670339a1c2SMark Johnston x->d86_len++; 46680339a1c2SMark Johnston NOMEM; 46690339a1c2SMark Johnston break; 46700339a1c2SMark Johnston 46710339a1c2SMark Johnston case CBW: 46720339a1c2SMark Johnston #ifdef DIS_TEXT 46730339a1c2SMark Johnston if (opnd_size == SIZE16) 46740339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "cbtw", OPLEN); 46750339a1c2SMark Johnston else if (opnd_size == SIZE32) 46760339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "cwtl", OPLEN); 46770339a1c2SMark Johnston else 46780339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "cltq", OPLEN); 46790339a1c2SMark Johnston #endif 46800339a1c2SMark Johnston wbit = LONG_OPND; 46810339a1c2SMark Johnston NOMEM; 46820339a1c2SMark Johnston break; 46830339a1c2SMark Johnston 46840339a1c2SMark Johnston case CWD: 46850339a1c2SMark Johnston #ifdef DIS_TEXT 46860339a1c2SMark Johnston if (opnd_size == SIZE16) 46870339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "cwtd", OPLEN); 46880339a1c2SMark Johnston else if (opnd_size == SIZE32) 46890339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "cltd", OPLEN); 46900339a1c2SMark Johnston else 46910339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "cqtd", OPLEN); 46920339a1c2SMark Johnston #endif 46930339a1c2SMark Johnston wbit = LONG_OPND; 46940339a1c2SMark Johnston NOMEM; 46950339a1c2SMark Johnston break; 46960339a1c2SMark Johnston 46970339a1c2SMark Johnston case XMMSFNC: 46980339a1c2SMark Johnston /* 46990339a1c2SMark Johnston * sfence is sfence if mode is REG_ONLY. If mode isn't 47000339a1c2SMark Johnston * REG_ONLY, mnemonic should be 'clflush'. 47010339a1c2SMark Johnston */ 47020339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 47030339a1c2SMark Johnston 47040339a1c2SMark Johnston /* sfence doesn't take operands */ 47050339a1c2SMark Johnston #ifdef DIS_TEXT 47060339a1c2SMark Johnston if (mode == REG_ONLY) { 47070339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "sfence", OPLEN); 47080339a1c2SMark Johnston } else { 47090339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "clflush", OPLEN); 47100339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 47110339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0); 47120339a1c2SMark Johnston NOMEM; 47130339a1c2SMark Johnston } 47140339a1c2SMark Johnston #else 47150339a1c2SMark Johnston if (mode != REG_ONLY) { 47160339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 47170339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 0); 47180339a1c2SMark Johnston NOMEM; 47190339a1c2SMark Johnston } 47200339a1c2SMark Johnston #endif 47210339a1c2SMark Johnston break; 47220339a1c2SMark Johnston 47230339a1c2SMark Johnston /* 47240339a1c2SMark Johnston * no disassembly, the mnemonic was all there was so go on 47250339a1c2SMark Johnston */ 47260339a1c2SMark Johnston case NORM: 47270339a1c2SMark Johnston if (dp->it_invalid32 && cpu_mode != SIZE64) 47280339a1c2SMark Johnston goto error; 47290339a1c2SMark Johnston NOMEM; 47300339a1c2SMark Johnston /*FALLTHROUGH*/ 47310339a1c2SMark Johnston case IMPLMEM: 47320339a1c2SMark Johnston break; 47330339a1c2SMark Johnston 47340339a1c2SMark Johnston case XMMFENCE: 47350339a1c2SMark Johnston /* 47360339a1c2SMark Johnston * XRSTOR and LFENCE share the same opcode but differ in mode 47370339a1c2SMark Johnston */ 47380339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 47390339a1c2SMark Johnston 47400339a1c2SMark Johnston if (mode == REG_ONLY) { 47410339a1c2SMark Johnston /* 47420339a1c2SMark Johnston * Only the following exact byte sequences are allowed: 47430339a1c2SMark Johnston * 47440339a1c2SMark Johnston * 0f ae e8 lfence 47450339a1c2SMark Johnston * 0f ae f0 mfence 47460339a1c2SMark Johnston */ 47470339a1c2SMark Johnston if ((uint8_t)x->d86_bytes[x->d86_len - 1] != 0xe8 && 47480339a1c2SMark Johnston (uint8_t)x->d86_bytes[x->d86_len - 1] != 0xf0) 47490339a1c2SMark Johnston goto error; 47500339a1c2SMark Johnston } else { 47510339a1c2SMark Johnston #ifdef DIS_TEXT 47520339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "xrstor", OPLEN); 47530339a1c2SMark Johnston #endif 47540339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 47550339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0); 47560339a1c2SMark Johnston } 47570339a1c2SMark Johnston break; 47580339a1c2SMark Johnston 47590339a1c2SMark Johnston /* float reg */ 47600339a1c2SMark Johnston case F: 47610339a1c2SMark Johnston #ifdef DIS_TEXT 47620339a1c2SMark Johnston x->d86_numopnds = 1; 47630339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "%st(X)", OPLEN); 47640339a1c2SMark Johnston x->d86_opnd[0].d86_opnd[4] = r_m + '0'; 47650339a1c2SMark Johnston #endif 47660339a1c2SMark Johnston NOMEM; 47670339a1c2SMark Johnston break; 47680339a1c2SMark Johnston 47690339a1c2SMark Johnston /* float reg to float reg, with ret bit present */ 47700339a1c2SMark Johnston case FF: 47710339a1c2SMark Johnston vbit = opcode2 >> 2 & 0x1; /* vbit = 1: st -> st(i) */ 47720339a1c2SMark Johnston /*FALLTHROUGH*/ 47730339a1c2SMark Johnston case FFC: /* case for vbit always = 0 */ 47740339a1c2SMark Johnston #ifdef DIS_TEXT 47750339a1c2SMark Johnston x->d86_numopnds = 2; 47760339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1 - vbit].d86_opnd, "%st", OPLEN); 47770339a1c2SMark Johnston (void) strlcat(x->d86_opnd[vbit].d86_opnd, "%st(X)", OPLEN); 47780339a1c2SMark Johnston x->d86_opnd[vbit].d86_opnd[4] = r_m + '0'; 47790339a1c2SMark Johnston #endif 47800339a1c2SMark Johnston NOMEM; 47810339a1c2SMark Johnston break; 47820339a1c2SMark Johnston 47830339a1c2SMark Johnston /* AVX instructions */ 47840339a1c2SMark Johnston case VEX_MO: 47850339a1c2SMark Johnston /* op(ModR/M.r/m) */ 47860339a1c2SMark Johnston x->d86_numopnds = 1; 47870339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 47880339a1c2SMark Johnston #ifdef DIS_TEXT 47890339a1c2SMark Johnston if ((dp == &dis_opAVX0F[0xA][0xE]) && (reg == 3)) 47900339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "vstmxcsr", OPLEN); 47910339a1c2SMark Johnston #endif 47920339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 47930339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 47940339a1c2SMark Johnston break; 47950339a1c2SMark Johnston case VEX_RMrX: 4796*b3b5bfebSMark Johnston case FMA: 47970339a1c2SMark Johnston /* ModR/M.reg := op(VEX.vvvv, ModR/M.r/m) */ 47980339a1c2SMark Johnston x->d86_numopnds = 3; 47990339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 48000339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 48010339a1c2SMark Johnston 4802*b3b5bfebSMark Johnston /* 4803*b3b5bfebSMark Johnston * In classic Intel fashion, the opcodes for all of the FMA 4804*b3b5bfebSMark Johnston * instructions all have two possible mnemonics which vary by 4805*b3b5bfebSMark Johnston * one letter, which is selected based on the value of the wbit. 4806*b3b5bfebSMark Johnston * When wbit is one, they have the 'd' suffix and when 'wbit' is 4807*b3b5bfebSMark Johnston * 0, they have the 's' suffix. Otherwise, the FMA instructions 4808*b3b5bfebSMark Johnston * are all a standard VEX_RMrX. 4809*b3b5bfebSMark Johnston */ 4810*b3b5bfebSMark Johnston #ifdef DIS_TEXT 4811*b3b5bfebSMark Johnston if (dp->it_adrmode == FMA) { 4812*b3b5bfebSMark Johnston size_t len = strlen(dp->it_name); 4813*b3b5bfebSMark Johnston (void) strncpy(x->d86_mnem, dp->it_name, OPLEN); 4814*b3b5bfebSMark Johnston if (len + 1 < OPLEN) { 4815*b3b5bfebSMark Johnston (void) strncpy(x->d86_mnem + len, 4816*b3b5bfebSMark Johnston vex_W != 0 ? "d" : "s", OPLEN - len); 4817*b3b5bfebSMark Johnston } 4818*b3b5bfebSMark Johnston } 4819*b3b5bfebSMark Johnston #endif 4820*b3b5bfebSMark Johnston 48210339a1c2SMark Johnston if (mode != REG_ONLY) { 48220339a1c2SMark Johnston if ((dp == &dis_opAVXF20F[0x10]) || 48230339a1c2SMark Johnston (dp == &dis_opAVXF30F[0x10])) { 48240339a1c2SMark Johnston /* vmovsd <m64>, <xmm> */ 48250339a1c2SMark Johnston /* or vmovss <m64>, <xmm> */ 48260339a1c2SMark Johnston x->d86_numopnds = 2; 48270339a1c2SMark Johnston goto L_VEX_MX; 48280339a1c2SMark Johnston } 48290339a1c2SMark Johnston } 48300339a1c2SMark Johnston 48310339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 2); 48320339a1c2SMark Johnston /* 48330339a1c2SMark Johnston * VEX prefix uses the 1's complement form to encode the 48340339a1c2SMark Johnston * XMM/YMM regs 48350339a1c2SMark Johnston */ 48360339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 48370339a1c2SMark Johnston 48380339a1c2SMark Johnston if ((dp == &dis_opAVXF20F[0x2A]) || 48390339a1c2SMark Johnston (dp == &dis_opAVXF30F[0x2A])) { 48400339a1c2SMark Johnston /* 48410339a1c2SMark Johnston * vcvtsi2si </r,m>, <xmm>, <xmm> or vcvtsi2ss </r,m>, 48420339a1c2SMark Johnston * <xmm>, <xmm> 48430339a1c2SMark Johnston */ 48440339a1c2SMark Johnston wbit = LONG_OPND; 48450339a1c2SMark Johnston } 48460339a1c2SMark Johnston #ifdef DIS_TEXT 48470339a1c2SMark Johnston else if ((mode == REG_ONLY) && 48480339a1c2SMark Johnston (dp == &dis_opAVX0F[0x1][0x6])) { /* vmovlhps */ 48490339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "vmovlhps", OPLEN); 48500339a1c2SMark Johnston } else if ((mode == REG_ONLY) && 48510339a1c2SMark Johnston (dp == &dis_opAVX0F[0x1][0x2])) { /* vmovhlps */ 48520339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "vmovhlps", OPLEN); 48530339a1c2SMark Johnston } 48540339a1c2SMark Johnston #endif 48550339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 48560339a1c2SMark Johnston 48570339a1c2SMark Johnston break; 48580339a1c2SMark Johnston 4859*b3b5bfebSMark Johnston case VEX_VRMrX: 4860*b3b5bfebSMark Johnston /* ModR/M.reg := op(MODR/M.r/m, VEX.vvvv) */ 4861*b3b5bfebSMark Johnston x->d86_numopnds = 3; 4862*b3b5bfebSMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 4863*b3b5bfebSMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4864*b3b5bfebSMark Johnston 4865*b3b5bfebSMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 2); 4866*b3b5bfebSMark Johnston /* 4867*b3b5bfebSMark Johnston * VEX prefix uses the 1's complement form to encode the 4868*b3b5bfebSMark Johnston * XMM/YMM regs 4869*b3b5bfebSMark Johnston */ 4870*b3b5bfebSMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 0); 4871*b3b5bfebSMark Johnston 4872*b3b5bfebSMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 4873*b3b5bfebSMark Johnston break; 4874*b3b5bfebSMark Johnston 4875*b3b5bfebSMark Johnston case VEX_SbVM: 4876*b3b5bfebSMark Johnston /* ModR/M.reg := op(MODR/M.r/m, VSIB, VEX.vvvv) */ 4877*b3b5bfebSMark Johnston x->d86_numopnds = 3; 4878*b3b5bfebSMark Johnston x->d86_vsib = 1; 4879*b3b5bfebSMark Johnston 4880*b3b5bfebSMark Johnston /* 4881*b3b5bfebSMark Johnston * All instructions that use VSIB are currently a mess. See the 4882*b3b5bfebSMark Johnston * comment around the dis_gather_regs_t structure definition. 4883*b3b5bfebSMark Johnston */ 4884*b3b5bfebSMark Johnston 4885*b3b5bfebSMark Johnston vreg = &dis_vgather[opcode2][vex_W][vex_L]; 4886*b3b5bfebSMark Johnston 4887*b3b5bfebSMark Johnston #ifdef DIS_TEXT 4888*b3b5bfebSMark Johnston (void) strncpy(x->d86_mnem, dp->it_name, OPLEN); 4889*b3b5bfebSMark Johnston (void) strlcat(x->d86_mnem + strlen(dp->it_name), 4890*b3b5bfebSMark Johnston vreg->dgr_suffix, OPLEN - strlen(dp->it_name)); 4891*b3b5bfebSMark Johnston #endif 4892*b3b5bfebSMark Johnston 4893*b3b5bfebSMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 4894*b3b5bfebSMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 4895*b3b5bfebSMark Johnston 4896*b3b5bfebSMark Johnston dtrace_get_operand(x, REG_ONLY, reg, vreg->dgr_arg2, 2); 4897*b3b5bfebSMark Johnston /* 4898*b3b5bfebSMark Johnston * VEX prefix uses the 1's complement form to encode the 4899*b3b5bfebSMark Johnston * XMM/YMM regs 4900*b3b5bfebSMark Johnston */ 4901*b3b5bfebSMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), vreg->dgr_arg0, 4902*b3b5bfebSMark Johnston 0); 4903*b3b5bfebSMark Johnston dtrace_get_operand(x, mode, r_m, vreg->dgr_arg1, 1); 4904*b3b5bfebSMark Johnston break; 4905*b3b5bfebSMark Johnston 49060339a1c2SMark Johnston case VEX_RRX: 49070339a1c2SMark Johnston /* ModR/M.rm := op(VEX.vvvv, ModR/M.reg) */ 49080339a1c2SMark Johnston x->d86_numopnds = 3; 49090339a1c2SMark Johnston 49100339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 49110339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 49120339a1c2SMark Johnston 49130339a1c2SMark Johnston if (mode != REG_ONLY) { 49140339a1c2SMark Johnston if ((dp == &dis_opAVXF20F[0x11]) || 49150339a1c2SMark Johnston (dp == &dis_opAVXF30F[0x11])) { 49160339a1c2SMark Johnston /* vmovsd <xmm>, <m64> */ 49170339a1c2SMark Johnston /* or vmovss <xmm>, <m64> */ 49180339a1c2SMark Johnston x->d86_numopnds = 2; 49190339a1c2SMark Johnston goto L_VEX_RM; 49200339a1c2SMark Johnston } 49210339a1c2SMark Johnston } 49220339a1c2SMark Johnston 49230339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 2); 49240339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 49250339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 0); 49260339a1c2SMark Johnston break; 49270339a1c2SMark Johnston 49280339a1c2SMark Johnston case VEX_RMRX: 49290339a1c2SMark Johnston /* ModR/M.reg := op(VEX.vvvv, ModR/M.r_m, imm8[7:4]) */ 49300339a1c2SMark Johnston x->d86_numopnds = 4; 49310339a1c2SMark Johnston 49320339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 49330339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 49340339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 3); 49350339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 2); 49360339a1c2SMark Johnston if (dp == &dis_opAVX660F3A[0x18]) { 49370339a1c2SMark Johnston /* vinsertf128 <imm8>, <xmm>, <ymm>, <ymm> */ 49380339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, XMM_OPND, 1); 49390339a1c2SMark Johnston } else if ((dp == &dis_opAVX660F3A[0x20]) || 49400339a1c2SMark Johnston (dp == & dis_opAVX660F[0xC4])) { 49410339a1c2SMark Johnston /* vpinsrb <imm8>, <reg/mm>, <xmm>, <xmm> */ 49420339a1c2SMark Johnston /* or vpinsrw <imm8>, <reg/mm>, <xmm>, <xmm> */ 49430339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 1); 49440339a1c2SMark Johnston } else if (dp == &dis_opAVX660F3A[0x22]) { 49450339a1c2SMark Johnston /* vpinsrd/q <imm8>, <reg/mm>, <xmm>, <xmm> */ 49460339a1c2SMark Johnston #ifdef DIS_TEXT 49470339a1c2SMark Johnston if (vex_W) 49480339a1c2SMark Johnston x->d86_mnem[6] = 'q'; 49490339a1c2SMark Johnston #endif 49500339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 1); 49510339a1c2SMark Johnston } else { 49520339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 49530339a1c2SMark Johnston } 49540339a1c2SMark Johnston 49550339a1c2SMark Johnston /* one byte immediate number */ 49560339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 49570339a1c2SMark Johnston 49580339a1c2SMark Johnston /* vblendvpd, vblendvps, vblendvb use the imm encode the regs */ 49590339a1c2SMark Johnston if ((dp == &dis_opAVX660F3A[0x4A]) || 49600339a1c2SMark Johnston (dp == &dis_opAVX660F3A[0x4B]) || 49610339a1c2SMark Johnston (dp == &dis_opAVX660F3A[0x4C])) { 49620339a1c2SMark Johnston #ifdef DIS_TEXT 49630339a1c2SMark Johnston int regnum = (x->d86_opnd[0].d86_value & 0xF0) >> 4; 49640339a1c2SMark Johnston #endif 49650339a1c2SMark Johnston x->d86_opnd[0].d86_mode = MODE_NONE; 49660339a1c2SMark Johnston #ifdef DIS_TEXT 49670339a1c2SMark Johnston if (vex_L) 49680339a1c2SMark Johnston (void) strncpy(x->d86_opnd[0].d86_opnd, 49690339a1c2SMark Johnston dis_YMMREG[regnum], OPLEN); 49700339a1c2SMark Johnston else 49710339a1c2SMark Johnston (void) strncpy(x->d86_opnd[0].d86_opnd, 49720339a1c2SMark Johnston dis_XMMREG[regnum], OPLEN); 49730339a1c2SMark Johnston #endif 49740339a1c2SMark Johnston } 49750339a1c2SMark Johnston break; 49760339a1c2SMark Johnston 49770339a1c2SMark Johnston case VEX_MX: 49780339a1c2SMark Johnston /* ModR/M.reg := op(ModR/M.rm) */ 49790339a1c2SMark Johnston x->d86_numopnds = 2; 49800339a1c2SMark Johnston 49810339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 49820339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 49830339a1c2SMark Johnston L_VEX_MX: 49840339a1c2SMark Johnston 49850339a1c2SMark Johnston if ((dp == &dis_opAVXF20F[0xE6]) || 49860339a1c2SMark Johnston (dp == &dis_opAVX660F[0x5A]) || 49870339a1c2SMark Johnston (dp == &dis_opAVX660F[0xE6])) { 49880339a1c2SMark Johnston /* vcvtpd2dq <ymm>, <xmm> */ 49890339a1c2SMark Johnston /* or vcvtpd2ps <ymm>, <xmm> */ 49900339a1c2SMark Johnston /* or vcvttpd2dq <ymm>, <xmm> */ 49910339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, XMM_OPND, 1); 49920339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 49930339a1c2SMark Johnston } else if ((dp == &dis_opAVXF30F[0xE6]) || 4994c3ddb60eSPeter Grehan (dp == &dis_opAVX0F[0x5][0xA]) || 4995*b3b5bfebSMark Johnston (dp == &dis_opAVX660F38[0x13]) || 4996*b3b5bfebSMark Johnston (dp == &dis_opAVX660F38[0x18]) || 4997*b3b5bfebSMark Johnston (dp == &dis_opAVX660F38[0x19]) || 4998*b3b5bfebSMark Johnston (dp == &dis_opAVX660F38[0x58]) || 4999*b3b5bfebSMark Johnston (dp == &dis_opAVX660F38[0x78]) || 5000*b3b5bfebSMark Johnston (dp == &dis_opAVX660F38[0x79]) || 5001*b3b5bfebSMark Johnston (dp == &dis_opAVX660F38[0x59])) { 50020339a1c2SMark Johnston /* vcvtdq2pd <xmm>, <ymm> */ 50030339a1c2SMark Johnston /* or vcvtps2pd <xmm>, <ymm> */ 5004*b3b5bfebSMark Johnston /* or vcvtph2ps <xmm>, <ymm> */ 5005*b3b5bfebSMark Johnston /* or vbroadcasts* <xmm>, <ymm> */ 50060339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 50070339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, XMM_OPND, 0); 50080339a1c2SMark Johnston } else if (dp == &dis_opAVX660F[0x6E]) { 50090339a1c2SMark Johnston /* vmovd/q <reg/mem 32/64>, <xmm> */ 50100339a1c2SMark Johnston #ifdef DIS_TEXT 50110339a1c2SMark Johnston if (vex_W) 50120339a1c2SMark Johnston x->d86_mnem[4] = 'q'; 50130339a1c2SMark Johnston #endif 50140339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 50150339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 0); 50160339a1c2SMark Johnston } else { 50170339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 50180339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 50190339a1c2SMark Johnston } 50200339a1c2SMark Johnston 50210339a1c2SMark Johnston break; 50220339a1c2SMark Johnston 50230339a1c2SMark Johnston case VEX_MXI: 50240339a1c2SMark Johnston /* ModR/M.reg := op(ModR/M.rm, imm8) */ 50250339a1c2SMark Johnston x->d86_numopnds = 3; 50260339a1c2SMark Johnston 50270339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 50280339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 50290339a1c2SMark Johnston 50300339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 2); 50310339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 50320339a1c2SMark Johnston 50330339a1c2SMark Johnston /* one byte immediate number */ 50340339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 50350339a1c2SMark Johnston break; 50360339a1c2SMark Johnston 50370339a1c2SMark Johnston case VEX_XXI: 50380339a1c2SMark Johnston /* VEX.vvvv := op(ModR/M.rm, imm8) */ 50390339a1c2SMark Johnston x->d86_numopnds = 3; 50400339a1c2SMark Johnston 50410339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 50420339a1c2SMark Johnston #ifdef DIS_TEXT 50430339a1c2SMark Johnston (void) strncpy(x->d86_mnem, dis_AVXvgrp7[opcode2 - 1][reg], 50440339a1c2SMark Johnston OPLEN); 50450339a1c2SMark Johnston #endif 50460339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 50470339a1c2SMark Johnston 50480339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 2); 50490339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, r_m, wbit, 1); 50500339a1c2SMark Johnston 50510339a1c2SMark Johnston /* one byte immediate number */ 50520339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 50530339a1c2SMark Johnston break; 50540339a1c2SMark Johnston 50550339a1c2SMark Johnston case VEX_MR: 50560339a1c2SMark Johnston /* ModR/M.reg (reg32/64) := op(ModR/M.rm) */ 50570339a1c2SMark Johnston if (dp == &dis_opAVX660F[0xC5]) { 50580339a1c2SMark Johnston /* vpextrw <imm8>, <xmm>, <reg> */ 50590339a1c2SMark Johnston x->d86_numopnds = 2; 50600339a1c2SMark Johnston vbit = 2; 50610339a1c2SMark Johnston } else { 50620339a1c2SMark Johnston x->d86_numopnds = 2; 50630339a1c2SMark Johnston vbit = 1; 50640339a1c2SMark Johnston } 50650339a1c2SMark Johnston 50660339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 50670339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 50680339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, vbit); 50690339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, vbit - 1); 50700339a1c2SMark Johnston 50710339a1c2SMark Johnston if (vbit == 2) 50720339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 50730339a1c2SMark Johnston 50740339a1c2SMark Johnston break; 50750339a1c2SMark Johnston 50760339a1c2SMark Johnston case VEX_RRI: 50770339a1c2SMark Johnston /* implicit(eflags/r32) := op(ModR/M.reg, ModR/M.rm) */ 50780339a1c2SMark Johnston x->d86_numopnds = 2; 50790339a1c2SMark Johnston 50800339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 50810339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 50820339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 50830339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 50840339a1c2SMark Johnston break; 50850339a1c2SMark Johnston 50860339a1c2SMark Johnston case VEX_RX: 50870339a1c2SMark Johnston /* ModR/M.rm := op(ModR/M.reg) */ 5088c3ddb60eSPeter Grehan /* vextractf128 || vcvtps2ph */ 5089c3ddb60eSPeter Grehan if (dp == &dis_opAVX660F3A[0x19] || 5090c3ddb60eSPeter Grehan dp == &dis_opAVX660F3A[0x1d]) { 50910339a1c2SMark Johnston x->d86_numopnds = 3; 50920339a1c2SMark Johnston 50930339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 50940339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 50950339a1c2SMark Johnston 50960339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, XMM_OPND, 2); 50970339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 50980339a1c2SMark Johnston 50990339a1c2SMark Johnston /* one byte immediate number */ 51000339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 51010339a1c2SMark Johnston break; 51020339a1c2SMark Johnston } 51030339a1c2SMark Johnston 51040339a1c2SMark Johnston x->d86_numopnds = 2; 51050339a1c2SMark Johnston 51060339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 51070339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 51080339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 51090339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 0); 51100339a1c2SMark Johnston break; 51110339a1c2SMark Johnston 51120339a1c2SMark Johnston case VEX_RR: 51130339a1c2SMark Johnston /* ModR/M.rm := op(ModR/M.reg) */ 51140339a1c2SMark Johnston x->d86_numopnds = 2; 51150339a1c2SMark Johnston 51160339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 51170339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 51180339a1c2SMark Johnston 51190339a1c2SMark Johnston if (dp == &dis_opAVX660F[0x7E]) { 51200339a1c2SMark Johnston /* vmovd/q <reg/mem 32/64>, <xmm> */ 51210339a1c2SMark Johnston #ifdef DIS_TEXT 51220339a1c2SMark Johnston if (vex_W) 51230339a1c2SMark Johnston x->d86_mnem[4] = 'q'; 51240339a1c2SMark Johnston #endif 51250339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 1); 51260339a1c2SMark Johnston } else 51270339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 51280339a1c2SMark Johnston 51290339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 0); 51300339a1c2SMark Johnston break; 51310339a1c2SMark Johnston 51320339a1c2SMark Johnston case VEX_RRi: 51330339a1c2SMark Johnston /* ModR/M.rm := op(ModR/M.reg, imm) */ 51340339a1c2SMark Johnston x->d86_numopnds = 3; 51350339a1c2SMark Johnston 51360339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 51370339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 51380339a1c2SMark Johnston 51390339a1c2SMark Johnston #ifdef DIS_TEXT 51400339a1c2SMark Johnston if (dp == &dis_opAVX660F3A[0x16]) { 51410339a1c2SMark Johnston /* vpextrd/q <imm>, <xmm>, <reg/mem 32/64> */ 51420339a1c2SMark Johnston if (vex_W) 51430339a1c2SMark Johnston x->d86_mnem[6] = 'q'; 51440339a1c2SMark Johnston } 51450339a1c2SMark Johnston #endif 51460339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 2); 51470339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 51480339a1c2SMark Johnston 51490339a1c2SMark Johnston /* one byte immediate number */ 51500339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 51510339a1c2SMark Johnston break; 5152*b3b5bfebSMark Johnston case VEX_RIM: 5153*b3b5bfebSMark Johnston /* ModR/M.rm := op(ModR/M.reg, imm) */ 5154*b3b5bfebSMark Johnston x->d86_numopnds = 3; 5155*b3b5bfebSMark Johnston 5156*b3b5bfebSMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 5157*b3b5bfebSMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 5158*b3b5bfebSMark Johnston 5159*b3b5bfebSMark Johnston dtrace_get_operand(x, mode, r_m, XMM_OPND, 2); 5160*b3b5bfebSMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 5161*b3b5bfebSMark Johnston /* one byte immediate number */ 5162*b3b5bfebSMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 5163*b3b5bfebSMark Johnston break; 51640339a1c2SMark Johnston 51650339a1c2SMark Johnston case VEX_RM: 51660339a1c2SMark Johnston /* ModR/M.rm := op(ModR/M.reg) */ 51670339a1c2SMark Johnston if (dp == &dis_opAVX660F3A[0x17]) { /* vextractps */ 51680339a1c2SMark Johnston x->d86_numopnds = 3; 51690339a1c2SMark Johnston 51700339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 51710339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 51720339a1c2SMark Johnston 51730339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 2); 51740339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 51750339a1c2SMark Johnston /* one byte immediate number */ 51760339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 51770339a1c2SMark Johnston break; 51780339a1c2SMark Johnston } 51790339a1c2SMark Johnston x->d86_numopnds = 2; 51800339a1c2SMark Johnston 51810339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 51820339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 51830339a1c2SMark Johnston L_VEX_RM: 51840339a1c2SMark Johnston vbit = 1; 51850339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, vbit); 51860339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit - 1); 51870339a1c2SMark Johnston 51880339a1c2SMark Johnston break; 51890339a1c2SMark Johnston 51900339a1c2SMark Johnston case VEX_RRM: 51910339a1c2SMark Johnston /* ModR/M.rm := op(VEX.vvvv, ModR/M.reg) */ 51920339a1c2SMark Johnston x->d86_numopnds = 3; 51930339a1c2SMark Johnston 51940339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 51950339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 51960339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 2); 51970339a1c2SMark Johnston /* VEX use the 1's complement form encode the XMM/YMM regs */ 51980339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 51990339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 0); 52000339a1c2SMark Johnston break; 52010339a1c2SMark Johnston 52020339a1c2SMark Johnston case VEX_RMX: 52030339a1c2SMark Johnston /* ModR/M.reg := op(VEX.vvvv, ModR/M.rm) */ 52040339a1c2SMark Johnston x->d86_numopnds = 3; 52050339a1c2SMark Johnston 52060339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 52070339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 52080339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 2); 52090339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 52100339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, r_m, wbit, 0); 52110339a1c2SMark Johnston break; 52120339a1c2SMark Johnston 52130339a1c2SMark Johnston case VEX_NONE: 52140339a1c2SMark Johnston #ifdef DIS_TEXT 52150339a1c2SMark Johnston if (vex_L) 52160339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "vzeroall", OPLEN); 52170339a1c2SMark Johnston #endif 52180339a1c2SMark Johnston break; 5219*b3b5bfebSMark Johnston case BLS: { 5220*b3b5bfebSMark Johnston 5221*b3b5bfebSMark Johnston /* 5222*b3b5bfebSMark Johnston * The BLS instructions are VEX instructions that are based on 5223*b3b5bfebSMark Johnston * VEX.0F38.F3; however, they are considered special group 17 5224*b3b5bfebSMark Johnston * and like everything else, they use the bits in 3-5 of the 5225*b3b5bfebSMark Johnston * MOD R/M to determine the sub instruction. Unlike many others 5226*b3b5bfebSMark Johnston * like the VMX instructions, these are valid both for memory 5227*b3b5bfebSMark Johnston * and register forms. 5228*b3b5bfebSMark Johnston */ 5229*b3b5bfebSMark Johnston 5230*b3b5bfebSMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 5231*b3b5bfebSMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 5232*b3b5bfebSMark Johnston 5233*b3b5bfebSMark Johnston switch (reg) { 5234*b3b5bfebSMark Johnston case 1: 5235*b3b5bfebSMark Johnston #ifdef DIS_TEXT 5236*b3b5bfebSMark Johnston blsinstr = "blsr"; 5237*b3b5bfebSMark Johnston #endif 5238*b3b5bfebSMark Johnston break; 5239*b3b5bfebSMark Johnston case 2: 5240*b3b5bfebSMark Johnston #ifdef DIS_TEXT 5241*b3b5bfebSMark Johnston blsinstr = "blsmsk"; 5242*b3b5bfebSMark Johnston #endif 5243*b3b5bfebSMark Johnston break; 5244*b3b5bfebSMark Johnston case 3: 5245*b3b5bfebSMark Johnston #ifdef DIS_TEXT 5246*b3b5bfebSMark Johnston blsinstr = "blsi"; 5247*b3b5bfebSMark Johnston #endif 5248*b3b5bfebSMark Johnston break; 5249*b3b5bfebSMark Johnston default: 5250*b3b5bfebSMark Johnston goto error; 5251*b3b5bfebSMark Johnston } 5252*b3b5bfebSMark Johnston 5253*b3b5bfebSMark Johnston x->d86_numopnds = 2; 5254*b3b5bfebSMark Johnston #ifdef DIS_TEXT 5255*b3b5bfebSMark Johnston (void) strncpy(x->d86_mnem, blsinstr, OPLEN); 5256*b3b5bfebSMark Johnston #endif 5257*b3b5bfebSMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 5258*b3b5bfebSMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 5259*b3b5bfebSMark Johnston break; 5260*b3b5bfebSMark Johnston } 52610339a1c2SMark Johnston /* an invalid op code */ 52620339a1c2SMark Johnston case AM: 52630339a1c2SMark Johnston case DM: 52640339a1c2SMark Johnston case OVERRIDE: 52650339a1c2SMark Johnston case PREFIX: 52660339a1c2SMark Johnston case UNKNOWN: 52670339a1c2SMark Johnston NOMEM; 52680339a1c2SMark Johnston default: 52690339a1c2SMark Johnston goto error; 52700339a1c2SMark Johnston } /* end switch */ 52710339a1c2SMark Johnston if (x->d86_error) 52720339a1c2SMark Johnston goto error; 52730339a1c2SMark Johnston 52740339a1c2SMark Johnston done: 52750339a1c2SMark Johnston #ifdef DIS_MEM 52760339a1c2SMark Johnston /* 52770339a1c2SMark Johnston * compute the size of any memory accessed by the instruction 52780339a1c2SMark Johnston */ 52790339a1c2SMark Johnston if (x->d86_memsize != 0) { 52800339a1c2SMark Johnston return (0); 52810339a1c2SMark Johnston } else if (dp->it_stackop) { 52820339a1c2SMark Johnston switch (opnd_size) { 52830339a1c2SMark Johnston case SIZE16: 52840339a1c2SMark Johnston x->d86_memsize = 2; 52850339a1c2SMark Johnston break; 52860339a1c2SMark Johnston case SIZE32: 52870339a1c2SMark Johnston x->d86_memsize = 4; 52880339a1c2SMark Johnston break; 52890339a1c2SMark Johnston case SIZE64: 52900339a1c2SMark Johnston x->d86_memsize = 8; 52910339a1c2SMark Johnston break; 52920339a1c2SMark Johnston } 52930339a1c2SMark Johnston } else if (nomem || mode == REG_ONLY) { 52940339a1c2SMark Johnston x->d86_memsize = 0; 52950339a1c2SMark Johnston 52960339a1c2SMark Johnston } else if (dp->it_size != 0) { 52970339a1c2SMark Johnston /* 52980339a1c2SMark Johnston * In 64 bit mode descriptor table entries 52990339a1c2SMark Johnston * go up to 10 bytes and popf/pushf are always 8 bytes 53000339a1c2SMark Johnston */ 53010339a1c2SMark Johnston if (x->d86_mode == SIZE64 && dp->it_size == 6) 53020339a1c2SMark Johnston x->d86_memsize = 10; 53030339a1c2SMark Johnston else if (x->d86_mode == SIZE64 && opcode1 == 0x9 && 53040339a1c2SMark Johnston (opcode2 == 0xc || opcode2 == 0xd)) 53050339a1c2SMark Johnston x->d86_memsize = 8; 53060339a1c2SMark Johnston else 53070339a1c2SMark Johnston x->d86_memsize = dp->it_size; 53080339a1c2SMark Johnston 53090339a1c2SMark Johnston } else if (wbit == 0) { 53100339a1c2SMark Johnston x->d86_memsize = 1; 53110339a1c2SMark Johnston 53120339a1c2SMark Johnston } else if (wbit == LONG_OPND) { 53130339a1c2SMark Johnston if (opnd_size == SIZE64) 53140339a1c2SMark Johnston x->d86_memsize = 8; 53150339a1c2SMark Johnston else if (opnd_size == SIZE32) 53160339a1c2SMark Johnston x->d86_memsize = 4; 53170339a1c2SMark Johnston else 53180339a1c2SMark Johnston x->d86_memsize = 2; 53190339a1c2SMark Johnston 53200339a1c2SMark Johnston } else if (wbit == SEG_OPND) { 53210339a1c2SMark Johnston x->d86_memsize = 4; 53220339a1c2SMark Johnston 53230339a1c2SMark Johnston } else { 53240339a1c2SMark Johnston x->d86_memsize = 8; 53250339a1c2SMark Johnston } 53260339a1c2SMark Johnston #endif 53270339a1c2SMark Johnston return (0); 53280339a1c2SMark Johnston 53290339a1c2SMark Johnston error: 53300339a1c2SMark Johnston #ifdef DIS_TEXT 53310339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "undef", OPLEN); 53320339a1c2SMark Johnston #endif 53330339a1c2SMark Johnston return (1); 53340339a1c2SMark Johnston } 53350339a1c2SMark Johnston 53360339a1c2SMark Johnston #ifdef DIS_TEXT 53370339a1c2SMark Johnston 53380339a1c2SMark Johnston /* 53390339a1c2SMark Johnston * Some instructions should have immediate operands printed 53400339a1c2SMark Johnston * as unsigned integers. We compare against this table. 53410339a1c2SMark Johnston */ 53420339a1c2SMark Johnston static char *unsigned_ops[] = { 53430339a1c2SMark Johnston "or", "and", "xor", "test", "in", "out", "lcall", "ljmp", 53440339a1c2SMark Johnston "rcr", "rcl", "ror", "rol", "shl", "shr", "sal", "psr", "psl", 53450339a1c2SMark Johnston 0 53460339a1c2SMark Johnston }; 53470339a1c2SMark Johnston 53480339a1c2SMark Johnston 53490339a1c2SMark Johnston static int 53500339a1c2SMark Johnston isunsigned_op(char *opcode) 53510339a1c2SMark Johnston { 53520339a1c2SMark Johnston char *where; 53530339a1c2SMark Johnston int i; 53540339a1c2SMark Johnston int is_unsigned = 0; 53550339a1c2SMark Johnston 53560339a1c2SMark Johnston /* 53570339a1c2SMark Johnston * Work back to start of last mnemonic, since we may have 53580339a1c2SMark Johnston * prefixes on some opcodes. 53590339a1c2SMark Johnston */ 53600339a1c2SMark Johnston where = opcode + strlen(opcode) - 1; 53610339a1c2SMark Johnston while (where > opcode && *where != ' ') 53620339a1c2SMark Johnston --where; 53630339a1c2SMark Johnston if (*where == ' ') 53640339a1c2SMark Johnston ++where; 53650339a1c2SMark Johnston 53660339a1c2SMark Johnston for (i = 0; unsigned_ops[i]; ++i) { 53670339a1c2SMark Johnston if (strncmp(where, unsigned_ops[i], 53680339a1c2SMark Johnston strlen(unsigned_ops[i]))) 53690339a1c2SMark Johnston continue; 53700339a1c2SMark Johnston is_unsigned = 1; 53710339a1c2SMark Johnston break; 53720339a1c2SMark Johnston } 53730339a1c2SMark Johnston return (is_unsigned); 53740339a1c2SMark Johnston } 53750339a1c2SMark Johnston 53760339a1c2SMark Johnston /* 53770339a1c2SMark Johnston * Print a numeric immediate into end of buf, maximum length buflen. 53780339a1c2SMark Johnston * The immediate may be an address or a displacement. Mask is set 53790339a1c2SMark Johnston * for address size. If the immediate is a "small negative", or 53800339a1c2SMark Johnston * if it's a negative displacement of any magnitude, print as -<absval>. 53810339a1c2SMark Johnston * Respect the "octal" flag. "Small negative" is defined as "in the 53820339a1c2SMark Johnston * interval [NEG_LIMIT, 0)". 53830339a1c2SMark Johnston * 53840339a1c2SMark Johnston * Also, "isunsigned_op()" instructions never print negatives. 53850339a1c2SMark Johnston * 53860339a1c2SMark Johnston * Return whether we decided to print a negative value or not. 53870339a1c2SMark Johnston */ 53880339a1c2SMark Johnston 53890339a1c2SMark Johnston #define NEG_LIMIT -255 53900339a1c2SMark Johnston enum {IMM, DISP}; 53910339a1c2SMark Johnston enum {POS, TRY_NEG}; 53920339a1c2SMark Johnston 53930339a1c2SMark Johnston static int 53940339a1c2SMark Johnston print_imm(dis86_t *dis, uint64_t usv, uint64_t mask, char *buf, 53950339a1c2SMark Johnston size_t buflen, int disp, int try_neg) 53960339a1c2SMark Johnston { 53970339a1c2SMark Johnston int curlen; 53980339a1c2SMark Johnston int64_t sv = (int64_t)usv; 53990339a1c2SMark Johnston int octal = dis->d86_flags & DIS_F_OCTAL; 54000339a1c2SMark Johnston 54010339a1c2SMark Johnston curlen = strlen(buf); 54020339a1c2SMark Johnston 54030339a1c2SMark Johnston if (try_neg == TRY_NEG && sv < 0 && 54040339a1c2SMark Johnston (disp || sv >= NEG_LIMIT) && 54050339a1c2SMark Johnston !isunsigned_op(dis->d86_mnem)) { 54060339a1c2SMark Johnston dis->d86_sprintf_func(buf + curlen, buflen - curlen, 54070339a1c2SMark Johnston octal ? "-0%llo" : "-0x%llx", (-sv) & mask); 54080339a1c2SMark Johnston return (1); 54090339a1c2SMark Johnston } else { 54100339a1c2SMark Johnston if (disp == DISP) 54110339a1c2SMark Johnston dis->d86_sprintf_func(buf + curlen, buflen - curlen, 54120339a1c2SMark Johnston octal ? "+0%llo" : "+0x%llx", usv & mask); 54130339a1c2SMark Johnston else 54140339a1c2SMark Johnston dis->d86_sprintf_func(buf + curlen, buflen - curlen, 54150339a1c2SMark Johnston octal ? "0%llo" : "0x%llx", usv & mask); 54160339a1c2SMark Johnston return (0); 54170339a1c2SMark Johnston 54180339a1c2SMark Johnston } 54190339a1c2SMark Johnston } 54200339a1c2SMark Johnston 54210339a1c2SMark Johnston 54220339a1c2SMark Johnston static int 54230339a1c2SMark Johnston log2(int size) 54240339a1c2SMark Johnston { 54250339a1c2SMark Johnston switch (size) { 54260339a1c2SMark Johnston case 1: return (0); 54270339a1c2SMark Johnston case 2: return (1); 54280339a1c2SMark Johnston case 4: return (2); 54290339a1c2SMark Johnston case 8: return (3); 54300339a1c2SMark Johnston } 54310339a1c2SMark Johnston return (0); 54320339a1c2SMark Johnston } 54330339a1c2SMark Johnston 54340339a1c2SMark Johnston /* ARGSUSED */ 54350339a1c2SMark Johnston void 54360339a1c2SMark Johnston dtrace_disx86_str(dis86_t *dis, uint_t mode, uint64_t pc, char *buf, 54370339a1c2SMark Johnston size_t buflen) 54380339a1c2SMark Johnston { 54390339a1c2SMark Johnston uint64_t reltgt = 0; 54400339a1c2SMark Johnston uint64_t tgt = 0; 54410339a1c2SMark Johnston int curlen; 54420339a1c2SMark Johnston int (*lookup)(void *, uint64_t, char *, size_t); 54430339a1c2SMark Johnston int i; 54440339a1c2SMark Johnston int64_t sv; 54450339a1c2SMark Johnston uint64_t usv, mask, save_mask, save_usv; 54460339a1c2SMark Johnston static uint64_t masks[] = 54470339a1c2SMark Johnston {0xffU, 0xffffU, 0xffffffffU, 0xffffffffffffffffULL}; 54480339a1c2SMark Johnston save_usv = 0; 54490339a1c2SMark Johnston 54500339a1c2SMark Johnston dis->d86_sprintf_func(buf, buflen, "%-6s ", dis->d86_mnem); 54510339a1c2SMark Johnston 54520339a1c2SMark Johnston /* 54530339a1c2SMark Johnston * For PC-relative jumps, the pc is really the next pc after executing 54540339a1c2SMark Johnston * this instruction, so increment it appropriately. 54550339a1c2SMark Johnston */ 54560339a1c2SMark Johnston pc += dis->d86_len; 54570339a1c2SMark Johnston 54580339a1c2SMark Johnston for (i = 0; i < dis->d86_numopnds; i++) { 54590339a1c2SMark Johnston d86opnd_t *op = &dis->d86_opnd[i]; 54600339a1c2SMark Johnston 54610339a1c2SMark Johnston if (i != 0) 54620339a1c2SMark Johnston (void) strlcat(buf, ",", buflen); 54630339a1c2SMark Johnston 54640339a1c2SMark Johnston (void) strlcat(buf, op->d86_prefix, buflen); 54650339a1c2SMark Johnston 54660339a1c2SMark Johnston /* 54670339a1c2SMark Johnston * sv is for the signed, possibly-truncated immediate or 54680339a1c2SMark Johnston * displacement; usv retains the original size and 54690339a1c2SMark Johnston * unsignedness for symbol lookup. 54700339a1c2SMark Johnston */ 54710339a1c2SMark Johnston 54720339a1c2SMark Johnston sv = usv = op->d86_value; 54730339a1c2SMark Johnston 54740339a1c2SMark Johnston /* 54750339a1c2SMark Johnston * About masks: for immediates that represent 54760339a1c2SMark Johnston * addresses, the appropriate display size is 54770339a1c2SMark Johnston * the effective address size of the instruction. 54780339a1c2SMark Johnston * This includes MODE_OFFSET, MODE_IPREL, and 54790339a1c2SMark Johnston * MODE_RIPREL. Immediates that are simply 54800339a1c2SMark Johnston * immediate values should display in the operand's 54810339a1c2SMark Johnston * size, however, since they don't represent addresses. 54820339a1c2SMark Johnston */ 54830339a1c2SMark Johnston 54840339a1c2SMark Johnston /* d86_addr_size is SIZEnn, which is log2(real size) */ 54850339a1c2SMark Johnston mask = masks[dis->d86_addr_size]; 54860339a1c2SMark Johnston 54870339a1c2SMark Johnston /* d86_value_size and d86_imm_bytes are in bytes */ 54880339a1c2SMark Johnston if (op->d86_mode == MODE_SIGNED || 54890339a1c2SMark Johnston op->d86_mode == MODE_IMPLIED) 54900339a1c2SMark Johnston mask = masks[log2(op->d86_value_size)]; 54910339a1c2SMark Johnston 54920339a1c2SMark Johnston switch (op->d86_mode) { 54930339a1c2SMark Johnston 54940339a1c2SMark Johnston case MODE_NONE: 54950339a1c2SMark Johnston 54960339a1c2SMark Johnston (void) strlcat(buf, op->d86_opnd, buflen); 54970339a1c2SMark Johnston break; 54980339a1c2SMark Johnston 54990339a1c2SMark Johnston case MODE_SIGNED: 55000339a1c2SMark Johnston case MODE_IMPLIED: 55010339a1c2SMark Johnston case MODE_OFFSET: 55020339a1c2SMark Johnston 55030339a1c2SMark Johnston tgt = usv; 55040339a1c2SMark Johnston 55050339a1c2SMark Johnston if (dis->d86_seg_prefix) 55060339a1c2SMark Johnston (void) strlcat(buf, dis->d86_seg_prefix, 55070339a1c2SMark Johnston buflen); 55080339a1c2SMark Johnston 55090339a1c2SMark Johnston if (op->d86_mode == MODE_SIGNED || 55100339a1c2SMark Johnston op->d86_mode == MODE_IMPLIED) { 55110339a1c2SMark Johnston (void) strlcat(buf, "$", buflen); 55120339a1c2SMark Johnston } 55130339a1c2SMark Johnston 55140339a1c2SMark Johnston if (print_imm(dis, usv, mask, buf, buflen, 55150339a1c2SMark Johnston IMM, TRY_NEG) && 55160339a1c2SMark Johnston (op->d86_mode == MODE_SIGNED || 55170339a1c2SMark Johnston op->d86_mode == MODE_IMPLIED)) { 55180339a1c2SMark Johnston 55190339a1c2SMark Johnston /* 55200339a1c2SMark Johnston * We printed a negative value for an 55210339a1c2SMark Johnston * immediate that wasn't a 55220339a1c2SMark Johnston * displacement. Note that fact so we can 55230339a1c2SMark Johnston * print the positive value as an 55240339a1c2SMark Johnston * annotation. 55250339a1c2SMark Johnston */ 55260339a1c2SMark Johnston 55270339a1c2SMark Johnston save_usv = usv; 55280339a1c2SMark Johnston save_mask = mask; 55290339a1c2SMark Johnston } 55300339a1c2SMark Johnston (void) strlcat(buf, op->d86_opnd, buflen); 55310339a1c2SMark Johnston 55320339a1c2SMark Johnston break; 55330339a1c2SMark Johnston 55340339a1c2SMark Johnston case MODE_IPREL: 55350339a1c2SMark Johnston case MODE_RIPREL: 55360339a1c2SMark Johnston 55370339a1c2SMark Johnston reltgt = pc + sv; 55380339a1c2SMark Johnston 55390339a1c2SMark Johnston switch (mode) { 55400339a1c2SMark Johnston case SIZE16: 55410339a1c2SMark Johnston reltgt = (uint16_t)reltgt; 55420339a1c2SMark Johnston break; 55430339a1c2SMark Johnston case SIZE32: 55440339a1c2SMark Johnston reltgt = (uint32_t)reltgt; 55450339a1c2SMark Johnston break; 55460339a1c2SMark Johnston } 55470339a1c2SMark Johnston 55480339a1c2SMark Johnston (void) print_imm(dis, usv, mask, buf, buflen, 55490339a1c2SMark Johnston DISP, TRY_NEG); 55500339a1c2SMark Johnston 55510339a1c2SMark Johnston if (op->d86_mode == MODE_RIPREL) 55520339a1c2SMark Johnston (void) strlcat(buf, "(%rip)", buflen); 55530339a1c2SMark Johnston break; 55540339a1c2SMark Johnston } 55550339a1c2SMark Johnston } 55560339a1c2SMark Johnston 55570339a1c2SMark Johnston /* 55580339a1c2SMark Johnston * The symbol lookups may result in false positives, 55590339a1c2SMark Johnston * particularly on object files, where small numbers may match 55600339a1c2SMark Johnston * the 0-relative non-relocated addresses of symbols. 55610339a1c2SMark Johnston */ 55620339a1c2SMark Johnston 55630339a1c2SMark Johnston lookup = dis->d86_sym_lookup; 55640339a1c2SMark Johnston if (tgt != 0) { 55650339a1c2SMark Johnston if ((dis->d86_flags & DIS_F_NOIMMSYM) == 0 && 55660339a1c2SMark Johnston lookup(dis->d86_data, tgt, NULL, 0) == 0) { 55670339a1c2SMark Johnston (void) strlcat(buf, "\t<", buflen); 55680339a1c2SMark Johnston curlen = strlen(buf); 55690339a1c2SMark Johnston lookup(dis->d86_data, tgt, buf + curlen, 55700339a1c2SMark Johnston buflen - curlen); 55710339a1c2SMark Johnston (void) strlcat(buf, ">", buflen); 55720339a1c2SMark Johnston } 55730339a1c2SMark Johnston 55740339a1c2SMark Johnston /* 55750339a1c2SMark Johnston * If we printed a negative immediate above, print the 55760339a1c2SMark Johnston * positive in case our heuristic was unhelpful 55770339a1c2SMark Johnston */ 55780339a1c2SMark Johnston if (save_usv) { 55790339a1c2SMark Johnston (void) strlcat(buf, "\t<", buflen); 55800339a1c2SMark Johnston (void) print_imm(dis, save_usv, save_mask, buf, buflen, 55810339a1c2SMark Johnston IMM, POS); 55820339a1c2SMark Johnston (void) strlcat(buf, ">", buflen); 55830339a1c2SMark Johnston } 55840339a1c2SMark Johnston } 55850339a1c2SMark Johnston 55860339a1c2SMark Johnston if (reltgt != 0) { 55870339a1c2SMark Johnston /* Print symbol or effective address for reltgt */ 55880339a1c2SMark Johnston 55890339a1c2SMark Johnston (void) strlcat(buf, "\t<", buflen); 55900339a1c2SMark Johnston curlen = strlen(buf); 55910339a1c2SMark Johnston lookup(dis->d86_data, reltgt, buf + curlen, 55920339a1c2SMark Johnston buflen - curlen); 55930339a1c2SMark Johnston (void) strlcat(buf, ">", buflen); 55940339a1c2SMark Johnston } 55950339a1c2SMark Johnston } 55960339a1c2SMark Johnston 55970339a1c2SMark Johnston #endif /* DIS_TEXT */ 5598