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. 24c3ddb60eSPeter Grehan * Copyright (c) 2012, Joyent, Inc. All rights reserved. 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 */ 900339a1c2SMark Johnston } instable_t; 910339a1c2SMark Johnston 920339a1c2SMark Johnston /* 930339a1c2SMark Johnston * Instruction formats. 940339a1c2SMark Johnston */ 950339a1c2SMark Johnston enum { 960339a1c2SMark Johnston UNKNOWN, 970339a1c2SMark Johnston MRw, 980339a1c2SMark Johnston IMlw, 990339a1c2SMark Johnston IMw, 1000339a1c2SMark Johnston IR, 1010339a1c2SMark Johnston OA, 1020339a1c2SMark Johnston AO, 1030339a1c2SMark Johnston MS, 1040339a1c2SMark Johnston SM, 1050339a1c2SMark Johnston Mv, 1060339a1c2SMark Johnston Mw, 1070339a1c2SMark Johnston M, /* register or memory */ 108c3ddb60eSPeter Grehan MG9, /* register or memory in group 9 (prefix optional) */ 1090339a1c2SMark Johnston Mb, /* register or memory, always byte sized */ 1100339a1c2SMark Johnston MO, /* memory only (no registers) */ 1110339a1c2SMark Johnston PREF, 112c3ddb60eSPeter Grehan SWAPGS_RDTSCP, 1130339a1c2SMark Johnston MONITOR_MWAIT, 1140339a1c2SMark Johnston R, 1150339a1c2SMark Johnston RA, 1160339a1c2SMark Johnston SEG, 1170339a1c2SMark Johnston MR, 1180339a1c2SMark Johnston RM, 119c3ddb60eSPeter Grehan RM_66r, /* RM, but with a required 0x66 prefix */ 1200339a1c2SMark Johnston IA, 1210339a1c2SMark Johnston MA, 1220339a1c2SMark Johnston SD, 1230339a1c2SMark Johnston AD, 1240339a1c2SMark Johnston SA, 1250339a1c2SMark Johnston D, 1260339a1c2SMark Johnston INM, 1270339a1c2SMark Johnston SO, 1280339a1c2SMark Johnston BD, 1290339a1c2SMark Johnston I, 1300339a1c2SMark Johnston P, 1310339a1c2SMark Johnston V, 1320339a1c2SMark Johnston DSHIFT, /* for double shift that has an 8-bit immediate */ 1330339a1c2SMark Johnston U, 1340339a1c2SMark Johnston OVERRIDE, 1350339a1c2SMark Johnston NORM, /* instructions w/o ModR/M byte, no memory access */ 1360339a1c2SMark Johnston IMPLMEM, /* instructions w/o ModR/M byte, implicit mem access */ 1370339a1c2SMark Johnston O, /* for call */ 1380339a1c2SMark Johnston JTAB, /* jump table */ 1390339a1c2SMark Johnston IMUL, /* for 186 iimul instr */ 1400339a1c2SMark Johnston CBW, /* so data16 can be evaluated for cbw and variants */ 1410339a1c2SMark Johnston MvI, /* for 186 logicals */ 1420339a1c2SMark Johnston ENTER, /* for 186 enter instr */ 1430339a1c2SMark Johnston RMw, /* for 286 arpl instr */ 1440339a1c2SMark Johnston Ib, /* for push immediate byte */ 1450339a1c2SMark Johnston F, /* for 287 instructions */ 1460339a1c2SMark Johnston FF, /* for 287 instructions */ 1470339a1c2SMark Johnston FFC, /* for 287 instructions */ 1480339a1c2SMark Johnston DM, /* 16-bit data */ 1490339a1c2SMark Johnston AM, /* 16-bit addr */ 1500339a1c2SMark Johnston LSEG, /* for 3-bit seg reg encoding */ 1510339a1c2SMark Johnston MIb, /* for 386 logicals */ 1520339a1c2SMark Johnston SREG, /* for 386 special registers */ 1530339a1c2SMark Johnston PREFIX, /* a REP instruction prefix */ 1540339a1c2SMark Johnston LOCK, /* a LOCK instruction prefix */ 1550339a1c2SMark Johnston INT3, /* The int 3 instruction, which has a fake operand */ 1560339a1c2SMark Johnston INTx, /* The normal int instruction, with explicit int num */ 1570339a1c2SMark Johnston DSHIFTcl, /* for double shift that implicitly uses %cl */ 1580339a1c2SMark Johnston CWD, /* so data16 can be evaluated for cwd and variants */ 1590339a1c2SMark Johnston RET, /* single immediate 16-bit operand */ 1600339a1c2SMark Johnston MOVZ, /* for movs and movz, with different size operands */ 1610339a1c2SMark Johnston CRC32, /* for crc32, with different size operands */ 1620339a1c2SMark Johnston XADDB, /* for xaddb */ 1630339a1c2SMark Johnston MOVSXZ, /* AMD64 mov sign extend 32 to 64 bit instruction */ 1640339a1c2SMark Johnston MOVBE, /* movbe instruction */ 1650339a1c2SMark Johnston 1660339a1c2SMark Johnston /* 1670339a1c2SMark Johnston * MMX/SIMD addressing modes. 1680339a1c2SMark Johnston */ 1690339a1c2SMark Johnston 1700339a1c2SMark Johnston MMO, /* Prefixable MMX/SIMD-Int mm/mem -> mm */ 1710339a1c2SMark Johnston MMOIMPL, /* Prefixable MMX/SIMD-Int mm -> mm (mem) */ 1720339a1c2SMark Johnston MMO3P, /* Prefixable MMX/SIMD-Int mm -> r32,imm8 */ 1730339a1c2SMark Johnston MMOM3, /* Prefixable MMX/SIMD-Int mm -> r32 */ 1740339a1c2SMark Johnston MMOS, /* Prefixable MMX/SIMD-Int mm -> mm/mem */ 1750339a1c2SMark Johnston MMOMS, /* Prefixable MMX/SIMD-Int mm -> mem */ 1760339a1c2SMark Johnston MMOPM, /* MMX/SIMD-Int mm/mem -> mm,imm8 */ 1770339a1c2SMark Johnston MMOPM_66o, /* MMX/SIMD-Int 0x66 optional mm/mem -> mm,imm8 */ 1780339a1c2SMark Johnston MMOPRM, /* Prefixable MMX/SIMD-Int r32/mem -> mm,imm8 */ 1790339a1c2SMark Johnston MMOSH, /* Prefixable MMX mm,imm8 */ 1800339a1c2SMark Johnston MM, /* MMX/SIMD-Int mm/mem -> mm */ 1810339a1c2SMark Johnston MMS, /* MMX/SIMD-Int mm -> mm/mem */ 1820339a1c2SMark Johnston MMSH, /* MMX mm,imm8 */ 1830339a1c2SMark Johnston XMMO, /* Prefixable SIMD xmm/mem -> xmm */ 1840339a1c2SMark Johnston XMMOS, /* Prefixable SIMD xmm -> xmm/mem */ 1850339a1c2SMark Johnston XMMOPM, /* Prefixable SIMD xmm/mem w/to xmm,imm8 */ 1860339a1c2SMark Johnston XMMOMX, /* Prefixable SIMD mm/mem -> xmm */ 1870339a1c2SMark Johnston XMMOX3, /* Prefixable SIMD xmm -> r32 */ 1880339a1c2SMark Johnston XMMOXMM, /* Prefixable SIMD xmm/mem -> mm */ 1890339a1c2SMark Johnston XMMOM, /* Prefixable SIMD xmm -> mem */ 1900339a1c2SMark Johnston XMMOMS, /* Prefixable SIMD mem -> xmm */ 1910339a1c2SMark Johnston XMM, /* SIMD xmm/mem -> xmm */ 1920339a1c2SMark Johnston XMM_66r, /* SIMD 0x66 prefix required xmm/mem -> xmm */ 1930339a1c2SMark Johnston XMM_66o, /* SIMD 0x66 prefix optional xmm/mem -> xmm */ 1940339a1c2SMark Johnston XMMXIMPL, /* SIMD xmm -> xmm (mem) */ 1950339a1c2SMark Johnston XMM3P, /* SIMD xmm -> r32,imm8 */ 1960339a1c2SMark Johnston XMM3PM_66r, /* SIMD 0x66 prefix required xmm -> r32/mem,imm8 */ 1970339a1c2SMark Johnston XMMP, /* SIMD xmm/mem w/to xmm,imm8 */ 1980339a1c2SMark Johnston XMMP_66o, /* SIMD 0x66 prefix optional xmm/mem w/to xmm,imm8 */ 1990339a1c2SMark Johnston XMMP_66r, /* SIMD 0x66 prefix required xmm/mem w/to xmm,imm8 */ 2000339a1c2SMark Johnston XMMPRM, /* SIMD r32/mem -> xmm,imm8 */ 2010339a1c2SMark Johnston XMMPRM_66r, /* SIMD 0x66 prefix required r32/mem -> xmm,imm8 */ 2020339a1c2SMark Johnston XMMS, /* SIMD xmm -> xmm/mem */ 2030339a1c2SMark Johnston XMMM, /* SIMD mem -> xmm */ 2040339a1c2SMark Johnston XMMM_66r, /* SIMD 0x66 prefix required mem -> xmm */ 2050339a1c2SMark Johnston XMMMS, /* SIMD xmm -> mem */ 2060339a1c2SMark Johnston XMM3MX, /* SIMD r32/mem -> xmm */ 2070339a1c2SMark Johnston XMM3MXS, /* SIMD xmm -> r32/mem */ 2080339a1c2SMark Johnston XMMSH, /* SIMD xmm,imm8 */ 2090339a1c2SMark Johnston XMMXM3, /* SIMD xmm/mem -> r32 */ 2100339a1c2SMark Johnston XMMX3, /* SIMD xmm -> r32 */ 2110339a1c2SMark Johnston XMMXMM, /* SIMD xmm/mem -> mm */ 2120339a1c2SMark Johnston XMMMX, /* SIMD mm -> xmm */ 2130339a1c2SMark Johnston XMMXM, /* SIMD xmm -> mm */ 2140339a1c2SMark Johnston XMMX2I, /* SIMD xmm -> xmm, imm, imm */ 2150339a1c2SMark Johnston XMM2I, /* SIMD xmm, imm, imm */ 2160339a1c2SMark Johnston XMMFENCE, /* SIMD lfence or mfence */ 2170339a1c2SMark Johnston XMMSFNC, /* SIMD sfence (none or mem) */ 2180339a1c2SMark Johnston XGETBV_XSETBV, 2190339a1c2SMark Johnston VEX_NONE, /* VEX no operand */ 2200339a1c2SMark Johnston VEX_MO, /* VEX mod_rm -> implicit reg */ 2210339a1c2SMark Johnston VEX_RMrX, /* VEX VEX.vvvv, mod_rm -> mod_reg */ 2220339a1c2SMark Johnston VEX_RRX, /* VEX VEX.vvvv, mod_reg -> mod_rm */ 2230339a1c2SMark Johnston VEX_RMRX, /* VEX VEX.vvvv, mod_rm, imm8[7:4] -> mod_reg */ 2240339a1c2SMark Johnston VEX_MX, /* VEX mod_rm -> mod_reg */ 2250339a1c2SMark Johnston VEX_MXI, /* VEX mod_rm, imm8 -> mod_reg */ 2260339a1c2SMark Johnston VEX_XXI, /* VEX mod_rm, imm8 -> VEX.vvvv */ 2270339a1c2SMark Johnston VEX_MR, /* VEX mod_rm -> mod_reg */ 2280339a1c2SMark Johnston VEX_RRI, /* VEX mod_reg, mod_rm -> implicit(eflags/r32) */ 2290339a1c2SMark Johnston VEX_RX, /* VEX mod_reg -> mod_rm */ 2300339a1c2SMark Johnston VEX_RR, /* VEX mod_rm -> mod_reg */ 2310339a1c2SMark Johnston VEX_RRi, /* VEX mod_rm, imm8 -> mod_reg */ 2320339a1c2SMark Johnston VEX_RM, /* VEX mod_reg -> mod_rm */ 2330339a1c2SMark Johnston VEX_RRM, /* VEX VEX.vvvv, mod_reg -> mod_rm */ 234c3ddb60eSPeter Grehan VEX_RMX, /* VEX VEX.vvvv, mod_rm -> mod_reg */ 235c3ddb60eSPeter Grehan VMx, /* vmcall/vmlaunch/vmresume/vmxoff */ 236c3ddb60eSPeter Grehan VMxo, /* VMx instruction with optional prefix */ 237c3ddb60eSPeter Grehan SVM /* AMD SVM instructions */ 2380339a1c2SMark Johnston }; 2390339a1c2SMark Johnston 2400339a1c2SMark Johnston /* 2410339a1c2SMark Johnston * VEX prefixes 2420339a1c2SMark Johnston */ 2430339a1c2SMark Johnston #define VEX_2bytes 0xC5 /* the first byte of two-byte form */ 2440339a1c2SMark Johnston #define VEX_3bytes 0xC4 /* the first byte of three-byte form */ 2450339a1c2SMark Johnston 2460339a1c2SMark Johnston #define FILL 0x90 /* Fill byte used for alignment (nop) */ 2470339a1c2SMark Johnston 2480339a1c2SMark Johnston /* 2490339a1c2SMark Johnston ** Register numbers for the i386 2500339a1c2SMark Johnston */ 2510339a1c2SMark Johnston #define EAX_REGNO 0 2520339a1c2SMark Johnston #define ECX_REGNO 1 2530339a1c2SMark Johnston #define EDX_REGNO 2 2540339a1c2SMark Johnston #define EBX_REGNO 3 2550339a1c2SMark Johnston #define ESP_REGNO 4 2560339a1c2SMark Johnston #define EBP_REGNO 5 2570339a1c2SMark Johnston #define ESI_REGNO 6 2580339a1c2SMark Johnston #define EDI_REGNO 7 2590339a1c2SMark Johnston 2600339a1c2SMark Johnston /* 2610339a1c2SMark Johnston * modes for immediate values 2620339a1c2SMark Johnston */ 2630339a1c2SMark Johnston #define MODE_NONE 0 2640339a1c2SMark Johnston #define MODE_IPREL 1 /* signed IP relative value */ 2650339a1c2SMark Johnston #define MODE_SIGNED 2 /* sign extended immediate */ 2660339a1c2SMark Johnston #define MODE_IMPLIED 3 /* constant value implied from opcode */ 2670339a1c2SMark Johnston #define MODE_OFFSET 4 /* offset part of an address */ 2680339a1c2SMark Johnston #define MODE_RIPREL 5 /* like IPREL, but from %rip (amd64) */ 2690339a1c2SMark Johnston 2700339a1c2SMark Johnston /* 2710339a1c2SMark Johnston * The letters used in these macros are: 2720339a1c2SMark Johnston * IND - indirect to another to another table 2730339a1c2SMark Johnston * "T" - means to Terminate indirections (this is the final opcode) 2740339a1c2SMark Johnston * "S" - means "operand length suffix required" 2750339a1c2SMark Johnston * "NS" - means "no suffix" which is the operand length suffix of the opcode 2760339a1c2SMark Johnston * "Z" - means instruction size arg required 2770339a1c2SMark Johnston * "u" - means the opcode is invalid in IA32 but valid in amd64 2780339a1c2SMark Johnston * "x" - means the opcode is invalid in amd64, but not IA32 2790339a1c2SMark Johnston * "y" - means the operand size is always 64 bits in 64 bit mode 2800339a1c2SMark Johnston * "p" - means push/pop stack operation 2810339a1c2SMark Johnston */ 2820339a1c2SMark Johnston 2830339a1c2SMark Johnston #if defined(DIS_TEXT) && defined(DIS_MEM) 2840339a1c2SMark Johnston #define IND(table) {(instable_t *)table, 0, "", 0, 0, 0, 0, 0, 0} 2850339a1c2SMark Johnston #define INDx(table) {(instable_t *)table, 0, "", 0, 0, 1, 0, 0, 0} 2860339a1c2SMark Johnston #define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0, 0} 2870339a1c2SMark Johnston #define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 0, 1, 0} 2880339a1c2SMark Johnston #define TNSx(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0, 0} 2890339a1c2SMark Johnston #define TNSy(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 0} 2900339a1c2SMark Johnston #define TNSyp(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0, 1} 2910339a1c2SMark Johnston #define TNSZ(name, amode, sz) {TERM, amode, name, 0, sz, 0, 0, 0, 0} 2920339a1c2SMark Johnston #define TNSZy(name, amode, sz) {TERM, amode, name, 0, sz, 0, 1, 0, 0} 2930339a1c2SMark Johnston #define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 0} 2940339a1c2SMark Johnston #define TSx(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0, 0} 2950339a1c2SMark Johnston #define TSy(name, amode) {TERM, amode, name, 1, 0, 0, 1, 0, 0} 2960339a1c2SMark Johnston #define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0, 1} 2970339a1c2SMark Johnston #define TSZ(name, amode, sz) {TERM, amode, name, 1, sz, 0, 0, 0, 0} 2980339a1c2SMark Johnston #define TSZx(name, amode, sz) {TERM, amode, name, 1, sz, 1, 0, 0, 0} 2990339a1c2SMark Johnston #define TSZy(name, amode, sz) {TERM, amode, name, 1, sz, 0, 1, 0, 0} 3000339a1c2SMark Johnston #define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0} 3010339a1c2SMark Johnston #elif defined(DIS_TEXT) 3020339a1c2SMark Johnston #define IND(table) {(instable_t *)table, 0, "", 0, 0, 0, 0, 0} 3030339a1c2SMark Johnston #define INDx(table) {(instable_t *)table, 0, "", 0, 1, 0, 0, 0} 3040339a1c2SMark Johnston #define TNS(name, amode) {TERM, amode, name, 0, 0, 0, 0, 0} 3050339a1c2SMark Johnston #define TNSu(name, amode) {TERM, amode, name, 0, 0, 0, 1, 0} 3060339a1c2SMark Johnston #define TNSx(name, amode) {TERM, amode, name, 0, 1, 0, 0, 0} 3070339a1c2SMark Johnston #define TNSy(name, amode) {TERM, amode, name, 0, 0, 1, 0, 0} 3080339a1c2SMark Johnston #define TNSyp(name, amode) {TERM, amode, name, 0, 0, 1, 0, 1} 3090339a1c2SMark Johnston #define TNSZ(name, amode, sz) {TERM, amode, name, 0, 0, 0, 0, 0} 3100339a1c2SMark Johnston #define TNSZy(name, amode, sz) {TERM, amode, name, 0, 0, 1, 0, 0} 3110339a1c2SMark Johnston #define TS(name, amode) {TERM, amode, name, 1, 0, 0, 0, 0} 3120339a1c2SMark Johnston #define TSx(name, amode) {TERM, amode, name, 1, 1, 0, 0, 0} 3130339a1c2SMark Johnston #define TSy(name, amode) {TERM, amode, name, 1, 0, 1, 0, 0} 3140339a1c2SMark Johnston #define TSp(name, amode) {TERM, amode, name, 1, 0, 0, 0, 1} 3150339a1c2SMark Johnston #define TSZ(name, amode, sz) {TERM, amode, name, 1, 0, 0, 0, 0} 3160339a1c2SMark Johnston #define TSZx(name, amode, sz) {TERM, amode, name, 1, 1, 0, 0, 0} 3170339a1c2SMark Johnston #define TSZy(name, amode, sz) {TERM, amode, name, 1, 0, 1, 0, 0} 3180339a1c2SMark Johnston #define INVALID {TERM, UNKNOWN, "", 0, 0, 0, 0, 0} 3190339a1c2SMark Johnston #elif defined(DIS_MEM) 3200339a1c2SMark Johnston #define IND(table) {(instable_t *)table, 0, 0, 0, 0, 0, 0} 3210339a1c2SMark Johnston #define INDx(table) {(instable_t *)table, 0, 0, 1, 0, 0, 0} 3220339a1c2SMark Johnston #define TNS(name, amode) {TERM, amode, 0, 0, 0, 0, 0} 3230339a1c2SMark Johnston #define TNSu(name, amode) {TERM, amode, 0, 0, 0, 1, 0} 3240339a1c2SMark Johnston #define TNSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0} 3250339a1c2SMark Johnston #define TNSyp(name, amode) {TERM, amode, 0, 0, 1, 0, 1} 3260339a1c2SMark Johnston #define TNSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0} 3270339a1c2SMark Johnston #define TNSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0} 3280339a1c2SMark Johnston #define TNSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0} 3290339a1c2SMark Johnston #define TS(name, amode) {TERM, amode, 0, 0, 0, 0, 0} 3300339a1c2SMark Johnston #define TSx(name, amode) {TERM, amode, 0, 1, 0, 0, 0} 3310339a1c2SMark Johnston #define TSy(name, amode) {TERM, amode, 0, 0, 1, 0, 0} 3320339a1c2SMark Johnston #define TSp(name, amode) {TERM, amode, 0, 0, 0, 0, 1} 3330339a1c2SMark Johnston #define TSZ(name, amode, sz) {TERM, amode, sz, 0, 0, 0, 0} 3340339a1c2SMark Johnston #define TSZx(name, amode, sz) {TERM, amode, sz, 1, 0, 0, 0} 3350339a1c2SMark Johnston #define TSZy(name, amode, sz) {TERM, amode, sz, 0, 1, 0, 0} 3360339a1c2SMark Johnston #define INVALID {TERM, UNKNOWN, 0, 0, 0, 0, 0} 3370339a1c2SMark Johnston #else 3380339a1c2SMark Johnston #define IND(table) {(instable_t *)table, 0, 0, 0, 0, 0} 3390339a1c2SMark Johnston #define INDx(table) {(instable_t *)table, 0, 1, 0, 0, 0} 3400339a1c2SMark Johnston #define TNS(name, amode) {TERM, amode, 0, 0, 0, 0} 3410339a1c2SMark Johnston #define TNSu(name, amode) {TERM, amode, 0, 0, 1, 0} 3420339a1c2SMark Johnston #define TNSy(name, amode) {TERM, amode, 0, 1, 0, 0} 3430339a1c2SMark Johnston #define TNSyp(name, amode) {TERM, amode, 0, 1, 0, 1} 3440339a1c2SMark Johnston #define TNSx(name, amode) {TERM, amode, 1, 0, 0, 0} 3450339a1c2SMark Johnston #define TNSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0} 3460339a1c2SMark Johnston #define TNSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0} 3470339a1c2SMark Johnston #define TS(name, amode) {TERM, amode, 0, 0, 0, 0} 3480339a1c2SMark Johnston #define TSx(name, amode) {TERM, amode, 1, 0, 0, 0} 3490339a1c2SMark Johnston #define TSy(name, amode) {TERM, amode, 0, 1, 0, 0} 3500339a1c2SMark Johnston #define TSp(name, amode) {TERM, amode, 0, 0, 0, 1} 3510339a1c2SMark Johnston #define TSZ(name, amode, sz) {TERM, amode, 0, 0, 0, 0} 3520339a1c2SMark Johnston #define TSZx(name, amode, sz) {TERM, amode, 1, 0, 0, 0} 3530339a1c2SMark Johnston #define TSZy(name, amode, sz) {TERM, amode, 0, 1, 0, 0} 3540339a1c2SMark Johnston #define INVALID {TERM, UNKNOWN, 0, 0, 0, 0} 3550339a1c2SMark Johnston #endif 3560339a1c2SMark Johnston 3570339a1c2SMark Johnston #ifdef DIS_TEXT 3580339a1c2SMark Johnston /* 3590339a1c2SMark Johnston * this decodes the r_m field for mode's 0, 1, 2 in 16 bit mode 3600339a1c2SMark Johnston */ 3610339a1c2SMark Johnston const char *const dis_addr16[3][8] = { 3620339a1c2SMark Johnston "(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "", 3630339a1c2SMark Johnston "(%bx)", 3640339a1c2SMark Johnston "(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di", "(%bp)", 3650339a1c2SMark Johnston "(%bx)", 3660339a1c2SMark Johnston "(%bx,%si)", "(%bx,%di)", "(%bp,%si)", "(%bp,%di)", "(%si)", "(%di)", "(%bp)", 3670339a1c2SMark Johnston "(%bx)", 3680339a1c2SMark Johnston }; 3690339a1c2SMark Johnston 3700339a1c2SMark Johnston 3710339a1c2SMark Johnston /* 3720339a1c2SMark Johnston * This decodes 32 bit addressing mode r_m field for modes 0, 1, 2 3730339a1c2SMark Johnston */ 3740339a1c2SMark Johnston const char *const dis_addr32_mode0[16] = { 3750339a1c2SMark Johnston "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "", "(%esi)", "(%edi)", 3760339a1c2SMark Johnston "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "", "(%r14d)", "(%r15d)" 3770339a1c2SMark Johnston }; 3780339a1c2SMark Johnston 3790339a1c2SMark Johnston const char *const dis_addr32_mode12[16] = { 3800339a1c2SMark Johnston "(%eax)", "(%ecx)", "(%edx)", "(%ebx)", "", "(%ebp)", "(%esi)", "(%edi)", 3810339a1c2SMark Johnston "(%r8d)", "(%r9d)", "(%r10d)", "(%r11d)", "", "(%r13d)", "(%r14d)", "(%r15d)" 3820339a1c2SMark Johnston }; 3830339a1c2SMark Johnston 3840339a1c2SMark Johnston /* 3850339a1c2SMark Johnston * This decodes 64 bit addressing mode r_m field for modes 0, 1, 2 3860339a1c2SMark Johnston */ 3870339a1c2SMark Johnston const char *const dis_addr64_mode0[16] = { 3880339a1c2SMark Johnston "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rip)", "(%rsi)", "(%rdi)", 3890339a1c2SMark Johnston "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%rip)", "(%r14)", "(%r15)" 3900339a1c2SMark Johnston }; 3910339a1c2SMark Johnston const char *const dis_addr64_mode12[16] = { 3920339a1c2SMark Johnston "(%rax)", "(%rcx)", "(%rdx)", "(%rbx)", "", "(%rbp)", "(%rsi)", "(%rdi)", 3930339a1c2SMark Johnston "(%r8)", "(%r9)", "(%r10)", "(%r11)", "(%r12)", "(%r13)", "(%r14)", "(%r15)" 3940339a1c2SMark Johnston }; 3950339a1c2SMark Johnston 3960339a1c2SMark Johnston /* 3970339a1c2SMark Johnston * decode for scale from SIB byte 3980339a1c2SMark Johnston */ 3990339a1c2SMark Johnston const char *const dis_scale_factor[4] = { ")", ",2)", ",4)", ",8)" }; 4000339a1c2SMark Johnston 4010339a1c2SMark Johnston /* 4020339a1c2SMark Johnston * register decoding for normal references to registers (ie. not addressing) 4030339a1c2SMark Johnston */ 4040339a1c2SMark Johnston const char *const dis_REG8[16] = { 4050339a1c2SMark Johnston "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", 4060339a1c2SMark Johnston "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" 4070339a1c2SMark Johnston }; 4080339a1c2SMark Johnston 4090339a1c2SMark Johnston const char *const dis_REG8_REX[16] = { 4100339a1c2SMark Johnston "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", 4110339a1c2SMark Johnston "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" 4120339a1c2SMark Johnston }; 4130339a1c2SMark Johnston 4140339a1c2SMark Johnston const char *const dis_REG16[16] = { 4150339a1c2SMark Johnston "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", 4160339a1c2SMark Johnston "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" 4170339a1c2SMark Johnston }; 4180339a1c2SMark Johnston 4190339a1c2SMark Johnston const char *const dis_REG32[16] = { 4200339a1c2SMark Johnston "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", 4210339a1c2SMark Johnston "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" 4220339a1c2SMark Johnston }; 4230339a1c2SMark Johnston 4240339a1c2SMark Johnston const char *const dis_REG64[16] = { 4250339a1c2SMark Johnston "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", 4260339a1c2SMark Johnston "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" 4270339a1c2SMark Johnston }; 4280339a1c2SMark Johnston 4290339a1c2SMark Johnston const char *const dis_DEBUGREG[16] = { 4300339a1c2SMark Johnston "%db0", "%db1", "%db2", "%db3", "%db4", "%db5", "%db6", "%db7", 4310339a1c2SMark Johnston "%db8", "%db9", "%db10", "%db11", "%db12", "%db13", "%db14", "%db15" 4320339a1c2SMark Johnston }; 4330339a1c2SMark Johnston 4340339a1c2SMark Johnston const char *const dis_CONTROLREG[16] = { 4350339a1c2SMark Johnston "%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5?", "%cr6?", "%cr7?", 4360339a1c2SMark Johnston "%cr8", "%cr9?", "%cr10?", "%cr11?", "%cr12?", "%cr13?", "%cr14?", "%cr15?" 4370339a1c2SMark Johnston }; 4380339a1c2SMark Johnston 4390339a1c2SMark Johnston const char *const dis_TESTREG[16] = { 4400339a1c2SMark Johnston "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7", 4410339a1c2SMark Johnston "%tr0?", "%tr1?", "%tr2?", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7" 4420339a1c2SMark Johnston }; 4430339a1c2SMark Johnston 4440339a1c2SMark Johnston const char *const dis_MMREG[16] = { 4450339a1c2SMark Johnston "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7", 4460339a1c2SMark Johnston "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" 4470339a1c2SMark Johnston }; 4480339a1c2SMark Johnston 4490339a1c2SMark Johnston const char *const dis_XMMREG[16] = { 4500339a1c2SMark Johnston "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", 4510339a1c2SMark Johnston "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" 4520339a1c2SMark Johnston }; 4530339a1c2SMark Johnston 4540339a1c2SMark Johnston const char *const dis_YMMREG[16] = { 4550339a1c2SMark Johnston "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6", "%ymm7", 4560339a1c2SMark Johnston "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13", "%ymm14", "%ymm15" 4570339a1c2SMark Johnston }; 4580339a1c2SMark Johnston 4590339a1c2SMark Johnston const char *const dis_SEGREG[16] = { 4600339a1c2SMark Johnston "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>", 4610339a1c2SMark Johnston "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "<reserved>", "<reserved>" 4620339a1c2SMark Johnston }; 4630339a1c2SMark Johnston 4640339a1c2SMark Johnston /* 4650339a1c2SMark Johnston * SIMD predicate suffixes 4660339a1c2SMark Johnston */ 4670339a1c2SMark Johnston const char *const dis_PREDSUFFIX[8] = { 4680339a1c2SMark Johnston "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord" 4690339a1c2SMark Johnston }; 4700339a1c2SMark Johnston 4710339a1c2SMark Johnston const char *const dis_AVXvgrp7[3][8] = { 4720339a1c2SMark Johnston /*0 1 2 3 4 5 6 7*/ 4730339a1c2SMark Johnston /*71*/ {"", "", "vpsrlw", "", "vpsraw", "", "vpsllw", ""}, 4740339a1c2SMark Johnston /*72*/ {"", "", "vpsrld", "", "vpsrad", "", "vpslld", ""}, 4750339a1c2SMark Johnston /*73*/ {"", "", "vpsrlq", "vpsrldq", "", "", "vpsllq", "vpslldq"} 4760339a1c2SMark Johnston }; 4770339a1c2SMark Johnston 4780339a1c2SMark Johnston #endif /* DIS_TEXT */ 4790339a1c2SMark Johnston 4800339a1c2SMark Johnston /* 4810339a1c2SMark Johnston * "decode table" for 64 bit mode MOVSXD instruction (opcode 0x63) 4820339a1c2SMark Johnston */ 4830339a1c2SMark Johnston const instable_t dis_opMOVSLD = TNS("movslq",MOVSXZ); 4840339a1c2SMark Johnston 4850339a1c2SMark Johnston /* 4860339a1c2SMark Johnston * "decode table" for pause and clflush instructions 4870339a1c2SMark Johnston */ 4880339a1c2SMark Johnston const instable_t dis_opPause = TNS("pause", NORM); 4890339a1c2SMark Johnston 4900339a1c2SMark Johnston /* 4910339a1c2SMark Johnston * Decode table for 0x0F00 opcodes 4920339a1c2SMark Johnston */ 4930339a1c2SMark Johnston const instable_t dis_op0F00[8] = { 4940339a1c2SMark Johnston 4950339a1c2SMark Johnston /* [0] */ TNS("sldt",M), TNS("str",M), TNSy("lldt",M), TNSy("ltr",M), 4960339a1c2SMark Johnston /* [4] */ TNSZ("verr",M,2), TNSZ("verw",M,2), INVALID, INVALID, 4970339a1c2SMark Johnston }; 4980339a1c2SMark Johnston 4990339a1c2SMark Johnston 5000339a1c2SMark Johnston /* 5010339a1c2SMark Johnston * Decode table for 0x0F01 opcodes 5020339a1c2SMark Johnston */ 5030339a1c2SMark Johnston const instable_t dis_op0F01[8] = { 5040339a1c2SMark Johnston 505c3ddb60eSPeter Grehan /* [0] */ TNSZ("sgdt",VMx,6), TNSZ("sidt",MONITOR_MWAIT,6), TNSZ("lgdt",XGETBV_XSETBV,6), TNSZ("lidt",SVM,6), 506c3ddb60eSPeter Grehan /* [4] */ TNSZ("smsw",M,2), INVALID, TNSZ("lmsw",M,2), TNS("invlpg",SWAPGS_RDTSCP), 5070339a1c2SMark Johnston }; 5080339a1c2SMark Johnston 5090339a1c2SMark Johnston /* 5100339a1c2SMark Johnston * Decode table for 0x0F18 opcodes -- SIMD prefetch 5110339a1c2SMark Johnston */ 5120339a1c2SMark Johnston const instable_t dis_op0F18[8] = { 5130339a1c2SMark Johnston 5140339a1c2SMark Johnston /* [0] */ TNS("prefetchnta",PREF),TNS("prefetcht0",PREF), TNS("prefetcht1",PREF), TNS("prefetcht2",PREF), 5150339a1c2SMark Johnston /* [4] */ INVALID, INVALID, INVALID, INVALID, 5160339a1c2SMark Johnston }; 5170339a1c2SMark Johnston 5180339a1c2SMark Johnston /* 5190339a1c2SMark Johnston * Decode table for 0x0FAE opcodes -- SIMD state save/restore 5200339a1c2SMark Johnston */ 5210339a1c2SMark Johnston const instable_t dis_op0FAE[8] = { 5220339a1c2SMark Johnston /* [0] */ TNSZ("fxsave",M,512), TNSZ("fxrstor",M,512), TNS("ldmxcsr",M), TNS("stmxcsr",M), 5230339a1c2SMark Johnston /* [4] */ TNSZ("xsave",M,512), TNS("lfence",XMMFENCE), TNS("mfence",XMMFENCE), TNS("sfence",XMMSFNC), 5240339a1c2SMark Johnston }; 5250339a1c2SMark Johnston 5260339a1c2SMark Johnston /* 5270339a1c2SMark Johnston * Decode table for 0x0FBA opcodes 5280339a1c2SMark Johnston */ 5290339a1c2SMark Johnston 5300339a1c2SMark Johnston const instable_t dis_op0FBA[8] = { 5310339a1c2SMark Johnston 5320339a1c2SMark Johnston /* [0] */ INVALID, INVALID, INVALID, INVALID, 5330339a1c2SMark Johnston /* [4] */ TS("bt",MIb), TS("bts",MIb), TS("btr",MIb), TS("btc",MIb), 5340339a1c2SMark Johnston }; 5350339a1c2SMark Johnston 5360339a1c2SMark Johnston /* 537c3ddb60eSPeter Grehan * Decode table for 0x0FC7 opcode (group 9) 5380339a1c2SMark Johnston */ 5390339a1c2SMark Johnston 5400339a1c2SMark Johnston const instable_t dis_op0FC7[8] = { 5410339a1c2SMark Johnston 5420339a1c2SMark Johnston /* [0] */ INVALID, TNS("cmpxchg8b",M), INVALID, INVALID, 543c3ddb60eSPeter Grehan /* [4] */ INVALID, INVALID, TNS("vmptrld",MG9), TNS("vmptrst",MG9), 5440339a1c2SMark Johnston }; 5450339a1c2SMark Johnston 546c3ddb60eSPeter Grehan /* 547c3ddb60eSPeter Grehan * Decode table for 0x0FC7 opcode (group 9) mode 3 548c3ddb60eSPeter Grehan */ 549c3ddb60eSPeter Grehan 550c3ddb60eSPeter Grehan const instable_t dis_op0FC7m3[8] = { 551c3ddb60eSPeter Grehan 552c3ddb60eSPeter Grehan /* [0] */ INVALID, INVALID, INVALID, INVALID, 553c3ddb60eSPeter Grehan /* [4] */ INVALID, INVALID, TNS("rdrand",MG9), INVALID, 554c3ddb60eSPeter Grehan }; 555c3ddb60eSPeter Grehan 556c3ddb60eSPeter Grehan /* 557c3ddb60eSPeter Grehan * Decode table for 0x0FC7 opcode with 0x66 prefix 558c3ddb60eSPeter Grehan */ 559c3ddb60eSPeter Grehan 560c3ddb60eSPeter Grehan const instable_t dis_op660FC7[8] = { 561c3ddb60eSPeter Grehan 562c3ddb60eSPeter Grehan /* [0] */ INVALID, INVALID, INVALID, INVALID, 563c3ddb60eSPeter Grehan /* [4] */ INVALID, INVALID, TNS("vmclear",M), INVALID, 564c3ddb60eSPeter Grehan }; 565c3ddb60eSPeter Grehan 566c3ddb60eSPeter Grehan /* 567c3ddb60eSPeter Grehan * Decode table for 0x0FC7 opcode with 0xF3 prefix 568c3ddb60eSPeter Grehan */ 569c3ddb60eSPeter Grehan 570c3ddb60eSPeter Grehan const instable_t dis_opF30FC7[8] = { 571c3ddb60eSPeter Grehan 572c3ddb60eSPeter Grehan /* [0] */ INVALID, INVALID, INVALID, INVALID, 573c3ddb60eSPeter Grehan /* [4] */ INVALID, INVALID, TNS("vmxon",M), INVALID, 574c3ddb60eSPeter Grehan }; 5750339a1c2SMark Johnston 5760339a1c2SMark Johnston /* 5770339a1c2SMark Johnston * Decode table for 0x0FC8 opcode -- 486 bswap instruction 5780339a1c2SMark Johnston * 5790339a1c2SMark Johnston *bit pattern: 0000 1111 1100 1reg 5800339a1c2SMark Johnston */ 5810339a1c2SMark Johnston const instable_t dis_op0FC8[4] = { 5820339a1c2SMark Johnston /* [0] */ TNS("bswap",R), INVALID, INVALID, INVALID, 5830339a1c2SMark Johnston }; 5840339a1c2SMark Johnston 5850339a1c2SMark Johnston /* 5860339a1c2SMark Johnston * Decode table for 0x0F71, 0x0F72, and 0x0F73 opcodes -- MMX instructions 5870339a1c2SMark Johnston */ 5880339a1c2SMark Johnston const instable_t dis_op0F7123[4][8] = { 5890339a1c2SMark Johnston { 5900339a1c2SMark Johnston /* [70].0 */ INVALID, INVALID, INVALID, INVALID, 5910339a1c2SMark Johnston /* .4 */ INVALID, INVALID, INVALID, INVALID, 5920339a1c2SMark Johnston }, { 5930339a1c2SMark Johnston /* [71].0 */ INVALID, INVALID, TNS("psrlw",MMOSH), INVALID, 5940339a1c2SMark Johnston /* .4 */ TNS("psraw",MMOSH), INVALID, TNS("psllw",MMOSH), INVALID, 5950339a1c2SMark Johnston }, { 5960339a1c2SMark Johnston /* [72].0 */ INVALID, INVALID, TNS("psrld",MMOSH), INVALID, 5970339a1c2SMark Johnston /* .4 */ TNS("psrad",MMOSH), INVALID, TNS("pslld",MMOSH), INVALID, 5980339a1c2SMark Johnston }, { 5990339a1c2SMark Johnston /* [73].0 */ INVALID, INVALID, TNS("psrlq",MMOSH), TNS("INVALID",MMOSH), 6000339a1c2SMark Johnston /* .4 */ INVALID, INVALID, TNS("psllq",MMOSH), TNS("INVALID",MMOSH), 6010339a1c2SMark Johnston } }; 6020339a1c2SMark Johnston 6030339a1c2SMark Johnston /* 6040339a1c2SMark Johnston * Decode table for SIMD extensions to above 0x0F71-0x0F73 opcodes. 6050339a1c2SMark Johnston */ 6060339a1c2SMark Johnston const instable_t dis_opSIMD7123[32] = { 6070339a1c2SMark Johnston /* [70].0 */ INVALID, INVALID, INVALID, INVALID, 6080339a1c2SMark Johnston /* .4 */ INVALID, INVALID, INVALID, INVALID, 6090339a1c2SMark Johnston 6100339a1c2SMark Johnston /* [71].0 */ INVALID, INVALID, TNS("psrlw",XMMSH), INVALID, 6110339a1c2SMark Johnston /* .4 */ TNS("psraw",XMMSH), INVALID, TNS("psllw",XMMSH), INVALID, 6120339a1c2SMark Johnston 6130339a1c2SMark Johnston /* [72].0 */ INVALID, INVALID, TNS("psrld",XMMSH), INVALID, 6140339a1c2SMark Johnston /* .4 */ TNS("psrad",XMMSH), INVALID, TNS("pslld",XMMSH), INVALID, 6150339a1c2SMark Johnston 6160339a1c2SMark Johnston /* [73].0 */ INVALID, INVALID, TNS("psrlq",XMMSH), TNS("psrldq",XMMSH), 6170339a1c2SMark Johnston /* .4 */ INVALID, INVALID, TNS("psllq",XMMSH), TNS("pslldq",XMMSH), 6180339a1c2SMark Johnston }; 6190339a1c2SMark Johnston 6200339a1c2SMark Johnston /* 6210339a1c2SMark Johnston * SIMD instructions have been wedged into the existing IA32 instruction 6220339a1c2SMark Johnston * set through the use of prefixes. That is, while 0xf0 0x58 may be 6230339a1c2SMark Johnston * addps, 0xf3 0xf0 0x58 (literally, repz addps) is a completely different 6240339a1c2SMark Johnston * instruction - addss. At present, three prefixes have been coopted in 6250339a1c2SMark Johnston * this manner - address size (0x66), repnz (0xf2) and repz (0xf3). The 6260339a1c2SMark Johnston * following tables are used to provide the prefixed instruction names. 6270339a1c2SMark Johnston * The arrays are sparse, but they're fast. 6280339a1c2SMark Johnston */ 6290339a1c2SMark Johnston 6300339a1c2SMark Johnston /* 6310339a1c2SMark Johnston * Decode table for SIMD instructions with the address size (0x66) prefix. 6320339a1c2SMark Johnston */ 6330339a1c2SMark Johnston const instable_t dis_opSIMDdata16[256] = { 6340339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 6350339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 6360339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 6370339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 6380339a1c2SMark Johnston 6390339a1c2SMark Johnston /* [10] */ TNSZ("movupd",XMM,16), TNSZ("movupd",XMMS,16), TNSZ("movlpd",XMMM,8), TNSZ("movlpd",XMMMS,8), 6400339a1c2SMark Johnston /* [14] */ TNSZ("unpcklpd",XMM,16),TNSZ("unpckhpd",XMM,16),TNSZ("movhpd",XMMM,8), TNSZ("movhpd",XMMMS,8), 6410339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 6420339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 6430339a1c2SMark Johnston 6440339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 6450339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 6460339a1c2SMark Johnston /* [28] */ TNSZ("movapd",XMM,16), TNSZ("movapd",XMMS,16), TNSZ("cvtpi2pd",XMMOMX,8),TNSZ("movntpd",XMMOMS,16), 6470339a1c2SMark Johnston /* [2C] */ TNSZ("cvttpd2pi",XMMXMM,16),TNSZ("cvtpd2pi",XMMXMM,16),TNSZ("ucomisd",XMM,8),TNSZ("comisd",XMM,8), 6480339a1c2SMark Johnston 6490339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 6500339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 6510339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 6520339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 6530339a1c2SMark Johnston 6540339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 6550339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 6560339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 6570339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 6580339a1c2SMark Johnston 6590339a1c2SMark Johnston /* [50] */ TNS("movmskpd",XMMOX3), TNSZ("sqrtpd",XMM,16), INVALID, INVALID, 6600339a1c2SMark Johnston /* [54] */ TNSZ("andpd",XMM,16), TNSZ("andnpd",XMM,16), TNSZ("orpd",XMM,16), TNSZ("xorpd",XMM,16), 6610339a1c2SMark Johnston /* [58] */ TNSZ("addpd",XMM,16), TNSZ("mulpd",XMM,16), TNSZ("cvtpd2ps",XMM,16),TNSZ("cvtps2dq",XMM,16), 6620339a1c2SMark Johnston /* [5C] */ TNSZ("subpd",XMM,16), TNSZ("minpd",XMM,16), TNSZ("divpd",XMM,16), TNSZ("maxpd",XMM,16), 6630339a1c2SMark Johnston 6640339a1c2SMark Johnston /* [60] */ TNSZ("punpcklbw",XMM,16),TNSZ("punpcklwd",XMM,16),TNSZ("punpckldq",XMM,16),TNSZ("packsswb",XMM,16), 6650339a1c2SMark Johnston /* [64] */ TNSZ("pcmpgtb",XMM,16), TNSZ("pcmpgtw",XMM,16), TNSZ("pcmpgtd",XMM,16), TNSZ("packuswb",XMM,16), 6660339a1c2SMark Johnston /* [68] */ TNSZ("punpckhbw",XMM,16),TNSZ("punpckhwd",XMM,16),TNSZ("punpckhdq",XMM,16),TNSZ("packssdw",XMM,16), 6670339a1c2SMark Johnston /* [6C] */ TNSZ("punpcklqdq",XMM,16),TNSZ("punpckhqdq",XMM,16),TNSZ("movd",XMM3MX,4),TNSZ("movdqa",XMM,16), 6680339a1c2SMark Johnston 6690339a1c2SMark Johnston /* [70] */ TNSZ("pshufd",XMMP,16), INVALID, INVALID, INVALID, 6700339a1c2SMark Johnston /* [74] */ TNSZ("pcmpeqb",XMM,16), TNSZ("pcmpeqw",XMM,16), TNSZ("pcmpeqd",XMM,16), INVALID, 6710339a1c2SMark Johnston /* [78] */ TNSZ("extrq",XMM2I,16), TNSZ("extrq",XMM,16), INVALID, INVALID, 6720339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, TNSZ("movd",XMM3MXS,4), TNSZ("movdqa",XMMS,16), 6730339a1c2SMark Johnston 6740339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 6750339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 6760339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 6770339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 6780339a1c2SMark Johnston 6790339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 6800339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 6810339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 6820339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 6830339a1c2SMark Johnston 6840339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 6850339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 6860339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 6870339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 6880339a1c2SMark Johnston 6890339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 6900339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 6910339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 6920339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 6930339a1c2SMark Johnston 6940339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("cmppd",XMMP,16), INVALID, 6950339a1c2SMark Johnston /* [C4] */ TNSZ("pinsrw",XMMPRM,2),TNS("pextrw",XMM3P), TNSZ("shufpd",XMMP,16), INVALID, 6960339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 6970339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 6980339a1c2SMark Johnston 6990339a1c2SMark Johnston /* [D0] */ INVALID, TNSZ("psrlw",XMM,16), TNSZ("psrld",XMM,16), TNSZ("psrlq",XMM,16), 7000339a1c2SMark Johnston /* [D4] */ TNSZ("paddq",XMM,16), TNSZ("pmullw",XMM,16), TNSZ("movq",XMMS,8), TNS("pmovmskb",XMMX3), 7010339a1c2SMark Johnston /* [D8] */ TNSZ("psubusb",XMM,16), TNSZ("psubusw",XMM,16), TNSZ("pminub",XMM,16), TNSZ("pand",XMM,16), 7020339a1c2SMark Johnston /* [DC] */ TNSZ("paddusb",XMM,16), TNSZ("paddusw",XMM,16), TNSZ("pmaxub",XMM,16), TNSZ("pandn",XMM,16), 7030339a1c2SMark Johnston 7040339a1c2SMark Johnston /* [E0] */ TNSZ("pavgb",XMM,16), TNSZ("psraw",XMM,16), TNSZ("psrad",XMM,16), TNSZ("pavgw",XMM,16), 7050339a1c2SMark Johnston /* [E4] */ TNSZ("pmulhuw",XMM,16), TNSZ("pmulhw",XMM,16), TNSZ("cvttpd2dq",XMM,16),TNSZ("movntdq",XMMS,16), 7060339a1c2SMark Johnston /* [E8] */ TNSZ("psubsb",XMM,16), TNSZ("psubsw",XMM,16), TNSZ("pminsw",XMM,16), TNSZ("por",XMM,16), 7070339a1c2SMark Johnston /* [EC] */ TNSZ("paddsb",XMM,16), TNSZ("paddsw",XMM,16), TNSZ("pmaxsw",XMM,16), TNSZ("pxor",XMM,16), 7080339a1c2SMark Johnston 7090339a1c2SMark Johnston /* [F0] */ INVALID, TNSZ("psllw",XMM,16), TNSZ("pslld",XMM,16), TNSZ("psllq",XMM,16), 7100339a1c2SMark Johnston /* [F4] */ TNSZ("pmuludq",XMM,16), TNSZ("pmaddwd",XMM,16), TNSZ("psadbw",XMM,16), TNSZ("maskmovdqu", XMMXIMPL,16), 7110339a1c2SMark Johnston /* [F8] */ TNSZ("psubb",XMM,16), TNSZ("psubw",XMM,16), TNSZ("psubd",XMM,16), TNSZ("psubq",XMM,16), 7120339a1c2SMark Johnston /* [FC] */ TNSZ("paddb",XMM,16), TNSZ("paddw",XMM,16), TNSZ("paddd",XMM,16), INVALID, 7130339a1c2SMark Johnston }; 7140339a1c2SMark Johnston 7150339a1c2SMark Johnston const instable_t dis_opAVX660F[256] = { 7160339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 7170339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 7180339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 7190339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 7200339a1c2SMark Johnston 7210339a1c2SMark Johnston /* [10] */ TNSZ("vmovupd",VEX_MX,16), TNSZ("vmovupd",VEX_RX,16), TNSZ("vmovlpd",VEX_RMrX,8), TNSZ("vmovlpd",VEX_RM,8), 7220339a1c2SMark Johnston /* [14] */ TNSZ("vunpcklpd",VEX_RMrX,16),TNSZ("vunpckhpd",VEX_RMrX,16),TNSZ("vmovhpd",VEX_RMrX,8), TNSZ("vmovhpd",VEX_RM,8), 7230339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 7240339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 7250339a1c2SMark Johnston 7260339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 7270339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 7280339a1c2SMark Johnston /* [28] */ TNSZ("vmovapd",VEX_MX,16), TNSZ("vmovapd",VEX_RX,16), INVALID, TNSZ("vmovntpd",VEX_RM,16), 7290339a1c2SMark Johnston /* [2C] */ INVALID, INVALID, TNSZ("vucomisd",VEX_MX,8),TNSZ("vcomisd",VEX_MX,8), 7300339a1c2SMark Johnston 7310339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 7320339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 7330339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 7340339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 7350339a1c2SMark Johnston 7360339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 7370339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 7380339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 7390339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 7400339a1c2SMark Johnston 7410339a1c2SMark Johnston /* [50] */ TNS("vmovmskpd",VEX_MR), TNSZ("vsqrtpd",VEX_MX,16), INVALID, INVALID, 7420339a1c2SMark Johnston /* [54] */ TNSZ("vandpd",VEX_RMrX,16), TNSZ("vandnpd",VEX_RMrX,16), TNSZ("vorpd",VEX_RMrX,16), TNSZ("vxorpd",VEX_RMrX,16), 7430339a1c2SMark Johnston /* [58] */ TNSZ("vaddpd",VEX_RMrX,16), TNSZ("vmulpd",VEX_RMrX,16), TNSZ("vcvtpd2ps",VEX_MX,16),TNSZ("vcvtps2dq",VEX_MX,16), 7440339a1c2SMark Johnston /* [5C] */ TNSZ("vsubpd",VEX_RMrX,16), TNSZ("vminpd",VEX_RMrX,16), TNSZ("vdivpd",VEX_RMrX,16), TNSZ("vmaxpd",VEX_RMrX,16), 7450339a1c2SMark Johnston 7460339a1c2SMark Johnston /* [60] */ TNSZ("vpunpcklbw",VEX_RMrX,16),TNSZ("vpunpcklwd",VEX_RMrX,16),TNSZ("vpunpckldq",VEX_RMrX,16),TNSZ("vpacksswb",VEX_RMrX,16), 7470339a1c2SMark Johnston /* [64] */ TNSZ("vpcmpgtb",VEX_RMrX,16), TNSZ("vpcmpgtw",VEX_RMrX,16), TNSZ("vpcmpgtd",VEX_RMrX,16), TNSZ("vpackuswb",VEX_RMrX,16), 7480339a1c2SMark Johnston /* [68] */ TNSZ("vpunpckhbw",VEX_RMrX,16),TNSZ("vpunpckhwd",VEX_RMrX,16),TNSZ("vpunpckhdq",VEX_RMrX,16),TNSZ("vpackssdw",VEX_RMrX,16), 7490339a1c2SMark Johnston /* [6C] */ TNSZ("vpunpcklqdq",VEX_RMrX,16),TNSZ("vpunpckhqdq",VEX_RMrX,16),TNSZ("vmovd",VEX_MX,4),TNSZ("vmovdqa",VEX_MX,16), 7500339a1c2SMark Johnston 7510339a1c2SMark Johnston /* [70] */ TNSZ("vpshufd",VEX_MXI,16), TNSZ("vgrp71",VEX_XXI,16), TNSZ("vgrp72",VEX_XXI,16), TNSZ("vgrp73",VEX_XXI,16), 7520339a1c2SMark Johnston /* [74] */ TNSZ("vpcmpeqb",VEX_RMrX,16), TNSZ("vpcmpeqw",VEX_RMrX,16), TNSZ("vpcmpeqd",VEX_RMrX,16), INVALID, 7530339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 7540339a1c2SMark Johnston /* [7C] */ TNSZ("vhaddpd",VEX_RMrX,16), TNSZ("vhsubpd",VEX_RMrX,16), TNSZ("vmovd",VEX_RR,4), TNSZ("vmovdqa",VEX_RX,16), 7550339a1c2SMark Johnston 7560339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 7570339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 7580339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 7590339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 7600339a1c2SMark Johnston 7610339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 7620339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 7630339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 7640339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 7650339a1c2SMark Johnston 7660339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 7670339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 7680339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 7690339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 7700339a1c2SMark Johnston 7710339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 7720339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 7730339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 7740339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 7750339a1c2SMark Johnston 7760339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("vcmppd",VEX_RMRX,16), INVALID, 7770339a1c2SMark Johnston /* [C4] */ TNSZ("vpinsrw",VEX_RMRX,2),TNS("vpextrw",VEX_MR), TNSZ("vshufpd",VEX_RMRX,16), INVALID, 7780339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 7790339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 7800339a1c2SMark Johnston 7810339a1c2SMark Johnston /* [D0] */ TNSZ("vaddsubpd",VEX_RMrX,16),TNSZ("vpsrlw",VEX_RMrX,16), TNSZ("vpsrld",VEX_RMrX,16), TNSZ("vpsrlq",VEX_RMrX,16), 7820339a1c2SMark Johnston /* [D4] */ TNSZ("vpaddq",VEX_RMrX,16), TNSZ("vpmullw",VEX_RMrX,16), TNSZ("vmovq",VEX_RX,8), TNS("vpmovmskb",VEX_MR), 7830339a1c2SMark Johnston /* [D8] */ TNSZ("vpsubusb",VEX_RMrX,16), TNSZ("vpsubusw",VEX_RMrX,16), TNSZ("vpminub",VEX_RMrX,16), TNSZ("vpand",VEX_RMrX,16), 7840339a1c2SMark Johnston /* [DC] */ TNSZ("vpaddusb",VEX_RMrX,16), TNSZ("vpaddusw",VEX_RMrX,16), TNSZ("vpmaxub",VEX_RMrX,16), TNSZ("vpandn",VEX_RMrX,16), 7850339a1c2SMark Johnston 7860339a1c2SMark Johnston /* [E0] */ TNSZ("vpavgb",VEX_RMrX,16), TNSZ("vpsraw",VEX_RMrX,16), TNSZ("vpsrad",VEX_RMrX,16), TNSZ("vpavgw",VEX_RMrX,16), 7870339a1c2SMark Johnston /* [E4] */ TNSZ("vpmulhuw",VEX_RMrX,16), TNSZ("vpmulhw",VEX_RMrX,16), TNSZ("vcvttpd2dq",VEX_MX,16),TNSZ("vmovntdq",VEX_RM,16), 7880339a1c2SMark Johnston /* [E8] */ TNSZ("vpsubsb",VEX_RMrX,16), TNSZ("vpsubsw",VEX_RMrX,16), TNSZ("vpminsw",VEX_RMrX,16), TNSZ("vpor",VEX_RMrX,16), 7890339a1c2SMark Johnston /* [EC] */ TNSZ("vpaddsb",VEX_RMrX,16), TNSZ("vpaddsw",VEX_RMrX,16), TNSZ("vpmaxsw",VEX_RMrX,16), TNSZ("vpxor",VEX_RMrX,16), 7900339a1c2SMark Johnston 7910339a1c2SMark Johnston /* [F0] */ INVALID, TNSZ("vpsllw",VEX_RMrX,16), TNSZ("vpslld",VEX_RMrX,16), TNSZ("vpsllq",VEX_RMrX,16), 7920339a1c2SMark Johnston /* [F4] */ TNSZ("vpmuludq",VEX_RMrX,16), TNSZ("vpmaddwd",VEX_RMrX,16), TNSZ("vpsadbw",VEX_RMrX,16), TNS("vmaskmovdqu",VEX_MX), 7930339a1c2SMark Johnston /* [F8] */ TNSZ("vpsubb",VEX_RMrX,16), TNSZ("vpsubw",VEX_RMrX,16), TNSZ("vpsubd",VEX_RMrX,16), TNSZ("vpsubq",VEX_RMrX,16), 7940339a1c2SMark Johnston /* [FC] */ TNSZ("vpaddb",VEX_RMrX,16), TNSZ("vpaddw",VEX_RMrX,16), TNSZ("vpaddd",VEX_RMrX,16), INVALID, 7950339a1c2SMark Johnston }; 7960339a1c2SMark Johnston 7970339a1c2SMark Johnston /* 7980339a1c2SMark Johnston * Decode table for SIMD instructions with the repnz (0xf2) prefix. 7990339a1c2SMark Johnston */ 8000339a1c2SMark Johnston const instable_t dis_opSIMDrepnz[256] = { 8010339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 8020339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 8030339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 8040339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 8050339a1c2SMark Johnston 8060339a1c2SMark Johnston /* [10] */ TNSZ("movsd",XMM,8), TNSZ("movsd",XMMS,8), INVALID, INVALID, 8070339a1c2SMark Johnston /* [14] */ INVALID, INVALID, INVALID, INVALID, 8080339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 8090339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 8100339a1c2SMark Johnston 8110339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 8120339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 8130339a1c2SMark Johnston /* [28] */ INVALID, INVALID, TNSZ("cvtsi2sd",XMM3MX,4),TNSZ("movntsd",XMMMS,8), 8140339a1c2SMark Johnston /* [2C] */ TNSZ("cvttsd2si",XMMXM3,8),TNSZ("cvtsd2si",XMMXM3,8),INVALID, INVALID, 8150339a1c2SMark Johnston 8160339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 8170339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 8180339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 8190339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 8200339a1c2SMark Johnston 8210339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 8220339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 8230339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 8240339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 8250339a1c2SMark Johnston 8260339a1c2SMark Johnston /* [50] */ INVALID, TNSZ("sqrtsd",XMM,8), INVALID, INVALID, 8270339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 8280339a1c2SMark Johnston /* [58] */ TNSZ("addsd",XMM,8), TNSZ("mulsd",XMM,8), TNSZ("cvtsd2ss",XMM,8), INVALID, 8290339a1c2SMark Johnston /* [5C] */ TNSZ("subsd",XMM,8), TNSZ("minsd",XMM,8), TNSZ("divsd",XMM,8), TNSZ("maxsd",XMM,8), 8300339a1c2SMark Johnston 8310339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 8320339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 8330339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 8340339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 8350339a1c2SMark Johnston 8360339a1c2SMark Johnston /* [70] */ TNSZ("pshuflw",XMMP,16),INVALID, INVALID, INVALID, 8370339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 8380339a1c2SMark Johnston /* [78] */ TNSZ("insertq",XMMX2I,16),TNSZ("insertq",XMM,8),INVALID, INVALID, 8390339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 8400339a1c2SMark Johnston 8410339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 8420339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 8430339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 8440339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 8450339a1c2SMark Johnston 8460339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 8470339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 8480339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 8490339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 8500339a1c2SMark Johnston 8510339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 8520339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 8530339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 8540339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 8550339a1c2SMark Johnston 8560339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 8570339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 8580339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 8590339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 8600339a1c2SMark Johnston 8610339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("cmpsd",XMMP,8), INVALID, 8620339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 8630339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 8640339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 8650339a1c2SMark Johnston 8660339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 8670339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, TNS("movdq2q",XMMXM), INVALID, 8680339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 8690339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 8700339a1c2SMark Johnston 8710339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 8720339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, TNSZ("cvtpd2dq",XMM,16),INVALID, 8730339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 8740339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 8750339a1c2SMark Johnston 8760339a1c2SMark Johnston /* [F0] */ INVALID, INVALID, INVALID, INVALID, 8770339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 8780339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 8790339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 8800339a1c2SMark Johnston }; 8810339a1c2SMark Johnston 8820339a1c2SMark Johnston const instable_t dis_opAVXF20F[256] = { 8830339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 8840339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 8850339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 8860339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 8870339a1c2SMark Johnston 8880339a1c2SMark Johnston /* [10] */ TNSZ("vmovsd",VEX_RMrX,8), TNSZ("vmovsd",VEX_RRX,8), TNSZ("vmovddup",VEX_MX,8), INVALID, 8890339a1c2SMark Johnston /* [14] */ INVALID, INVALID, INVALID, INVALID, 8900339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 8910339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 8920339a1c2SMark Johnston 8930339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 8940339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 8950339a1c2SMark Johnston /* [28] */ INVALID, INVALID, TNSZ("vcvtsi2sd",VEX_RMrX,4),INVALID, 8960339a1c2SMark Johnston /* [2C] */ TNSZ("vcvttsd2si",VEX_MR,8),TNSZ("vcvtsd2si",VEX_MR,8),INVALID, INVALID, 8970339a1c2SMark Johnston 8980339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 8990339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 9000339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 9010339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 9020339a1c2SMark Johnston 9030339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 9040339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 9050339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 9060339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 9070339a1c2SMark Johnston 9080339a1c2SMark Johnston /* [50] */ INVALID, TNSZ("vsqrtsd",VEX_RMrX,8), INVALID, INVALID, 9090339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 9100339a1c2SMark Johnston /* [58] */ TNSZ("vaddsd",VEX_RMrX,8), TNSZ("vmulsd",VEX_RMrX,8), TNSZ("vcvtsd2ss",VEX_RMrX,8), INVALID, 9110339a1c2SMark Johnston /* [5C] */ TNSZ("vsubsd",VEX_RMrX,8), TNSZ("vminsd",VEX_RMrX,8), TNSZ("vdivsd",VEX_RMrX,8), TNSZ("vmaxsd",VEX_RMrX,8), 9120339a1c2SMark Johnston 9130339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 9140339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 9150339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 9160339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 9170339a1c2SMark Johnston 9180339a1c2SMark Johnston /* [70] */ TNSZ("vpshuflw",VEX_MXI,16),INVALID, INVALID, INVALID, 9190339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 9200339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 9210339a1c2SMark Johnston /* [7C] */ TNSZ("vhaddps",VEX_RMrX,8), TNSZ("vhsubps",VEX_RMrX,8), INVALID, INVALID, 9220339a1c2SMark Johnston 9230339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 9240339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 9250339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 9260339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 9270339a1c2SMark Johnston 9280339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 9290339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 9300339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 9310339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 9320339a1c2SMark Johnston 9330339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 9340339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 9350339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 9360339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 9370339a1c2SMark Johnston 9380339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 9390339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 9400339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 9410339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 9420339a1c2SMark Johnston 9430339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("vcmpsd",VEX_RMRX,8), INVALID, 9440339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 9450339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 9460339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 9470339a1c2SMark Johnston 9480339a1c2SMark Johnston /* [D0] */ TNSZ("vaddsubps",VEX_RMrX,8), INVALID, INVALID, INVALID, 9490339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 9500339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 9510339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 9520339a1c2SMark Johnston 9530339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 9540339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, TNSZ("vcvtpd2dq",VEX_MX,16),INVALID, 9550339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 9560339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 9570339a1c2SMark Johnston 9580339a1c2SMark Johnston /* [F0] */ TNSZ("vlddqu",VEX_MX,16), INVALID, INVALID, INVALID, 9590339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 9600339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 9610339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 9620339a1c2SMark Johnston }; 9630339a1c2SMark Johnston 9640339a1c2SMark Johnston /* 9650339a1c2SMark Johnston * Decode table for SIMD instructions with the repz (0xf3) prefix. 9660339a1c2SMark Johnston */ 9670339a1c2SMark Johnston const instable_t dis_opSIMDrepz[256] = { 9680339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 9690339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 9700339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 9710339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 9720339a1c2SMark Johnston 9730339a1c2SMark Johnston /* [10] */ TNSZ("movss",XMM,4), TNSZ("movss",XMMS,4), INVALID, INVALID, 9740339a1c2SMark Johnston /* [14] */ INVALID, INVALID, INVALID, INVALID, 9750339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 9760339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 9770339a1c2SMark Johnston 9780339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 9790339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 9800339a1c2SMark Johnston /* [28] */ INVALID, INVALID, TNSZ("cvtsi2ss",XMM3MX,4),TNSZ("movntss",XMMMS,4), 9810339a1c2SMark Johnston /* [2C] */ TNSZ("cvttss2si",XMMXM3,4),TNSZ("cvtss2si",XMMXM3,4),INVALID, INVALID, 9820339a1c2SMark Johnston 9830339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 9840339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 9850339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 9860339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 9870339a1c2SMark Johnston 9880339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 9890339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 9900339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 9910339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 9920339a1c2SMark Johnston 9930339a1c2SMark Johnston /* [50] */ INVALID, TNSZ("sqrtss",XMM,4), TNSZ("rsqrtss",XMM,4), TNSZ("rcpss",XMM,4), 9940339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 9950339a1c2SMark Johnston /* [58] */ TNSZ("addss",XMM,4), TNSZ("mulss",XMM,4), TNSZ("cvtss2sd",XMM,4), TNSZ("cvttps2dq",XMM,16), 9960339a1c2SMark Johnston /* [5C] */ TNSZ("subss",XMM,4), TNSZ("minss",XMM,4), TNSZ("divss",XMM,4), TNSZ("maxss",XMM,4), 9970339a1c2SMark Johnston 9980339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 9990339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 10000339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 10010339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, TNSZ("movdqu",XMM,16), 10020339a1c2SMark Johnston 10030339a1c2SMark Johnston /* [70] */ TNSZ("pshufhw",XMMP,16),INVALID, INVALID, INVALID, 10040339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 10050339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 10060339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, TNSZ("movq",XMM,8), TNSZ("movdqu",XMMS,16), 10070339a1c2SMark Johnston 10080339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 10090339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 10100339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 10110339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 10120339a1c2SMark Johnston 10130339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 10140339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 10150339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 10160339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 10170339a1c2SMark Johnston 10180339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 10190339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 10200339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 10210339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 10220339a1c2SMark Johnston 10230339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 10240339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 10250339a1c2SMark Johnston /* [B8] */ TS("popcnt",MRw), INVALID, INVALID, INVALID, 10260339a1c2SMark Johnston /* [BC] */ INVALID, TS("lzcnt",MRw), INVALID, INVALID, 10270339a1c2SMark Johnston 10280339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("cmpss",XMMP,4), INVALID, 10290339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 10300339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 10310339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 10320339a1c2SMark Johnston 10330339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 10340339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, TNS("movq2dq",XMMMX), INVALID, 10350339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 10360339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 10370339a1c2SMark Johnston 10380339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 10390339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, TNSZ("cvtdq2pd",XMM,8), INVALID, 10400339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 10410339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 10420339a1c2SMark Johnston 10430339a1c2SMark Johnston /* [F0] */ INVALID, INVALID, INVALID, INVALID, 10440339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 10450339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 10460339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 10470339a1c2SMark Johnston }; 10480339a1c2SMark Johnston 10490339a1c2SMark Johnston const instable_t dis_opAVXF30F[256] = { 10500339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 10510339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 10520339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 10530339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 10540339a1c2SMark Johnston 10550339a1c2SMark Johnston /* [10] */ TNSZ("vmovss",VEX_RMrX,4), TNSZ("vmovss",VEX_RRX,4), TNSZ("vmovsldup",VEX_MX,4), INVALID, 10560339a1c2SMark Johnston /* [14] */ INVALID, INVALID, TNSZ("vmovshdup",VEX_MX,4), INVALID, 10570339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 10580339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 10590339a1c2SMark Johnston 10600339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 10610339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 10620339a1c2SMark Johnston /* [28] */ INVALID, INVALID, TNSZ("vcvtsi2ss",VEX_RMrX,4),INVALID, 10630339a1c2SMark Johnston /* [2C] */ TNSZ("vcvttss2si",VEX_MR,4),TNSZ("vcvtss2si",VEX_MR,4),INVALID, INVALID, 10640339a1c2SMark Johnston 10650339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 10660339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 10670339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 10680339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 10690339a1c2SMark Johnston 10700339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 10710339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 10720339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 10730339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 10740339a1c2SMark Johnston 10750339a1c2SMark Johnston /* [50] */ INVALID, TNSZ("vsqrtss",VEX_RMrX,4), TNSZ("vrsqrtss",VEX_RMrX,4), TNSZ("vrcpss",VEX_RMrX,4), 10760339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 10770339a1c2SMark Johnston /* [58] */ TNSZ("vaddss",VEX_RMrX,4), TNSZ("vmulss",VEX_RMrX,4), TNSZ("vcvtss2sd",VEX_RMrX,4), TNSZ("vcvttps2dq",VEX_MX,16), 10780339a1c2SMark Johnston /* [5C] */ TNSZ("vsubss",VEX_RMrX,4), TNSZ("vminss",VEX_RMrX,4), TNSZ("vdivss",VEX_RMrX,4), TNSZ("vmaxss",VEX_RMrX,4), 10790339a1c2SMark Johnston 10800339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 10810339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 10820339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 10830339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, TNSZ("vmovdqu",VEX_MX,16), 10840339a1c2SMark Johnston 10850339a1c2SMark Johnston /* [70] */ TNSZ("vpshufhw",VEX_MXI,16),INVALID, INVALID, INVALID, 10860339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 10870339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 10880339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, TNSZ("vmovq",VEX_MX,8), TNSZ("vmovdqu",VEX_RX,16), 10890339a1c2SMark Johnston 10900339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 10910339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 10920339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 10930339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 10940339a1c2SMark Johnston 10950339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 10960339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 10970339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 10980339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 10990339a1c2SMark Johnston 11000339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 11010339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 11020339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 11030339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 11040339a1c2SMark Johnston 11050339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 11060339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 11070339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 11080339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 11090339a1c2SMark Johnston 11100339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("vcmpss",VEX_RMRX,4), INVALID, 11110339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 11120339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 11130339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 11140339a1c2SMark Johnston 11150339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 11160339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 11170339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 11180339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 11190339a1c2SMark Johnston 11200339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 11210339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, TNSZ("vcvtdq2pd",VEX_MX,8), INVALID, 11220339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 11230339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 11240339a1c2SMark Johnston 11250339a1c2SMark Johnston /* [F0] */ INVALID, INVALID, INVALID, INVALID, 11260339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 11270339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 11280339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 11290339a1c2SMark Johnston }; 11300339a1c2SMark Johnston /* 11310339a1c2SMark Johnston * The following two tables are used to encode crc32 and movbe 11320339a1c2SMark Johnston * since they share the same opcodes. 11330339a1c2SMark Johnston */ 11340339a1c2SMark Johnston const instable_t dis_op0F38F0[2] = { 11350339a1c2SMark Johnston /* [00] */ TNS("crc32b",CRC32), 11360339a1c2SMark Johnston TS("movbe",MOVBE), 11370339a1c2SMark Johnston }; 11380339a1c2SMark Johnston 11390339a1c2SMark Johnston const instable_t dis_op0F38F1[2] = { 11400339a1c2SMark Johnston /* [00] */ TS("crc32",CRC32), 11410339a1c2SMark Johnston TS("movbe",MOVBE), 11420339a1c2SMark Johnston }; 11430339a1c2SMark Johnston 11440339a1c2SMark Johnston const instable_t dis_op0F38[256] = { 11450339a1c2SMark Johnston /* [00] */ TNSZ("pshufb",XMM_66o,16),TNSZ("phaddw",XMM_66o,16),TNSZ("phaddd",XMM_66o,16),TNSZ("phaddsw",XMM_66o,16), 11460339a1c2SMark Johnston /* [04] */ TNSZ("pmaddubsw",XMM_66o,16),TNSZ("phsubw",XMM_66o,16), TNSZ("phsubd",XMM_66o,16),TNSZ("phsubsw",XMM_66o,16), 11470339a1c2SMark Johnston /* [08] */ TNSZ("psignb",XMM_66o,16),TNSZ("psignw",XMM_66o,16),TNSZ("psignd",XMM_66o,16),TNSZ("pmulhrsw",XMM_66o,16), 11480339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 11490339a1c2SMark Johnston 11500339a1c2SMark Johnston /* [10] */ TNSZ("pblendvb",XMM_66r,16),INVALID, INVALID, INVALID, 11510339a1c2SMark Johnston /* [14] */ TNSZ("blendvps",XMM_66r,16),TNSZ("blendvpd",XMM_66r,16),INVALID, TNSZ("ptest",XMM_66r,16), 11520339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 11530339a1c2SMark Johnston /* [1C] */ TNSZ("pabsb",XMM_66o,16),TNSZ("pabsw",XMM_66o,16),TNSZ("pabsd",XMM_66o,16),INVALID, 11540339a1c2SMark Johnston 11550339a1c2SMark Johnston /* [20] */ TNSZ("pmovsxbw",XMM_66r,16),TNSZ("pmovsxbd",XMM_66r,16),TNSZ("pmovsxbq",XMM_66r,16),TNSZ("pmovsxwd",XMM_66r,16), 11560339a1c2SMark Johnston /* [24] */ TNSZ("pmovsxwq",XMM_66r,16),TNSZ("pmovsxdq",XMM_66r,16),INVALID, INVALID, 11570339a1c2SMark Johnston /* [28] */ TNSZ("pmuldq",XMM_66r,16),TNSZ("pcmpeqq",XMM_66r,16),TNSZ("movntdqa",XMMM_66r,16),TNSZ("packusdw",XMM_66r,16), 11580339a1c2SMark Johnston /* [2C] */ INVALID, INVALID, INVALID, INVALID, 11590339a1c2SMark Johnston 11600339a1c2SMark Johnston /* [30] */ TNSZ("pmovzxbw",XMM_66r,16),TNSZ("pmovzxbd",XMM_66r,16),TNSZ("pmovzxbq",XMM_66r,16),TNSZ("pmovzxwd",XMM_66r,16), 11610339a1c2SMark Johnston /* [34] */ TNSZ("pmovzxwq",XMM_66r,16),TNSZ("pmovzxdq",XMM_66r,16),INVALID, TNSZ("pcmpgtq",XMM_66r,16), 11620339a1c2SMark Johnston /* [38] */ TNSZ("pminsb",XMM_66r,16),TNSZ("pminsd",XMM_66r,16),TNSZ("pminuw",XMM_66r,16),TNSZ("pminud",XMM_66r,16), 11630339a1c2SMark Johnston /* [3C] */ TNSZ("pmaxsb",XMM_66r,16),TNSZ("pmaxsd",XMM_66r,16),TNSZ("pmaxuw",XMM_66r,16),TNSZ("pmaxud",XMM_66r,16), 11640339a1c2SMark Johnston 11650339a1c2SMark Johnston /* [40] */ TNSZ("pmulld",XMM_66r,16),TNSZ("phminposuw",XMM_66r,16),INVALID, INVALID, 11660339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 11670339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 11680339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 11690339a1c2SMark Johnston 11700339a1c2SMark Johnston /* [50] */ INVALID, INVALID, INVALID, INVALID, 11710339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 11720339a1c2SMark Johnston /* [58] */ INVALID, INVALID, INVALID, INVALID, 11730339a1c2SMark Johnston /* [5C] */ INVALID, INVALID, INVALID, INVALID, 11740339a1c2SMark Johnston 11750339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 11760339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 11770339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 11780339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 11790339a1c2SMark Johnston 11800339a1c2SMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 11810339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 11820339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 11830339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 11840339a1c2SMark Johnston 1185c3ddb60eSPeter Grehan /* [80] */ TNSy("invept", RM_66r), TNSy("invvpid", RM_66r),INVALID, INVALID, 11860339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 11870339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 11880339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 11890339a1c2SMark Johnston 11900339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 11910339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 11920339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 11930339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 11940339a1c2SMark Johnston 11950339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 11960339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 11970339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 11980339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 11990339a1c2SMark Johnston 12000339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 12010339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 12020339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 12030339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 12040339a1c2SMark Johnston 12050339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, INVALID, INVALID, 12060339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 12070339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 12080339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 12090339a1c2SMark Johnston 12100339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 12110339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 12120339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, TNSZ("aesimc",XMM_66r,16), 12130339a1c2SMark Johnston /* [DC] */ TNSZ("aesenc",XMM_66r,16),TNSZ("aesenclast",XMM_66r,16),TNSZ("aesdec",XMM_66r,16),TNSZ("aesdeclast",XMM_66r,16), 12140339a1c2SMark Johnston 12150339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 12160339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 12170339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 12180339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 12190339a1c2SMark Johnston /* [F0] */ IND(dis_op0F38F0), IND(dis_op0F38F1), INVALID, INVALID, 12200339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 12210339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 12220339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 12230339a1c2SMark Johnston }; 12240339a1c2SMark Johnston 12250339a1c2SMark Johnston const instable_t dis_opAVX660F38[256] = { 12260339a1c2SMark Johnston /* [00] */ TNSZ("vpshufb",VEX_RMrX,16),TNSZ("vphaddw",VEX_RMrX,16),TNSZ("vphaddd",VEX_RMrX,16),TNSZ("vphaddsw",VEX_RMrX,16), 12270339a1c2SMark Johnston /* [04] */ TNSZ("vpmaddubsw",VEX_RMrX,16),TNSZ("vphsubw",VEX_RMrX,16), TNSZ("vphsubd",VEX_RMrX,16),TNSZ("vphsubsw",VEX_RMrX,16), 12280339a1c2SMark Johnston /* [08] */ TNSZ("vpsignb",VEX_RMrX,16),TNSZ("vpsignw",VEX_RMrX,16),TNSZ("vpsignd",VEX_RMrX,16),TNSZ("vpmulhrsw",VEX_RMrX,16), 12290339a1c2SMark Johnston /* [0C] */ TNSZ("vpermilps",VEX_RMrX,8),TNSZ("vpermilpd",VEX_RMrX,16),TNSZ("vtestps",VEX_RRI,8), TNSZ("vtestpd",VEX_RRI,16), 12300339a1c2SMark Johnston 1231c3ddb60eSPeter Grehan /* [10] */ INVALID, INVALID, INVALID, TNSZ("vcvtph2ps",VEX_MX,16), 12320339a1c2SMark Johnston /* [14] */ INVALID, INVALID, INVALID, TNSZ("vptest",VEX_RRI,16), 12330339a1c2SMark Johnston /* [18] */ TNSZ("vbroadcastss",VEX_MX,4),TNSZ("vbroadcastsd",VEX_MX,8),TNSZ("vbroadcastf128",VEX_MX,16),INVALID, 12340339a1c2SMark Johnston /* [1C] */ TNSZ("vpabsb",VEX_MX,16),TNSZ("vpabsw",VEX_MX,16),TNSZ("vpabsd",VEX_MX,16),INVALID, 12350339a1c2SMark Johnston 12360339a1c2SMark Johnston /* [20] */ TNSZ("vpmovsxbw",VEX_MX,16),TNSZ("vpmovsxbd",VEX_MX,16),TNSZ("vpmovsxbq",VEX_MX,16),TNSZ("vpmovsxwd",VEX_MX,16), 12370339a1c2SMark Johnston /* [24] */ TNSZ("vpmovsxwq",VEX_MX,16),TNSZ("vpmovsxdq",VEX_MX,16),INVALID, INVALID, 12380339a1c2SMark Johnston /* [28] */ TNSZ("vpmuldq",VEX_RMrX,16),TNSZ("vpcmpeqq",VEX_RMrX,16),TNSZ("vmovntdqa",VEX_MX,16),TNSZ("vpackusdw",VEX_RMrX,16), 12390339a1c2SMark Johnston /* [2C] */ TNSZ("vmaskmovps",VEX_RMrX,8),TNSZ("vmaskmovpd",VEX_RMrX,16),TNSZ("vmaskmovps",VEX_RRM,8),TNSZ("vmaskmovpd",VEX_RRM,16), 12400339a1c2SMark Johnston 12410339a1c2SMark Johnston /* [30] */ TNSZ("vpmovzxbw",VEX_MX,16),TNSZ("vpmovzxbd",VEX_MX,16),TNSZ("vpmovzxbq",VEX_MX,16),TNSZ("vpmovzxwd",VEX_MX,16), 12420339a1c2SMark Johnston /* [34] */ TNSZ("vpmovzxwq",VEX_MX,16),TNSZ("vpmovzxdq",VEX_MX,16),INVALID, TNSZ("vpcmpgtq",VEX_RMrX,16), 12430339a1c2SMark Johnston /* [38] */ TNSZ("vpminsb",VEX_RMrX,16),TNSZ("vpminsd",VEX_RMrX,16),TNSZ("vpminuw",VEX_RMrX,16),TNSZ("vpminud",VEX_RMrX,16), 12440339a1c2SMark Johnston /* [3C] */ TNSZ("vpmaxsb",VEX_RMrX,16),TNSZ("vpmaxsd",VEX_RMrX,16),TNSZ("vpmaxuw",VEX_RMrX,16),TNSZ("vpmaxud",VEX_RMrX,16), 12450339a1c2SMark Johnston 12460339a1c2SMark Johnston /* [40] */ TNSZ("vpmulld",VEX_RMrX,16),TNSZ("vphminposuw",VEX_MX,16),INVALID, INVALID, 12470339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 12480339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 12490339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 12500339a1c2SMark Johnston 12510339a1c2SMark Johnston /* [50] */ INVALID, INVALID, INVALID, INVALID, 12520339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 12530339a1c2SMark Johnston /* [58] */ INVALID, INVALID, INVALID, INVALID, 12540339a1c2SMark Johnston /* [5C] */ INVALID, INVALID, INVALID, INVALID, 12550339a1c2SMark Johnston 12560339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 12570339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 12580339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 12590339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 12600339a1c2SMark Johnston 12610339a1c2SMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 12620339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 12630339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 12640339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 12650339a1c2SMark Johnston 12660339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 12670339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 12680339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 12690339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 12700339a1c2SMark Johnston 12710339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 12720339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 12730339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 12740339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 12750339a1c2SMark Johnston 12760339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 12770339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 12780339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 12790339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 12800339a1c2SMark Johnston 12810339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 12820339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 12830339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 12840339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 12850339a1c2SMark Johnston 12860339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, INVALID, INVALID, 12870339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 12880339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 12890339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 12900339a1c2SMark Johnston 12910339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 12920339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 12930339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, TNSZ("vaesimc",VEX_MX,16), 12940339a1c2SMark Johnston /* [DC] */ TNSZ("vaesenc",VEX_RMrX,16),TNSZ("vaesenclast",VEX_RMrX,16),TNSZ("vaesdec",VEX_RMrX,16),TNSZ("vaesdeclast",VEX_RMrX,16), 12950339a1c2SMark Johnston 12960339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 12970339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 12980339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 12990339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 13000339a1c2SMark Johnston /* [F0] */ IND(dis_op0F38F0), IND(dis_op0F38F1), INVALID, INVALID, 13010339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 13020339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 13030339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 13040339a1c2SMark Johnston }; 13050339a1c2SMark Johnston 13060339a1c2SMark Johnston const instable_t dis_op0F3A[256] = { 13070339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 13080339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 13090339a1c2SMark Johnston /* [08] */ TNSZ("roundps",XMMP_66r,16),TNSZ("roundpd",XMMP_66r,16),TNSZ("roundss",XMMP_66r,16),TNSZ("roundsd",XMMP_66r,16), 13100339a1c2SMark Johnston /* [0C] */ TNSZ("blendps",XMMP_66r,16),TNSZ("blendpd",XMMP_66r,16),TNSZ("pblendw",XMMP_66r,16),TNSZ("palignr",XMMP_66o,16), 13110339a1c2SMark Johnston 13120339a1c2SMark Johnston /* [10] */ INVALID, INVALID, INVALID, INVALID, 13130339a1c2SMark Johnston /* [14] */ TNSZ("pextrb",XMM3PM_66r,8),TNSZ("pextrw",XMM3PM_66r,16),TSZ("pextr",XMM3PM_66r,16),TNSZ("extractps",XMM3PM_66r,16), 13140339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 13150339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 13160339a1c2SMark Johnston 13170339a1c2SMark Johnston /* [20] */ TNSZ("pinsrb",XMMPRM_66r,8),TNSZ("insertps",XMMP_66r,16),TSZ("pinsr",XMMPRM_66r,16),INVALID, 13180339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 13190339a1c2SMark Johnston /* [28] */ INVALID, INVALID, INVALID, INVALID, 13200339a1c2SMark Johnston /* [2C] */ INVALID, INVALID, INVALID, INVALID, 13210339a1c2SMark Johnston 13220339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 13230339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 13240339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 13250339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 13260339a1c2SMark Johnston 13270339a1c2SMark Johnston /* [40] */ TNSZ("dpps",XMMP_66r,16),TNSZ("dppd",XMMP_66r,16),TNSZ("mpsadbw",XMMP_66r,16),INVALID, 13280339a1c2SMark Johnston /* [44] */ TNSZ("pclmulqdq",XMMP_66r,16),INVALID, INVALID, INVALID, 13290339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 13300339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 13310339a1c2SMark Johnston 13320339a1c2SMark Johnston /* [50] */ INVALID, INVALID, INVALID, INVALID, 13330339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 13340339a1c2SMark Johnston /* [58] */ INVALID, INVALID, INVALID, INVALID, 13350339a1c2SMark Johnston /* [5C] */ INVALID, INVALID, INVALID, INVALID, 13360339a1c2SMark Johnston 13370339a1c2SMark Johnston /* [60] */ TNSZ("pcmpestrm",XMMP_66r,16),TNSZ("pcmpestri",XMMP_66r,16),TNSZ("pcmpistrm",XMMP_66r,16),TNSZ("pcmpistri",XMMP_66r,16), 13380339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 13390339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 13400339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 13410339a1c2SMark Johnston 13420339a1c2SMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 13430339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 13440339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 13450339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 13460339a1c2SMark Johnston 13470339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 13480339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 13490339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 13500339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 13510339a1c2SMark Johnston 13520339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 13530339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 13540339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 13550339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 13560339a1c2SMark Johnston 13570339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 13580339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 13590339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 13600339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 13610339a1c2SMark Johnston 13620339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 13630339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 13640339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 13650339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 13660339a1c2SMark Johnston 13670339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, INVALID, INVALID, 13680339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 13690339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 13700339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 13710339a1c2SMark Johnston 13720339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 13730339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 13740339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 13750339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, TNSZ("aeskeygenassist",XMMP_66r,16), 13760339a1c2SMark Johnston 13770339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 13780339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 13790339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 13800339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 13810339a1c2SMark Johnston 13820339a1c2SMark Johnston /* [F0] */ INVALID, INVALID, INVALID, INVALID, 13830339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 13840339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 13850339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 13860339a1c2SMark Johnston }; 13870339a1c2SMark Johnston 13880339a1c2SMark Johnston const instable_t dis_opAVX660F3A[256] = { 13890339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 13900339a1c2SMark Johnston /* [04] */ TNSZ("vpermilps",VEX_MXI,8),TNSZ("vpermilpd",VEX_MXI,16),TNSZ("vperm2f128",VEX_RMRX,16),INVALID, 13910339a1c2SMark Johnston /* [08] */ TNSZ("vroundps",VEX_MXI,16),TNSZ("vroundpd",VEX_MXI,16),TNSZ("vroundss",VEX_RMRX,16),TNSZ("vroundsd",VEX_RMRX,16), 13920339a1c2SMark Johnston /* [0C] */ TNSZ("vblendps",VEX_RMRX,16),TNSZ("vblendpd",VEX_RMRX,16),TNSZ("vpblendw",VEX_RMRX,16),TNSZ("vpalignr",VEX_RMRX,16), 13930339a1c2SMark Johnston 13940339a1c2SMark Johnston /* [10] */ INVALID, INVALID, INVALID, INVALID, 13950339a1c2SMark Johnston /* [14] */ TNSZ("vpextrb",VEX_RRi,8),TNSZ("vpextrw",VEX_RRi,16),TNSZ("vpextrd",VEX_RRi,16),TNSZ("vextractps",VEX_RM,16), 13960339a1c2SMark Johnston /* [18] */ TNSZ("vinsertf128",VEX_RMRX,16),TNSZ("vextractf128",VEX_RX,16),INVALID, INVALID, 1397c3ddb60eSPeter Grehan /* [1C] */ INVALID, TNSZ("vcvtps2ph",VEX_RX,16), INVALID, INVALID, 13980339a1c2SMark Johnston 13990339a1c2SMark Johnston /* [20] */ TNSZ("vpinsrb",VEX_RMRX,8),TNSZ("vinsertps",VEX_RMRX,16),TNSZ("vpinsrd",VEX_RMRX,16),INVALID, 14000339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 14010339a1c2SMark Johnston /* [28] */ INVALID, INVALID, INVALID, INVALID, 14020339a1c2SMark Johnston /* [2C] */ INVALID, INVALID, INVALID, INVALID, 14030339a1c2SMark Johnston 14040339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 14050339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 14060339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 14070339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 14080339a1c2SMark Johnston 14090339a1c2SMark Johnston /* [40] */ TNSZ("vdpps",VEX_RMRX,16),TNSZ("vdppd",VEX_RMRX,16),TNSZ("vmpsadbw",VEX_RMRX,16),INVALID, 14100339a1c2SMark Johnston /* [44] */ TNSZ("vpclmulqdq",VEX_RMRX,16),INVALID, INVALID, INVALID, 14110339a1c2SMark Johnston /* [48] */ INVALID, INVALID, TNSZ("vblendvps",VEX_RMRX,8), TNSZ("vblendvpd",VEX_RMRX,16), 14120339a1c2SMark Johnston /* [4C] */ TNSZ("vpblendvb",VEX_RMRX,16),INVALID, INVALID, INVALID, 14130339a1c2SMark Johnston 14140339a1c2SMark Johnston /* [50] */ INVALID, INVALID, INVALID, INVALID, 14150339a1c2SMark Johnston /* [54] */ INVALID, INVALID, INVALID, INVALID, 14160339a1c2SMark Johnston /* [58] */ INVALID, INVALID, INVALID, INVALID, 14170339a1c2SMark Johnston /* [5C] */ INVALID, INVALID, INVALID, INVALID, 14180339a1c2SMark Johnston 14190339a1c2SMark Johnston /* [60] */ TNSZ("vpcmpestrm",VEX_MXI,16),TNSZ("vpcmpestri",VEX_MXI,16),TNSZ("vpcmpistrm",VEX_MXI,16),TNSZ("vpcmpistri",VEX_MXI,16), 14200339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 14210339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 14220339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 14230339a1c2SMark Johnston 14240339a1c2SMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 14250339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, INVALID, 14260339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 14270339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 14280339a1c2SMark Johnston 14290339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 14300339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 14310339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 14320339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 14330339a1c2SMark Johnston 14340339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 14350339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 14360339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 14370339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 14380339a1c2SMark Johnston 14390339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 14400339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 14410339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 14420339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, INVALID, INVALID, 14430339a1c2SMark Johnston 14440339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 14450339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 14460339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 14470339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 14480339a1c2SMark Johnston 14490339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, INVALID, INVALID, 14500339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, INVALID, INVALID, 14510339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 14520339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 14530339a1c2SMark Johnston 14540339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 14550339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 14560339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 14570339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, TNSZ("vaeskeygenassist",VEX_MXI,16), 14580339a1c2SMark Johnston 14590339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 14600339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 14610339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 14620339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 14630339a1c2SMark Johnston 14640339a1c2SMark Johnston /* [F0] */ INVALID, INVALID, INVALID, INVALID, 14650339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 14660339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 14670339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 14680339a1c2SMark Johnston }; 14690339a1c2SMark Johnston 14700339a1c2SMark Johnston /* 14710339a1c2SMark Johnston * Decode table for 0x0F opcodes 14720339a1c2SMark Johnston */ 14730339a1c2SMark Johnston 14740339a1c2SMark Johnston const instable_t dis_op0F[16][16] = { 14750339a1c2SMark Johnston { 14760339a1c2SMark Johnston /* [00] */ IND(dis_op0F00), IND(dis_op0F01), TNS("lar",MR), TNS("lsl",MR), 14770339a1c2SMark Johnston /* [04] */ INVALID, TNS("syscall",NORM), TNS("clts",NORM), TNS("sysret",NORM), 14780339a1c2SMark Johnston /* [08] */ TNS("invd",NORM), TNS("wbinvd",NORM), INVALID, TNS("ud2",NORM), 14790339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 14800339a1c2SMark Johnston }, { 14810339a1c2SMark Johnston /* [10] */ TNSZ("movups",XMMO,16), TNSZ("movups",XMMOS,16),TNSZ("movlps",XMMO,8), TNSZ("movlps",XMMOS,8), 14820339a1c2SMark Johnston /* [14] */ TNSZ("unpcklps",XMMO,16),TNSZ("unpckhps",XMMO,16),TNSZ("movhps",XMMOM,8),TNSZ("movhps",XMMOMS,8), 14830339a1c2SMark Johnston /* [18] */ IND(dis_op0F18), INVALID, INVALID, INVALID, 1484c3ddb60eSPeter Grehan /* [1C] */ INVALID, INVALID, INVALID, TS("nop",Mw), 14850339a1c2SMark Johnston }, { 14860339a1c2SMark Johnston /* [20] */ TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG), 14870339a1c2SMark Johnston /* [24] */ TSx("mov",SREG), INVALID, TSx("mov",SREG), INVALID, 14880339a1c2SMark Johnston /* [28] */ TNSZ("movaps",XMMO,16), TNSZ("movaps",XMMOS,16),TNSZ("cvtpi2ps",XMMOMX,8),TNSZ("movntps",XMMOS,16), 14890339a1c2SMark Johnston /* [2C] */ TNSZ("cvttps2pi",XMMOXMM,8),TNSZ("cvtps2pi",XMMOXMM,8),TNSZ("ucomiss",XMMO,4),TNSZ("comiss",XMMO,4), 14900339a1c2SMark Johnston }, { 14910339a1c2SMark Johnston /* [30] */ TNS("wrmsr",NORM), TNS("rdtsc",NORM), TNS("rdmsr",NORM), TNS("rdpmc",NORM), 14920339a1c2SMark Johnston /* [34] */ TNSx("sysenter",NORM), TNSx("sysexit",NORM), INVALID, INVALID, 14930339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 14940339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 14950339a1c2SMark Johnston }, { 14960339a1c2SMark Johnston /* [40] */ TS("cmovx.o",MR), TS("cmovx.no",MR), TS("cmovx.b",MR), TS("cmovx.ae",MR), 14970339a1c2SMark Johnston /* [44] */ TS("cmovx.e",MR), TS("cmovx.ne",MR), TS("cmovx.be",MR), TS("cmovx.a",MR), 14980339a1c2SMark Johnston /* [48] */ TS("cmovx.s",MR), TS("cmovx.ns",MR), TS("cmovx.pe",MR), TS("cmovx.po",MR), 14990339a1c2SMark Johnston /* [4C] */ TS("cmovx.l",MR), TS("cmovx.ge",MR), TS("cmovx.le",MR), TS("cmovx.g",MR), 15000339a1c2SMark Johnston }, { 15010339a1c2SMark Johnston /* [50] */ TNS("movmskps",XMMOX3), TNSZ("sqrtps",XMMO,16), TNSZ("rsqrtps",XMMO,16),TNSZ("rcpps",XMMO,16), 15020339a1c2SMark Johnston /* [54] */ TNSZ("andps",XMMO,16), TNSZ("andnps",XMMO,16), TNSZ("orps",XMMO,16), TNSZ("xorps",XMMO,16), 15030339a1c2SMark Johnston /* [58] */ TNSZ("addps",XMMO,16), TNSZ("mulps",XMMO,16), TNSZ("cvtps2pd",XMMO,8),TNSZ("cvtdq2ps",XMMO,16), 15040339a1c2SMark Johnston /* [5C] */ TNSZ("subps",XMMO,16), TNSZ("minps",XMMO,16), TNSZ("divps",XMMO,16), TNSZ("maxps",XMMO,16), 15050339a1c2SMark Johnston }, { 15060339a1c2SMark Johnston /* [60] */ TNSZ("punpcklbw",MMO,4),TNSZ("punpcklwd",MMO,4),TNSZ("punpckldq",MMO,4),TNSZ("packsswb",MMO,8), 15070339a1c2SMark Johnston /* [64] */ TNSZ("pcmpgtb",MMO,8), TNSZ("pcmpgtw",MMO,8), TNSZ("pcmpgtd",MMO,8), TNSZ("packuswb",MMO,8), 15080339a1c2SMark Johnston /* [68] */ TNSZ("punpckhbw",MMO,8),TNSZ("punpckhwd",MMO,8),TNSZ("punpckhdq",MMO,8),TNSZ("packssdw",MMO,8), 15090339a1c2SMark Johnston /* [6C] */ TNSZ("INVALID",MMO,0), TNSZ("INVALID",MMO,0), TNSZ("movd",MMO,4), TNSZ("movq",MMO,8), 15100339a1c2SMark Johnston }, { 15110339a1c2SMark Johnston /* [70] */ TNSZ("pshufw",MMOPM,8), TNS("psrXXX",MR), TNS("psrXXX",MR), TNS("psrXXX",MR), 15120339a1c2SMark Johnston /* [74] */ TNSZ("pcmpeqb",MMO,8), TNSZ("pcmpeqw",MMO,8), TNSZ("pcmpeqd",MMO,8), TNS("emms",NORM), 1513c3ddb60eSPeter Grehan /* [78] */ TNSy("vmread",RM), TNSy("vmwrite",MR), INVALID, INVALID, 15140339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, TNSZ("movd",MMOS,4), TNSZ("movq",MMOS,8), 15150339a1c2SMark Johnston }, { 15160339a1c2SMark Johnston /* [80] */ TNS("jo",D), TNS("jno",D), TNS("jb",D), TNS("jae",D), 15170339a1c2SMark Johnston /* [84] */ TNS("je",D), TNS("jne",D), TNS("jbe",D), TNS("ja",D), 15180339a1c2SMark Johnston /* [88] */ TNS("js",D), TNS("jns",D), TNS("jp",D), TNS("jnp",D), 15190339a1c2SMark Johnston /* [8C] */ TNS("jl",D), TNS("jge",D), TNS("jle",D), TNS("jg",D), 15200339a1c2SMark Johnston }, { 15210339a1c2SMark Johnston /* [90] */ TNS("seto",Mb), TNS("setno",Mb), TNS("setb",Mb), TNS("setae",Mb), 15220339a1c2SMark Johnston /* [94] */ TNS("sete",Mb), TNS("setne",Mb), TNS("setbe",Mb), TNS("seta",Mb), 15230339a1c2SMark Johnston /* [98] */ TNS("sets",Mb), TNS("setns",Mb), TNS("setp",Mb), TNS("setnp",Mb), 15240339a1c2SMark Johnston /* [9C] */ TNS("setl",Mb), TNS("setge",Mb), TNS("setle",Mb), TNS("setg",Mb), 15250339a1c2SMark Johnston }, { 15260339a1c2SMark Johnston /* [A0] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("cpuid",NORM), TS("bt",RMw), 15270339a1c2SMark Johnston /* [A4] */ TS("shld",DSHIFT), TS("shld",DSHIFTcl), INVALID, INVALID, 15280339a1c2SMark Johnston /* [A8] */ TSp("push",LSEG), TSp("pop",LSEG), TNS("rsm",NORM), TS("bts",RMw), 15290339a1c2SMark Johnston /* [AC] */ TS("shrd",DSHIFT), TS("shrd",DSHIFTcl), IND(dis_op0FAE), TS("imul",MRw), 15300339a1c2SMark Johnston }, { 15310339a1c2SMark Johnston /* [B0] */ TNS("cmpxchgb",RMw), TS("cmpxchg",RMw), TS("lss",MR), TS("btr",RMw), 15320339a1c2SMark Johnston /* [B4] */ TS("lfs",MR), TS("lgs",MR), TS("movzb",MOVZ), TNS("movzwl",MOVZ), 15330339a1c2SMark Johnston /* [B8] */ TNS("INVALID",MRw), INVALID, IND(dis_op0FBA), TS("btc",RMw), 15340339a1c2SMark Johnston /* [BC] */ TS("bsf",MRw), TS("bsr",MRw), TS("movsb",MOVZ), TNS("movswl",MOVZ), 15350339a1c2SMark Johnston }, { 15360339a1c2SMark Johnston /* [C0] */ TNS("xaddb",XADDB), TS("xadd",RMw), TNSZ("cmpps",XMMOPM,16),TNS("movnti",RM), 15370339a1c2SMark Johnston /* [C4] */ TNSZ("pinsrw",MMOPRM,2),TNS("pextrw",MMO3P), TNSZ("shufps",XMMOPM,16),IND(dis_op0FC7), 15380339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 15390339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 15400339a1c2SMark Johnston }, { 15410339a1c2SMark Johnston /* [D0] */ INVALID, TNSZ("psrlw",MMO,8), TNSZ("psrld",MMO,8), TNSZ("psrlq",MMO,8), 15420339a1c2SMark Johnston /* [D4] */ TNSZ("paddq",MMO,8), TNSZ("pmullw",MMO,8), TNSZ("INVALID",MMO,0), TNS("pmovmskb",MMOM3), 15430339a1c2SMark Johnston /* [D8] */ TNSZ("psubusb",MMO,8), TNSZ("psubusw",MMO,8), TNSZ("pminub",MMO,8), TNSZ("pand",MMO,8), 15440339a1c2SMark Johnston /* [DC] */ TNSZ("paddusb",MMO,8), TNSZ("paddusw",MMO,8), TNSZ("pmaxub",MMO,8), TNSZ("pandn",MMO,8), 15450339a1c2SMark Johnston }, { 15460339a1c2SMark Johnston /* [E0] */ TNSZ("pavgb",MMO,8), TNSZ("psraw",MMO,8), TNSZ("psrad",MMO,8), TNSZ("pavgw",MMO,8), 15470339a1c2SMark Johnston /* [E4] */ TNSZ("pmulhuw",MMO,8), TNSZ("pmulhw",MMO,8), TNS("INVALID",XMMO), TNSZ("movntq",MMOMS,8), 15480339a1c2SMark Johnston /* [E8] */ TNSZ("psubsb",MMO,8), TNSZ("psubsw",MMO,8), TNSZ("pminsw",MMO,8), TNSZ("por",MMO,8), 15490339a1c2SMark Johnston /* [EC] */ TNSZ("paddsb",MMO,8), TNSZ("paddsw",MMO,8), TNSZ("pmaxsw",MMO,8), TNSZ("pxor",MMO,8), 15500339a1c2SMark Johnston }, { 15510339a1c2SMark Johnston /* [F0] */ INVALID, TNSZ("psllw",MMO,8), TNSZ("pslld",MMO,8), TNSZ("psllq",MMO,8), 15520339a1c2SMark Johnston /* [F4] */ TNSZ("pmuludq",MMO,8), TNSZ("pmaddwd",MMO,8), TNSZ("psadbw",MMO,8), TNSZ("maskmovq",MMOIMPL,8), 15530339a1c2SMark Johnston /* [F8] */ TNSZ("psubb",MMO,8), TNSZ("psubw",MMO,8), TNSZ("psubd",MMO,8), TNSZ("psubq",MMO,8), 15540339a1c2SMark Johnston /* [FC] */ TNSZ("paddb",MMO,8), TNSZ("paddw",MMO,8), TNSZ("paddd",MMO,8), INVALID, 15550339a1c2SMark Johnston } }; 15560339a1c2SMark Johnston 15570339a1c2SMark Johnston const instable_t dis_opAVX0F[16][16] = { 15580339a1c2SMark Johnston { 15590339a1c2SMark Johnston /* [00] */ INVALID, INVALID, INVALID, INVALID, 15600339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 15610339a1c2SMark Johnston /* [08] */ INVALID, INVALID, INVALID, INVALID, 15620339a1c2SMark Johnston /* [0C] */ INVALID, INVALID, INVALID, INVALID, 15630339a1c2SMark Johnston }, { 15640339a1c2SMark Johnston /* [10] */ TNSZ("vmovups",VEX_MX,16), TNSZ("vmovups",VEX_RM,16),TNSZ("vmovlps",VEX_RMrX,8), TNSZ("vmovlps",VEX_RM,8), 15650339a1c2SMark Johnston /* [14] */ TNSZ("vunpcklps",VEX_RMrX,16),TNSZ("vunpckhps",VEX_RMrX,16),TNSZ("vmovhps",VEX_RMrX,8),TNSZ("vmovhps",VEX_RM,8), 15660339a1c2SMark Johnston /* [18] */ INVALID, INVALID, INVALID, INVALID, 15670339a1c2SMark Johnston /* [1C] */ INVALID, INVALID, INVALID, INVALID, 15680339a1c2SMark Johnston }, { 15690339a1c2SMark Johnston /* [20] */ INVALID, INVALID, INVALID, INVALID, 15700339a1c2SMark Johnston /* [24] */ INVALID, INVALID, INVALID, INVALID, 15710339a1c2SMark Johnston /* [28] */ TNSZ("vmovaps",VEX_MX,16), TNSZ("vmovaps",VEX_RX,16),INVALID, TNSZ("vmovntps",VEX_RM,16), 15720339a1c2SMark Johnston /* [2C] */ INVALID, INVALID, TNSZ("vucomiss",VEX_MX,4),TNSZ("vcomiss",VEX_MX,4), 15730339a1c2SMark Johnston }, { 15740339a1c2SMark Johnston /* [30] */ INVALID, INVALID, INVALID, INVALID, 15750339a1c2SMark Johnston /* [34] */ INVALID, INVALID, INVALID, INVALID, 15760339a1c2SMark Johnston /* [38] */ INVALID, INVALID, INVALID, INVALID, 15770339a1c2SMark Johnston /* [3C] */ INVALID, INVALID, INVALID, INVALID, 15780339a1c2SMark Johnston }, { 15790339a1c2SMark Johnston /* [40] */ INVALID, INVALID, INVALID, INVALID, 15800339a1c2SMark Johnston /* [44] */ INVALID, INVALID, INVALID, INVALID, 15810339a1c2SMark Johnston /* [48] */ INVALID, INVALID, INVALID, INVALID, 15820339a1c2SMark Johnston /* [4C] */ INVALID, INVALID, INVALID, INVALID, 15830339a1c2SMark Johnston }, { 15840339a1c2SMark Johnston /* [50] */ TNS("vmovmskps",VEX_MR), TNSZ("vsqrtps",VEX_MX,16), TNSZ("vrsqrtps",VEX_MX,16),TNSZ("vrcpps",VEX_MX,16), 15850339a1c2SMark Johnston /* [54] */ TNSZ("vandps",VEX_RMrX,16), TNSZ("vandnps",VEX_RMrX,16), TNSZ("vorps",VEX_RMrX,16), TNSZ("vxorps",VEX_RMrX,16), 15860339a1c2SMark Johnston /* [58] */ TNSZ("vaddps",VEX_RMrX,16), TNSZ("vmulps",VEX_RMrX,16), TNSZ("vcvtps2pd",VEX_MX,8),TNSZ("vcvtdq2ps",VEX_MX,16), 15870339a1c2SMark Johnston /* [5C] */ TNSZ("vsubps",VEX_RMrX,16), TNSZ("vminps",VEX_RMrX,16), TNSZ("vdivps",VEX_RMrX,16), TNSZ("vmaxps",VEX_RMrX,16), 15880339a1c2SMark Johnston }, { 15890339a1c2SMark Johnston /* [60] */ INVALID, INVALID, INVALID, INVALID, 15900339a1c2SMark Johnston /* [64] */ INVALID, INVALID, INVALID, INVALID, 15910339a1c2SMark Johnston /* [68] */ INVALID, INVALID, INVALID, INVALID, 15920339a1c2SMark Johnston /* [6C] */ INVALID, INVALID, INVALID, INVALID, 15930339a1c2SMark Johnston }, { 15940339a1c2SMark Johnston /* [70] */ INVALID, INVALID, INVALID, INVALID, 15950339a1c2SMark Johnston /* [74] */ INVALID, INVALID, INVALID, TNS("vzeroupper", VEX_NONE), 15960339a1c2SMark Johnston /* [78] */ INVALID, INVALID, INVALID, INVALID, 15970339a1c2SMark Johnston /* [7C] */ INVALID, INVALID, INVALID, INVALID, 15980339a1c2SMark Johnston }, { 15990339a1c2SMark Johnston /* [80] */ INVALID, INVALID, INVALID, INVALID, 16000339a1c2SMark Johnston /* [84] */ INVALID, INVALID, INVALID, INVALID, 16010339a1c2SMark Johnston /* [88] */ INVALID, INVALID, INVALID, INVALID, 16020339a1c2SMark Johnston /* [8C] */ INVALID, INVALID, INVALID, INVALID, 16030339a1c2SMark Johnston }, { 16040339a1c2SMark Johnston /* [90] */ INVALID, INVALID, INVALID, INVALID, 16050339a1c2SMark Johnston /* [94] */ INVALID, INVALID, INVALID, INVALID, 16060339a1c2SMark Johnston /* [98] */ INVALID, INVALID, INVALID, INVALID, 16070339a1c2SMark Johnston /* [9C] */ INVALID, INVALID, INVALID, INVALID, 16080339a1c2SMark Johnston }, { 16090339a1c2SMark Johnston /* [A0] */ INVALID, INVALID, INVALID, INVALID, 16100339a1c2SMark Johnston /* [A4] */ INVALID, INVALID, INVALID, INVALID, 16110339a1c2SMark Johnston /* [A8] */ INVALID, INVALID, INVALID, INVALID, 16120339a1c2SMark Johnston /* [AC] */ INVALID, INVALID, TNSZ("vldmxcsr",VEX_MO,2), INVALID, 16130339a1c2SMark Johnston }, { 16140339a1c2SMark Johnston /* [B0] */ INVALID, INVALID, INVALID, INVALID, 16150339a1c2SMark Johnston /* [B4] */ INVALID, INVALID, INVALID, INVALID, 16160339a1c2SMark Johnston /* [B8] */ INVALID, INVALID, INVALID, INVALID, 16170339a1c2SMark Johnston /* [BC] */ INVALID, INVALID, INVALID, INVALID, 16180339a1c2SMark Johnston }, { 16190339a1c2SMark Johnston /* [C0] */ INVALID, INVALID, TNSZ("vcmpps",VEX_RMRX,16),INVALID, 16200339a1c2SMark Johnston /* [C4] */ INVALID, INVALID, TNSZ("vshufps",VEX_RMRX,16),INVALID, 16210339a1c2SMark Johnston /* [C8] */ INVALID, INVALID, INVALID, INVALID, 16220339a1c2SMark Johnston /* [CC] */ INVALID, INVALID, INVALID, INVALID, 16230339a1c2SMark Johnston }, { 16240339a1c2SMark Johnston /* [D0] */ INVALID, INVALID, INVALID, INVALID, 16250339a1c2SMark Johnston /* [D4] */ INVALID, INVALID, INVALID, INVALID, 16260339a1c2SMark Johnston /* [D8] */ INVALID, INVALID, INVALID, INVALID, 16270339a1c2SMark Johnston /* [DC] */ INVALID, INVALID, INVALID, INVALID, 16280339a1c2SMark Johnston }, { 16290339a1c2SMark Johnston /* [E0] */ INVALID, INVALID, INVALID, INVALID, 16300339a1c2SMark Johnston /* [E4] */ INVALID, INVALID, INVALID, INVALID, 16310339a1c2SMark Johnston /* [E8] */ INVALID, INVALID, INVALID, INVALID, 16320339a1c2SMark Johnston /* [EC] */ INVALID, INVALID, INVALID, INVALID, 16330339a1c2SMark Johnston }, { 16340339a1c2SMark Johnston /* [F0] */ INVALID, INVALID, INVALID, INVALID, 16350339a1c2SMark Johnston /* [F4] */ INVALID, INVALID, INVALID, INVALID, 16360339a1c2SMark Johnston /* [F8] */ INVALID, INVALID, INVALID, INVALID, 16370339a1c2SMark Johnston /* [FC] */ INVALID, INVALID, INVALID, INVALID, 16380339a1c2SMark Johnston } }; 16390339a1c2SMark Johnston 16400339a1c2SMark Johnston /* 16410339a1c2SMark Johnston * Decode table for 0x80 opcodes 16420339a1c2SMark Johnston */ 16430339a1c2SMark Johnston 16440339a1c2SMark Johnston const instable_t dis_op80[8] = { 16450339a1c2SMark Johnston 16460339a1c2SMark Johnston /* [0] */ TNS("addb",IMlw), TNS("orb",IMw), TNS("adcb",IMlw), TNS("sbbb",IMlw), 16470339a1c2SMark Johnston /* [4] */ TNS("andb",IMw), TNS("subb",IMlw), TNS("xorb",IMw), TNS("cmpb",IMlw), 16480339a1c2SMark Johnston }; 16490339a1c2SMark Johnston 16500339a1c2SMark Johnston 16510339a1c2SMark Johnston /* 16520339a1c2SMark Johnston * Decode table for 0x81 opcodes. 16530339a1c2SMark Johnston */ 16540339a1c2SMark Johnston 16550339a1c2SMark Johnston const instable_t dis_op81[8] = { 16560339a1c2SMark Johnston 16570339a1c2SMark Johnston /* [0] */ TS("add",IMlw), TS("or",IMw), TS("adc",IMlw), TS("sbb",IMlw), 16580339a1c2SMark Johnston /* [4] */ TS("and",IMw), TS("sub",IMlw), TS("xor",IMw), TS("cmp",IMlw), 16590339a1c2SMark Johnston }; 16600339a1c2SMark Johnston 16610339a1c2SMark Johnston 16620339a1c2SMark Johnston /* 16630339a1c2SMark Johnston * Decode table for 0x82 opcodes. 16640339a1c2SMark Johnston */ 16650339a1c2SMark Johnston 16660339a1c2SMark Johnston const instable_t dis_op82[8] = { 16670339a1c2SMark Johnston 16680339a1c2SMark Johnston /* [0] */ TNSx("addb",IMlw), TNSx("orb",IMlw), TNSx("adcb",IMlw), TNSx("sbbb",IMlw), 16690339a1c2SMark Johnston /* [4] */ TNSx("andb",IMlw), TNSx("subb",IMlw), TNSx("xorb",IMlw), TNSx("cmpb",IMlw), 16700339a1c2SMark Johnston }; 16710339a1c2SMark Johnston /* 16720339a1c2SMark Johnston * Decode table for 0x83 opcodes. 16730339a1c2SMark Johnston */ 16740339a1c2SMark Johnston 16750339a1c2SMark Johnston const instable_t dis_op83[8] = { 16760339a1c2SMark Johnston 16770339a1c2SMark Johnston /* [0] */ TS("add",IMlw), TS("or",IMlw), TS("adc",IMlw), TS("sbb",IMlw), 16780339a1c2SMark Johnston /* [4] */ TS("and",IMlw), TS("sub",IMlw), TS("xor",IMlw), TS("cmp",IMlw), 16790339a1c2SMark Johnston }; 16800339a1c2SMark Johnston 16810339a1c2SMark Johnston /* 16820339a1c2SMark Johnston * Decode table for 0xC0 opcodes. 16830339a1c2SMark Johnston */ 16840339a1c2SMark Johnston 16850339a1c2SMark Johnston const instable_t dis_opC0[8] = { 16860339a1c2SMark Johnston 16870339a1c2SMark Johnston /* [0] */ TNS("rolb",MvI), TNS("rorb",MvI), TNS("rclb",MvI), TNS("rcrb",MvI), 16880339a1c2SMark Johnston /* [4] */ TNS("shlb",MvI), TNS("shrb",MvI), INVALID, TNS("sarb",MvI), 16890339a1c2SMark Johnston }; 16900339a1c2SMark Johnston 16910339a1c2SMark Johnston /* 16920339a1c2SMark Johnston * Decode table for 0xD0 opcodes. 16930339a1c2SMark Johnston */ 16940339a1c2SMark Johnston 16950339a1c2SMark Johnston const instable_t dis_opD0[8] = { 16960339a1c2SMark Johnston 16970339a1c2SMark Johnston /* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv), 16980339a1c2SMark Johnston /* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv), 16990339a1c2SMark Johnston }; 17000339a1c2SMark Johnston 17010339a1c2SMark Johnston /* 17020339a1c2SMark Johnston * Decode table for 0xC1 opcodes. 17030339a1c2SMark Johnston * 186 instruction set 17040339a1c2SMark Johnston */ 17050339a1c2SMark Johnston 17060339a1c2SMark Johnston const instable_t dis_opC1[8] = { 17070339a1c2SMark Johnston 17080339a1c2SMark Johnston /* [0] */ TS("rol",MvI), TS("ror",MvI), TS("rcl",MvI), TS("rcr",MvI), 17090339a1c2SMark Johnston /* [4] */ TS("shl",MvI), TS("shr",MvI), TS("sal",MvI), TS("sar",MvI), 17100339a1c2SMark Johnston }; 17110339a1c2SMark Johnston 17120339a1c2SMark Johnston /* 17130339a1c2SMark Johnston * Decode table for 0xD1 opcodes. 17140339a1c2SMark Johnston */ 17150339a1c2SMark Johnston 17160339a1c2SMark Johnston const instable_t dis_opD1[8] = { 17170339a1c2SMark Johnston 17180339a1c2SMark Johnston /* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv), 17190339a1c2SMark Johnston /* [4] */ TS("shl",Mv), TS("shr",Mv), TS("sal",Mv), TS("sar",Mv), 17200339a1c2SMark Johnston }; 17210339a1c2SMark Johnston 17220339a1c2SMark Johnston 17230339a1c2SMark Johnston /* 17240339a1c2SMark Johnston * Decode table for 0xD2 opcodes. 17250339a1c2SMark Johnston */ 17260339a1c2SMark Johnston 17270339a1c2SMark Johnston const instable_t dis_opD2[8] = { 17280339a1c2SMark Johnston 17290339a1c2SMark Johnston /* [0] */ TNS("rolb",Mv), TNS("rorb",Mv), TNS("rclb",Mv), TNS("rcrb",Mv), 17300339a1c2SMark Johnston /* [4] */ TNS("shlb",Mv), TNS("shrb",Mv), TNS("salb",Mv), TNS("sarb",Mv), 17310339a1c2SMark Johnston }; 17320339a1c2SMark Johnston /* 17330339a1c2SMark Johnston * Decode table for 0xD3 opcodes. 17340339a1c2SMark Johnston */ 17350339a1c2SMark Johnston 17360339a1c2SMark Johnston const instable_t dis_opD3[8] = { 17370339a1c2SMark Johnston 17380339a1c2SMark Johnston /* [0] */ TS("rol",Mv), TS("ror",Mv), TS("rcl",Mv), TS("rcr",Mv), 17390339a1c2SMark Johnston /* [4] */ TS("shl",Mv), TS("shr",Mv), TS("salb",Mv), TS("sar",Mv), 17400339a1c2SMark Johnston }; 17410339a1c2SMark Johnston 17420339a1c2SMark Johnston 17430339a1c2SMark Johnston /* 17440339a1c2SMark Johnston * Decode table for 0xF6 opcodes. 17450339a1c2SMark Johnston */ 17460339a1c2SMark Johnston 17470339a1c2SMark Johnston const instable_t dis_opF6[8] = { 17480339a1c2SMark Johnston 17490339a1c2SMark Johnston /* [0] */ TNS("testb",IMw), TNS("testb",IMw), TNS("notb",Mw), TNS("negb",Mw), 17500339a1c2SMark Johnston /* [4] */ TNS("mulb",MA), TNS("imulb",MA), TNS("divb",MA), TNS("idivb",MA), 17510339a1c2SMark Johnston }; 17520339a1c2SMark Johnston 17530339a1c2SMark Johnston 17540339a1c2SMark Johnston /* 17550339a1c2SMark Johnston * Decode table for 0xF7 opcodes. 17560339a1c2SMark Johnston */ 17570339a1c2SMark Johnston 17580339a1c2SMark Johnston const instable_t dis_opF7[8] = { 17590339a1c2SMark Johnston 17600339a1c2SMark Johnston /* [0] */ TS("test",IMw), TS("test",IMw), TS("not",Mw), TS("neg",Mw), 17610339a1c2SMark Johnston /* [4] */ TS("mul",MA), TS("imul",MA), TS("div",MA), TS("idiv",MA), 17620339a1c2SMark Johnston }; 17630339a1c2SMark Johnston 17640339a1c2SMark Johnston 17650339a1c2SMark Johnston /* 17660339a1c2SMark Johnston * Decode table for 0xFE opcodes. 17670339a1c2SMark Johnston */ 17680339a1c2SMark Johnston 17690339a1c2SMark Johnston const instable_t dis_opFE[8] = { 17700339a1c2SMark Johnston 17710339a1c2SMark Johnston /* [0] */ TNS("incb",Mw), TNS("decb",Mw), INVALID, INVALID, 17720339a1c2SMark Johnston /* [4] */ INVALID, INVALID, INVALID, INVALID, 17730339a1c2SMark Johnston }; 17740339a1c2SMark Johnston /* 17750339a1c2SMark Johnston * Decode table for 0xFF opcodes. 17760339a1c2SMark Johnston */ 17770339a1c2SMark Johnston 17780339a1c2SMark Johnston const instable_t dis_opFF[8] = { 17790339a1c2SMark Johnston 17800339a1c2SMark Johnston /* [0] */ TS("inc",Mw), TS("dec",Mw), TNSyp("call",INM), TNS("lcall",INM), 17810339a1c2SMark Johnston /* [4] */ TNSy("jmp",INM), TNS("ljmp",INM), TSp("push",M), INVALID, 17820339a1c2SMark Johnston }; 17830339a1c2SMark Johnston 17840339a1c2SMark Johnston /* for 287 instructions, which are a mess to decode */ 17850339a1c2SMark Johnston 17860339a1c2SMark Johnston const instable_t dis_opFP1n2[8][8] = { 17870339a1c2SMark Johnston { 17880339a1c2SMark Johnston /* bit pattern: 1101 1xxx MODxx xR/M */ 17890339a1c2SMark Johnston /* [0,0] */ TNS("fadds",M), TNS("fmuls",M), TNS("fcoms",M), TNS("fcomps",M), 17900339a1c2SMark Johnston /* [0,4] */ TNS("fsubs",M), TNS("fsubrs",M), TNS("fdivs",M), TNS("fdivrs",M), 17910339a1c2SMark Johnston }, { 17920339a1c2SMark Johnston /* [1,0] */ TNS("flds",M), INVALID, TNS("fsts",M), TNS("fstps",M), 17930339a1c2SMark Johnston /* [1,4] */ TNSZ("fldenv",M,28), TNSZ("fldcw",M,2), TNSZ("fnstenv",M,28), TNSZ("fnstcw",M,2), 17940339a1c2SMark Johnston }, { 17950339a1c2SMark Johnston /* [2,0] */ TNS("fiaddl",M), TNS("fimull",M), TNS("ficoml",M), TNS("ficompl",M), 17960339a1c2SMark Johnston /* [2,4] */ TNS("fisubl",M), TNS("fisubrl",M), TNS("fidivl",M), TNS("fidivrl",M), 17970339a1c2SMark Johnston }, { 17980339a1c2SMark Johnston /* [3,0] */ TNS("fildl",M), INVALID, TNS("fistl",M), TNS("fistpl",M), 17990339a1c2SMark Johnston /* [3,4] */ INVALID, TNSZ("fldt",M,10), INVALID, TNSZ("fstpt",M,10), 18000339a1c2SMark Johnston }, { 18010339a1c2SMark Johnston /* [4,0] */ TNSZ("faddl",M,8), TNSZ("fmull",M,8), TNSZ("fcoml",M,8), TNSZ("fcompl",M,8), 18020339a1c2SMark Johnston /* [4,1] */ TNSZ("fsubl",M,8), TNSZ("fsubrl",M,8), TNSZ("fdivl",M,8), TNSZ("fdivrl",M,8), 18030339a1c2SMark Johnston }, { 18040339a1c2SMark Johnston /* [5,0] */ TNSZ("fldl",M,8), INVALID, TNSZ("fstl",M,8), TNSZ("fstpl",M,8), 18050339a1c2SMark Johnston /* [5,4] */ TNSZ("frstor",M,108), INVALID, TNSZ("fnsave",M,108), TNSZ("fnstsw",M,2), 18060339a1c2SMark Johnston }, { 18070339a1c2SMark Johnston /* [6,0] */ TNSZ("fiadd",M,2), TNSZ("fimul",M,2), TNSZ("ficom",M,2), TNSZ("ficomp",M,2), 18080339a1c2SMark Johnston /* [6,4] */ TNSZ("fisub",M,2), TNSZ("fisubr",M,2), TNSZ("fidiv",M,2), TNSZ("fidivr",M,2), 18090339a1c2SMark Johnston }, { 18100339a1c2SMark Johnston /* [7,0] */ TNSZ("fild",M,2), INVALID, TNSZ("fist",M,2), TNSZ("fistp",M,2), 18110339a1c2SMark Johnston /* [7,4] */ TNSZ("fbld",M,10), TNSZ("fildll",M,8), TNSZ("fbstp",M,10), TNSZ("fistpll",M,8), 18120339a1c2SMark Johnston } }; 18130339a1c2SMark Johnston 18140339a1c2SMark Johnston const instable_t dis_opFP3[8][8] = { 18150339a1c2SMark Johnston { 18160339a1c2SMark Johnston /* bit pattern: 1101 1xxx 11xx xREG */ 18170339a1c2SMark Johnston /* [0,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F), 18180339a1c2SMark Johnston /* [0,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF), 18190339a1c2SMark Johnston }, { 18200339a1c2SMark Johnston /* [1,0] */ TNS("fld",F), TNS("fxch",F), TNS("fnop",NORM), TNS("fstp",F), 18210339a1c2SMark Johnston /* [1,4] */ INVALID, INVALID, INVALID, INVALID, 18220339a1c2SMark Johnston }, { 18230339a1c2SMark Johnston /* [2,0] */ INVALID, INVALID, INVALID, INVALID, 18240339a1c2SMark Johnston /* [2,4] */ INVALID, TNS("fucompp",NORM), INVALID, INVALID, 18250339a1c2SMark Johnston }, { 18260339a1c2SMark Johnston /* [3,0] */ INVALID, INVALID, INVALID, INVALID, 18270339a1c2SMark Johnston /* [3,4] */ INVALID, INVALID, INVALID, INVALID, 18280339a1c2SMark Johnston }, { 18290339a1c2SMark Johnston /* [4,0] */ TNS("fadd",FF), TNS("fmul",FF), TNS("fcom",F), TNS("fcomp",F), 18300339a1c2SMark Johnston /* [4,4] */ TNS("fsub",FF), TNS("fsubr",FF), TNS("fdiv",FF), TNS("fdivr",FF), 18310339a1c2SMark Johnston }, { 18320339a1c2SMark Johnston /* [5,0] */ TNS("ffree",F), TNS("fxch",F), TNS("fst",F), TNS("fstp",F), 18330339a1c2SMark Johnston /* [5,4] */ TNS("fucom",F), TNS("fucomp",F), INVALID, INVALID, 18340339a1c2SMark Johnston }, { 18350339a1c2SMark Johnston /* [6,0] */ TNS("faddp",FF), TNS("fmulp",FF), TNS("fcomp",F), TNS("fcompp",NORM), 18360339a1c2SMark Johnston /* [6,4] */ TNS("fsubp",FF), TNS("fsubrp",FF), TNS("fdivp",FF), TNS("fdivrp",FF), 18370339a1c2SMark Johnston }, { 18380339a1c2SMark Johnston /* [7,0] */ TNS("ffreep",F), TNS("fxch",F), TNS("fstp",F), TNS("fstp",F), 18390339a1c2SMark Johnston /* [7,4] */ TNS("fnstsw",M), TNS("fucomip",FFC), TNS("fcomip",FFC), INVALID, 18400339a1c2SMark Johnston } }; 18410339a1c2SMark Johnston 18420339a1c2SMark Johnston const instable_t dis_opFP4[4][8] = { 18430339a1c2SMark Johnston { 18440339a1c2SMark Johnston /* bit pattern: 1101 1001 111x xxxx */ 18450339a1c2SMark Johnston /* [0,0] */ TNS("fchs",NORM), TNS("fabs",NORM), INVALID, INVALID, 18460339a1c2SMark Johnston /* [0,4] */ TNS("ftst",NORM), TNS("fxam",NORM), TNS("ftstp",NORM), INVALID, 18470339a1c2SMark Johnston }, { 18480339a1c2SMark Johnston /* [1,0] */ TNS("fld1",NORM), TNS("fldl2t",NORM), TNS("fldl2e",NORM), TNS("fldpi",NORM), 18490339a1c2SMark Johnston /* [1,4] */ TNS("fldlg2",NORM), TNS("fldln2",NORM), TNS("fldz",NORM), INVALID, 18500339a1c2SMark Johnston }, { 18510339a1c2SMark Johnston /* [2,0] */ TNS("f2xm1",NORM), TNS("fyl2x",NORM), TNS("fptan",NORM), TNS("fpatan",NORM), 18520339a1c2SMark Johnston /* [2,4] */ TNS("fxtract",NORM), TNS("fprem1",NORM), TNS("fdecstp",NORM), TNS("fincstp",NORM), 18530339a1c2SMark Johnston }, { 18540339a1c2SMark Johnston /* [3,0] */ TNS("fprem",NORM), TNS("fyl2xp1",NORM), TNS("fsqrt",NORM), TNS("fsincos",NORM), 18550339a1c2SMark Johnston /* [3,4] */ TNS("frndint",NORM), TNS("fscale",NORM), TNS("fsin",NORM), TNS("fcos",NORM), 18560339a1c2SMark Johnston } }; 18570339a1c2SMark Johnston 18580339a1c2SMark Johnston const instable_t dis_opFP5[8] = { 18590339a1c2SMark Johnston /* bit pattern: 1101 1011 111x xxxx */ 18600339a1c2SMark Johnston /* [0] */ TNS("feni",NORM), TNS("fdisi",NORM), TNS("fnclex",NORM), TNS("fninit",NORM), 18610339a1c2SMark Johnston /* [4] */ TNS("fsetpm",NORM), TNS("frstpm",NORM), INVALID, INVALID, 18620339a1c2SMark Johnston }; 18630339a1c2SMark Johnston 18640339a1c2SMark Johnston const instable_t dis_opFP6[8] = { 18650339a1c2SMark Johnston /* bit pattern: 1101 1011 11yy yxxx */ 18660339a1c2SMark Johnston /* [00] */ TNS("fcmov.nb",FF), TNS("fcmov.ne",FF), TNS("fcmov.nbe",FF), TNS("fcmov.nu",FF), 18670339a1c2SMark Johnston /* [04] */ INVALID, TNS("fucomi",F), TNS("fcomi",F), INVALID, 18680339a1c2SMark Johnston }; 18690339a1c2SMark Johnston 18700339a1c2SMark Johnston const instable_t dis_opFP7[8] = { 18710339a1c2SMark Johnston /* bit pattern: 1101 1010 11yy yxxx */ 18720339a1c2SMark Johnston /* [00] */ TNS("fcmov.b",FF), TNS("fcmov.e",FF), TNS("fcmov.be",FF), TNS("fcmov.u",FF), 18730339a1c2SMark Johnston /* [04] */ INVALID, INVALID, INVALID, INVALID, 18740339a1c2SMark Johnston }; 18750339a1c2SMark Johnston 18760339a1c2SMark Johnston /* 18770339a1c2SMark Johnston * Main decode table for the op codes. The first two nibbles 18780339a1c2SMark Johnston * will be used as an index into the table. If there is a 18790339a1c2SMark Johnston * a need to further decode an instruction, the array to be 18800339a1c2SMark Johnston * referenced is indicated with the other two entries being 18810339a1c2SMark Johnston * empty. 18820339a1c2SMark Johnston */ 18830339a1c2SMark Johnston 18840339a1c2SMark Johnston const instable_t dis_distable[16][16] = { 18850339a1c2SMark Johnston { 18860339a1c2SMark Johnston /* [0,0] */ TNS("addb",RMw), TS("add",RMw), TNS("addb",MRw), TS("add",MRw), 18870339a1c2SMark Johnston /* [0,4] */ TNS("addb",IA), TS("add",IA), TSx("push",SEG), TSx("pop",SEG), 18880339a1c2SMark Johnston /* [0,8] */ TNS("orb",RMw), TS("or",RMw), TNS("orb",MRw), TS("or",MRw), 18890339a1c2SMark Johnston /* [0,C] */ TNS("orb",IA), TS("or",IA), TSx("push",SEG), IND(dis_op0F), 18900339a1c2SMark Johnston }, { 18910339a1c2SMark Johnston /* [1,0] */ TNS("adcb",RMw), TS("adc",RMw), TNS("adcb",MRw), TS("adc",MRw), 18920339a1c2SMark Johnston /* [1,4] */ TNS("adcb",IA), TS("adc",IA), TSx("push",SEG), TSx("pop",SEG), 18930339a1c2SMark Johnston /* [1,8] */ TNS("sbbb",RMw), TS("sbb",RMw), TNS("sbbb",MRw), TS("sbb",MRw), 18940339a1c2SMark Johnston /* [1,C] */ TNS("sbbb",IA), TS("sbb",IA), TSx("push",SEG), TSx("pop",SEG), 18950339a1c2SMark Johnston }, { 18960339a1c2SMark Johnston /* [2,0] */ TNS("andb",RMw), TS("and",RMw), TNS("andb",MRw), TS("and",MRw), 1897c3ddb60eSPeter Grehan /* [2,4] */ TNS("andb",IA), TS("and",IA), TNSx("%es:",OVERRIDE), TNSx("daa",NORM), 18980339a1c2SMark Johnston /* [2,8] */ TNS("subb",RMw), TS("sub",RMw), TNS("subb",MRw), TS("sub",MRw), 18990339a1c2SMark Johnston /* [2,C] */ TNS("subb",IA), TS("sub",IA), TNS("%cs:",OVERRIDE), TNSx("das",NORM), 19000339a1c2SMark Johnston }, { 19010339a1c2SMark Johnston /* [3,0] */ TNS("xorb",RMw), TS("xor",RMw), TNS("xorb",MRw), TS("xor",MRw), 1902c3ddb60eSPeter Grehan /* [3,4] */ TNS("xorb",IA), TS("xor",IA), TNSx("%ss:",OVERRIDE), TNSx("aaa",NORM), 19030339a1c2SMark Johnston /* [3,8] */ TNS("cmpb",RMw), TS("cmp",RMw), TNS("cmpb",MRw), TS("cmp",MRw), 1904c3ddb60eSPeter Grehan /* [3,C] */ TNS("cmpb",IA), TS("cmp",IA), TNSx("%ds:",OVERRIDE), TNSx("aas",NORM), 19050339a1c2SMark Johnston }, { 19060339a1c2SMark Johnston /* [4,0] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R), 19070339a1c2SMark Johnston /* [4,4] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R), 19080339a1c2SMark Johnston /* [4,8] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R), 19090339a1c2SMark Johnston /* [4,C] */ TSx("dec",R), TSx("dec",R), TSx("dec",R), TSx("dec",R), 19100339a1c2SMark Johnston }, { 19110339a1c2SMark Johnston /* [5,0] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R), 19120339a1c2SMark Johnston /* [5,4] */ TSp("push",R), TSp("push",R), TSp("push",R), TSp("push",R), 19130339a1c2SMark Johnston /* [5,8] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R), 19140339a1c2SMark Johnston /* [5,C] */ TSp("pop",R), TSp("pop",R), TSp("pop",R), TSp("pop",R), 19150339a1c2SMark Johnston }, { 19160339a1c2SMark Johnston /* [6,0] */ TSZx("pusha",IMPLMEM,28),TSZx("popa",IMPLMEM,28), TSx("bound",MR), TNS("arpl",RMw), 19170339a1c2SMark Johnston /* [6,4] */ TNS("%fs:",OVERRIDE), TNS("%gs:",OVERRIDE), TNS("data16",DM), TNS("addr16",AM), 19180339a1c2SMark Johnston /* [6,8] */ TSp("push",I), TS("imul",IMUL), TSp("push",Ib), TS("imul",IMUL), 19190339a1c2SMark Johnston /* [6,C] */ TNSZ("insb",IMPLMEM,1), TSZ("ins",IMPLMEM,4), TNSZ("outsb",IMPLMEM,1),TSZ("outs",IMPLMEM,4), 19200339a1c2SMark Johnston }, { 19210339a1c2SMark Johnston /* [7,0] */ TNSy("jo",BD), TNSy("jno",BD), TNSy("jb",BD), TNSy("jae",BD), 19220339a1c2SMark Johnston /* [7,4] */ TNSy("je",BD), TNSy("jne",BD), TNSy("jbe",BD), TNSy("ja",BD), 19230339a1c2SMark Johnston /* [7,8] */ TNSy("js",BD), TNSy("jns",BD), TNSy("jp",BD), TNSy("jnp",BD), 19240339a1c2SMark Johnston /* [7,C] */ TNSy("jl",BD), TNSy("jge",BD), TNSy("jle",BD), TNSy("jg",BD), 19250339a1c2SMark Johnston }, { 19260339a1c2SMark Johnston /* [8,0] */ IND(dis_op80), IND(dis_op81), INDx(dis_op82), IND(dis_op83), 19270339a1c2SMark Johnston /* [8,4] */ TNS("testb",RMw), TS("test",RMw), TNS("xchgb",RMw), TS("xchg",RMw), 19280339a1c2SMark Johnston /* [8,8] */ TNS("movb",RMw), TS("mov",RMw), TNS("movb",MRw), TS("mov",MRw), 19290339a1c2SMark Johnston /* [8,C] */ TNS("movw",SM), TS("lea",MR), TNS("movw",MS), TSp("pop",M), 19300339a1c2SMark Johnston }, { 19310339a1c2SMark Johnston /* [9,0] */ TNS("nop",NORM), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), 19320339a1c2SMark Johnston /* [9,4] */ TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), TS("xchg",RA), 19330339a1c2SMark Johnston /* [9,8] */ TNS("cXtX",CBW), TNS("cXtX",CWD), TNSx("lcall",SO), TNS("fwait",NORM), 1934*2d69831bSAndriy Gapon /* [9,C] */ TSZy("pushf",IMPLMEM,4),TSZy("popf",IMPLMEM,4), TNS("sahf",NORM), TNS("lahf",NORM), 19350339a1c2SMark Johnston }, { 19360339a1c2SMark Johnston /* [A,0] */ TNS("movb",OA), TS("mov",OA), TNS("movb",AO), TS("mov",AO), 19370339a1c2SMark Johnston /* [A,4] */ TNSZ("movsb",SD,1), TS("movs",SD), TNSZ("cmpsb",SD,1), TS("cmps",SD), 19380339a1c2SMark Johnston /* [A,8] */ TNS("testb",IA), TS("test",IA), TNS("stosb",AD), TS("stos",AD), 19390339a1c2SMark Johnston /* [A,C] */ TNS("lodsb",SA), TS("lods",SA), TNS("scasb",AD), TS("scas",AD), 19400339a1c2SMark Johnston }, { 19410339a1c2SMark Johnston /* [B,0] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), 19420339a1c2SMark Johnston /* [B,4] */ TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), TNS("movb",IR), 19430339a1c2SMark Johnston /* [B,8] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR), 19440339a1c2SMark Johnston /* [B,C] */ TS("mov",IR), TS("mov",IR), TS("mov",IR), TS("mov",IR), 19450339a1c2SMark Johnston }, { 19460339a1c2SMark Johnston /* [C,0] */ IND(dis_opC0), IND(dis_opC1), TNSyp("ret",RET), TNSyp("ret",NORM), 19470339a1c2SMark Johnston /* [C,4] */ TNSx("les",MR), TNSx("lds",MR), TNS("movb",IMw), TS("mov",IMw), 19480339a1c2SMark Johnston /* [C,8] */ TNSyp("enter",ENTER), TNSyp("leave",NORM), TNS("lret",RET), TNS("lret",NORM), 19490339a1c2SMark Johnston /* [C,C] */ TNS("int",INT3), TNS("int",INTx), TNSx("into",NORM), TNS("iret",NORM), 19500339a1c2SMark Johnston }, { 19510339a1c2SMark Johnston /* [D,0] */ IND(dis_opD0), IND(dis_opD1), IND(dis_opD2), IND(dis_opD3), 19520339a1c2SMark Johnston /* [D,4] */ TNSx("aam",U), TNSx("aad",U), TNSx("falc",NORM), TNSZ("xlat",IMPLMEM,1), 19530339a1c2SMark Johnston 19540339a1c2SMark Johnston /* 287 instructions. Note that although the indirect field */ 19550339a1c2SMark Johnston /* indicates opFP1n2 for further decoding, this is not necessarily */ 19560339a1c2SMark Johnston /* the case since the opFP arrays are not partitioned according to key1 */ 19570339a1c2SMark Johnston /* and key2. opFP1n2 is given only to indicate that we haven't */ 19580339a1c2SMark Johnston /* finished decoding the instruction. */ 19590339a1c2SMark Johnston /* [D,8] */ IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), 19600339a1c2SMark Johnston /* [D,C] */ IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), IND(dis_opFP1n2), 19610339a1c2SMark Johnston }, { 19620339a1c2SMark Johnston /* [E,0] */ TNSy("loopnz",BD), TNSy("loopz",BD), TNSy("loop",BD), TNSy("jcxz",BD), 19630339a1c2SMark Johnston /* [E,4] */ TNS("inb",P), TS("in",P), TNS("outb",P), TS("out",P), 19640339a1c2SMark Johnston /* [E,8] */ TNSyp("call",D), TNSy("jmp",D), TNSx("ljmp",SO), TNSy("jmp",BD), 19650339a1c2SMark Johnston /* [E,C] */ TNS("inb",V), TS("in",V), TNS("outb",V), TS("out",V), 19660339a1c2SMark Johnston }, { 19670339a1c2SMark Johnston /* [F,0] */ TNS("lock",LOCK), TNS("icebp", NORM), TNS("repnz",PREFIX), TNS("repz",PREFIX), 19680339a1c2SMark Johnston /* [F,4] */ TNS("hlt",NORM), TNS("cmc",NORM), IND(dis_opF6), IND(dis_opF7), 19690339a1c2SMark Johnston /* [F,8] */ TNS("clc",NORM), TNS("stc",NORM), TNS("cli",NORM), TNS("sti",NORM), 19700339a1c2SMark Johnston /* [F,C] */ TNS("cld",NORM), TNS("std",NORM), IND(dis_opFE), IND(dis_opFF), 19710339a1c2SMark Johnston } }; 19720339a1c2SMark Johnston 19730339a1c2SMark Johnston /* END CSTYLED */ 19740339a1c2SMark Johnston 19750339a1c2SMark Johnston /* 19760339a1c2SMark Johnston * common functions to decode and disassemble an x86 or amd64 instruction 19770339a1c2SMark Johnston */ 19780339a1c2SMark Johnston 19790339a1c2SMark Johnston /* 19800339a1c2SMark Johnston * These are the individual fields of a REX prefix. Note that a REX 19810339a1c2SMark Johnston * prefix with none of these set is still needed to: 19820339a1c2SMark Johnston * - use the MOVSXD (sign extend 32 to 64 bits) instruction 19830339a1c2SMark Johnston * - access the %sil, %dil, %bpl, %spl registers 19840339a1c2SMark Johnston */ 19850339a1c2SMark Johnston #define REX_W 0x08 /* 64 bit operand size when set */ 19860339a1c2SMark Johnston #define REX_R 0x04 /* high order bit extension of ModRM reg field */ 19870339a1c2SMark Johnston #define REX_X 0x02 /* high order bit extension of SIB index field */ 19880339a1c2SMark Johnston #define REX_B 0x01 /* extends ModRM r_m, SIB base, or opcode reg */ 19890339a1c2SMark Johnston 19900339a1c2SMark Johnston /* 19910339a1c2SMark Johnston * These are the individual fields of a VEX prefix. 19920339a1c2SMark Johnston */ 19930339a1c2SMark Johnston #define VEX_R 0x08 /* REX.R in 1's complement form */ 19940339a1c2SMark Johnston #define VEX_X 0x04 /* REX.X in 1's complement form */ 19950339a1c2SMark Johnston #define VEX_B 0x02 /* REX.B in 1's complement form */ 19960339a1c2SMark Johnston /* Vector Length, 0: scalar or 128-bit vector, 1: 256-bit vector */ 19970339a1c2SMark Johnston #define VEX_L 0x04 19980339a1c2SMark Johnston #define VEX_W 0x08 /* opcode specific, use like REX.W */ 19990339a1c2SMark Johnston #define VEX_m 0x1F /* VEX m-mmmm field */ 20000339a1c2SMark Johnston #define VEX_v 0x78 /* VEX register specifier */ 20010339a1c2SMark Johnston #define VEX_p 0x03 /* VEX pp field, opcode extension */ 20020339a1c2SMark Johnston 20030339a1c2SMark Johnston /* VEX m-mmmm field, only used by three bytes prefix */ 20040339a1c2SMark Johnston #define VEX_m_0F 0x01 /* implied 0F leading opcode byte */ 20050339a1c2SMark Johnston #define VEX_m_0F38 0x02 /* implied 0F 38 leading opcode byte */ 20060339a1c2SMark Johnston #define VEX_m_0F3A 0x03 /* implied 0F 3A leading opcode byte */ 20070339a1c2SMark Johnston 20080339a1c2SMark Johnston /* VEX pp field, providing equivalent functionality of a SIMD prefix */ 20090339a1c2SMark Johnston #define VEX_p_66 0x01 20100339a1c2SMark Johnston #define VEX_p_F3 0x02 20110339a1c2SMark Johnston #define VEX_p_F2 0x03 20120339a1c2SMark Johnston 20130339a1c2SMark Johnston /* 20140339a1c2SMark Johnston * Even in 64 bit mode, usually only 4 byte immediate operands are supported. 20150339a1c2SMark Johnston */ 20160339a1c2SMark Johnston static int isize[] = {1, 2, 4, 4}; 20170339a1c2SMark Johnston static int isize64[] = {1, 2, 4, 8}; 20180339a1c2SMark Johnston 20190339a1c2SMark Johnston /* 20200339a1c2SMark Johnston * Just a bunch of useful macros. 20210339a1c2SMark Johnston */ 20220339a1c2SMark Johnston #define WBIT(x) (x & 0x1) /* to get w bit */ 20230339a1c2SMark Johnston #define REGNO(x) (x & 0x7) /* to get 3 bit register */ 20240339a1c2SMark Johnston #define VBIT(x) ((x)>>1 & 0x1) /* to get 'v' bit */ 20250339a1c2SMark Johnston #define OPSIZE(osize, wbit) ((wbit) ? isize[osize] : 1) 20260339a1c2SMark Johnston #define OPSIZE64(osize, wbit) ((wbit) ? isize64[osize] : 1) 20270339a1c2SMark Johnston 20280339a1c2SMark Johnston #define REG_ONLY 3 /* mode to indicate a register operand (not memory) */ 20290339a1c2SMark Johnston 20300339a1c2SMark Johnston #define BYTE_OPND 0 /* w-bit value indicating byte register */ 20310339a1c2SMark Johnston #define LONG_OPND 1 /* w-bit value indicating opnd_size register */ 20320339a1c2SMark Johnston #define MM_OPND 2 /* "value" used to indicate a mmx reg */ 20330339a1c2SMark Johnston #define XMM_OPND 3 /* "value" used to indicate a xmm reg */ 20340339a1c2SMark Johnston #define SEG_OPND 4 /* "value" used to indicate a segment reg */ 20350339a1c2SMark Johnston #define CONTROL_OPND 5 /* "value" used to indicate a control reg */ 20360339a1c2SMark Johnston #define DEBUG_OPND 6 /* "value" used to indicate a debug reg */ 20370339a1c2SMark Johnston #define TEST_OPND 7 /* "value" used to indicate a test reg */ 20380339a1c2SMark Johnston #define WORD_OPND 8 /* w-bit value indicating word size reg */ 20390339a1c2SMark Johnston #define YMM_OPND 9 /* "value" used to indicate a ymm reg */ 20400339a1c2SMark Johnston 20410339a1c2SMark Johnston /* 20420339a1c2SMark Johnston * Get the next byte and separate the op code into the high and low nibbles. 20430339a1c2SMark Johnston */ 20440339a1c2SMark Johnston static int 20450339a1c2SMark Johnston dtrace_get_opcode(dis86_t *x, uint_t *high, uint_t *low) 20460339a1c2SMark Johnston { 20470339a1c2SMark Johnston int byte; 20480339a1c2SMark Johnston 20490339a1c2SMark Johnston /* 20500339a1c2SMark Johnston * x86 instructions have a maximum length of 15 bytes. Bail out if 20510339a1c2SMark Johnston * we try to read more. 20520339a1c2SMark Johnston */ 20530339a1c2SMark Johnston if (x->d86_len >= 15) 20540339a1c2SMark Johnston return (x->d86_error = 1); 20550339a1c2SMark Johnston 20560339a1c2SMark Johnston if (x->d86_error) 20570339a1c2SMark Johnston return (1); 20580339a1c2SMark Johnston byte = x->d86_get_byte(x->d86_data); 20590339a1c2SMark Johnston if (byte < 0) 20600339a1c2SMark Johnston return (x->d86_error = 1); 20610339a1c2SMark Johnston x->d86_bytes[x->d86_len++] = byte; 20620339a1c2SMark Johnston *low = byte & 0xf; /* ----xxxx low 4 bits */ 20630339a1c2SMark Johnston *high = byte >> 4 & 0xf; /* xxxx---- bits 7 to 4 */ 20640339a1c2SMark Johnston return (0); 20650339a1c2SMark Johnston } 20660339a1c2SMark Johnston 20670339a1c2SMark Johnston /* 20680339a1c2SMark Johnston * Get and decode an SIB (scaled index base) byte 20690339a1c2SMark Johnston */ 20700339a1c2SMark Johnston static void 20710339a1c2SMark Johnston dtrace_get_SIB(dis86_t *x, uint_t *ss, uint_t *index, uint_t *base) 20720339a1c2SMark Johnston { 20730339a1c2SMark Johnston int byte; 20740339a1c2SMark Johnston 20750339a1c2SMark Johnston if (x->d86_error) 20760339a1c2SMark Johnston return; 20770339a1c2SMark Johnston 20780339a1c2SMark Johnston byte = x->d86_get_byte(x->d86_data); 20790339a1c2SMark Johnston if (byte < 0) { 20800339a1c2SMark Johnston x->d86_error = 1; 20810339a1c2SMark Johnston return; 20820339a1c2SMark Johnston } 20830339a1c2SMark Johnston x->d86_bytes[x->d86_len++] = byte; 20840339a1c2SMark Johnston 20850339a1c2SMark Johnston *base = byte & 0x7; 20860339a1c2SMark Johnston *index = (byte >> 3) & 0x7; 20870339a1c2SMark Johnston *ss = (byte >> 6) & 0x3; 20880339a1c2SMark Johnston } 20890339a1c2SMark Johnston 20900339a1c2SMark Johnston /* 20910339a1c2SMark Johnston * Get the byte following the op code and separate it into the 20920339a1c2SMark Johnston * mode, register, and r/m fields. 20930339a1c2SMark Johnston */ 20940339a1c2SMark Johnston static void 20950339a1c2SMark Johnston dtrace_get_modrm(dis86_t *x, uint_t *mode, uint_t *reg, uint_t *r_m) 20960339a1c2SMark Johnston { 20970339a1c2SMark Johnston if (x->d86_got_modrm == 0) { 20980339a1c2SMark Johnston if (x->d86_rmindex == -1) 20990339a1c2SMark Johnston x->d86_rmindex = x->d86_len; 21000339a1c2SMark Johnston dtrace_get_SIB(x, mode, reg, r_m); 21010339a1c2SMark Johnston x->d86_got_modrm = 1; 21020339a1c2SMark Johnston } 21030339a1c2SMark Johnston } 21040339a1c2SMark Johnston 21050339a1c2SMark Johnston /* 21060339a1c2SMark Johnston * Adjust register selection based on any REX prefix bits present. 21070339a1c2SMark Johnston */ 21080339a1c2SMark Johnston /*ARGSUSED*/ 21090339a1c2SMark Johnston static void 21100339a1c2SMark Johnston dtrace_rex_adjust(uint_t rex_prefix, uint_t mode, uint_t *reg, uint_t *r_m) 21110339a1c2SMark Johnston { 21120339a1c2SMark Johnston if (reg != NULL && r_m == NULL) { 21130339a1c2SMark Johnston if (rex_prefix & REX_B) 21140339a1c2SMark Johnston *reg += 8; 21150339a1c2SMark Johnston } else { 21160339a1c2SMark Johnston if (reg != NULL && (REX_R & rex_prefix) != 0) 21170339a1c2SMark Johnston *reg += 8; 21180339a1c2SMark Johnston if (r_m != NULL && (REX_B & rex_prefix) != 0) 21190339a1c2SMark Johnston *r_m += 8; 21200339a1c2SMark Johnston } 21210339a1c2SMark Johnston } 21220339a1c2SMark Johnston 21230339a1c2SMark Johnston /* 21240339a1c2SMark Johnston * Adjust register selection based on any VEX prefix bits present. 21250339a1c2SMark Johnston * Notes: VEX.R, VEX.X and VEX.B use the inverted form compared with REX prefix 21260339a1c2SMark Johnston */ 21270339a1c2SMark Johnston /*ARGSUSED*/ 21280339a1c2SMark Johnston static void 21290339a1c2SMark Johnston dtrace_vex_adjust(uint_t vex_byte1, uint_t mode, uint_t *reg, uint_t *r_m) 21300339a1c2SMark Johnston { 21310339a1c2SMark Johnston if (reg != NULL && r_m == NULL) { 21320339a1c2SMark Johnston if (!(vex_byte1 & VEX_B)) 21330339a1c2SMark Johnston *reg += 8; 21340339a1c2SMark Johnston } else { 21350339a1c2SMark Johnston if (reg != NULL && ((VEX_R & vex_byte1) == 0)) 21360339a1c2SMark Johnston *reg += 8; 21370339a1c2SMark Johnston if (r_m != NULL && ((VEX_B & vex_byte1) == 0)) 21380339a1c2SMark Johnston *r_m += 8; 21390339a1c2SMark Johnston } 21400339a1c2SMark Johnston } 21410339a1c2SMark Johnston 21420339a1c2SMark Johnston /* 21430339a1c2SMark Johnston * Get an immediate operand of the given size, with sign extension. 21440339a1c2SMark Johnston */ 21450339a1c2SMark Johnston static void 21460339a1c2SMark Johnston dtrace_imm_opnd(dis86_t *x, int wbit, int size, int opindex) 21470339a1c2SMark Johnston { 21480339a1c2SMark Johnston int i; 21490339a1c2SMark Johnston int byte; 21500339a1c2SMark Johnston int valsize; 21510339a1c2SMark Johnston 21520339a1c2SMark Johnston if (x->d86_numopnds < opindex + 1) 21530339a1c2SMark Johnston x->d86_numopnds = opindex + 1; 21540339a1c2SMark Johnston 21550339a1c2SMark Johnston switch (wbit) { 21560339a1c2SMark Johnston case BYTE_OPND: 21570339a1c2SMark Johnston valsize = 1; 21580339a1c2SMark Johnston break; 21590339a1c2SMark Johnston case LONG_OPND: 21600339a1c2SMark Johnston if (x->d86_opnd_size == SIZE16) 21610339a1c2SMark Johnston valsize = 2; 21620339a1c2SMark Johnston else if (x->d86_opnd_size == SIZE32) 21630339a1c2SMark Johnston valsize = 4; 21640339a1c2SMark Johnston else 21650339a1c2SMark Johnston valsize = 8; 21660339a1c2SMark Johnston break; 21670339a1c2SMark Johnston case MM_OPND: 21680339a1c2SMark Johnston case XMM_OPND: 21690339a1c2SMark Johnston case YMM_OPND: 21700339a1c2SMark Johnston case SEG_OPND: 21710339a1c2SMark Johnston case CONTROL_OPND: 21720339a1c2SMark Johnston case DEBUG_OPND: 21730339a1c2SMark Johnston case TEST_OPND: 21740339a1c2SMark Johnston valsize = size; 21750339a1c2SMark Johnston break; 21760339a1c2SMark Johnston case WORD_OPND: 21770339a1c2SMark Johnston valsize = 2; 21780339a1c2SMark Johnston break; 21790339a1c2SMark Johnston } 21800339a1c2SMark Johnston if (valsize < size) 21810339a1c2SMark Johnston valsize = size; 21820339a1c2SMark Johnston 21830339a1c2SMark Johnston if (x->d86_error) 21840339a1c2SMark Johnston return; 21850339a1c2SMark Johnston x->d86_opnd[opindex].d86_value = 0; 21860339a1c2SMark Johnston for (i = 0; i < size; ++i) { 21870339a1c2SMark Johnston byte = x->d86_get_byte(x->d86_data); 21880339a1c2SMark Johnston if (byte < 0) { 21890339a1c2SMark Johnston x->d86_error = 1; 21900339a1c2SMark Johnston return; 21910339a1c2SMark Johnston } 21920339a1c2SMark Johnston x->d86_bytes[x->d86_len++] = byte; 21930339a1c2SMark Johnston x->d86_opnd[opindex].d86_value |= (uint64_t)byte << (i * 8); 21940339a1c2SMark Johnston } 21950339a1c2SMark Johnston /* Do sign extension */ 21960339a1c2SMark Johnston if (x->d86_bytes[x->d86_len - 1] & 0x80) { 21970339a1c2SMark Johnston for (; i < sizeof (uint64_t); i++) 21980339a1c2SMark Johnston x->d86_opnd[opindex].d86_value |= 21990339a1c2SMark Johnston (uint64_t)0xff << (i * 8); 22000339a1c2SMark Johnston } 22010339a1c2SMark Johnston #ifdef DIS_TEXT 22020339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = MODE_SIGNED; 22030339a1c2SMark Johnston x->d86_opnd[opindex].d86_value_size = valsize; 22040339a1c2SMark Johnston x->d86_imm_bytes += size; 22050339a1c2SMark Johnston #endif 22060339a1c2SMark Johnston } 22070339a1c2SMark Johnston 22080339a1c2SMark Johnston /* 22090339a1c2SMark Johnston * Get an ip relative operand of the given size, with sign extension. 22100339a1c2SMark Johnston */ 22110339a1c2SMark Johnston static void 22120339a1c2SMark Johnston dtrace_disp_opnd(dis86_t *x, int wbit, int size, int opindex) 22130339a1c2SMark Johnston { 22140339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, size, opindex); 22150339a1c2SMark Johnston #ifdef DIS_TEXT 22160339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = MODE_IPREL; 22170339a1c2SMark Johnston #endif 22180339a1c2SMark Johnston } 22190339a1c2SMark Johnston 22200339a1c2SMark Johnston /* 22210339a1c2SMark Johnston * Check to see if there is a segment override prefix pending. 22220339a1c2SMark Johnston * If so, print it in the current 'operand' location and set 22230339a1c2SMark Johnston * the override flag back to false. 22240339a1c2SMark Johnston */ 22250339a1c2SMark Johnston /*ARGSUSED*/ 22260339a1c2SMark Johnston static void 22270339a1c2SMark Johnston dtrace_check_override(dis86_t *x, int opindex) 22280339a1c2SMark Johnston { 22290339a1c2SMark Johnston #ifdef DIS_TEXT 22300339a1c2SMark Johnston if (x->d86_seg_prefix) { 22310339a1c2SMark Johnston (void) strlcat(x->d86_opnd[opindex].d86_prefix, 22320339a1c2SMark Johnston x->d86_seg_prefix, PFIXLEN); 22330339a1c2SMark Johnston } 22340339a1c2SMark Johnston #endif 22350339a1c2SMark Johnston x->d86_seg_prefix = NULL; 22360339a1c2SMark Johnston } 22370339a1c2SMark Johnston 22380339a1c2SMark Johnston 22390339a1c2SMark Johnston /* 22400339a1c2SMark Johnston * Process a single instruction Register or Memory operand. 22410339a1c2SMark Johnston * 22420339a1c2SMark Johnston * mode = addressing mode from ModRM byte 22430339a1c2SMark Johnston * r_m = r_m (or reg if mode == 3) field from ModRM byte 22440339a1c2SMark Johnston * wbit = indicates which register (8bit, 16bit, ... MMX, etc.) set to use. 22450339a1c2SMark Johnston * o = index of operand that we are processing (0, 1 or 2) 22460339a1c2SMark Johnston * 22470339a1c2SMark Johnston * the value of reg or r_m must have already been adjusted for any REX prefix. 22480339a1c2SMark Johnston */ 22490339a1c2SMark Johnston /*ARGSUSED*/ 22500339a1c2SMark Johnston static void 22510339a1c2SMark Johnston dtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex) 22520339a1c2SMark Johnston { 22530339a1c2SMark Johnston int have_SIB = 0; /* flag presence of scale-index-byte */ 22540339a1c2SMark Johnston uint_t ss; /* scale-factor from opcode */ 22550339a1c2SMark Johnston uint_t index; /* index register number */ 22560339a1c2SMark Johnston uint_t base; /* base register number */ 22570339a1c2SMark Johnston int dispsize; /* size of displacement in bytes */ 22580339a1c2SMark Johnston #ifdef DIS_TEXT 22590339a1c2SMark Johnston char *opnd = x->d86_opnd[opindex].d86_opnd; 22600339a1c2SMark Johnston #endif 22610339a1c2SMark Johnston 22620339a1c2SMark Johnston if (x->d86_numopnds < opindex + 1) 22630339a1c2SMark Johnston x->d86_numopnds = opindex + 1; 22640339a1c2SMark Johnston 22650339a1c2SMark Johnston if (x->d86_error) 22660339a1c2SMark Johnston return; 22670339a1c2SMark Johnston 22680339a1c2SMark Johnston /* 22690339a1c2SMark Johnston * first handle a simple register 22700339a1c2SMark Johnston */ 22710339a1c2SMark Johnston if (mode == REG_ONLY) { 22720339a1c2SMark Johnston #ifdef DIS_TEXT 22730339a1c2SMark Johnston switch (wbit) { 22740339a1c2SMark Johnston case MM_OPND: 22750339a1c2SMark Johnston (void) strlcat(opnd, dis_MMREG[r_m], OPLEN); 22760339a1c2SMark Johnston break; 22770339a1c2SMark Johnston case XMM_OPND: 22780339a1c2SMark Johnston (void) strlcat(opnd, dis_XMMREG[r_m], OPLEN); 22790339a1c2SMark Johnston break; 22800339a1c2SMark Johnston case YMM_OPND: 22810339a1c2SMark Johnston (void) strlcat(opnd, dis_YMMREG[r_m], OPLEN); 22820339a1c2SMark Johnston break; 22830339a1c2SMark Johnston case SEG_OPND: 22840339a1c2SMark Johnston (void) strlcat(opnd, dis_SEGREG[r_m], OPLEN); 22850339a1c2SMark Johnston break; 22860339a1c2SMark Johnston case CONTROL_OPND: 22870339a1c2SMark Johnston (void) strlcat(opnd, dis_CONTROLREG[r_m], OPLEN); 22880339a1c2SMark Johnston break; 22890339a1c2SMark Johnston case DEBUG_OPND: 22900339a1c2SMark Johnston (void) strlcat(opnd, dis_DEBUGREG[r_m], OPLEN); 22910339a1c2SMark Johnston break; 22920339a1c2SMark Johnston case TEST_OPND: 22930339a1c2SMark Johnston (void) strlcat(opnd, dis_TESTREG[r_m], OPLEN); 22940339a1c2SMark Johnston break; 22950339a1c2SMark Johnston case BYTE_OPND: 22960339a1c2SMark Johnston if (x->d86_rex_prefix == 0) 22970339a1c2SMark Johnston (void) strlcat(opnd, dis_REG8[r_m], OPLEN); 22980339a1c2SMark Johnston else 22990339a1c2SMark Johnston (void) strlcat(opnd, dis_REG8_REX[r_m], OPLEN); 23000339a1c2SMark Johnston break; 23010339a1c2SMark Johnston case WORD_OPND: 23020339a1c2SMark Johnston (void) strlcat(opnd, dis_REG16[r_m], OPLEN); 23030339a1c2SMark Johnston break; 23040339a1c2SMark Johnston case LONG_OPND: 23050339a1c2SMark Johnston if (x->d86_opnd_size == SIZE16) 23060339a1c2SMark Johnston (void) strlcat(opnd, dis_REG16[r_m], OPLEN); 23070339a1c2SMark Johnston else if (x->d86_opnd_size == SIZE32) 23080339a1c2SMark Johnston (void) strlcat(opnd, dis_REG32[r_m], OPLEN); 23090339a1c2SMark Johnston else 23100339a1c2SMark Johnston (void) strlcat(opnd, dis_REG64[r_m], OPLEN); 23110339a1c2SMark Johnston break; 23120339a1c2SMark Johnston } 23130339a1c2SMark Johnston #endif /* DIS_TEXT */ 23140339a1c2SMark Johnston return; 23150339a1c2SMark Johnston } 23160339a1c2SMark Johnston 23170339a1c2SMark Johnston /* 23180339a1c2SMark Johnston * if symbolic representation, skip override prefix, if any 23190339a1c2SMark Johnston */ 23200339a1c2SMark Johnston dtrace_check_override(x, opindex); 23210339a1c2SMark Johnston 23220339a1c2SMark Johnston /* 23230339a1c2SMark Johnston * Handle 16 bit memory references first, since they decode 23240339a1c2SMark Johnston * the mode values more simply. 23250339a1c2SMark Johnston * mode 1 is r_m + 8 bit displacement 23260339a1c2SMark Johnston * mode 2 is r_m + 16 bit displacement 23270339a1c2SMark Johnston * mode 0 is just r_m, unless r_m is 6 which is 16 bit disp 23280339a1c2SMark Johnston */ 23290339a1c2SMark Johnston if (x->d86_addr_size == SIZE16) { 23300339a1c2SMark Johnston if ((mode == 0 && r_m == 6) || mode == 2) 23310339a1c2SMark Johnston dtrace_imm_opnd(x, WORD_OPND, 2, opindex); 23320339a1c2SMark Johnston else if (mode == 1) 23330339a1c2SMark Johnston dtrace_imm_opnd(x, BYTE_OPND, 1, opindex); 23340339a1c2SMark Johnston #ifdef DIS_TEXT 23350339a1c2SMark Johnston if (mode == 0 && r_m == 6) 23360339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = MODE_SIGNED; 23370339a1c2SMark Johnston else if (mode == 0) 23380339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = MODE_NONE; 23390339a1c2SMark Johnston else 23400339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = MODE_OFFSET; 23410339a1c2SMark Johnston (void) strlcat(opnd, dis_addr16[mode][r_m], OPLEN); 23420339a1c2SMark Johnston #endif 23430339a1c2SMark Johnston return; 23440339a1c2SMark Johnston } 23450339a1c2SMark Johnston 23460339a1c2SMark Johnston /* 23470339a1c2SMark Johnston * 32 and 64 bit addressing modes are more complex since they 23480339a1c2SMark Johnston * can involve an SIB (scaled index and base) byte to decode. 23490339a1c2SMark Johnston */ 23500339a1c2SMark Johnston if (r_m == ESP_REGNO || r_m == ESP_REGNO + 8) { 23510339a1c2SMark Johnston have_SIB = 1; 23520339a1c2SMark Johnston dtrace_get_SIB(x, &ss, &index, &base); 23530339a1c2SMark Johnston if (x->d86_error) 23540339a1c2SMark Johnston return; 23550339a1c2SMark Johnston if (base != 5 || mode != 0) 23560339a1c2SMark Johnston if (x->d86_rex_prefix & REX_B) 23570339a1c2SMark Johnston base += 8; 23580339a1c2SMark Johnston if (x->d86_rex_prefix & REX_X) 23590339a1c2SMark Johnston index += 8; 23600339a1c2SMark Johnston } else { 23610339a1c2SMark Johnston base = r_m; 23620339a1c2SMark Johnston } 23630339a1c2SMark Johnston 23640339a1c2SMark Johnston /* 23650339a1c2SMark Johnston * Compute the displacement size and get its bytes 23660339a1c2SMark Johnston */ 23670339a1c2SMark Johnston dispsize = 0; 23680339a1c2SMark Johnston 23690339a1c2SMark Johnston if (mode == 1) 23700339a1c2SMark Johnston dispsize = 1; 23710339a1c2SMark Johnston else if (mode == 2) 23720339a1c2SMark Johnston dispsize = 4; 23730339a1c2SMark Johnston else if ((r_m & 7) == EBP_REGNO || 23740339a1c2SMark Johnston (have_SIB && (base & 7) == EBP_REGNO)) 23750339a1c2SMark Johnston dispsize = 4; 23760339a1c2SMark Johnston 23770339a1c2SMark Johnston if (dispsize > 0) { 23780339a1c2SMark Johnston dtrace_imm_opnd(x, dispsize == 4 ? LONG_OPND : BYTE_OPND, 23790339a1c2SMark Johnston dispsize, opindex); 23800339a1c2SMark Johnston if (x->d86_error) 23810339a1c2SMark Johnston return; 23820339a1c2SMark Johnston } 23830339a1c2SMark Johnston 23840339a1c2SMark Johnston #ifdef DIS_TEXT 23850339a1c2SMark Johnston if (dispsize > 0) 23860339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = MODE_OFFSET; 23870339a1c2SMark Johnston 23880339a1c2SMark Johnston if (have_SIB == 0) { 23890339a1c2SMark Johnston if (x->d86_mode == SIZE32) { 23900339a1c2SMark Johnston if (mode == 0) 23910339a1c2SMark Johnston (void) strlcat(opnd, dis_addr32_mode0[r_m], 23920339a1c2SMark Johnston OPLEN); 23930339a1c2SMark Johnston else 23940339a1c2SMark Johnston (void) strlcat(opnd, dis_addr32_mode12[r_m], 23950339a1c2SMark Johnston OPLEN); 23960339a1c2SMark Johnston } else { 23970339a1c2SMark Johnston if (mode == 0) { 23980339a1c2SMark Johnston (void) strlcat(opnd, dis_addr64_mode0[r_m], 23990339a1c2SMark Johnston OPLEN); 24000339a1c2SMark Johnston if (r_m == 5) { 24010339a1c2SMark Johnston x->d86_opnd[opindex].d86_mode = 24020339a1c2SMark Johnston MODE_RIPREL; 24030339a1c2SMark Johnston } 24040339a1c2SMark Johnston } else { 24050339a1c2SMark Johnston (void) strlcat(opnd, dis_addr64_mode12[r_m], 24060339a1c2SMark Johnston OPLEN); 24070339a1c2SMark Johnston } 24080339a1c2SMark Johnston } 24090339a1c2SMark Johnston } else { 24100339a1c2SMark Johnston uint_t need_paren = 0; 24110339a1c2SMark Johnston char **regs; 24120339a1c2SMark Johnston if (x->d86_mode == SIZE32) /* NOTE this is not addr_size! */ 24130339a1c2SMark Johnston regs = (char **)dis_REG32; 24140339a1c2SMark Johnston else 24150339a1c2SMark Johnston regs = (char **)dis_REG64; 24160339a1c2SMark Johnston 24170339a1c2SMark Johnston /* 24180339a1c2SMark Johnston * print the base (if any) 24190339a1c2SMark Johnston */ 24200339a1c2SMark Johnston if (base == EBP_REGNO && mode == 0) { 24210339a1c2SMark Johnston if (index != ESP_REGNO) { 24220339a1c2SMark Johnston (void) strlcat(opnd, "(", OPLEN); 24230339a1c2SMark Johnston need_paren = 1; 24240339a1c2SMark Johnston } 24250339a1c2SMark Johnston } else { 24260339a1c2SMark Johnston (void) strlcat(opnd, "(", OPLEN); 24270339a1c2SMark Johnston (void) strlcat(opnd, regs[base], OPLEN); 24280339a1c2SMark Johnston need_paren = 1; 24290339a1c2SMark Johnston } 24300339a1c2SMark Johnston 24310339a1c2SMark Johnston /* 24320339a1c2SMark Johnston * print the index (if any) 24330339a1c2SMark Johnston */ 24340339a1c2SMark Johnston if (index != ESP_REGNO) { 24350339a1c2SMark Johnston (void) strlcat(opnd, ",", OPLEN); 24360339a1c2SMark Johnston (void) strlcat(opnd, regs[index], OPLEN); 24370339a1c2SMark Johnston (void) strlcat(opnd, dis_scale_factor[ss], OPLEN); 24380339a1c2SMark Johnston } else 24390339a1c2SMark Johnston if (need_paren) 24400339a1c2SMark Johnston (void) strlcat(opnd, ")", OPLEN); 24410339a1c2SMark Johnston } 24420339a1c2SMark Johnston #endif 24430339a1c2SMark Johnston } 24440339a1c2SMark Johnston 24450339a1c2SMark Johnston /* 24460339a1c2SMark Johnston * Operand sequence for standard instruction involving one register 24470339a1c2SMark Johnston * and one register/memory operand. 24480339a1c2SMark Johnston * wbit indicates a byte(0) or opnd_size(1) operation 24490339a1c2SMark Johnston * vbit indicates direction (0 for "opcode r,r_m") or (1 for "opcode r_m, r") 24500339a1c2SMark Johnston */ 24510339a1c2SMark Johnston #define STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, vbit) { \ 24520339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); \ 24530339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 24540339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, vbit); \ 24550339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1 - vbit); \ 24560339a1c2SMark Johnston } 24570339a1c2SMark Johnston 24580339a1c2SMark Johnston /* 24590339a1c2SMark Johnston * Similar to above, but allows for the two operands to be of different 24600339a1c2SMark Johnston * classes (ie. wbit). 24610339a1c2SMark Johnston * wbit is for the r_m operand 24620339a1c2SMark Johnston * w2 is for the reg operand 24630339a1c2SMark Johnston */ 24640339a1c2SMark Johnston #define MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, w2, vbit) { \ 24650339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); \ 24660339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 24670339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, vbit); \ 24680339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, w2, 1 - vbit); \ 24690339a1c2SMark Johnston } 24700339a1c2SMark Johnston 24710339a1c2SMark Johnston /* 24720339a1c2SMark Johnston * Similar, but for 2 operands plus an immediate. 24730339a1c2SMark Johnston * vbit indicates direction 24740339a1c2SMark Johnston * 0 for "opcode imm, r, r_m" or 24750339a1c2SMark Johnston * 1 for "opcode imm, r_m, r" 24760339a1c2SMark Johnston */ 24770339a1c2SMark Johnston #define THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize, vbit) { \ 24780339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); \ 24790339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 24800339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 2-vbit); \ 24810339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, w2, 1+vbit); \ 24820339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, immsize, 0); \ 24830339a1c2SMark Johnston } 24840339a1c2SMark Johnston 24850339a1c2SMark Johnston /* 24860339a1c2SMark Johnston * Similar, but for 2 operands plus two immediates. 24870339a1c2SMark Johnston */ 24880339a1c2SMark Johnston #define FOUROPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, immsize) { \ 24890339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); \ 24900339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 24910339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 2); \ 24920339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, w2, 3); \ 24930339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, immsize, 1); \ 24940339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, immsize, 0); \ 24950339a1c2SMark Johnston } 24960339a1c2SMark Johnston 24970339a1c2SMark Johnston /* 24980339a1c2SMark Johnston * 1 operands plus two immediates. 24990339a1c2SMark Johnston */ 25000339a1c2SMark Johnston #define ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, wbit, immsize) { \ 25010339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); \ 25020339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); \ 25030339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 2); \ 25040339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, immsize, 1); \ 25050339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, immsize, 0); \ 25060339a1c2SMark Johnston } 25070339a1c2SMark Johnston 25080339a1c2SMark Johnston /* 25090339a1c2SMark Johnston * Dissassemble a single x86 or amd64 instruction. 25100339a1c2SMark Johnston * 25110339a1c2SMark Johnston * Mode determines the default operating mode (SIZE16, SIZE32 or SIZE64) 25120339a1c2SMark Johnston * for interpreting instructions. 25130339a1c2SMark Johnston * 25140339a1c2SMark Johnston * returns non-zero for bad opcode 25150339a1c2SMark Johnston */ 25160339a1c2SMark Johnston int 25170339a1c2SMark Johnston dtrace_disx86(dis86_t *x, uint_t cpu_mode) 25180339a1c2SMark Johnston { 25190339a1c2SMark Johnston instable_t *dp; /* decode table being used */ 25200339a1c2SMark Johnston #ifdef DIS_TEXT 25210339a1c2SMark Johnston uint_t i; 25220339a1c2SMark Johnston #endif 25230339a1c2SMark Johnston #ifdef DIS_MEM 25240339a1c2SMark Johnston uint_t nomem = 0; 25250339a1c2SMark Johnston #define NOMEM (nomem = 1) 25260339a1c2SMark Johnston #else 25270339a1c2SMark Johnston #define NOMEM /* nothing */ 25280339a1c2SMark Johnston #endif 25290339a1c2SMark Johnston uint_t opnd_size; /* SIZE16, SIZE32 or SIZE64 */ 25300339a1c2SMark Johnston uint_t addr_size; /* SIZE16, SIZE32 or SIZE64 */ 25310339a1c2SMark Johnston uint_t wbit; /* opcode wbit, 0 is 8 bit, !0 for opnd_size */ 25320339a1c2SMark Johnston uint_t w2; /* wbit value for second operand */ 25330339a1c2SMark Johnston uint_t vbit; 25340339a1c2SMark Johnston uint_t mode = 0; /* mode value from ModRM byte */ 25350339a1c2SMark Johnston uint_t reg; /* reg value from ModRM byte */ 25360339a1c2SMark Johnston uint_t r_m; /* r_m value from ModRM byte */ 25370339a1c2SMark Johnston 25380339a1c2SMark Johnston uint_t opcode1; /* high nibble of 1st byte */ 25390339a1c2SMark Johnston uint_t opcode2; /* low nibble of 1st byte */ 25400339a1c2SMark Johnston uint_t opcode3; /* extra opcode bits usually from ModRM byte */ 25410339a1c2SMark Johnston uint_t opcode4; /* high nibble of 2nd byte */ 25420339a1c2SMark Johnston uint_t opcode5; /* low nibble of 2nd byte */ 25430339a1c2SMark Johnston uint_t opcode6; /* high nibble of 3rd byte */ 25440339a1c2SMark Johnston uint_t opcode7; /* low nibble of 3rd byte */ 25450339a1c2SMark Johnston uint_t opcode_bytes = 1; 25460339a1c2SMark Johnston 25470339a1c2SMark Johnston /* 25480339a1c2SMark Johnston * legacy prefixes come in 5 flavors, you should have only one of each 25490339a1c2SMark Johnston */ 25500339a1c2SMark Johnston uint_t opnd_size_prefix = 0; 25510339a1c2SMark Johnston uint_t addr_size_prefix = 0; 25520339a1c2SMark Johnston uint_t segment_prefix = 0; 25530339a1c2SMark Johnston uint_t lock_prefix = 0; 25540339a1c2SMark Johnston uint_t rep_prefix = 0; 25550339a1c2SMark Johnston uint_t rex_prefix = 0; /* amd64 register extension prefix */ 25560339a1c2SMark Johnston 25570339a1c2SMark Johnston /* 25580339a1c2SMark Johnston * Intel VEX instruction encoding prefix and fields 25590339a1c2SMark Johnston */ 25600339a1c2SMark Johnston 25610339a1c2SMark Johnston /* 0xC4 means 3 bytes prefix, 0xC5 means 2 bytes prefix */ 25620339a1c2SMark Johnston uint_t vex_prefix = 0; 25630339a1c2SMark Johnston 25640339a1c2SMark Johnston /* 25650339a1c2SMark Johnston * VEX prefix byte 1, includes vex.r, vex.x and vex.b 25660339a1c2SMark Johnston * (for 3 bytes prefix) 25670339a1c2SMark Johnston */ 25680339a1c2SMark Johnston uint_t vex_byte1 = 0; 25690339a1c2SMark Johnston 25700339a1c2SMark Johnston /* 25710339a1c2SMark Johnston * For 32-bit mode, it should prefetch the next byte to 25720339a1c2SMark Johnston * distinguish between AVX and les/lds 25730339a1c2SMark Johnston */ 25740339a1c2SMark Johnston uint_t vex_prefetch = 0; 25750339a1c2SMark Johnston 25760339a1c2SMark Johnston uint_t vex_m = 0; 25770339a1c2SMark Johnston uint_t vex_v = 0; 25780339a1c2SMark Johnston uint_t vex_p = 0; 25790339a1c2SMark Johnston uint_t vex_R = 1; 25800339a1c2SMark Johnston uint_t vex_X = 1; 25810339a1c2SMark Johnston uint_t vex_B = 1; 25820339a1c2SMark Johnston uint_t vex_W = 0; 25830339a1c2SMark Johnston uint_t vex_L; 25840339a1c2SMark Johnston 25850339a1c2SMark Johnston 25860339a1c2SMark Johnston size_t off; 25870339a1c2SMark Johnston 25880339a1c2SMark Johnston instable_t dp_mmx; 25890339a1c2SMark Johnston 25900339a1c2SMark Johnston x->d86_len = 0; 25910339a1c2SMark Johnston x->d86_rmindex = -1; 25920339a1c2SMark Johnston x->d86_error = 0; 25930339a1c2SMark Johnston #ifdef DIS_TEXT 25940339a1c2SMark Johnston x->d86_numopnds = 0; 25950339a1c2SMark Johnston x->d86_seg_prefix = NULL; 25960339a1c2SMark Johnston x->d86_mnem[0] = 0; 25970339a1c2SMark Johnston for (i = 0; i < 4; ++i) { 25980339a1c2SMark Johnston x->d86_opnd[i].d86_opnd[0] = 0; 25990339a1c2SMark Johnston x->d86_opnd[i].d86_prefix[0] = 0; 26000339a1c2SMark Johnston x->d86_opnd[i].d86_value_size = 0; 26010339a1c2SMark Johnston x->d86_opnd[i].d86_value = 0; 26020339a1c2SMark Johnston x->d86_opnd[i].d86_mode = MODE_NONE; 26030339a1c2SMark Johnston } 26040339a1c2SMark Johnston #endif 26050339a1c2SMark Johnston x->d86_rex_prefix = 0; 26060339a1c2SMark Johnston x->d86_got_modrm = 0; 26070339a1c2SMark Johnston x->d86_memsize = 0; 26080339a1c2SMark Johnston 26090339a1c2SMark Johnston if (cpu_mode == SIZE16) { 26100339a1c2SMark Johnston opnd_size = SIZE16; 26110339a1c2SMark Johnston addr_size = SIZE16; 26120339a1c2SMark Johnston } else if (cpu_mode == SIZE32) { 26130339a1c2SMark Johnston opnd_size = SIZE32; 26140339a1c2SMark Johnston addr_size = SIZE32; 26150339a1c2SMark Johnston } else { 26160339a1c2SMark Johnston opnd_size = SIZE32; 26170339a1c2SMark Johnston addr_size = SIZE64; 26180339a1c2SMark Johnston } 26190339a1c2SMark Johnston 26200339a1c2SMark Johnston /* 26210339a1c2SMark Johnston * Get one opcode byte and check for zero padding that follows 26220339a1c2SMark Johnston * jump tables. 26230339a1c2SMark Johnston */ 26240339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 26250339a1c2SMark Johnston goto error; 26260339a1c2SMark Johnston 26270339a1c2SMark Johnston if (opcode1 == 0 && opcode2 == 0 && 26280339a1c2SMark Johnston x->d86_check_func != NULL && x->d86_check_func(x->d86_data)) { 26290339a1c2SMark Johnston #ifdef DIS_TEXT 26300339a1c2SMark Johnston (void) strncpy(x->d86_mnem, ".byte\t0", OPLEN); 26310339a1c2SMark Johnston #endif 26320339a1c2SMark Johnston goto done; 26330339a1c2SMark Johnston } 26340339a1c2SMark Johnston 26350339a1c2SMark Johnston /* 26360339a1c2SMark Johnston * Gather up legacy x86 prefix bytes. 26370339a1c2SMark Johnston */ 26380339a1c2SMark Johnston for (;;) { 26390339a1c2SMark Johnston uint_t *which_prefix = NULL; 26400339a1c2SMark Johnston 26410339a1c2SMark Johnston dp = (instable_t *)&dis_distable[opcode1][opcode2]; 26420339a1c2SMark Johnston 26430339a1c2SMark Johnston switch (dp->it_adrmode) { 26440339a1c2SMark Johnston case PREFIX: 26450339a1c2SMark Johnston which_prefix = &rep_prefix; 26460339a1c2SMark Johnston break; 26470339a1c2SMark Johnston case LOCK: 26480339a1c2SMark Johnston which_prefix = &lock_prefix; 26490339a1c2SMark Johnston break; 26500339a1c2SMark Johnston case OVERRIDE: 26510339a1c2SMark Johnston which_prefix = &segment_prefix; 26520339a1c2SMark Johnston #ifdef DIS_TEXT 26530339a1c2SMark Johnston x->d86_seg_prefix = (char *)dp->it_name; 26540339a1c2SMark Johnston #endif 26550339a1c2SMark Johnston if (dp->it_invalid64 && cpu_mode == SIZE64) 26560339a1c2SMark Johnston goto error; 26570339a1c2SMark Johnston break; 26580339a1c2SMark Johnston case AM: 26590339a1c2SMark Johnston which_prefix = &addr_size_prefix; 26600339a1c2SMark Johnston break; 26610339a1c2SMark Johnston case DM: 26620339a1c2SMark Johnston which_prefix = &opnd_size_prefix; 26630339a1c2SMark Johnston break; 26640339a1c2SMark Johnston } 26650339a1c2SMark Johnston if (which_prefix == NULL) 26660339a1c2SMark Johnston break; 26670339a1c2SMark Johnston *which_prefix = (opcode1 << 4) | opcode2; 26680339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 26690339a1c2SMark Johnston goto error; 26700339a1c2SMark Johnston } 26710339a1c2SMark Johnston 26720339a1c2SMark Johnston /* 26730339a1c2SMark Johnston * Handle amd64 mode PREFIX values. 26740339a1c2SMark Johnston * Some of the segment prefixes are no-ops. (only FS/GS actually work) 26750339a1c2SMark Johnston * We might have a REX prefix (opcodes 0x40-0x4f) 26760339a1c2SMark Johnston */ 26770339a1c2SMark Johnston if (cpu_mode == SIZE64) { 26780339a1c2SMark Johnston if (segment_prefix != 0x64 && segment_prefix != 0x65) 26790339a1c2SMark Johnston segment_prefix = 0; 26800339a1c2SMark Johnston 26810339a1c2SMark Johnston if (opcode1 == 0x4) { 26820339a1c2SMark Johnston rex_prefix = (opcode1 << 4) | opcode2; 26830339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 26840339a1c2SMark Johnston goto error; 26850339a1c2SMark Johnston dp = (instable_t *)&dis_distable[opcode1][opcode2]; 26860339a1c2SMark Johnston } else if (opcode1 == 0xC && 26870339a1c2SMark Johnston (opcode2 == 0x4 || opcode2 == 0x5)) { 26880339a1c2SMark Johnston /* AVX instructions */ 26890339a1c2SMark Johnston vex_prefix = (opcode1 << 4) | opcode2; 26900339a1c2SMark Johnston x->d86_rex_prefix = 0x40; 26910339a1c2SMark Johnston } 26920339a1c2SMark Johnston } else if (opcode1 == 0xC && (opcode2 == 0x4 || opcode2 == 0x5)) { 26930339a1c2SMark Johnston /* LDS, LES or AVX */ 26940339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 26950339a1c2SMark Johnston vex_prefetch = 1; 26960339a1c2SMark Johnston 26970339a1c2SMark Johnston if (mode == REG_ONLY) { 26980339a1c2SMark Johnston /* AVX */ 26990339a1c2SMark Johnston vex_prefix = (opcode1 << 4) | opcode2; 27000339a1c2SMark Johnston x->d86_rex_prefix = 0x40; 27010339a1c2SMark Johnston opcode3 = (((mode << 3) | reg)>>1) & 0x0F; 27020339a1c2SMark Johnston opcode4 = ((reg << 3) | r_m) & 0x0F; 27030339a1c2SMark Johnston } 27040339a1c2SMark Johnston } 27050339a1c2SMark Johnston 27060339a1c2SMark Johnston if (vex_prefix == VEX_2bytes) { 27070339a1c2SMark Johnston if (!vex_prefetch) { 27080339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode3, &opcode4) != 0) 27090339a1c2SMark Johnston goto error; 27100339a1c2SMark Johnston } 27110339a1c2SMark Johnston vex_R = ((opcode3 & VEX_R) & 0x0F) >> 3; 27120339a1c2SMark Johnston vex_L = ((opcode4 & VEX_L) & 0x0F) >> 2; 27130339a1c2SMark Johnston vex_v = (((opcode3 << 4) | opcode4) & VEX_v) >> 3; 27140339a1c2SMark Johnston vex_p = opcode4 & VEX_p; 27150339a1c2SMark Johnston /* 27160339a1c2SMark Johnston * The vex.x and vex.b bits are not defined in two bytes 27170339a1c2SMark Johnston * mode vex prefix, their default values are 1 27180339a1c2SMark Johnston */ 27190339a1c2SMark Johnston vex_byte1 = (opcode3 & VEX_R) | VEX_X | VEX_B; 27200339a1c2SMark Johnston 27210339a1c2SMark Johnston if (vex_R == 0) 27220339a1c2SMark Johnston x->d86_rex_prefix |= REX_R; 27230339a1c2SMark Johnston 27240339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 27250339a1c2SMark Johnston goto error; 27260339a1c2SMark Johnston 27270339a1c2SMark Johnston switch (vex_p) { 27280339a1c2SMark Johnston case VEX_p_66: 27290339a1c2SMark Johnston dp = (instable_t *) 27300339a1c2SMark Johnston &dis_opAVX660F[(opcode1 << 4) | opcode2]; 27310339a1c2SMark Johnston break; 27320339a1c2SMark Johnston case VEX_p_F3: 27330339a1c2SMark Johnston dp = (instable_t *) 27340339a1c2SMark Johnston &dis_opAVXF30F[(opcode1 << 4) | opcode2]; 27350339a1c2SMark Johnston break; 27360339a1c2SMark Johnston case VEX_p_F2: 27370339a1c2SMark Johnston dp = (instable_t *) 27380339a1c2SMark Johnston &dis_opAVXF20F [(opcode1 << 4) | opcode2]; 27390339a1c2SMark Johnston break; 27400339a1c2SMark Johnston default: 27410339a1c2SMark Johnston dp = (instable_t *) 27420339a1c2SMark Johnston &dis_opAVX0F[opcode1][opcode2]; 27430339a1c2SMark Johnston 27440339a1c2SMark Johnston } 27450339a1c2SMark Johnston 27460339a1c2SMark Johnston } else if (vex_prefix == VEX_3bytes) { 27470339a1c2SMark Johnston if (!vex_prefetch) { 27480339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode3, &opcode4) != 0) 27490339a1c2SMark Johnston goto error; 27500339a1c2SMark Johnston } 27510339a1c2SMark Johnston vex_R = (opcode3 & VEX_R) >> 3; 27520339a1c2SMark Johnston vex_X = (opcode3 & VEX_X) >> 2; 27530339a1c2SMark Johnston vex_B = (opcode3 & VEX_B) >> 1; 27540339a1c2SMark Johnston vex_m = (((opcode3 << 4) | opcode4) & VEX_m); 27550339a1c2SMark Johnston vex_byte1 = opcode3 & (VEX_R | VEX_X | VEX_B); 27560339a1c2SMark Johnston 27570339a1c2SMark Johnston if (vex_R == 0) 27580339a1c2SMark Johnston x->d86_rex_prefix |= REX_R; 27590339a1c2SMark Johnston if (vex_X == 0) 27600339a1c2SMark Johnston x->d86_rex_prefix |= REX_X; 27610339a1c2SMark Johnston if (vex_B == 0) 27620339a1c2SMark Johnston x->d86_rex_prefix |= REX_B; 27630339a1c2SMark Johnston 27640339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode5, &opcode6) != 0) 27650339a1c2SMark Johnston goto error; 27660339a1c2SMark Johnston vex_W = (opcode5 & VEX_W) >> 3; 27670339a1c2SMark Johnston vex_L = (opcode6 & VEX_L) >> 2; 27680339a1c2SMark Johnston vex_v = (((opcode5 << 4) | opcode6) & VEX_v) >> 3; 27690339a1c2SMark Johnston vex_p = opcode6 & VEX_p; 27700339a1c2SMark Johnston 27710339a1c2SMark Johnston if (vex_W) 27720339a1c2SMark Johnston x->d86_rex_prefix |= REX_W; 27730339a1c2SMark Johnston 27740339a1c2SMark Johnston /* Only these three vex_m values valid; others are reserved */ 27750339a1c2SMark Johnston if ((vex_m != VEX_m_0F) && (vex_m != VEX_m_0F38) && 27760339a1c2SMark Johnston (vex_m != VEX_m_0F3A)) 27770339a1c2SMark Johnston goto error; 27780339a1c2SMark Johnston 27790339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode1, &opcode2) != 0) 27800339a1c2SMark Johnston goto error; 27810339a1c2SMark Johnston 27820339a1c2SMark Johnston switch (vex_p) { 27830339a1c2SMark Johnston case VEX_p_66: 27840339a1c2SMark Johnston if (vex_m == VEX_m_0F) { 27850339a1c2SMark Johnston dp = (instable_t *) 27860339a1c2SMark Johnston &dis_opAVX660F 27870339a1c2SMark Johnston [(opcode1 << 4) | opcode2]; 27880339a1c2SMark Johnston } else if (vex_m == VEX_m_0F38) { 27890339a1c2SMark Johnston dp = (instable_t *) 27900339a1c2SMark Johnston &dis_opAVX660F38 27910339a1c2SMark Johnston [(opcode1 << 4) | opcode2]; 27920339a1c2SMark Johnston } else if (vex_m == VEX_m_0F3A) { 27930339a1c2SMark Johnston dp = (instable_t *) 27940339a1c2SMark Johnston &dis_opAVX660F3A 27950339a1c2SMark Johnston [(opcode1 << 4) | opcode2]; 27960339a1c2SMark Johnston } else { 27970339a1c2SMark Johnston goto error; 27980339a1c2SMark Johnston } 27990339a1c2SMark Johnston break; 28000339a1c2SMark Johnston case VEX_p_F3: 28010339a1c2SMark Johnston if (vex_m == VEX_m_0F) { 28020339a1c2SMark Johnston dp = (instable_t *) 28030339a1c2SMark Johnston &dis_opAVXF30F 28040339a1c2SMark Johnston [(opcode1 << 4) | opcode2]; 28050339a1c2SMark Johnston } else { 28060339a1c2SMark Johnston goto error; 28070339a1c2SMark Johnston } 28080339a1c2SMark Johnston break; 28090339a1c2SMark Johnston case VEX_p_F2: 28100339a1c2SMark Johnston if (vex_m == VEX_m_0F) { 28110339a1c2SMark Johnston dp = (instable_t *) 28120339a1c2SMark Johnston &dis_opAVXF20F 28130339a1c2SMark Johnston [(opcode1 << 4) | opcode2]; 28140339a1c2SMark Johnston } else { 28150339a1c2SMark Johnston goto error; 28160339a1c2SMark Johnston } 28170339a1c2SMark Johnston break; 28180339a1c2SMark Johnston default: 28190339a1c2SMark Johnston dp = (instable_t *) 28200339a1c2SMark Johnston &dis_opAVX0F[opcode1][opcode2]; 28210339a1c2SMark Johnston 28220339a1c2SMark Johnston } 28230339a1c2SMark Johnston } 28240339a1c2SMark Johnston if (vex_prefix) { 28250339a1c2SMark Johnston if (vex_L) 28260339a1c2SMark Johnston wbit = YMM_OPND; 28270339a1c2SMark Johnston else 28280339a1c2SMark Johnston wbit = XMM_OPND; 28290339a1c2SMark Johnston } 28300339a1c2SMark Johnston 28310339a1c2SMark Johnston /* 28320339a1c2SMark Johnston * Deal with selection of operand and address size now. 28330339a1c2SMark Johnston * Note that the REX.W bit being set causes opnd_size_prefix to be 28340339a1c2SMark Johnston * ignored. 28350339a1c2SMark Johnston */ 28360339a1c2SMark Johnston if (cpu_mode == SIZE64) { 28370339a1c2SMark Johnston if ((rex_prefix & REX_W) || vex_W) 28380339a1c2SMark Johnston opnd_size = SIZE64; 28390339a1c2SMark Johnston else if (opnd_size_prefix) 28400339a1c2SMark Johnston opnd_size = SIZE16; 28410339a1c2SMark Johnston 28420339a1c2SMark Johnston if (addr_size_prefix) 28430339a1c2SMark Johnston addr_size = SIZE32; 28440339a1c2SMark Johnston } else if (cpu_mode == SIZE32) { 28450339a1c2SMark Johnston if (opnd_size_prefix) 28460339a1c2SMark Johnston opnd_size = SIZE16; 28470339a1c2SMark Johnston if (addr_size_prefix) 28480339a1c2SMark Johnston addr_size = SIZE16; 28490339a1c2SMark Johnston } else { 28500339a1c2SMark Johnston if (opnd_size_prefix) 28510339a1c2SMark Johnston opnd_size = SIZE32; 28520339a1c2SMark Johnston if (addr_size_prefix) 28530339a1c2SMark Johnston addr_size = SIZE32; 28540339a1c2SMark Johnston } 28550339a1c2SMark Johnston /* 28560339a1c2SMark Johnston * The pause instruction - a repz'd nop. This doesn't fit 28570339a1c2SMark Johnston * with any of the other prefix goop added for SSE, so we'll 28580339a1c2SMark Johnston * special-case it here. 28590339a1c2SMark Johnston */ 28600339a1c2SMark Johnston if (rep_prefix == 0xf3 && opcode1 == 0x9 && opcode2 == 0x0) { 28610339a1c2SMark Johnston rep_prefix = 0; 28620339a1c2SMark Johnston dp = (instable_t *)&dis_opPause; 28630339a1c2SMark Johnston } 28640339a1c2SMark Johnston 28650339a1c2SMark Johnston /* 28660339a1c2SMark Johnston * Some 386 instructions have 2 bytes of opcode before the mod_r/m 28670339a1c2SMark Johnston * byte so we may need to perform a table indirection. 28680339a1c2SMark Johnston */ 28690339a1c2SMark Johnston if (dp->it_indirect == (instable_t *)dis_op0F) { 28700339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode4, &opcode5) != 0) 28710339a1c2SMark Johnston goto error; 28720339a1c2SMark Johnston opcode_bytes = 2; 28730339a1c2SMark Johnston if (opcode4 == 0x7 && opcode5 >= 0x1 && opcode5 <= 0x3) { 28740339a1c2SMark Johnston uint_t subcode; 28750339a1c2SMark Johnston 28760339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 28770339a1c2SMark Johnston goto error; 28780339a1c2SMark Johnston opcode_bytes = 3; 28790339a1c2SMark Johnston subcode = ((opcode6 & 0x3) << 1) | 28800339a1c2SMark Johnston ((opcode7 & 0x8) >> 3); 28810339a1c2SMark Johnston dp = (instable_t *)&dis_op0F7123[opcode5][subcode]; 28820339a1c2SMark Johnston } else if ((opcode4 == 0xc) && (opcode5 >= 0x8)) { 28830339a1c2SMark Johnston dp = (instable_t *)&dis_op0FC8[0]; 28840339a1c2SMark Johnston } else if ((opcode4 == 0x3) && (opcode5 == 0xA)) { 28850339a1c2SMark Johnston opcode_bytes = 3; 28860339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 28870339a1c2SMark Johnston goto error; 28880339a1c2SMark Johnston if (opnd_size == SIZE16) 28890339a1c2SMark Johnston opnd_size = SIZE32; 28900339a1c2SMark Johnston 28910339a1c2SMark Johnston dp = (instable_t *)&dis_op0F3A[(opcode6<<4)|opcode7]; 28920339a1c2SMark Johnston #ifdef DIS_TEXT 28930339a1c2SMark Johnston if (strcmp(dp->it_name, "INVALID") == 0) 28940339a1c2SMark Johnston goto error; 28950339a1c2SMark Johnston #endif 28960339a1c2SMark Johnston switch (dp->it_adrmode) { 28970339a1c2SMark Johnston case XMMP_66r: 28980339a1c2SMark Johnston case XMMPRM_66r: 28990339a1c2SMark Johnston case XMM3PM_66r: 29000339a1c2SMark Johnston if (opnd_size_prefix == 0) { 29010339a1c2SMark Johnston goto error; 29020339a1c2SMark Johnston } 29030339a1c2SMark Johnston break; 29040339a1c2SMark Johnston case XMMP_66o: 29050339a1c2SMark Johnston if (opnd_size_prefix == 0) { 29060339a1c2SMark Johnston /* SSSE3 MMX instructions */ 29070339a1c2SMark Johnston dp_mmx = *dp; 29080339a1c2SMark Johnston dp = &dp_mmx; 29090339a1c2SMark Johnston dp->it_adrmode = MMOPM_66o; 29100339a1c2SMark Johnston #ifdef DIS_MEM 29110339a1c2SMark Johnston dp->it_size = 8; 29120339a1c2SMark Johnston #endif 29130339a1c2SMark Johnston } 29140339a1c2SMark Johnston break; 29150339a1c2SMark Johnston default: 29160339a1c2SMark Johnston goto error; 29170339a1c2SMark Johnston } 29180339a1c2SMark Johnston } else if ((opcode4 == 0x3) && (opcode5 == 0x8)) { 29190339a1c2SMark Johnston opcode_bytes = 3; 29200339a1c2SMark Johnston if (dtrace_get_opcode(x, &opcode6, &opcode7) != 0) 29210339a1c2SMark Johnston goto error; 29220339a1c2SMark Johnston dp = (instable_t *)&dis_op0F38[(opcode6<<4)|opcode7]; 29230339a1c2SMark Johnston 29240339a1c2SMark Johnston /* 29250339a1c2SMark Johnston * Both crc32 and movbe have the same 3rd opcode 29260339a1c2SMark Johnston * byte of either 0xF0 or 0xF1, so we use another 29270339a1c2SMark Johnston * indirection to distinguish between the two. 29280339a1c2SMark Johnston */ 29290339a1c2SMark Johnston if (dp->it_indirect == (instable_t *)dis_op0F38F0 || 29300339a1c2SMark Johnston dp->it_indirect == (instable_t *)dis_op0F38F1) { 29310339a1c2SMark Johnston 29320339a1c2SMark Johnston dp = dp->it_indirect; 29330339a1c2SMark Johnston if (rep_prefix != 0xF2) { 29340339a1c2SMark Johnston /* It is movbe */ 29350339a1c2SMark Johnston dp++; 29360339a1c2SMark Johnston } 29370339a1c2SMark Johnston } 29380339a1c2SMark Johnston #ifdef DIS_TEXT 29390339a1c2SMark Johnston if (strcmp(dp->it_name, "INVALID") == 0) 29400339a1c2SMark Johnston goto error; 29410339a1c2SMark Johnston #endif 29420339a1c2SMark Johnston switch (dp->it_adrmode) { 2943c3ddb60eSPeter Grehan case RM_66r: 29440339a1c2SMark Johnston case XMM_66r: 29450339a1c2SMark Johnston case XMMM_66r: 29460339a1c2SMark Johnston if (opnd_size_prefix == 0) { 29470339a1c2SMark Johnston goto error; 29480339a1c2SMark Johnston } 29490339a1c2SMark Johnston break; 29500339a1c2SMark Johnston case XMM_66o: 29510339a1c2SMark Johnston if (opnd_size_prefix == 0) { 29520339a1c2SMark Johnston /* SSSE3 MMX instructions */ 29530339a1c2SMark Johnston dp_mmx = *dp; 29540339a1c2SMark Johnston dp = &dp_mmx; 29550339a1c2SMark Johnston dp->it_adrmode = MM; 29560339a1c2SMark Johnston #ifdef DIS_MEM 29570339a1c2SMark Johnston dp->it_size = 8; 29580339a1c2SMark Johnston #endif 29590339a1c2SMark Johnston } 29600339a1c2SMark Johnston break; 29610339a1c2SMark Johnston case CRC32: 29620339a1c2SMark Johnston if (rep_prefix != 0xF2) { 29630339a1c2SMark Johnston goto error; 29640339a1c2SMark Johnston } 29650339a1c2SMark Johnston rep_prefix = 0; 29660339a1c2SMark Johnston break; 29670339a1c2SMark Johnston case MOVBE: 29680339a1c2SMark Johnston if (rep_prefix != 0x0) { 29690339a1c2SMark Johnston goto error; 29700339a1c2SMark Johnston } 29710339a1c2SMark Johnston break; 29720339a1c2SMark Johnston default: 29730339a1c2SMark Johnston goto error; 29740339a1c2SMark Johnston } 29750339a1c2SMark Johnston } else { 29760339a1c2SMark Johnston dp = (instable_t *)&dis_op0F[opcode4][opcode5]; 29770339a1c2SMark Johnston } 29780339a1c2SMark Johnston } 29790339a1c2SMark Johnston 29800339a1c2SMark Johnston /* 29810339a1c2SMark Johnston * If still not at a TERM decode entry, then a ModRM byte 29820339a1c2SMark Johnston * exists and its fields further decode the instruction. 29830339a1c2SMark Johnston */ 29840339a1c2SMark Johnston x->d86_got_modrm = 0; 29850339a1c2SMark Johnston if (dp->it_indirect != TERM) { 29860339a1c2SMark Johnston dtrace_get_modrm(x, &mode, &opcode3, &r_m); 29870339a1c2SMark Johnston if (x->d86_error) 29880339a1c2SMark Johnston goto error; 29890339a1c2SMark Johnston reg = opcode3; 29900339a1c2SMark Johnston 29910339a1c2SMark Johnston /* 29920339a1c2SMark Johnston * decode 287 instructions (D8-DF) from opcodeN 29930339a1c2SMark Johnston */ 29940339a1c2SMark Johnston if (opcode1 == 0xD && opcode2 >= 0x8) { 29950339a1c2SMark Johnston if (opcode2 == 0xB && mode == 0x3 && opcode3 == 4) 29960339a1c2SMark Johnston dp = (instable_t *)&dis_opFP5[r_m]; 29970339a1c2SMark Johnston else if (opcode2 == 0xA && mode == 0x3 && opcode3 < 4) 29980339a1c2SMark Johnston dp = (instable_t *)&dis_opFP7[opcode3]; 29990339a1c2SMark Johnston else if (opcode2 == 0xB && mode == 0x3) 30000339a1c2SMark Johnston dp = (instable_t *)&dis_opFP6[opcode3]; 30010339a1c2SMark Johnston else if (opcode2 == 0x9 && mode == 0x3 && opcode3 >= 4) 30020339a1c2SMark Johnston dp = (instable_t *)&dis_opFP4[opcode3 - 4][r_m]; 30030339a1c2SMark Johnston else if (mode == 0x3) 30040339a1c2SMark Johnston dp = (instable_t *) 30050339a1c2SMark Johnston &dis_opFP3[opcode2 - 8][opcode3]; 30060339a1c2SMark Johnston else 30070339a1c2SMark Johnston dp = (instable_t *) 30080339a1c2SMark Johnston &dis_opFP1n2[opcode2 - 8][opcode3]; 30090339a1c2SMark Johnston } else { 30100339a1c2SMark Johnston dp = (instable_t *)dp->it_indirect + opcode3; 30110339a1c2SMark Johnston } 30120339a1c2SMark Johnston } 30130339a1c2SMark Johnston 30140339a1c2SMark Johnston /* 30150339a1c2SMark Johnston * In amd64 bit mode, ARPL opcode is changed to MOVSXD 30160339a1c2SMark Johnston * (sign extend 32bit to 64 bit) 30170339a1c2SMark Johnston */ 30180339a1c2SMark Johnston if ((vex_prefix == 0) && cpu_mode == SIZE64 && 30190339a1c2SMark Johnston opcode1 == 0x6 && opcode2 == 0x3) 30200339a1c2SMark Johnston dp = (instable_t *)&dis_opMOVSLD; 30210339a1c2SMark Johnston 30220339a1c2SMark Johnston /* 30230339a1c2SMark Johnston * at this point we should have a correct (or invalid) opcode 30240339a1c2SMark Johnston */ 30250339a1c2SMark Johnston if (cpu_mode == SIZE64 && dp->it_invalid64 || 30260339a1c2SMark Johnston cpu_mode != SIZE64 && dp->it_invalid32) 30270339a1c2SMark Johnston goto error; 30280339a1c2SMark Johnston if (dp->it_indirect != TERM) 30290339a1c2SMark Johnston goto error; 30300339a1c2SMark Johnston 30310339a1c2SMark Johnston /* 30320339a1c2SMark Johnston * deal with MMX/SSE opcodes which are changed by prefixes 30330339a1c2SMark Johnston */ 30340339a1c2SMark Johnston switch (dp->it_adrmode) { 30350339a1c2SMark Johnston case MMO: 30360339a1c2SMark Johnston case MMOIMPL: 30370339a1c2SMark Johnston case MMO3P: 30380339a1c2SMark Johnston case MMOM3: 30390339a1c2SMark Johnston case MMOMS: 30400339a1c2SMark Johnston case MMOPM: 30410339a1c2SMark Johnston case MMOPRM: 30420339a1c2SMark Johnston case MMOS: 30430339a1c2SMark Johnston case XMMO: 30440339a1c2SMark Johnston case XMMOM: 30450339a1c2SMark Johnston case XMMOMS: 30460339a1c2SMark Johnston case XMMOPM: 30470339a1c2SMark Johnston case XMMOS: 30480339a1c2SMark Johnston case XMMOMX: 30490339a1c2SMark Johnston case XMMOX3: 30500339a1c2SMark Johnston case XMMOXMM: 30510339a1c2SMark Johnston /* 30520339a1c2SMark Johnston * This is horrible. Some SIMD instructions take the 30530339a1c2SMark Johnston * form 0x0F 0x?? ..., which is easily decoded using the 30540339a1c2SMark Johnston * existing tables. Other SIMD instructions use various 30550339a1c2SMark Johnston * prefix bytes to overload existing instructions. For 30560339a1c2SMark Johnston * Example, addps is F0, 58, whereas addss is F3 (repz), 30570339a1c2SMark Johnston * F0, 58. Presumably someone got a raise for this. 30580339a1c2SMark Johnston * 30590339a1c2SMark Johnston * If we see one of the instructions which can be 30600339a1c2SMark Johnston * modified in this way (if we've got one of the SIMDO* 30610339a1c2SMark Johnston * address modes), we'll check to see if the last prefix 30620339a1c2SMark Johnston * was a repz. If it was, we strip the prefix from the 30630339a1c2SMark Johnston * mnemonic, and we indirect using the dis_opSIMDrepz 30640339a1c2SMark Johnston * table. 30650339a1c2SMark Johnston */ 30660339a1c2SMark Johnston 30670339a1c2SMark Johnston /* 30680339a1c2SMark Johnston * Calculate our offset in dis_op0F 30690339a1c2SMark Johnston */ 30700339a1c2SMark Johnston if ((uintptr_t)dp - (uintptr_t)dis_op0F > sizeof (dis_op0F)) 30710339a1c2SMark Johnston goto error; 30720339a1c2SMark Johnston 30730339a1c2SMark Johnston off = ((uintptr_t)dp - (uintptr_t)dis_op0F) / 30740339a1c2SMark Johnston sizeof (instable_t); 30750339a1c2SMark Johnston 30760339a1c2SMark Johnston /* 30770339a1c2SMark Johnston * Rewrite if this instruction used one of the magic prefixes. 30780339a1c2SMark Johnston */ 30790339a1c2SMark Johnston if (rep_prefix) { 30800339a1c2SMark Johnston if (rep_prefix == 0xf2) 30810339a1c2SMark Johnston dp = (instable_t *)&dis_opSIMDrepnz[off]; 30820339a1c2SMark Johnston else 30830339a1c2SMark Johnston dp = (instable_t *)&dis_opSIMDrepz[off]; 30840339a1c2SMark Johnston rep_prefix = 0; 30850339a1c2SMark Johnston } else if (opnd_size_prefix) { 30860339a1c2SMark Johnston dp = (instable_t *)&dis_opSIMDdata16[off]; 30870339a1c2SMark Johnston opnd_size_prefix = 0; 30880339a1c2SMark Johnston if (opnd_size == SIZE16) 30890339a1c2SMark Johnston opnd_size = SIZE32; 30900339a1c2SMark Johnston } 30910339a1c2SMark Johnston break; 30920339a1c2SMark Johnston 3093c3ddb60eSPeter Grehan case MG9: 3094c3ddb60eSPeter Grehan /* 3095c3ddb60eSPeter Grehan * More horribleness: the group 9 (0xF0 0xC7) instructions are 3096c3ddb60eSPeter Grehan * allowed an optional prefix of 0x66 or 0xF3. This is similar 3097c3ddb60eSPeter Grehan * to the SIMD business described above, but with a different 3098c3ddb60eSPeter Grehan * addressing mode (and an indirect table), so we deal with it 3099c3ddb60eSPeter Grehan * separately (if similarly). 3100c3ddb60eSPeter Grehan * 3101c3ddb60eSPeter Grehan * Intel further complicated this with the release of Ivy Bridge 3102c3ddb60eSPeter Grehan * where they overloaded these instructions based on the ModR/M 3103c3ddb60eSPeter Grehan * bytes. The VMX instructions have a mode of 0 since they are 3104c3ddb60eSPeter Grehan * memory instructions but rdrand instructions have a mode of 3105c3ddb60eSPeter Grehan * 0b11 (REG_ONLY) because they only operate on registers. While 3106c3ddb60eSPeter Grehan * there are different prefix formats, for now it is sufficient 3107c3ddb60eSPeter Grehan * to use a single different table. 3108c3ddb60eSPeter Grehan */ 3109c3ddb60eSPeter Grehan 3110c3ddb60eSPeter Grehan /* 3111c3ddb60eSPeter Grehan * Calculate our offset in dis_op0FC7 (the group 9 table) 3112c3ddb60eSPeter Grehan */ 3113c3ddb60eSPeter Grehan if ((uintptr_t)dp - (uintptr_t)dis_op0FC7 > sizeof (dis_op0FC7)) 3114c3ddb60eSPeter Grehan goto error; 3115c3ddb60eSPeter Grehan 3116c3ddb60eSPeter Grehan off = ((uintptr_t)dp - (uintptr_t)dis_op0FC7) / 3117c3ddb60eSPeter Grehan sizeof (instable_t); 3118c3ddb60eSPeter Grehan 3119c3ddb60eSPeter Grehan /* 3120c3ddb60eSPeter Grehan * If we have a mode of 0b11 then we have to rewrite this. 3121c3ddb60eSPeter Grehan */ 3122c3ddb60eSPeter Grehan dtrace_get_modrm(x, &mode, ®, &r_m); 3123c3ddb60eSPeter Grehan if (mode == REG_ONLY) { 3124c3ddb60eSPeter Grehan dp = (instable_t *)&dis_op0FC7m3[off]; 3125c3ddb60eSPeter Grehan break; 3126c3ddb60eSPeter Grehan } 3127c3ddb60eSPeter Grehan 3128c3ddb60eSPeter Grehan /* 3129c3ddb60eSPeter Grehan * Rewrite if this instruction used one of the magic prefixes. 3130c3ddb60eSPeter Grehan */ 3131c3ddb60eSPeter Grehan if (rep_prefix) { 3132c3ddb60eSPeter Grehan if (rep_prefix == 0xf3) 3133c3ddb60eSPeter Grehan dp = (instable_t *)&dis_opF30FC7[off]; 3134c3ddb60eSPeter Grehan else 3135c3ddb60eSPeter Grehan goto error; 3136c3ddb60eSPeter Grehan rep_prefix = 0; 3137c3ddb60eSPeter Grehan } else if (opnd_size_prefix) { 3138c3ddb60eSPeter Grehan dp = (instable_t *)&dis_op660FC7[off]; 3139c3ddb60eSPeter Grehan opnd_size_prefix = 0; 3140c3ddb60eSPeter Grehan if (opnd_size == SIZE16) 3141c3ddb60eSPeter Grehan opnd_size = SIZE32; 3142c3ddb60eSPeter Grehan } 3143c3ddb60eSPeter Grehan break; 3144c3ddb60eSPeter Grehan 3145c3ddb60eSPeter Grehan 31460339a1c2SMark Johnston case MMOSH: 31470339a1c2SMark Johnston /* 31480339a1c2SMark Johnston * As with the "normal" SIMD instructions, the MMX 31490339a1c2SMark Johnston * shuffle instructions are overloaded. These 31500339a1c2SMark Johnston * instructions, however, are special in that they use 31510339a1c2SMark Johnston * an extra byte, and thus an extra table. As of this 31520339a1c2SMark Johnston * writing, they only use the opnd_size prefix. 31530339a1c2SMark Johnston */ 31540339a1c2SMark Johnston 31550339a1c2SMark Johnston /* 31560339a1c2SMark Johnston * Calculate our offset in dis_op0F7123 31570339a1c2SMark Johnston */ 31580339a1c2SMark Johnston if ((uintptr_t)dp - (uintptr_t)dis_op0F7123 > 31590339a1c2SMark Johnston sizeof (dis_op0F7123)) 31600339a1c2SMark Johnston goto error; 31610339a1c2SMark Johnston 31620339a1c2SMark Johnston if (opnd_size_prefix) { 31630339a1c2SMark Johnston off = ((uintptr_t)dp - (uintptr_t)dis_op0F7123) / 31640339a1c2SMark Johnston sizeof (instable_t); 31650339a1c2SMark Johnston dp = (instable_t *)&dis_opSIMD7123[off]; 31660339a1c2SMark Johnston opnd_size_prefix = 0; 31670339a1c2SMark Johnston if (opnd_size == SIZE16) 31680339a1c2SMark Johnston opnd_size = SIZE32; 31690339a1c2SMark Johnston } 31700339a1c2SMark Johnston break; 31710339a1c2SMark Johnston case MRw: 31720339a1c2SMark Johnston if (rep_prefix) { 31730339a1c2SMark Johnston if (rep_prefix == 0xf3) { 31740339a1c2SMark Johnston 31750339a1c2SMark Johnston /* 31760339a1c2SMark Johnston * Calculate our offset in dis_op0F 31770339a1c2SMark Johnston */ 31780339a1c2SMark Johnston if ((uintptr_t)dp - (uintptr_t)dis_op0F 31790339a1c2SMark Johnston > sizeof (dis_op0F)) 31800339a1c2SMark Johnston goto error; 31810339a1c2SMark Johnston 31820339a1c2SMark Johnston off = ((uintptr_t)dp - (uintptr_t)dis_op0F) / 31830339a1c2SMark Johnston sizeof (instable_t); 31840339a1c2SMark Johnston 31850339a1c2SMark Johnston dp = (instable_t *)&dis_opSIMDrepz[off]; 31860339a1c2SMark Johnston rep_prefix = 0; 31870339a1c2SMark Johnston } else { 31880339a1c2SMark Johnston goto error; 31890339a1c2SMark Johnston } 31900339a1c2SMark Johnston } 31910339a1c2SMark Johnston break; 31920339a1c2SMark Johnston } 31930339a1c2SMark Johnston 31940339a1c2SMark Johnston /* 31950339a1c2SMark Johnston * In 64 bit mode, some opcodes automatically use opnd_size == SIZE64. 31960339a1c2SMark Johnston */ 31970339a1c2SMark Johnston if (cpu_mode == SIZE64) 31980339a1c2SMark Johnston if (dp->it_always64 || (opnd_size == SIZE32 && dp->it_stackop)) 31990339a1c2SMark Johnston opnd_size = SIZE64; 32000339a1c2SMark Johnston 32010339a1c2SMark Johnston #ifdef DIS_TEXT 32020339a1c2SMark Johnston /* 32030339a1c2SMark Johnston * At this point most instructions can format the opcode mnemonic 32040339a1c2SMark Johnston * including the prefixes. 32050339a1c2SMark Johnston */ 32060339a1c2SMark Johnston if (lock_prefix) 32070339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "lock ", OPLEN); 32080339a1c2SMark Johnston 32090339a1c2SMark Johnston if (rep_prefix == 0xf2) 32100339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "repnz ", OPLEN); 32110339a1c2SMark Johnston else if (rep_prefix == 0xf3) 32120339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "repz ", OPLEN); 32130339a1c2SMark Johnston 32140339a1c2SMark Johnston if (cpu_mode == SIZE64 && addr_size_prefix) 32150339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "addr32 ", OPLEN); 32160339a1c2SMark Johnston 32170339a1c2SMark Johnston if (dp->it_adrmode != CBW && 32180339a1c2SMark Johnston dp->it_adrmode != CWD && 32190339a1c2SMark Johnston dp->it_adrmode != XMMSFNC) { 32200339a1c2SMark Johnston if (strcmp(dp->it_name, "INVALID") == 0) 32210339a1c2SMark Johnston goto error; 32220339a1c2SMark Johnston (void) strlcat(x->d86_mnem, dp->it_name, OPLEN); 32230339a1c2SMark Johnston if (dp->it_suffix) { 32240339a1c2SMark Johnston char *types[] = {"", "w", "l", "q"}; 32250339a1c2SMark Johnston if (opcode_bytes == 2 && opcode4 == 4) { 32260339a1c2SMark Johnston /* It's a cmovx.yy. Replace the suffix x */ 32270339a1c2SMark Johnston for (i = 5; i < OPLEN; i++) { 32280339a1c2SMark Johnston if (x->d86_mnem[i] == '.') 32290339a1c2SMark Johnston break; 32300339a1c2SMark Johnston } 32310339a1c2SMark Johnston x->d86_mnem[i - 1] = *types[opnd_size]; 32320339a1c2SMark Johnston } else if ((opnd_size == 2) && (opcode_bytes == 3) && 32330339a1c2SMark Johnston ((opcode6 == 1 && opcode7 == 6) || 32340339a1c2SMark Johnston (opcode6 == 2 && opcode7 == 2))) { 32350339a1c2SMark Johnston /* 32360339a1c2SMark Johnston * To handle PINSRD and PEXTRD 32370339a1c2SMark Johnston */ 32380339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "d", OPLEN); 32390339a1c2SMark Johnston } else { 32400339a1c2SMark Johnston (void) strlcat(x->d86_mnem, types[opnd_size], 32410339a1c2SMark Johnston OPLEN); 32420339a1c2SMark Johnston } 32430339a1c2SMark Johnston } 32440339a1c2SMark Johnston } 32450339a1c2SMark Johnston #endif 32460339a1c2SMark Johnston 32470339a1c2SMark Johnston /* 32480339a1c2SMark Johnston * Process operands based on the addressing modes. 32490339a1c2SMark Johnston */ 32500339a1c2SMark Johnston x->d86_mode = cpu_mode; 32510339a1c2SMark Johnston /* 32520339a1c2SMark Johnston * In vex mode the rex_prefix has no meaning 32530339a1c2SMark Johnston */ 32540339a1c2SMark Johnston if (!vex_prefix) 32550339a1c2SMark Johnston x->d86_rex_prefix = rex_prefix; 32560339a1c2SMark Johnston x->d86_opnd_size = opnd_size; 32570339a1c2SMark Johnston x->d86_addr_size = addr_size; 32580339a1c2SMark Johnston vbit = 0; /* initialize for mem/reg -> reg */ 32590339a1c2SMark Johnston switch (dp->it_adrmode) { 32600339a1c2SMark Johnston /* 32610339a1c2SMark Johnston * amd64 instruction to sign extend 32 bit reg/mem operands 32620339a1c2SMark Johnston * into 64 bit register values 32630339a1c2SMark Johnston */ 32640339a1c2SMark Johnston case MOVSXZ: 32650339a1c2SMark Johnston #ifdef DIS_TEXT 32660339a1c2SMark Johnston if (rex_prefix == 0) 32670339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "movzld", OPLEN); 32680339a1c2SMark Johnston #endif 32690339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 32700339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 32710339a1c2SMark Johnston x->d86_opnd_size = SIZE64; 32720339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 32730339a1c2SMark Johnston x->d86_opnd_size = opnd_size = SIZE32; 32740339a1c2SMark Johnston wbit = LONG_OPND; 32750339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 32760339a1c2SMark Johnston break; 32770339a1c2SMark Johnston 32780339a1c2SMark Johnston /* 32790339a1c2SMark Johnston * movsbl movsbw movsbq (0x0FBE) or movswl movswq (0x0FBF) 32800339a1c2SMark Johnston * movzbl movzbw movzbq (0x0FB6) or movzwl movzwq (0x0FB7) 32810339a1c2SMark Johnston * wbit lives in 2nd byte, note that operands 32820339a1c2SMark Johnston * are different sized 32830339a1c2SMark Johnston */ 32840339a1c2SMark Johnston case MOVZ: 32850339a1c2SMark Johnston if (rex_prefix & REX_W) { 32860339a1c2SMark Johnston /* target register size = 64 bit */ 32870339a1c2SMark Johnston x->d86_mnem[5] = 'q'; 32880339a1c2SMark Johnston } 32890339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 32900339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 32910339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 32920339a1c2SMark Johnston x->d86_opnd_size = opnd_size = SIZE16; 32930339a1c2SMark Johnston wbit = WBIT(opcode5); 32940339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 32950339a1c2SMark Johnston break; 32960339a1c2SMark Johnston case CRC32: 32970339a1c2SMark Johnston opnd_size = SIZE32; 32980339a1c2SMark Johnston if (rex_prefix & REX_W) 32990339a1c2SMark Johnston opnd_size = SIZE64; 33000339a1c2SMark Johnston x->d86_opnd_size = opnd_size; 33010339a1c2SMark Johnston 33020339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 33030339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 33040339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 33050339a1c2SMark Johnston wbit = WBIT(opcode7); 33060339a1c2SMark Johnston if (opnd_size_prefix) 33070339a1c2SMark Johnston x->d86_opnd_size = opnd_size = SIZE16; 33080339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 33090339a1c2SMark Johnston break; 33100339a1c2SMark Johnston case MOVBE: 33110339a1c2SMark Johnston opnd_size = SIZE32; 33120339a1c2SMark Johnston if (rex_prefix & REX_W) 33130339a1c2SMark Johnston opnd_size = SIZE64; 33140339a1c2SMark Johnston x->d86_opnd_size = opnd_size; 33150339a1c2SMark Johnston 33160339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 33170339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 33180339a1c2SMark Johnston wbit = WBIT(opcode7); 33190339a1c2SMark Johnston if (opnd_size_prefix) 33200339a1c2SMark Johnston x->d86_opnd_size = opnd_size = SIZE16; 33210339a1c2SMark Johnston if (wbit) { 33220339a1c2SMark Johnston /* reg -> mem */ 33230339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 33240339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 33250339a1c2SMark Johnston } else { 33260339a1c2SMark Johnston /* mem -> reg */ 33270339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 33280339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 33290339a1c2SMark Johnston } 33300339a1c2SMark Johnston break; 33310339a1c2SMark Johnston 33320339a1c2SMark Johnston /* 33330339a1c2SMark Johnston * imul instruction, with either 8-bit or longer immediate 33340339a1c2SMark Johnston * opcode 0x6B for byte, sign-extended displacement, 0x69 for word(s) 33350339a1c2SMark Johnston */ 33360339a1c2SMark Johnston case IMUL: 33370339a1c2SMark Johnston wbit = LONG_OPND; 33380339a1c2SMark Johnston THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 33390339a1c2SMark Johnston OPSIZE(opnd_size, opcode2 == 0x9), 1); 33400339a1c2SMark Johnston break; 33410339a1c2SMark Johnston 33420339a1c2SMark Johnston /* memory or register operand to register, with 'w' bit */ 33430339a1c2SMark Johnston case MRw: 33440339a1c2SMark Johnston wbit = WBIT(opcode2); 33450339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 33460339a1c2SMark Johnston break; 33470339a1c2SMark Johnston 33480339a1c2SMark Johnston /* register to memory or register operand, with 'w' bit */ 33490339a1c2SMark Johnston /* arpl happens to fit here also because it is odd */ 33500339a1c2SMark Johnston case RMw: 33510339a1c2SMark Johnston if (opcode_bytes == 2) 33520339a1c2SMark Johnston wbit = WBIT(opcode5); 33530339a1c2SMark Johnston else 33540339a1c2SMark Johnston wbit = WBIT(opcode2); 33550339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 33560339a1c2SMark Johnston break; 33570339a1c2SMark Johnston 33580339a1c2SMark Johnston /* xaddb instruction */ 33590339a1c2SMark Johnston case XADDB: 33600339a1c2SMark Johnston wbit = 0; 33610339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 33620339a1c2SMark Johnston break; 33630339a1c2SMark Johnston 33640339a1c2SMark Johnston /* MMX register to memory or register operand */ 33650339a1c2SMark Johnston case MMS: 33660339a1c2SMark Johnston case MMOS: 33670339a1c2SMark Johnston #ifdef DIS_TEXT 33680339a1c2SMark Johnston wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 33690339a1c2SMark Johnston #else 33700339a1c2SMark Johnston wbit = LONG_OPND; 33710339a1c2SMark Johnston #endif 33720339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1); 33730339a1c2SMark Johnston break; 33740339a1c2SMark Johnston 33750339a1c2SMark Johnston /* MMX register to memory */ 33760339a1c2SMark Johnston case MMOMS: 33770339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 33780339a1c2SMark Johnston if (mode == REG_ONLY) 33790339a1c2SMark Johnston goto error; 33800339a1c2SMark Johnston wbit = MM_OPND; 33810339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 1); 33820339a1c2SMark Johnston break; 33830339a1c2SMark Johnston 33840339a1c2SMark Johnston /* Double shift. Has immediate operand specifying the shift. */ 33850339a1c2SMark Johnston case DSHIFT: 33860339a1c2SMark Johnston wbit = LONG_OPND; 33870339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 33880339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 33890339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 2); 33900339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 33910339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 33920339a1c2SMark Johnston break; 33930339a1c2SMark Johnston 33940339a1c2SMark Johnston /* 33950339a1c2SMark Johnston * Double shift. With no immediate operand, specifies using %cl. 33960339a1c2SMark Johnston */ 33970339a1c2SMark Johnston case DSHIFTcl: 33980339a1c2SMark Johnston wbit = LONG_OPND; 33990339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 34000339a1c2SMark Johnston break; 34010339a1c2SMark Johnston 34020339a1c2SMark Johnston /* immediate to memory or register operand */ 34030339a1c2SMark Johnston case IMlw: 34040339a1c2SMark Johnston wbit = WBIT(opcode2); 34050339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 34060339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 34070339a1c2SMark Johnston /* 34080339a1c2SMark Johnston * Have long immediate for opcode 0x81, but not 0x80 nor 0x83 34090339a1c2SMark Johnston */ 34100339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, opcode2 == 1), 0); 34110339a1c2SMark Johnston break; 34120339a1c2SMark Johnston 34130339a1c2SMark Johnston /* immediate to memory or register operand with the */ 34140339a1c2SMark Johnston /* 'w' bit present */ 34150339a1c2SMark Johnston case IMw: 34160339a1c2SMark Johnston wbit = WBIT(opcode2); 34170339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 34180339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 34190339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 34200339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0); 34210339a1c2SMark Johnston break; 34220339a1c2SMark Johnston 34230339a1c2SMark Johnston /* immediate to register with register in low 3 bits */ 34240339a1c2SMark Johnston /* of op code */ 34250339a1c2SMark Johnston case IR: 34260339a1c2SMark Johnston /* w-bit here (with regs) is bit 3 */ 34270339a1c2SMark Johnston wbit = opcode2 >>3 & 0x1; 34280339a1c2SMark Johnston reg = REGNO(opcode2); 34290339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 34300339a1c2SMark Johnston mode = REG_ONLY; 34310339a1c2SMark Johnston r_m = reg; 34320339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 34330339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE64(opnd_size, wbit), 0); 34340339a1c2SMark Johnston break; 34350339a1c2SMark Johnston 34360339a1c2SMark Johnston /* MMX immediate shift of register */ 34370339a1c2SMark Johnston case MMSH: 34380339a1c2SMark Johnston case MMOSH: 34390339a1c2SMark Johnston wbit = MM_OPND; 34400339a1c2SMark Johnston goto mm_shift; /* in next case */ 34410339a1c2SMark Johnston 34420339a1c2SMark Johnston /* SIMD immediate shift of register */ 34430339a1c2SMark Johnston case XMMSH: 34440339a1c2SMark Johnston wbit = XMM_OPND; 34450339a1c2SMark Johnston mm_shift: 34460339a1c2SMark Johnston reg = REGNO(opcode7); 34470339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 34480339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 34490339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 34500339a1c2SMark Johnston NOMEM; 34510339a1c2SMark Johnston break; 34520339a1c2SMark Johnston 34530339a1c2SMark Johnston /* accumulator to memory operand */ 34540339a1c2SMark Johnston case AO: 34550339a1c2SMark Johnston vbit = 1; 34560339a1c2SMark Johnston /*FALLTHROUGH*/ 34570339a1c2SMark Johnston 34580339a1c2SMark Johnston /* memory operand to accumulator */ 34590339a1c2SMark Johnston case OA: 34600339a1c2SMark Johnston wbit = WBIT(opcode2); 34610339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1 - vbit); 34620339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE64(addr_size, LONG_OPND), vbit); 34630339a1c2SMark Johnston #ifdef DIS_TEXT 34640339a1c2SMark Johnston x->d86_opnd[vbit].d86_mode = MODE_OFFSET; 34650339a1c2SMark Johnston #endif 34660339a1c2SMark Johnston break; 34670339a1c2SMark Johnston 34680339a1c2SMark Johnston 34690339a1c2SMark Johnston /* segment register to memory or register operand */ 34700339a1c2SMark Johnston case SM: 34710339a1c2SMark Johnston vbit = 1; 34720339a1c2SMark Johnston /*FALLTHROUGH*/ 34730339a1c2SMark Johnston 34740339a1c2SMark Johnston /* memory or register operand to segment register */ 34750339a1c2SMark Johnston case MS: 34760339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 34770339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 34780339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, vbit); 34790339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 1 - vbit); 34800339a1c2SMark Johnston break; 34810339a1c2SMark Johnston 34820339a1c2SMark Johnston /* 34830339a1c2SMark Johnston * rotate or shift instructions, which may shift by 1 or 34840339a1c2SMark Johnston * consult the cl register, depending on the 'v' bit 34850339a1c2SMark Johnston */ 34860339a1c2SMark Johnston case Mv: 34870339a1c2SMark Johnston vbit = VBIT(opcode2); 34880339a1c2SMark Johnston wbit = WBIT(opcode2); 34890339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 34900339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 34910339a1c2SMark Johnston #ifdef DIS_TEXT 34920339a1c2SMark Johnston if (vbit) { 34930339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "%cl", OPLEN); 34940339a1c2SMark Johnston } else { 34950339a1c2SMark Johnston x->d86_opnd[0].d86_mode = MODE_SIGNED; 34960339a1c2SMark Johnston x->d86_opnd[0].d86_value_size = 1; 34970339a1c2SMark Johnston x->d86_opnd[0].d86_value = 1; 34980339a1c2SMark Johnston } 34990339a1c2SMark Johnston #endif 35000339a1c2SMark Johnston break; 35010339a1c2SMark Johnston /* 35020339a1c2SMark Johnston * immediate rotate or shift instructions 35030339a1c2SMark Johnston */ 35040339a1c2SMark Johnston case MvI: 35050339a1c2SMark Johnston wbit = WBIT(opcode2); 35060339a1c2SMark Johnston normal_imm_mem: 35070339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 35080339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 35090339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 35100339a1c2SMark Johnston break; 35110339a1c2SMark Johnston 35120339a1c2SMark Johnston /* bit test instructions */ 35130339a1c2SMark Johnston case MIb: 35140339a1c2SMark Johnston wbit = LONG_OPND; 35150339a1c2SMark Johnston goto normal_imm_mem; 35160339a1c2SMark Johnston 35170339a1c2SMark Johnston /* single memory or register operand with 'w' bit present */ 35180339a1c2SMark Johnston case Mw: 35190339a1c2SMark Johnston wbit = WBIT(opcode2); 35200339a1c2SMark Johnston just_mem: 35210339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 35220339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 35230339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 35240339a1c2SMark Johnston break; 35250339a1c2SMark Johnston 3526c3ddb60eSPeter Grehan case SWAPGS_RDTSCP: 35270339a1c2SMark Johnston if (cpu_mode == SIZE64 && mode == 3 && r_m == 0) { 35280339a1c2SMark Johnston #ifdef DIS_TEXT 35290339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "swapgs", OPLEN); 35300339a1c2SMark Johnston #endif 35310339a1c2SMark Johnston NOMEM; 35320339a1c2SMark Johnston break; 3533c3ddb60eSPeter Grehan } else if (mode == 3 && r_m == 1) { 3534c3ddb60eSPeter Grehan #ifdef DIS_TEXT 3535c3ddb60eSPeter Grehan (void) strncpy(x->d86_mnem, "rdtscp", OPLEN); 3536c3ddb60eSPeter Grehan #endif 3537c3ddb60eSPeter Grehan NOMEM; 3538c3ddb60eSPeter Grehan break; 35390339a1c2SMark Johnston } 3540c3ddb60eSPeter Grehan 35410339a1c2SMark Johnston /*FALLTHROUGH*/ 35420339a1c2SMark Johnston 35430339a1c2SMark Johnston /* prefetch instruction - memory operand, but no memory acess */ 35440339a1c2SMark Johnston case PREF: 35450339a1c2SMark Johnston NOMEM; 35460339a1c2SMark Johnston /*FALLTHROUGH*/ 35470339a1c2SMark Johnston 35480339a1c2SMark Johnston /* single memory or register operand */ 35490339a1c2SMark Johnston case M: 3550c3ddb60eSPeter Grehan case MG9: 35510339a1c2SMark Johnston wbit = LONG_OPND; 35520339a1c2SMark Johnston goto just_mem; 35530339a1c2SMark Johnston 35540339a1c2SMark Johnston /* single memory or register byte operand */ 35550339a1c2SMark Johnston case Mb: 35560339a1c2SMark Johnston wbit = BYTE_OPND; 35570339a1c2SMark Johnston goto just_mem; 35580339a1c2SMark Johnston 3559c3ddb60eSPeter Grehan case VMx: 3560c3ddb60eSPeter Grehan if (mode == 3) { 3561c3ddb60eSPeter Grehan #ifdef DIS_TEXT 3562c3ddb60eSPeter Grehan char *vminstr; 3563c3ddb60eSPeter Grehan 3564c3ddb60eSPeter Grehan switch (r_m) { 3565c3ddb60eSPeter Grehan case 1: 3566c3ddb60eSPeter Grehan vminstr = "vmcall"; 3567c3ddb60eSPeter Grehan break; 3568c3ddb60eSPeter Grehan case 2: 3569c3ddb60eSPeter Grehan vminstr = "vmlaunch"; 3570c3ddb60eSPeter Grehan break; 3571c3ddb60eSPeter Grehan case 3: 3572c3ddb60eSPeter Grehan vminstr = "vmresume"; 3573c3ddb60eSPeter Grehan break; 3574c3ddb60eSPeter Grehan case 4: 3575c3ddb60eSPeter Grehan vminstr = "vmxoff"; 3576c3ddb60eSPeter Grehan break; 3577c3ddb60eSPeter Grehan default: 3578c3ddb60eSPeter Grehan goto error; 3579c3ddb60eSPeter Grehan } 3580c3ddb60eSPeter Grehan 3581c3ddb60eSPeter Grehan (void) strncpy(x->d86_mnem, vminstr, OPLEN); 3582c3ddb60eSPeter Grehan #else 3583c3ddb60eSPeter Grehan if (r_m < 1 || r_m > 4) 3584c3ddb60eSPeter Grehan goto error; 3585c3ddb60eSPeter Grehan #endif 3586c3ddb60eSPeter Grehan 3587c3ddb60eSPeter Grehan NOMEM; 3588c3ddb60eSPeter Grehan break; 3589c3ddb60eSPeter Grehan } 3590c3ddb60eSPeter Grehan /*FALLTHROUGH*/ 3591c3ddb60eSPeter Grehan case SVM: 3592c3ddb60eSPeter Grehan if (mode == 3) { 3593c3ddb60eSPeter Grehan #ifdef DIS_TEXT 3594c3ddb60eSPeter Grehan char *vinstr; 3595c3ddb60eSPeter Grehan 3596c3ddb60eSPeter Grehan switch (r_m) { 3597c3ddb60eSPeter Grehan case 0: 3598c3ddb60eSPeter Grehan vinstr = "vmrun"; 3599c3ddb60eSPeter Grehan break; 3600c3ddb60eSPeter Grehan case 1: 3601c3ddb60eSPeter Grehan vinstr = "vmmcall"; 3602c3ddb60eSPeter Grehan break; 3603c3ddb60eSPeter Grehan case 2: 3604c3ddb60eSPeter Grehan vinstr = "vmload"; 3605c3ddb60eSPeter Grehan break; 3606c3ddb60eSPeter Grehan case 3: 3607c3ddb60eSPeter Grehan vinstr = "vmsave"; 3608c3ddb60eSPeter Grehan break; 3609c3ddb60eSPeter Grehan case 4: 3610c3ddb60eSPeter Grehan vinstr = "stgi"; 3611c3ddb60eSPeter Grehan break; 3612c3ddb60eSPeter Grehan case 5: 3613c3ddb60eSPeter Grehan vinstr = "clgi"; 3614c3ddb60eSPeter Grehan break; 3615c3ddb60eSPeter Grehan case 6: 3616c3ddb60eSPeter Grehan vinstr = "skinit"; 3617c3ddb60eSPeter Grehan break; 3618c3ddb60eSPeter Grehan case 7: 3619c3ddb60eSPeter Grehan vinstr = "invlpga"; 3620c3ddb60eSPeter Grehan break; 3621c3ddb60eSPeter Grehan } 3622c3ddb60eSPeter Grehan 3623c3ddb60eSPeter Grehan (void) strncpy(x->d86_mnem, vinstr, OPLEN); 3624c3ddb60eSPeter Grehan #endif 3625c3ddb60eSPeter Grehan NOMEM; 3626c3ddb60eSPeter Grehan break; 3627c3ddb60eSPeter Grehan } 3628c3ddb60eSPeter Grehan /*FALLTHROUGH*/ 36290339a1c2SMark Johnston case MONITOR_MWAIT: 36300339a1c2SMark Johnston if (mode == 3) { 36310339a1c2SMark Johnston if (r_m == 0) { 36320339a1c2SMark Johnston #ifdef DIS_TEXT 36330339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "monitor", OPLEN); 36340339a1c2SMark Johnston #endif 36350339a1c2SMark Johnston NOMEM; 36360339a1c2SMark Johnston break; 36370339a1c2SMark Johnston } else if (r_m == 1) { 36380339a1c2SMark Johnston #ifdef DIS_TEXT 36390339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "mwait", OPLEN); 36400339a1c2SMark Johnston #endif 36410339a1c2SMark Johnston NOMEM; 36420339a1c2SMark Johnston break; 36430339a1c2SMark Johnston } else { 36440339a1c2SMark Johnston goto error; 36450339a1c2SMark Johnston } 36460339a1c2SMark Johnston } 36470339a1c2SMark Johnston /*FALLTHROUGH*/ 36480339a1c2SMark Johnston case XGETBV_XSETBV: 36490339a1c2SMark Johnston if (mode == 3) { 36500339a1c2SMark Johnston if (r_m == 0) { 36510339a1c2SMark Johnston #ifdef DIS_TEXT 36520339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "xgetbv", OPLEN); 36530339a1c2SMark Johnston #endif 36540339a1c2SMark Johnston NOMEM; 36550339a1c2SMark Johnston break; 36560339a1c2SMark Johnston } else if (r_m == 1) { 36570339a1c2SMark Johnston #ifdef DIS_TEXT 36580339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "xsetbv", OPLEN); 36590339a1c2SMark Johnston #endif 36600339a1c2SMark Johnston NOMEM; 36610339a1c2SMark Johnston break; 36620339a1c2SMark Johnston } else { 36630339a1c2SMark Johnston goto error; 36640339a1c2SMark Johnston } 36650339a1c2SMark Johnston 36660339a1c2SMark Johnston } 36670339a1c2SMark Johnston /*FALLTHROUGH*/ 36680339a1c2SMark Johnston case MO: 36690339a1c2SMark Johnston /* Similar to M, but only memory (no direct registers) */ 36700339a1c2SMark Johnston wbit = LONG_OPND; 36710339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 36720339a1c2SMark Johnston if (mode == 3) 36730339a1c2SMark Johnston goto error; 36740339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 36750339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 36760339a1c2SMark Johnston break; 36770339a1c2SMark Johnston 36780339a1c2SMark Johnston /* move special register to register or reverse if vbit */ 36790339a1c2SMark Johnston case SREG: 36800339a1c2SMark Johnston switch (opcode5) { 36810339a1c2SMark Johnston 36820339a1c2SMark Johnston case 2: 36830339a1c2SMark Johnston vbit = 1; 36840339a1c2SMark Johnston /*FALLTHROUGH*/ 36850339a1c2SMark Johnston case 0: 36860339a1c2SMark Johnston wbit = CONTROL_OPND; 36870339a1c2SMark Johnston break; 36880339a1c2SMark Johnston 36890339a1c2SMark Johnston case 3: 36900339a1c2SMark Johnston vbit = 1; 36910339a1c2SMark Johnston /*FALLTHROUGH*/ 36920339a1c2SMark Johnston case 1: 36930339a1c2SMark Johnston wbit = DEBUG_OPND; 36940339a1c2SMark Johnston break; 36950339a1c2SMark Johnston 36960339a1c2SMark Johnston case 6: 36970339a1c2SMark Johnston vbit = 1; 36980339a1c2SMark Johnston /*FALLTHROUGH*/ 36990339a1c2SMark Johnston case 4: 37000339a1c2SMark Johnston wbit = TEST_OPND; 37010339a1c2SMark Johnston break; 37020339a1c2SMark Johnston 37030339a1c2SMark Johnston } 37040339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 37050339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 37060339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit); 37070339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, r_m, LONG_OPND, 1 - vbit); 37080339a1c2SMark Johnston NOMEM; 37090339a1c2SMark Johnston break; 37100339a1c2SMark Johnston 37110339a1c2SMark Johnston /* 37120339a1c2SMark Johnston * single register operand with register in the low 3 37130339a1c2SMark Johnston * bits of op code 37140339a1c2SMark Johnston */ 37150339a1c2SMark Johnston case R: 37160339a1c2SMark Johnston if (opcode_bytes == 2) 37170339a1c2SMark Johnston reg = REGNO(opcode5); 37180339a1c2SMark Johnston else 37190339a1c2SMark Johnston reg = REGNO(opcode2); 37200339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 37210339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 37220339a1c2SMark Johnston NOMEM; 37230339a1c2SMark Johnston break; 37240339a1c2SMark Johnston 37250339a1c2SMark Johnston /* 37260339a1c2SMark Johnston * register to accumulator with register in the low 3 37270339a1c2SMark Johnston * bits of op code, xchg instructions 37280339a1c2SMark Johnston */ 37290339a1c2SMark Johnston case RA: 37300339a1c2SMark Johnston NOMEM; 37310339a1c2SMark Johnston reg = REGNO(opcode2); 37320339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, NULL); 37330339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 0); 37340339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, EAX_REGNO, LONG_OPND, 1); 37350339a1c2SMark Johnston break; 37360339a1c2SMark Johnston 37370339a1c2SMark Johnston /* 37380339a1c2SMark Johnston * single segment register operand, with register in 37390339a1c2SMark Johnston * bits 3-4 of op code byte 37400339a1c2SMark Johnston */ 37410339a1c2SMark Johnston case SEG: 37420339a1c2SMark Johnston NOMEM; 37430339a1c2SMark Johnston reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x3; 37440339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0); 37450339a1c2SMark Johnston break; 37460339a1c2SMark Johnston 37470339a1c2SMark Johnston /* 37480339a1c2SMark Johnston * single segment register operand, with register in 37490339a1c2SMark Johnston * bits 3-5 of op code 37500339a1c2SMark Johnston */ 37510339a1c2SMark Johnston case LSEG: 37520339a1c2SMark Johnston NOMEM; 37530339a1c2SMark Johnston /* long seg reg from opcode */ 37540339a1c2SMark Johnston reg = (x->d86_bytes[x->d86_len - 1] >> 3) & 0x7; 37550339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, SEG_OPND, 0); 37560339a1c2SMark Johnston break; 37570339a1c2SMark Johnston 37580339a1c2SMark Johnston /* memory or register operand to register */ 37590339a1c2SMark Johnston case MR: 37600339a1c2SMark Johnston if (vex_prefetch) 37610339a1c2SMark Johnston x->d86_got_modrm = 1; 37620339a1c2SMark Johnston wbit = LONG_OPND; 37630339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 37640339a1c2SMark Johnston break; 37650339a1c2SMark Johnston 37660339a1c2SMark Johnston case RM: 3767c3ddb60eSPeter Grehan case RM_66r: 37680339a1c2SMark Johnston wbit = LONG_OPND; 37690339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1); 37700339a1c2SMark Johnston break; 37710339a1c2SMark Johnston 37720339a1c2SMark Johnston /* MMX/SIMD-Int memory or mm reg to mm reg */ 37730339a1c2SMark Johnston case MM: 37740339a1c2SMark Johnston case MMO: 37750339a1c2SMark Johnston #ifdef DIS_TEXT 37760339a1c2SMark Johnston wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 37770339a1c2SMark Johnston #else 37780339a1c2SMark Johnston wbit = LONG_OPND; 37790339a1c2SMark Johnston #endif 37800339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0); 37810339a1c2SMark Johnston break; 37820339a1c2SMark Johnston 37830339a1c2SMark Johnston case MMOIMPL: 37840339a1c2SMark Johnston #ifdef DIS_TEXT 37850339a1c2SMark Johnston wbit = strcmp(dp->it_name, "movd") ? MM_OPND : LONG_OPND; 37860339a1c2SMark Johnston #else 37870339a1c2SMark Johnston wbit = LONG_OPND; 37880339a1c2SMark Johnston #endif 37890339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 37900339a1c2SMark Johnston if (mode != REG_ONLY) 37910339a1c2SMark Johnston goto error; 37920339a1c2SMark Johnston 37930339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 37940339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 37950339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, MM_OPND, 1); 37960339a1c2SMark Johnston mode = 0; /* change for memory access size... */ 37970339a1c2SMark Johnston break; 37980339a1c2SMark Johnston 37990339a1c2SMark Johnston /* MMX/SIMD-Int and SIMD-FP predicated mm reg to r32 */ 38000339a1c2SMark Johnston case MMO3P: 38010339a1c2SMark Johnston wbit = MM_OPND; 38020339a1c2SMark Johnston goto xmm3p; 38030339a1c2SMark Johnston case XMM3P: 38040339a1c2SMark Johnston wbit = XMM_OPND; 38050339a1c2SMark Johnston xmm3p: 38060339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 38070339a1c2SMark Johnston if (mode != REG_ONLY) 38080339a1c2SMark Johnston goto error; 38090339a1c2SMark Johnston 38100339a1c2SMark Johnston THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 1, 38110339a1c2SMark Johnston 1); 38120339a1c2SMark Johnston NOMEM; 38130339a1c2SMark Johnston break; 38140339a1c2SMark Johnston 38150339a1c2SMark Johnston case XMM3PM_66r: 38160339a1c2SMark Johnston THREEOPERAND(x, mode, reg, r_m, rex_prefix, LONG_OPND, XMM_OPND, 38170339a1c2SMark Johnston 1, 0); 38180339a1c2SMark Johnston break; 38190339a1c2SMark Johnston 38200339a1c2SMark Johnston /* MMX/SIMD-Int predicated r32/mem to mm reg */ 38210339a1c2SMark Johnston case MMOPRM: 38220339a1c2SMark Johnston wbit = LONG_OPND; 38230339a1c2SMark Johnston w2 = MM_OPND; 38240339a1c2SMark Johnston goto xmmprm; 38250339a1c2SMark Johnston case XMMPRM: 38260339a1c2SMark Johnston case XMMPRM_66r: 38270339a1c2SMark Johnston wbit = LONG_OPND; 38280339a1c2SMark Johnston w2 = XMM_OPND; 38290339a1c2SMark Johnston xmmprm: 38300339a1c2SMark Johnston THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, w2, 1, 1); 38310339a1c2SMark Johnston break; 38320339a1c2SMark Johnston 38330339a1c2SMark Johnston /* MMX/SIMD-Int predicated mm/mem to mm reg */ 38340339a1c2SMark Johnston case MMOPM: 38350339a1c2SMark Johnston case MMOPM_66o: 38360339a1c2SMark Johnston wbit = w2 = MM_OPND; 38370339a1c2SMark Johnston goto xmmprm; 38380339a1c2SMark Johnston 38390339a1c2SMark Johnston /* MMX/SIMD-Int mm reg to r32 */ 38400339a1c2SMark Johnston case MMOM3: 38410339a1c2SMark Johnston NOMEM; 38420339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 38430339a1c2SMark Johnston if (mode != REG_ONLY) 38440339a1c2SMark Johnston goto error; 38450339a1c2SMark Johnston wbit = MM_OPND; 38460339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0); 38470339a1c2SMark Johnston break; 38480339a1c2SMark Johnston 38490339a1c2SMark Johnston /* SIMD memory or xmm reg operand to xmm reg */ 38500339a1c2SMark Johnston case XMM: 38510339a1c2SMark Johnston case XMM_66o: 38520339a1c2SMark Johnston case XMM_66r: 38530339a1c2SMark Johnston case XMMO: 38540339a1c2SMark Johnston case XMMXIMPL: 38550339a1c2SMark Johnston wbit = XMM_OPND; 38560339a1c2SMark Johnston STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0); 38570339a1c2SMark Johnston 38580339a1c2SMark Johnston if (dp->it_adrmode == XMMXIMPL && mode != REG_ONLY) 38590339a1c2SMark Johnston goto error; 38600339a1c2SMark Johnston 38610339a1c2SMark Johnston #ifdef DIS_TEXT 38620339a1c2SMark Johnston /* 38630339a1c2SMark Johnston * movlps and movhlps share opcodes. They differ in the 38640339a1c2SMark Johnston * addressing modes allowed for their operands. 38650339a1c2SMark Johnston * movhps and movlhps behave similarly. 38660339a1c2SMark Johnston */ 38670339a1c2SMark Johnston if (mode == REG_ONLY) { 38680339a1c2SMark Johnston if (strcmp(dp->it_name, "movlps") == 0) 38690339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "movhlps", OPLEN); 38700339a1c2SMark Johnston else if (strcmp(dp->it_name, "movhps") == 0) 38710339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "movlhps", OPLEN); 38720339a1c2SMark Johnston } 38730339a1c2SMark Johnston #endif 38740339a1c2SMark Johnston if (dp->it_adrmode == XMMXIMPL) 38750339a1c2SMark Johnston mode = 0; /* change for memory access size... */ 38760339a1c2SMark Johnston break; 38770339a1c2SMark Johnston 38780339a1c2SMark Johnston /* SIMD xmm reg to memory or xmm reg */ 38790339a1c2SMark Johnston case XMMS: 38800339a1c2SMark Johnston case XMMOS: 38810339a1c2SMark Johnston case XMMMS: 38820339a1c2SMark Johnston case XMMOMS: 38830339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 38840339a1c2SMark Johnston #ifdef DIS_TEXT 38850339a1c2SMark Johnston if ((strcmp(dp->it_name, "movlps") == 0 || 38860339a1c2SMark Johnston strcmp(dp->it_name, "movhps") == 0 || 38870339a1c2SMark Johnston strcmp(dp->it_name, "movntps") == 0) && 38880339a1c2SMark Johnston mode == REG_ONLY) 38890339a1c2SMark Johnston goto error; 38900339a1c2SMark Johnston #endif 38910339a1c2SMark Johnston wbit = XMM_OPND; 38920339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1); 38930339a1c2SMark Johnston break; 38940339a1c2SMark Johnston 38950339a1c2SMark Johnston /* SIMD memory to xmm reg */ 38960339a1c2SMark Johnston case XMMM: 38970339a1c2SMark Johnston case XMMM_66r: 38980339a1c2SMark Johnston case XMMOM: 38990339a1c2SMark Johnston wbit = XMM_OPND; 39000339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 39010339a1c2SMark Johnston #ifdef DIS_TEXT 39020339a1c2SMark Johnston if (mode == REG_ONLY) { 39030339a1c2SMark Johnston if (strcmp(dp->it_name, "movhps") == 0) 39040339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "movlhps", OPLEN); 39050339a1c2SMark Johnston else 39060339a1c2SMark Johnston goto error; 39070339a1c2SMark Johnston } 39080339a1c2SMark Johnston #endif 39090339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 39100339a1c2SMark Johnston break; 39110339a1c2SMark Johnston 39120339a1c2SMark Johnston /* SIMD memory or r32 to xmm reg */ 39130339a1c2SMark Johnston case XMM3MX: 39140339a1c2SMark Johnston wbit = LONG_OPND; 39150339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 39160339a1c2SMark Johnston break; 39170339a1c2SMark Johnston 39180339a1c2SMark Johnston case XMM3MXS: 39190339a1c2SMark Johnston wbit = LONG_OPND; 39200339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1); 39210339a1c2SMark Johnston break; 39220339a1c2SMark Johnston 39230339a1c2SMark Johnston /* SIMD memory or mm reg to xmm reg */ 39240339a1c2SMark Johnston case XMMOMX: 39250339a1c2SMark Johnston /* SIMD mm to xmm */ 39260339a1c2SMark Johnston case XMMMX: 39270339a1c2SMark Johnston wbit = MM_OPND; 39280339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 0); 39290339a1c2SMark Johnston break; 39300339a1c2SMark Johnston 39310339a1c2SMark Johnston /* SIMD memory or xmm reg to mm reg */ 39320339a1c2SMark Johnston case XMMXMM: 39330339a1c2SMark Johnston case XMMOXMM: 39340339a1c2SMark Johnston case XMMXM: 39350339a1c2SMark Johnston wbit = XMM_OPND; 39360339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, MM_OPND, 0); 39370339a1c2SMark Johnston break; 39380339a1c2SMark Johnston 39390339a1c2SMark Johnston 39400339a1c2SMark Johnston /* SIMD memory or xmm reg to r32 */ 39410339a1c2SMark Johnston case XMMXM3: 39420339a1c2SMark Johnston wbit = XMM_OPND; 39430339a1c2SMark Johnston MIXED_MM(x, mode, reg, r_m, rex_prefix, wbit, LONG_OPND, 0); 39440339a1c2SMark Johnston break; 39450339a1c2SMark Johnston 39460339a1c2SMark Johnston /* SIMD xmm to r32 */ 39470339a1c2SMark Johnston case XMMX3: 39480339a1c2SMark Johnston case XMMOX3: 39490339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 39500339a1c2SMark Johnston if (mode != REG_ONLY) 39510339a1c2SMark Johnston goto error; 39520339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 39530339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, XMM_OPND, 0); 39540339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, 1); 39550339a1c2SMark Johnston NOMEM; 39560339a1c2SMark Johnston break; 39570339a1c2SMark Johnston 39580339a1c2SMark Johnston /* SIMD predicated memory or xmm reg with/to xmm reg */ 39590339a1c2SMark Johnston case XMMP: 39600339a1c2SMark Johnston case XMMP_66r: 39610339a1c2SMark Johnston case XMMP_66o: 39620339a1c2SMark Johnston case XMMOPM: 39630339a1c2SMark Johnston wbit = XMM_OPND; 39640339a1c2SMark Johnston THREEOPERAND(x, mode, reg, r_m, rex_prefix, wbit, XMM_OPND, 1, 39650339a1c2SMark Johnston 1); 39660339a1c2SMark Johnston 39670339a1c2SMark Johnston #ifdef DIS_TEXT 39680339a1c2SMark Johnston /* 39690339a1c2SMark Johnston * cmpps and cmpss vary their instruction name based 39700339a1c2SMark Johnston * on the value of imm8. Other XMMP instructions, 39710339a1c2SMark Johnston * such as shufps, require explicit specification of 39720339a1c2SMark Johnston * the predicate. 39730339a1c2SMark Johnston */ 39740339a1c2SMark Johnston if (dp->it_name[0] == 'c' && 39750339a1c2SMark Johnston dp->it_name[1] == 'm' && 39760339a1c2SMark Johnston dp->it_name[2] == 'p' && 39770339a1c2SMark Johnston strlen(dp->it_name) == 5) { 39780339a1c2SMark Johnston uchar_t pred = x->d86_opnd[0].d86_value & 0xff; 39790339a1c2SMark Johnston 39800339a1c2SMark Johnston if (pred >= (sizeof (dis_PREDSUFFIX) / sizeof (char *))) 39810339a1c2SMark Johnston goto error; 39820339a1c2SMark Johnston 39830339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "cmp", OPLEN); 39840339a1c2SMark Johnston (void) strlcat(x->d86_mnem, dis_PREDSUFFIX[pred], 39850339a1c2SMark Johnston OPLEN); 39860339a1c2SMark Johnston (void) strlcat(x->d86_mnem, 39870339a1c2SMark Johnston dp->it_name + strlen(dp->it_name) - 2, 39880339a1c2SMark Johnston OPLEN); 39890339a1c2SMark Johnston x->d86_opnd[0] = x->d86_opnd[1]; 39900339a1c2SMark Johnston x->d86_opnd[1] = x->d86_opnd[2]; 39910339a1c2SMark Johnston x->d86_numopnds = 2; 39920339a1c2SMark Johnston } 39930339a1c2SMark Johnston #endif 39940339a1c2SMark Johnston break; 39950339a1c2SMark Johnston 39960339a1c2SMark Johnston case XMMX2I: 39970339a1c2SMark Johnston FOUROPERAND(x, mode, reg, r_m, rex_prefix, XMM_OPND, XMM_OPND, 39980339a1c2SMark Johnston 1); 39990339a1c2SMark Johnston NOMEM; 40000339a1c2SMark Johnston break; 40010339a1c2SMark Johnston 40020339a1c2SMark Johnston case XMM2I: 40030339a1c2SMark Johnston ONEOPERAND_TWOIMM(x, mode, reg, r_m, rex_prefix, XMM_OPND, 1); 40040339a1c2SMark Johnston NOMEM; 40050339a1c2SMark Johnston break; 40060339a1c2SMark Johnston 40070339a1c2SMark Johnston /* immediate operand to accumulator */ 40080339a1c2SMark Johnston case IA: 40090339a1c2SMark Johnston wbit = WBIT(opcode2); 40100339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1); 40110339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, wbit), 0); 40120339a1c2SMark Johnston NOMEM; 40130339a1c2SMark Johnston break; 40140339a1c2SMark Johnston 40150339a1c2SMark Johnston /* memory or register operand to accumulator */ 40160339a1c2SMark Johnston case MA: 40170339a1c2SMark Johnston wbit = WBIT(opcode2); 40180339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 40190339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 40200339a1c2SMark Johnston break; 40210339a1c2SMark Johnston 40220339a1c2SMark Johnston /* si register to di register used to reference memory */ 40230339a1c2SMark Johnston case SD: 40240339a1c2SMark Johnston #ifdef DIS_TEXT 40250339a1c2SMark Johnston dtrace_check_override(x, 0); 40260339a1c2SMark Johnston x->d86_numopnds = 2; 40270339a1c2SMark Johnston if (addr_size == SIZE64) { 40280339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", 40290339a1c2SMark Johnston OPLEN); 40300339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", 40310339a1c2SMark Johnston OPLEN); 40320339a1c2SMark Johnston } else if (addr_size == SIZE32) { 40330339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", 40340339a1c2SMark Johnston OPLEN); 40350339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", 40360339a1c2SMark Johnston OPLEN); 40370339a1c2SMark Johnston } else { 40380339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)", 40390339a1c2SMark Johnston OPLEN); 40400339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)", 40410339a1c2SMark Johnston OPLEN); 40420339a1c2SMark Johnston } 40430339a1c2SMark Johnston #endif 40440339a1c2SMark Johnston wbit = LONG_OPND; 40450339a1c2SMark Johnston break; 40460339a1c2SMark Johnston 40470339a1c2SMark Johnston /* accumulator to di register */ 40480339a1c2SMark Johnston case AD: 40490339a1c2SMark Johnston wbit = WBIT(opcode2); 40500339a1c2SMark Johnston #ifdef DIS_TEXT 40510339a1c2SMark Johnston dtrace_check_override(x, 1); 40520339a1c2SMark Johnston x->d86_numopnds = 2; 40530339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 0); 40540339a1c2SMark Johnston if (addr_size == SIZE64) 40550339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", 40560339a1c2SMark Johnston OPLEN); 40570339a1c2SMark Johnston else if (addr_size == SIZE32) 40580339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", 40590339a1c2SMark Johnston OPLEN); 40600339a1c2SMark Johnston else 40610339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)", 40620339a1c2SMark Johnston OPLEN); 40630339a1c2SMark Johnston #endif 40640339a1c2SMark Johnston break; 40650339a1c2SMark Johnston 40660339a1c2SMark Johnston /* si register to accumulator */ 40670339a1c2SMark Johnston case SA: 40680339a1c2SMark Johnston wbit = WBIT(opcode2); 40690339a1c2SMark Johnston #ifdef DIS_TEXT 40700339a1c2SMark Johnston dtrace_check_override(x, 0); 40710339a1c2SMark Johnston x->d86_numopnds = 2; 40720339a1c2SMark Johnston if (addr_size == SIZE64) 40730339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", 40740339a1c2SMark Johnston OPLEN); 40750339a1c2SMark Johnston else if (addr_size == SIZE32) 40760339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", 40770339a1c2SMark Johnston OPLEN); 40780339a1c2SMark Johnston else 40790339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)", 40800339a1c2SMark Johnston OPLEN); 40810339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1); 40820339a1c2SMark Johnston #endif 40830339a1c2SMark Johnston break; 40840339a1c2SMark Johnston 40850339a1c2SMark Johnston /* 40860339a1c2SMark Johnston * single operand, a 16/32 bit displacement 40870339a1c2SMark Johnston */ 40880339a1c2SMark Johnston case D: 40890339a1c2SMark Johnston wbit = LONG_OPND; 40900339a1c2SMark Johnston dtrace_disp_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0); 40910339a1c2SMark Johnston NOMEM; 40920339a1c2SMark Johnston break; 40930339a1c2SMark Johnston 40940339a1c2SMark Johnston /* jmp/call indirect to memory or register operand */ 40950339a1c2SMark Johnston case INM: 40960339a1c2SMark Johnston #ifdef DIS_TEXT 40970339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_prefix, "*", OPLEN); 40980339a1c2SMark Johnston #endif 40990339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); 41000339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 0); 41010339a1c2SMark Johnston wbit = LONG_OPND; 41020339a1c2SMark Johnston break; 41030339a1c2SMark Johnston 41040339a1c2SMark Johnston /* 41050339a1c2SMark Johnston * for long jumps and long calls -- a new code segment 41060339a1c2SMark Johnston * register and an offset in IP -- stored in object 41070339a1c2SMark Johnston * code in reverse order. Note - not valid in amd64 41080339a1c2SMark Johnston */ 41090339a1c2SMark Johnston case SO: 41100339a1c2SMark Johnston dtrace_check_override(x, 1); 41110339a1c2SMark Johnston wbit = LONG_OPND; 41120339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 1); 41130339a1c2SMark Johnston #ifdef DIS_TEXT 41140339a1c2SMark Johnston x->d86_opnd[1].d86_mode = MODE_SIGNED; 41150339a1c2SMark Johnston #endif 41160339a1c2SMark Johnston /* will now get segment operand */ 41170339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 2, 0); 41180339a1c2SMark Johnston break; 41190339a1c2SMark Johnston 41200339a1c2SMark Johnston /* 41210339a1c2SMark Johnston * jmp/call. single operand, 8 bit displacement. 41220339a1c2SMark Johnston * added to current EIP in 'compofff' 41230339a1c2SMark Johnston */ 41240339a1c2SMark Johnston case BD: 41250339a1c2SMark Johnston dtrace_disp_opnd(x, BYTE_OPND, 1, 0); 41260339a1c2SMark Johnston NOMEM; 41270339a1c2SMark Johnston break; 41280339a1c2SMark Johnston 41290339a1c2SMark Johnston /* single 32/16 bit immediate operand */ 41300339a1c2SMark Johnston case I: 41310339a1c2SMark Johnston wbit = LONG_OPND; 41320339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, OPSIZE(opnd_size, LONG_OPND), 0); 41330339a1c2SMark Johnston break; 41340339a1c2SMark Johnston 41350339a1c2SMark Johnston /* single 8 bit immediate operand */ 41360339a1c2SMark Johnston case Ib: 41370339a1c2SMark Johnston wbit = LONG_OPND; 41380339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 41390339a1c2SMark Johnston break; 41400339a1c2SMark Johnston 41410339a1c2SMark Johnston case ENTER: 41420339a1c2SMark Johnston wbit = LONG_OPND; 41430339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 2, 0); 41440339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 1); 41450339a1c2SMark Johnston switch (opnd_size) { 41460339a1c2SMark Johnston case SIZE64: 41470339a1c2SMark Johnston x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 8; 41480339a1c2SMark Johnston break; 41490339a1c2SMark Johnston case SIZE32: 41500339a1c2SMark Johnston x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 4; 41510339a1c2SMark Johnston break; 41520339a1c2SMark Johnston case SIZE16: 41530339a1c2SMark Johnston x->d86_memsize = (x->d86_opnd[1].d86_value + 1) * 2; 41540339a1c2SMark Johnston break; 41550339a1c2SMark Johnston } 41560339a1c2SMark Johnston 41570339a1c2SMark Johnston break; 41580339a1c2SMark Johnston 41590339a1c2SMark Johnston /* 16-bit immediate operand */ 41600339a1c2SMark Johnston case RET: 41610339a1c2SMark Johnston wbit = LONG_OPND; 41620339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 2, 0); 41630339a1c2SMark Johnston break; 41640339a1c2SMark Johnston 41650339a1c2SMark Johnston /* single 8 bit port operand */ 41660339a1c2SMark Johnston case P: 41670339a1c2SMark Johnston dtrace_check_override(x, 0); 41680339a1c2SMark Johnston dtrace_imm_opnd(x, BYTE_OPND, 1, 0); 41690339a1c2SMark Johnston NOMEM; 41700339a1c2SMark Johnston break; 41710339a1c2SMark Johnston 41720339a1c2SMark Johnston /* single operand, dx register (variable port instruction) */ 41730339a1c2SMark Johnston case V: 41740339a1c2SMark Johnston x->d86_numopnds = 1; 41750339a1c2SMark Johnston dtrace_check_override(x, 0); 41760339a1c2SMark Johnston #ifdef DIS_TEXT 41770339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "(%dx)", OPLEN); 41780339a1c2SMark Johnston #endif 41790339a1c2SMark Johnston NOMEM; 41800339a1c2SMark Johnston break; 41810339a1c2SMark Johnston 41820339a1c2SMark Johnston /* 41830339a1c2SMark Johnston * The int instruction, which has two forms: 41840339a1c2SMark Johnston * int 3 (breakpoint) or 41850339a1c2SMark Johnston * int n, where n is indicated in the subsequent 41860339a1c2SMark Johnston * byte (format Ib). The int 3 instruction (opcode 0xCC), 41870339a1c2SMark Johnston * where, although the 3 looks like an operand, 41880339a1c2SMark Johnston * it is implied by the opcode. It must be converted 41890339a1c2SMark Johnston * to the correct base and output. 41900339a1c2SMark Johnston */ 41910339a1c2SMark Johnston case INT3: 41920339a1c2SMark Johnston #ifdef DIS_TEXT 41930339a1c2SMark Johnston x->d86_numopnds = 1; 41940339a1c2SMark Johnston x->d86_opnd[0].d86_mode = MODE_SIGNED; 41950339a1c2SMark Johnston x->d86_opnd[0].d86_value_size = 1; 41960339a1c2SMark Johnston x->d86_opnd[0].d86_value = 3; 41970339a1c2SMark Johnston #endif 41980339a1c2SMark Johnston NOMEM; 41990339a1c2SMark Johnston break; 42000339a1c2SMark Johnston 42010339a1c2SMark Johnston /* single 8 bit immediate operand */ 42020339a1c2SMark Johnston case INTx: 42030339a1c2SMark Johnston dtrace_imm_opnd(x, BYTE_OPND, 1, 0); 42040339a1c2SMark Johnston NOMEM; 42050339a1c2SMark Johnston break; 42060339a1c2SMark Johnston 42070339a1c2SMark Johnston /* an unused byte must be discarded */ 42080339a1c2SMark Johnston case U: 42090339a1c2SMark Johnston if (x->d86_get_byte(x->d86_data) < 0) 42100339a1c2SMark Johnston goto error; 42110339a1c2SMark Johnston x->d86_len++; 42120339a1c2SMark Johnston NOMEM; 42130339a1c2SMark Johnston break; 42140339a1c2SMark Johnston 42150339a1c2SMark Johnston case CBW: 42160339a1c2SMark Johnston #ifdef DIS_TEXT 42170339a1c2SMark Johnston if (opnd_size == SIZE16) 42180339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "cbtw", OPLEN); 42190339a1c2SMark Johnston else if (opnd_size == SIZE32) 42200339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "cwtl", OPLEN); 42210339a1c2SMark Johnston else 42220339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "cltq", OPLEN); 42230339a1c2SMark Johnston #endif 42240339a1c2SMark Johnston wbit = LONG_OPND; 42250339a1c2SMark Johnston NOMEM; 42260339a1c2SMark Johnston break; 42270339a1c2SMark Johnston 42280339a1c2SMark Johnston case CWD: 42290339a1c2SMark Johnston #ifdef DIS_TEXT 42300339a1c2SMark Johnston if (opnd_size == SIZE16) 42310339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "cwtd", OPLEN); 42320339a1c2SMark Johnston else if (opnd_size == SIZE32) 42330339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "cltd", OPLEN); 42340339a1c2SMark Johnston else 42350339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "cqtd", OPLEN); 42360339a1c2SMark Johnston #endif 42370339a1c2SMark Johnston wbit = LONG_OPND; 42380339a1c2SMark Johnston NOMEM; 42390339a1c2SMark Johnston break; 42400339a1c2SMark Johnston 42410339a1c2SMark Johnston case XMMSFNC: 42420339a1c2SMark Johnston /* 42430339a1c2SMark Johnston * sfence is sfence if mode is REG_ONLY. If mode isn't 42440339a1c2SMark Johnston * REG_ONLY, mnemonic should be 'clflush'. 42450339a1c2SMark Johnston */ 42460339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 42470339a1c2SMark Johnston 42480339a1c2SMark Johnston /* sfence doesn't take operands */ 42490339a1c2SMark Johnston #ifdef DIS_TEXT 42500339a1c2SMark Johnston if (mode == REG_ONLY) { 42510339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "sfence", OPLEN); 42520339a1c2SMark Johnston } else { 42530339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "clflush", OPLEN); 42540339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 42550339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0); 42560339a1c2SMark Johnston NOMEM; 42570339a1c2SMark Johnston } 42580339a1c2SMark Johnston #else 42590339a1c2SMark Johnston if (mode != REG_ONLY) { 42600339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 42610339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 0); 42620339a1c2SMark Johnston NOMEM; 42630339a1c2SMark Johnston } 42640339a1c2SMark Johnston #endif 42650339a1c2SMark Johnston break; 42660339a1c2SMark Johnston 42670339a1c2SMark Johnston /* 42680339a1c2SMark Johnston * no disassembly, the mnemonic was all there was so go on 42690339a1c2SMark Johnston */ 42700339a1c2SMark Johnston case NORM: 42710339a1c2SMark Johnston if (dp->it_invalid32 && cpu_mode != SIZE64) 42720339a1c2SMark Johnston goto error; 42730339a1c2SMark Johnston NOMEM; 42740339a1c2SMark Johnston /*FALLTHROUGH*/ 42750339a1c2SMark Johnston case IMPLMEM: 42760339a1c2SMark Johnston break; 42770339a1c2SMark Johnston 42780339a1c2SMark Johnston case XMMFENCE: 42790339a1c2SMark Johnston /* 42800339a1c2SMark Johnston * XRSTOR and LFENCE share the same opcode but differ in mode 42810339a1c2SMark Johnston */ 42820339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 42830339a1c2SMark Johnston 42840339a1c2SMark Johnston if (mode == REG_ONLY) { 42850339a1c2SMark Johnston /* 42860339a1c2SMark Johnston * Only the following exact byte sequences are allowed: 42870339a1c2SMark Johnston * 42880339a1c2SMark Johnston * 0f ae e8 lfence 42890339a1c2SMark Johnston * 0f ae f0 mfence 42900339a1c2SMark Johnston */ 42910339a1c2SMark Johnston if ((uint8_t)x->d86_bytes[x->d86_len - 1] != 0xe8 && 42920339a1c2SMark Johnston (uint8_t)x->d86_bytes[x->d86_len - 1] != 0xf0) 42930339a1c2SMark Johnston goto error; 42940339a1c2SMark Johnston } else { 42950339a1c2SMark Johnston #ifdef DIS_TEXT 42960339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "xrstor", OPLEN); 42970339a1c2SMark Johnston #endif 42980339a1c2SMark Johnston dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); 42990339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0); 43000339a1c2SMark Johnston } 43010339a1c2SMark Johnston break; 43020339a1c2SMark Johnston 43030339a1c2SMark Johnston /* float reg */ 43040339a1c2SMark Johnston case F: 43050339a1c2SMark Johnston #ifdef DIS_TEXT 43060339a1c2SMark Johnston x->d86_numopnds = 1; 43070339a1c2SMark Johnston (void) strlcat(x->d86_opnd[0].d86_opnd, "%st(X)", OPLEN); 43080339a1c2SMark Johnston x->d86_opnd[0].d86_opnd[4] = r_m + '0'; 43090339a1c2SMark Johnston #endif 43100339a1c2SMark Johnston NOMEM; 43110339a1c2SMark Johnston break; 43120339a1c2SMark Johnston 43130339a1c2SMark Johnston /* float reg to float reg, with ret bit present */ 43140339a1c2SMark Johnston case FF: 43150339a1c2SMark Johnston vbit = opcode2 >> 2 & 0x1; /* vbit = 1: st -> st(i) */ 43160339a1c2SMark Johnston /*FALLTHROUGH*/ 43170339a1c2SMark Johnston case FFC: /* case for vbit always = 0 */ 43180339a1c2SMark Johnston #ifdef DIS_TEXT 43190339a1c2SMark Johnston x->d86_numopnds = 2; 43200339a1c2SMark Johnston (void) strlcat(x->d86_opnd[1 - vbit].d86_opnd, "%st", OPLEN); 43210339a1c2SMark Johnston (void) strlcat(x->d86_opnd[vbit].d86_opnd, "%st(X)", OPLEN); 43220339a1c2SMark Johnston x->d86_opnd[vbit].d86_opnd[4] = r_m + '0'; 43230339a1c2SMark Johnston #endif 43240339a1c2SMark Johnston NOMEM; 43250339a1c2SMark Johnston break; 43260339a1c2SMark Johnston 43270339a1c2SMark Johnston /* AVX instructions */ 43280339a1c2SMark Johnston case VEX_MO: 43290339a1c2SMark Johnston /* op(ModR/M.r/m) */ 43300339a1c2SMark Johnston x->d86_numopnds = 1; 43310339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 43320339a1c2SMark Johnston #ifdef DIS_TEXT 43330339a1c2SMark Johnston if ((dp == &dis_opAVX0F[0xA][0xE]) && (reg == 3)) 43340339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "vstmxcsr", OPLEN); 43350339a1c2SMark Johnston #endif 43360339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 43370339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 43380339a1c2SMark Johnston break; 43390339a1c2SMark Johnston case VEX_RMrX: 43400339a1c2SMark Johnston /* ModR/M.reg := op(VEX.vvvv, ModR/M.r/m) */ 43410339a1c2SMark Johnston x->d86_numopnds = 3; 43420339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 43430339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 43440339a1c2SMark Johnston 43450339a1c2SMark Johnston if (mode != REG_ONLY) { 43460339a1c2SMark Johnston if ((dp == &dis_opAVXF20F[0x10]) || 43470339a1c2SMark Johnston (dp == &dis_opAVXF30F[0x10])) { 43480339a1c2SMark Johnston /* vmovsd <m64>, <xmm> */ 43490339a1c2SMark Johnston /* or vmovss <m64>, <xmm> */ 43500339a1c2SMark Johnston x->d86_numopnds = 2; 43510339a1c2SMark Johnston goto L_VEX_MX; 43520339a1c2SMark Johnston } 43530339a1c2SMark Johnston } 43540339a1c2SMark Johnston 43550339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 2); 43560339a1c2SMark Johnston /* 43570339a1c2SMark Johnston * VEX prefix uses the 1's complement form to encode the 43580339a1c2SMark Johnston * XMM/YMM regs 43590339a1c2SMark Johnston */ 43600339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 43610339a1c2SMark Johnston 43620339a1c2SMark Johnston if ((dp == &dis_opAVXF20F[0x2A]) || 43630339a1c2SMark Johnston (dp == &dis_opAVXF30F[0x2A])) { 43640339a1c2SMark Johnston /* 43650339a1c2SMark Johnston * vcvtsi2si </r,m>, <xmm>, <xmm> or vcvtsi2ss </r,m>, 43660339a1c2SMark Johnston * <xmm>, <xmm> 43670339a1c2SMark Johnston */ 43680339a1c2SMark Johnston wbit = LONG_OPND; 43690339a1c2SMark Johnston } 43700339a1c2SMark Johnston #ifdef DIS_TEXT 43710339a1c2SMark Johnston else if ((mode == REG_ONLY) && 43720339a1c2SMark Johnston (dp == &dis_opAVX0F[0x1][0x6])) { /* vmovlhps */ 43730339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "vmovlhps", OPLEN); 43740339a1c2SMark Johnston } else if ((mode == REG_ONLY) && 43750339a1c2SMark Johnston (dp == &dis_opAVX0F[0x1][0x2])) { /* vmovhlps */ 43760339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "vmovhlps", OPLEN); 43770339a1c2SMark Johnston } 43780339a1c2SMark Johnston #endif 43790339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 43800339a1c2SMark Johnston 43810339a1c2SMark Johnston break; 43820339a1c2SMark Johnston 43830339a1c2SMark Johnston case VEX_RRX: 43840339a1c2SMark Johnston /* ModR/M.rm := op(VEX.vvvv, ModR/M.reg) */ 43850339a1c2SMark Johnston x->d86_numopnds = 3; 43860339a1c2SMark Johnston 43870339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 43880339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 43890339a1c2SMark Johnston 43900339a1c2SMark Johnston if (mode != REG_ONLY) { 43910339a1c2SMark Johnston if ((dp == &dis_opAVXF20F[0x11]) || 43920339a1c2SMark Johnston (dp == &dis_opAVXF30F[0x11])) { 43930339a1c2SMark Johnston /* vmovsd <xmm>, <m64> */ 43940339a1c2SMark Johnston /* or vmovss <xmm>, <m64> */ 43950339a1c2SMark Johnston x->d86_numopnds = 2; 43960339a1c2SMark Johnston goto L_VEX_RM; 43970339a1c2SMark Johnston } 43980339a1c2SMark Johnston } 43990339a1c2SMark Johnston 44000339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 2); 44010339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 44020339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 0); 44030339a1c2SMark Johnston break; 44040339a1c2SMark Johnston 44050339a1c2SMark Johnston case VEX_RMRX: 44060339a1c2SMark Johnston /* ModR/M.reg := op(VEX.vvvv, ModR/M.r_m, imm8[7:4]) */ 44070339a1c2SMark Johnston x->d86_numopnds = 4; 44080339a1c2SMark Johnston 44090339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 44100339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 44110339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 3); 44120339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 2); 44130339a1c2SMark Johnston if (dp == &dis_opAVX660F3A[0x18]) { 44140339a1c2SMark Johnston /* vinsertf128 <imm8>, <xmm>, <ymm>, <ymm> */ 44150339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, XMM_OPND, 1); 44160339a1c2SMark Johnston } else if ((dp == &dis_opAVX660F3A[0x20]) || 44170339a1c2SMark Johnston (dp == & dis_opAVX660F[0xC4])) { 44180339a1c2SMark Johnston /* vpinsrb <imm8>, <reg/mm>, <xmm>, <xmm> */ 44190339a1c2SMark Johnston /* or vpinsrw <imm8>, <reg/mm>, <xmm>, <xmm> */ 44200339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 1); 44210339a1c2SMark Johnston } else if (dp == &dis_opAVX660F3A[0x22]) { 44220339a1c2SMark Johnston /* vpinsrd/q <imm8>, <reg/mm>, <xmm>, <xmm> */ 44230339a1c2SMark Johnston #ifdef DIS_TEXT 44240339a1c2SMark Johnston if (vex_W) 44250339a1c2SMark Johnston x->d86_mnem[6] = 'q'; 44260339a1c2SMark Johnston #endif 44270339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 1); 44280339a1c2SMark Johnston } else { 44290339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 44300339a1c2SMark Johnston } 44310339a1c2SMark Johnston 44320339a1c2SMark Johnston /* one byte immediate number */ 44330339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 44340339a1c2SMark Johnston 44350339a1c2SMark Johnston /* vblendvpd, vblendvps, vblendvb use the imm encode the regs */ 44360339a1c2SMark Johnston if ((dp == &dis_opAVX660F3A[0x4A]) || 44370339a1c2SMark Johnston (dp == &dis_opAVX660F3A[0x4B]) || 44380339a1c2SMark Johnston (dp == &dis_opAVX660F3A[0x4C])) { 44390339a1c2SMark Johnston #ifdef DIS_TEXT 44400339a1c2SMark Johnston int regnum = (x->d86_opnd[0].d86_value & 0xF0) >> 4; 44410339a1c2SMark Johnston #endif 44420339a1c2SMark Johnston x->d86_opnd[0].d86_mode = MODE_NONE; 44430339a1c2SMark Johnston #ifdef DIS_TEXT 44440339a1c2SMark Johnston if (vex_L) 44450339a1c2SMark Johnston (void) strncpy(x->d86_opnd[0].d86_opnd, 44460339a1c2SMark Johnston dis_YMMREG[regnum], OPLEN); 44470339a1c2SMark Johnston else 44480339a1c2SMark Johnston (void) strncpy(x->d86_opnd[0].d86_opnd, 44490339a1c2SMark Johnston dis_XMMREG[regnum], OPLEN); 44500339a1c2SMark Johnston #endif 44510339a1c2SMark Johnston } 44520339a1c2SMark Johnston break; 44530339a1c2SMark Johnston 44540339a1c2SMark Johnston case VEX_MX: 44550339a1c2SMark Johnston /* ModR/M.reg := op(ModR/M.rm) */ 44560339a1c2SMark Johnston x->d86_numopnds = 2; 44570339a1c2SMark Johnston 44580339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 44590339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 44600339a1c2SMark Johnston L_VEX_MX: 44610339a1c2SMark Johnston 44620339a1c2SMark Johnston if ((dp == &dis_opAVXF20F[0xE6]) || 44630339a1c2SMark Johnston (dp == &dis_opAVX660F[0x5A]) || 44640339a1c2SMark Johnston (dp == &dis_opAVX660F[0xE6])) { 44650339a1c2SMark Johnston /* vcvtpd2dq <ymm>, <xmm> */ 44660339a1c2SMark Johnston /* or vcvtpd2ps <ymm>, <xmm> */ 44670339a1c2SMark Johnston /* or vcvttpd2dq <ymm>, <xmm> */ 44680339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, XMM_OPND, 1); 44690339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 44700339a1c2SMark Johnston } else if ((dp == &dis_opAVXF30F[0xE6]) || 4471c3ddb60eSPeter Grehan (dp == &dis_opAVX0F[0x5][0xA]) || 4472c3ddb60eSPeter Grehan (dp == &dis_opAVX660F38[0x13])) { 44730339a1c2SMark Johnston /* vcvtdq2pd <xmm>, <ymm> */ 44740339a1c2SMark Johnston /* or vcvtps2pd <xmm>, <ymm> */ 44750339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 44760339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, XMM_OPND, 0); 44770339a1c2SMark Johnston } else if (dp == &dis_opAVX660F[0x6E]) { 44780339a1c2SMark Johnston /* vmovd/q <reg/mem 32/64>, <xmm> */ 44790339a1c2SMark Johnston #ifdef DIS_TEXT 44800339a1c2SMark Johnston if (vex_W) 44810339a1c2SMark Johnston x->d86_mnem[4] = 'q'; 44820339a1c2SMark Johnston #endif 44830339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 44840339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 0); 44850339a1c2SMark Johnston } else { 44860339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 44870339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 44880339a1c2SMark Johnston } 44890339a1c2SMark Johnston 44900339a1c2SMark Johnston break; 44910339a1c2SMark Johnston 44920339a1c2SMark Johnston case VEX_MXI: 44930339a1c2SMark Johnston /* ModR/M.reg := op(ModR/M.rm, imm8) */ 44940339a1c2SMark Johnston x->d86_numopnds = 3; 44950339a1c2SMark Johnston 44960339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 44970339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 44980339a1c2SMark Johnston 44990339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 2); 45000339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 45010339a1c2SMark Johnston 45020339a1c2SMark Johnston /* one byte immediate number */ 45030339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 45040339a1c2SMark Johnston break; 45050339a1c2SMark Johnston 45060339a1c2SMark Johnston case VEX_XXI: 45070339a1c2SMark Johnston /* VEX.vvvv := op(ModR/M.rm, imm8) */ 45080339a1c2SMark Johnston x->d86_numopnds = 3; 45090339a1c2SMark Johnston 45100339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 45110339a1c2SMark Johnston #ifdef DIS_TEXT 45120339a1c2SMark Johnston (void) strncpy(x->d86_mnem, dis_AVXvgrp7[opcode2 - 1][reg], 45130339a1c2SMark Johnston OPLEN); 45140339a1c2SMark Johnston #endif 45150339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 45160339a1c2SMark Johnston 45170339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 2); 45180339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, r_m, wbit, 1); 45190339a1c2SMark Johnston 45200339a1c2SMark Johnston /* one byte immediate number */ 45210339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 45220339a1c2SMark Johnston break; 45230339a1c2SMark Johnston 45240339a1c2SMark Johnston case VEX_MR: 45250339a1c2SMark Johnston /* ModR/M.reg (reg32/64) := op(ModR/M.rm) */ 45260339a1c2SMark Johnston if (dp == &dis_opAVX660F[0xC5]) { 45270339a1c2SMark Johnston /* vpextrw <imm8>, <xmm>, <reg> */ 45280339a1c2SMark Johnston x->d86_numopnds = 2; 45290339a1c2SMark Johnston vbit = 2; 45300339a1c2SMark Johnston } else { 45310339a1c2SMark Johnston x->d86_numopnds = 2; 45320339a1c2SMark Johnston vbit = 1; 45330339a1c2SMark Johnston } 45340339a1c2SMark Johnston 45350339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 45360339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 45370339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, LONG_OPND, vbit); 45380339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, vbit - 1); 45390339a1c2SMark Johnston 45400339a1c2SMark Johnston if (vbit == 2) 45410339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 45420339a1c2SMark Johnston 45430339a1c2SMark Johnston break; 45440339a1c2SMark Johnston 45450339a1c2SMark Johnston case VEX_RRI: 45460339a1c2SMark Johnston /* implicit(eflags/r32) := op(ModR/M.reg, ModR/M.rm) */ 45470339a1c2SMark Johnston x->d86_numopnds = 2; 45480339a1c2SMark Johnston 45490339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 45500339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 45510339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 45520339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 0); 45530339a1c2SMark Johnston break; 45540339a1c2SMark Johnston 45550339a1c2SMark Johnston case VEX_RX: 45560339a1c2SMark Johnston /* ModR/M.rm := op(ModR/M.reg) */ 4557c3ddb60eSPeter Grehan /* vextractf128 || vcvtps2ph */ 4558c3ddb60eSPeter Grehan if (dp == &dis_opAVX660F3A[0x19] || 4559c3ddb60eSPeter Grehan dp == &dis_opAVX660F3A[0x1d]) { 45600339a1c2SMark Johnston x->d86_numopnds = 3; 45610339a1c2SMark Johnston 45620339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 45630339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 45640339a1c2SMark Johnston 45650339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, XMM_OPND, 2); 45660339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 45670339a1c2SMark Johnston 45680339a1c2SMark Johnston /* one byte immediate number */ 45690339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 45700339a1c2SMark Johnston break; 45710339a1c2SMark Johnston } 45720339a1c2SMark Johnston 45730339a1c2SMark Johnston x->d86_numopnds = 2; 45740339a1c2SMark Johnston 45750339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 45760339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 45770339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 45780339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 0); 45790339a1c2SMark Johnston break; 45800339a1c2SMark Johnston 45810339a1c2SMark Johnston case VEX_RR: 45820339a1c2SMark Johnston /* ModR/M.rm := op(ModR/M.reg) */ 45830339a1c2SMark Johnston x->d86_numopnds = 2; 45840339a1c2SMark Johnston 45850339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 45860339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 45870339a1c2SMark Johnston 45880339a1c2SMark Johnston if (dp == &dis_opAVX660F[0x7E]) { 45890339a1c2SMark Johnston /* vmovd/q <reg/mem 32/64>, <xmm> */ 45900339a1c2SMark Johnston #ifdef DIS_TEXT 45910339a1c2SMark Johnston if (vex_W) 45920339a1c2SMark Johnston x->d86_mnem[4] = 'q'; 45930339a1c2SMark Johnston #endif 45940339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 1); 45950339a1c2SMark Johnston } else 45960339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 1); 45970339a1c2SMark Johnston 45980339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 0); 45990339a1c2SMark Johnston break; 46000339a1c2SMark Johnston 46010339a1c2SMark Johnston case VEX_RRi: 46020339a1c2SMark Johnston /* ModR/M.rm := op(ModR/M.reg, imm) */ 46030339a1c2SMark Johnston x->d86_numopnds = 3; 46040339a1c2SMark Johnston 46050339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 46060339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 46070339a1c2SMark Johnston 46080339a1c2SMark Johnston #ifdef DIS_TEXT 46090339a1c2SMark Johnston if (dp == &dis_opAVX660F3A[0x16]) { 46100339a1c2SMark Johnston /* vpextrd/q <imm>, <xmm>, <reg/mem 32/64> */ 46110339a1c2SMark Johnston if (vex_W) 46120339a1c2SMark Johnston x->d86_mnem[6] = 'q'; 46130339a1c2SMark Johnston } 46140339a1c2SMark Johnston #endif 46150339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 2); 46160339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 46170339a1c2SMark Johnston 46180339a1c2SMark Johnston /* one byte immediate number */ 46190339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 46200339a1c2SMark Johnston break; 46210339a1c2SMark Johnston 46220339a1c2SMark Johnston case VEX_RM: 46230339a1c2SMark Johnston /* ModR/M.rm := op(ModR/M.reg) */ 46240339a1c2SMark Johnston if (dp == &dis_opAVX660F3A[0x17]) { /* vextractps */ 46250339a1c2SMark Johnston x->d86_numopnds = 3; 46260339a1c2SMark Johnston 46270339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 46280339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 46290339a1c2SMark Johnston 46300339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, LONG_OPND, 2); 46310339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 1); 46320339a1c2SMark Johnston /* one byte immediate number */ 46330339a1c2SMark Johnston dtrace_imm_opnd(x, wbit, 1, 0); 46340339a1c2SMark Johnston break; 46350339a1c2SMark Johnston } 46360339a1c2SMark Johnston x->d86_numopnds = 2; 46370339a1c2SMark Johnston 46380339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 46390339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 46400339a1c2SMark Johnston L_VEX_RM: 46410339a1c2SMark Johnston vbit = 1; 46420339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, vbit); 46430339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, vbit - 1); 46440339a1c2SMark Johnston 46450339a1c2SMark Johnston break; 46460339a1c2SMark Johnston 46470339a1c2SMark Johnston case VEX_RRM: 46480339a1c2SMark Johnston /* ModR/M.rm := op(VEX.vvvv, ModR/M.reg) */ 46490339a1c2SMark Johnston x->d86_numopnds = 3; 46500339a1c2SMark Johnston 46510339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 46520339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 46530339a1c2SMark Johnston dtrace_get_operand(x, mode, r_m, wbit, 2); 46540339a1c2SMark Johnston /* VEX use the 1's complement form encode the XMM/YMM regs */ 46550339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 46560339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 0); 46570339a1c2SMark Johnston break; 46580339a1c2SMark Johnston 46590339a1c2SMark Johnston case VEX_RMX: 46600339a1c2SMark Johnston /* ModR/M.reg := op(VEX.vvvv, ModR/M.rm) */ 46610339a1c2SMark Johnston x->d86_numopnds = 3; 46620339a1c2SMark Johnston 46630339a1c2SMark Johnston dtrace_get_modrm(x, &mode, ®, &r_m); 46640339a1c2SMark Johnston dtrace_vex_adjust(vex_byte1, mode, ®, &r_m); 46650339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, reg, wbit, 2); 46660339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, (0xF - vex_v), wbit, 1); 46670339a1c2SMark Johnston dtrace_get_operand(x, REG_ONLY, r_m, wbit, 0); 46680339a1c2SMark Johnston break; 46690339a1c2SMark Johnston 46700339a1c2SMark Johnston case VEX_NONE: 46710339a1c2SMark Johnston #ifdef DIS_TEXT 46720339a1c2SMark Johnston if (vex_L) 46730339a1c2SMark Johnston (void) strncpy(x->d86_mnem, "vzeroall", OPLEN); 46740339a1c2SMark Johnston #endif 46750339a1c2SMark Johnston break; 46760339a1c2SMark Johnston /* an invalid op code */ 46770339a1c2SMark Johnston case AM: 46780339a1c2SMark Johnston case DM: 46790339a1c2SMark Johnston case OVERRIDE: 46800339a1c2SMark Johnston case PREFIX: 46810339a1c2SMark Johnston case UNKNOWN: 46820339a1c2SMark Johnston NOMEM; 46830339a1c2SMark Johnston default: 46840339a1c2SMark Johnston goto error; 46850339a1c2SMark Johnston } /* end switch */ 46860339a1c2SMark Johnston if (x->d86_error) 46870339a1c2SMark Johnston goto error; 46880339a1c2SMark Johnston 46890339a1c2SMark Johnston done: 46900339a1c2SMark Johnston #ifdef DIS_MEM 46910339a1c2SMark Johnston /* 46920339a1c2SMark Johnston * compute the size of any memory accessed by the instruction 46930339a1c2SMark Johnston */ 46940339a1c2SMark Johnston if (x->d86_memsize != 0) { 46950339a1c2SMark Johnston return (0); 46960339a1c2SMark Johnston } else if (dp->it_stackop) { 46970339a1c2SMark Johnston switch (opnd_size) { 46980339a1c2SMark Johnston case SIZE16: 46990339a1c2SMark Johnston x->d86_memsize = 2; 47000339a1c2SMark Johnston break; 47010339a1c2SMark Johnston case SIZE32: 47020339a1c2SMark Johnston x->d86_memsize = 4; 47030339a1c2SMark Johnston break; 47040339a1c2SMark Johnston case SIZE64: 47050339a1c2SMark Johnston x->d86_memsize = 8; 47060339a1c2SMark Johnston break; 47070339a1c2SMark Johnston } 47080339a1c2SMark Johnston } else if (nomem || mode == REG_ONLY) { 47090339a1c2SMark Johnston x->d86_memsize = 0; 47100339a1c2SMark Johnston 47110339a1c2SMark Johnston } else if (dp->it_size != 0) { 47120339a1c2SMark Johnston /* 47130339a1c2SMark Johnston * In 64 bit mode descriptor table entries 47140339a1c2SMark Johnston * go up to 10 bytes and popf/pushf are always 8 bytes 47150339a1c2SMark Johnston */ 47160339a1c2SMark Johnston if (x->d86_mode == SIZE64 && dp->it_size == 6) 47170339a1c2SMark Johnston x->d86_memsize = 10; 47180339a1c2SMark Johnston else if (x->d86_mode == SIZE64 && opcode1 == 0x9 && 47190339a1c2SMark Johnston (opcode2 == 0xc || opcode2 == 0xd)) 47200339a1c2SMark Johnston x->d86_memsize = 8; 47210339a1c2SMark Johnston else 47220339a1c2SMark Johnston x->d86_memsize = dp->it_size; 47230339a1c2SMark Johnston 47240339a1c2SMark Johnston } else if (wbit == 0) { 47250339a1c2SMark Johnston x->d86_memsize = 1; 47260339a1c2SMark Johnston 47270339a1c2SMark Johnston } else if (wbit == LONG_OPND) { 47280339a1c2SMark Johnston if (opnd_size == SIZE64) 47290339a1c2SMark Johnston x->d86_memsize = 8; 47300339a1c2SMark Johnston else if (opnd_size == SIZE32) 47310339a1c2SMark Johnston x->d86_memsize = 4; 47320339a1c2SMark Johnston else 47330339a1c2SMark Johnston x->d86_memsize = 2; 47340339a1c2SMark Johnston 47350339a1c2SMark Johnston } else if (wbit == SEG_OPND) { 47360339a1c2SMark Johnston x->d86_memsize = 4; 47370339a1c2SMark Johnston 47380339a1c2SMark Johnston } else { 47390339a1c2SMark Johnston x->d86_memsize = 8; 47400339a1c2SMark Johnston } 47410339a1c2SMark Johnston #endif 47420339a1c2SMark Johnston return (0); 47430339a1c2SMark Johnston 47440339a1c2SMark Johnston error: 47450339a1c2SMark Johnston #ifdef DIS_TEXT 47460339a1c2SMark Johnston (void) strlcat(x->d86_mnem, "undef", OPLEN); 47470339a1c2SMark Johnston #endif 47480339a1c2SMark Johnston return (1); 47490339a1c2SMark Johnston } 47500339a1c2SMark Johnston 47510339a1c2SMark Johnston #ifdef DIS_TEXT 47520339a1c2SMark Johnston 47530339a1c2SMark Johnston /* 47540339a1c2SMark Johnston * Some instructions should have immediate operands printed 47550339a1c2SMark Johnston * as unsigned integers. We compare against this table. 47560339a1c2SMark Johnston */ 47570339a1c2SMark Johnston static char *unsigned_ops[] = { 47580339a1c2SMark Johnston "or", "and", "xor", "test", "in", "out", "lcall", "ljmp", 47590339a1c2SMark Johnston "rcr", "rcl", "ror", "rol", "shl", "shr", "sal", "psr", "psl", 47600339a1c2SMark Johnston 0 47610339a1c2SMark Johnston }; 47620339a1c2SMark Johnston 47630339a1c2SMark Johnston 47640339a1c2SMark Johnston static int 47650339a1c2SMark Johnston isunsigned_op(char *opcode) 47660339a1c2SMark Johnston { 47670339a1c2SMark Johnston char *where; 47680339a1c2SMark Johnston int i; 47690339a1c2SMark Johnston int is_unsigned = 0; 47700339a1c2SMark Johnston 47710339a1c2SMark Johnston /* 47720339a1c2SMark Johnston * Work back to start of last mnemonic, since we may have 47730339a1c2SMark Johnston * prefixes on some opcodes. 47740339a1c2SMark Johnston */ 47750339a1c2SMark Johnston where = opcode + strlen(opcode) - 1; 47760339a1c2SMark Johnston while (where > opcode && *where != ' ') 47770339a1c2SMark Johnston --where; 47780339a1c2SMark Johnston if (*where == ' ') 47790339a1c2SMark Johnston ++where; 47800339a1c2SMark Johnston 47810339a1c2SMark Johnston for (i = 0; unsigned_ops[i]; ++i) { 47820339a1c2SMark Johnston if (strncmp(where, unsigned_ops[i], 47830339a1c2SMark Johnston strlen(unsigned_ops[i]))) 47840339a1c2SMark Johnston continue; 47850339a1c2SMark Johnston is_unsigned = 1; 47860339a1c2SMark Johnston break; 47870339a1c2SMark Johnston } 47880339a1c2SMark Johnston return (is_unsigned); 47890339a1c2SMark Johnston } 47900339a1c2SMark Johnston 47910339a1c2SMark Johnston /* 47920339a1c2SMark Johnston * Print a numeric immediate into end of buf, maximum length buflen. 47930339a1c2SMark Johnston * The immediate may be an address or a displacement. Mask is set 47940339a1c2SMark Johnston * for address size. If the immediate is a "small negative", or 47950339a1c2SMark Johnston * if it's a negative displacement of any magnitude, print as -<absval>. 47960339a1c2SMark Johnston * Respect the "octal" flag. "Small negative" is defined as "in the 47970339a1c2SMark Johnston * interval [NEG_LIMIT, 0)". 47980339a1c2SMark Johnston * 47990339a1c2SMark Johnston * Also, "isunsigned_op()" instructions never print negatives. 48000339a1c2SMark Johnston * 48010339a1c2SMark Johnston * Return whether we decided to print a negative value or not. 48020339a1c2SMark Johnston */ 48030339a1c2SMark Johnston 48040339a1c2SMark Johnston #define NEG_LIMIT -255 48050339a1c2SMark Johnston enum {IMM, DISP}; 48060339a1c2SMark Johnston enum {POS, TRY_NEG}; 48070339a1c2SMark Johnston 48080339a1c2SMark Johnston static int 48090339a1c2SMark Johnston print_imm(dis86_t *dis, uint64_t usv, uint64_t mask, char *buf, 48100339a1c2SMark Johnston size_t buflen, int disp, int try_neg) 48110339a1c2SMark Johnston { 48120339a1c2SMark Johnston int curlen; 48130339a1c2SMark Johnston int64_t sv = (int64_t)usv; 48140339a1c2SMark Johnston int octal = dis->d86_flags & DIS_F_OCTAL; 48150339a1c2SMark Johnston 48160339a1c2SMark Johnston curlen = strlen(buf); 48170339a1c2SMark Johnston 48180339a1c2SMark Johnston if (try_neg == TRY_NEG && sv < 0 && 48190339a1c2SMark Johnston (disp || sv >= NEG_LIMIT) && 48200339a1c2SMark Johnston !isunsigned_op(dis->d86_mnem)) { 48210339a1c2SMark Johnston dis->d86_sprintf_func(buf + curlen, buflen - curlen, 48220339a1c2SMark Johnston octal ? "-0%llo" : "-0x%llx", (-sv) & mask); 48230339a1c2SMark Johnston return (1); 48240339a1c2SMark Johnston } else { 48250339a1c2SMark Johnston if (disp == DISP) 48260339a1c2SMark Johnston dis->d86_sprintf_func(buf + curlen, buflen - curlen, 48270339a1c2SMark Johnston octal ? "+0%llo" : "+0x%llx", usv & mask); 48280339a1c2SMark Johnston else 48290339a1c2SMark Johnston dis->d86_sprintf_func(buf + curlen, buflen - curlen, 48300339a1c2SMark Johnston octal ? "0%llo" : "0x%llx", usv & mask); 48310339a1c2SMark Johnston return (0); 48320339a1c2SMark Johnston 48330339a1c2SMark Johnston } 48340339a1c2SMark Johnston } 48350339a1c2SMark Johnston 48360339a1c2SMark Johnston 48370339a1c2SMark Johnston static int 48380339a1c2SMark Johnston log2(int size) 48390339a1c2SMark Johnston { 48400339a1c2SMark Johnston switch (size) { 48410339a1c2SMark Johnston case 1: return (0); 48420339a1c2SMark Johnston case 2: return (1); 48430339a1c2SMark Johnston case 4: return (2); 48440339a1c2SMark Johnston case 8: return (3); 48450339a1c2SMark Johnston } 48460339a1c2SMark Johnston return (0); 48470339a1c2SMark Johnston } 48480339a1c2SMark Johnston 48490339a1c2SMark Johnston /* ARGSUSED */ 48500339a1c2SMark Johnston void 48510339a1c2SMark Johnston dtrace_disx86_str(dis86_t *dis, uint_t mode, uint64_t pc, char *buf, 48520339a1c2SMark Johnston size_t buflen) 48530339a1c2SMark Johnston { 48540339a1c2SMark Johnston uint64_t reltgt = 0; 48550339a1c2SMark Johnston uint64_t tgt = 0; 48560339a1c2SMark Johnston int curlen; 48570339a1c2SMark Johnston int (*lookup)(void *, uint64_t, char *, size_t); 48580339a1c2SMark Johnston int i; 48590339a1c2SMark Johnston int64_t sv; 48600339a1c2SMark Johnston uint64_t usv, mask, save_mask, save_usv; 48610339a1c2SMark Johnston static uint64_t masks[] = 48620339a1c2SMark Johnston {0xffU, 0xffffU, 0xffffffffU, 0xffffffffffffffffULL}; 48630339a1c2SMark Johnston save_usv = 0; 48640339a1c2SMark Johnston 48650339a1c2SMark Johnston dis->d86_sprintf_func(buf, buflen, "%-6s ", dis->d86_mnem); 48660339a1c2SMark Johnston 48670339a1c2SMark Johnston /* 48680339a1c2SMark Johnston * For PC-relative jumps, the pc is really the next pc after executing 48690339a1c2SMark Johnston * this instruction, so increment it appropriately. 48700339a1c2SMark Johnston */ 48710339a1c2SMark Johnston pc += dis->d86_len; 48720339a1c2SMark Johnston 48730339a1c2SMark Johnston for (i = 0; i < dis->d86_numopnds; i++) { 48740339a1c2SMark Johnston d86opnd_t *op = &dis->d86_opnd[i]; 48750339a1c2SMark Johnston 48760339a1c2SMark Johnston if (i != 0) 48770339a1c2SMark Johnston (void) strlcat(buf, ",", buflen); 48780339a1c2SMark Johnston 48790339a1c2SMark Johnston (void) strlcat(buf, op->d86_prefix, buflen); 48800339a1c2SMark Johnston 48810339a1c2SMark Johnston /* 48820339a1c2SMark Johnston * sv is for the signed, possibly-truncated immediate or 48830339a1c2SMark Johnston * displacement; usv retains the original size and 48840339a1c2SMark Johnston * unsignedness for symbol lookup. 48850339a1c2SMark Johnston */ 48860339a1c2SMark Johnston 48870339a1c2SMark Johnston sv = usv = op->d86_value; 48880339a1c2SMark Johnston 48890339a1c2SMark Johnston /* 48900339a1c2SMark Johnston * About masks: for immediates that represent 48910339a1c2SMark Johnston * addresses, the appropriate display size is 48920339a1c2SMark Johnston * the effective address size of the instruction. 48930339a1c2SMark Johnston * This includes MODE_OFFSET, MODE_IPREL, and 48940339a1c2SMark Johnston * MODE_RIPREL. Immediates that are simply 48950339a1c2SMark Johnston * immediate values should display in the operand's 48960339a1c2SMark Johnston * size, however, since they don't represent addresses. 48970339a1c2SMark Johnston */ 48980339a1c2SMark Johnston 48990339a1c2SMark Johnston /* d86_addr_size is SIZEnn, which is log2(real size) */ 49000339a1c2SMark Johnston mask = masks[dis->d86_addr_size]; 49010339a1c2SMark Johnston 49020339a1c2SMark Johnston /* d86_value_size and d86_imm_bytes are in bytes */ 49030339a1c2SMark Johnston if (op->d86_mode == MODE_SIGNED || 49040339a1c2SMark Johnston op->d86_mode == MODE_IMPLIED) 49050339a1c2SMark Johnston mask = masks[log2(op->d86_value_size)]; 49060339a1c2SMark Johnston 49070339a1c2SMark Johnston switch (op->d86_mode) { 49080339a1c2SMark Johnston 49090339a1c2SMark Johnston case MODE_NONE: 49100339a1c2SMark Johnston 49110339a1c2SMark Johnston (void) strlcat(buf, op->d86_opnd, buflen); 49120339a1c2SMark Johnston break; 49130339a1c2SMark Johnston 49140339a1c2SMark Johnston case MODE_SIGNED: 49150339a1c2SMark Johnston case MODE_IMPLIED: 49160339a1c2SMark Johnston case MODE_OFFSET: 49170339a1c2SMark Johnston 49180339a1c2SMark Johnston tgt = usv; 49190339a1c2SMark Johnston 49200339a1c2SMark Johnston if (dis->d86_seg_prefix) 49210339a1c2SMark Johnston (void) strlcat(buf, dis->d86_seg_prefix, 49220339a1c2SMark Johnston buflen); 49230339a1c2SMark Johnston 49240339a1c2SMark Johnston if (op->d86_mode == MODE_SIGNED || 49250339a1c2SMark Johnston op->d86_mode == MODE_IMPLIED) { 49260339a1c2SMark Johnston (void) strlcat(buf, "$", buflen); 49270339a1c2SMark Johnston } 49280339a1c2SMark Johnston 49290339a1c2SMark Johnston if (print_imm(dis, usv, mask, buf, buflen, 49300339a1c2SMark Johnston IMM, TRY_NEG) && 49310339a1c2SMark Johnston (op->d86_mode == MODE_SIGNED || 49320339a1c2SMark Johnston op->d86_mode == MODE_IMPLIED)) { 49330339a1c2SMark Johnston 49340339a1c2SMark Johnston /* 49350339a1c2SMark Johnston * We printed a negative value for an 49360339a1c2SMark Johnston * immediate that wasn't a 49370339a1c2SMark Johnston * displacement. Note that fact so we can 49380339a1c2SMark Johnston * print the positive value as an 49390339a1c2SMark Johnston * annotation. 49400339a1c2SMark Johnston */ 49410339a1c2SMark Johnston 49420339a1c2SMark Johnston save_usv = usv; 49430339a1c2SMark Johnston save_mask = mask; 49440339a1c2SMark Johnston } 49450339a1c2SMark Johnston (void) strlcat(buf, op->d86_opnd, buflen); 49460339a1c2SMark Johnston 49470339a1c2SMark Johnston break; 49480339a1c2SMark Johnston 49490339a1c2SMark Johnston case MODE_IPREL: 49500339a1c2SMark Johnston case MODE_RIPREL: 49510339a1c2SMark Johnston 49520339a1c2SMark Johnston reltgt = pc + sv; 49530339a1c2SMark Johnston 49540339a1c2SMark Johnston switch (mode) { 49550339a1c2SMark Johnston case SIZE16: 49560339a1c2SMark Johnston reltgt = (uint16_t)reltgt; 49570339a1c2SMark Johnston break; 49580339a1c2SMark Johnston case SIZE32: 49590339a1c2SMark Johnston reltgt = (uint32_t)reltgt; 49600339a1c2SMark Johnston break; 49610339a1c2SMark Johnston } 49620339a1c2SMark Johnston 49630339a1c2SMark Johnston (void) print_imm(dis, usv, mask, buf, buflen, 49640339a1c2SMark Johnston DISP, TRY_NEG); 49650339a1c2SMark Johnston 49660339a1c2SMark Johnston if (op->d86_mode == MODE_RIPREL) 49670339a1c2SMark Johnston (void) strlcat(buf, "(%rip)", buflen); 49680339a1c2SMark Johnston break; 49690339a1c2SMark Johnston } 49700339a1c2SMark Johnston } 49710339a1c2SMark Johnston 49720339a1c2SMark Johnston /* 49730339a1c2SMark Johnston * The symbol lookups may result in false positives, 49740339a1c2SMark Johnston * particularly on object files, where small numbers may match 49750339a1c2SMark Johnston * the 0-relative non-relocated addresses of symbols. 49760339a1c2SMark Johnston */ 49770339a1c2SMark Johnston 49780339a1c2SMark Johnston lookup = dis->d86_sym_lookup; 49790339a1c2SMark Johnston if (tgt != 0) { 49800339a1c2SMark Johnston if ((dis->d86_flags & DIS_F_NOIMMSYM) == 0 && 49810339a1c2SMark Johnston lookup(dis->d86_data, tgt, NULL, 0) == 0) { 49820339a1c2SMark Johnston (void) strlcat(buf, "\t<", buflen); 49830339a1c2SMark Johnston curlen = strlen(buf); 49840339a1c2SMark Johnston lookup(dis->d86_data, tgt, buf + curlen, 49850339a1c2SMark Johnston buflen - curlen); 49860339a1c2SMark Johnston (void) strlcat(buf, ">", buflen); 49870339a1c2SMark Johnston } 49880339a1c2SMark Johnston 49890339a1c2SMark Johnston /* 49900339a1c2SMark Johnston * If we printed a negative immediate above, print the 49910339a1c2SMark Johnston * positive in case our heuristic was unhelpful 49920339a1c2SMark Johnston */ 49930339a1c2SMark Johnston if (save_usv) { 49940339a1c2SMark Johnston (void) strlcat(buf, "\t<", buflen); 49950339a1c2SMark Johnston (void) print_imm(dis, save_usv, save_mask, buf, buflen, 49960339a1c2SMark Johnston IMM, POS); 49970339a1c2SMark Johnston (void) strlcat(buf, ">", buflen); 49980339a1c2SMark Johnston } 49990339a1c2SMark Johnston } 50000339a1c2SMark Johnston 50010339a1c2SMark Johnston if (reltgt != 0) { 50020339a1c2SMark Johnston /* Print symbol or effective address for reltgt */ 50030339a1c2SMark Johnston 50040339a1c2SMark Johnston (void) strlcat(buf, "\t<", buflen); 50050339a1c2SMark Johnston curlen = strlen(buf); 50060339a1c2SMark Johnston lookup(dis->d86_data, reltgt, buf + curlen, 50070339a1c2SMark Johnston buflen - curlen); 50080339a1c2SMark Johnston (void) strlcat(buf, ">", buflen); 50090339a1c2SMark Johnston } 50100339a1c2SMark Johnston } 50110339a1c2SMark Johnston 50120339a1c2SMark Johnston #endif /* DIS_TEXT */ 5013