X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=opcodes%2Fi386-dis.c;h=dda176cae8cdbfa885f9f5eb77daf92ce7aabc7f;hb=876d4bfa30530cfcddc152a1ae47f8045d80fd47;hp=d0626dd200374a101c7dd7517d801097f56b5036;hpb=7967e09e27742a39425d8f0aaf563f1bdc99bf61;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index d0626dd200..dda176cae8 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -1,22 +1,24 @@ /* Print i386 instructions for GDB, the GNU debugger. Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. - This file is part of GDB. + This file is part of the GNU opcodes library. - This program is free software; you can redistribute it and/or modify + This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation; either version 3, or (at your option) + any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + /* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu) July 1988 @@ -50,6 +52,7 @@ static void oappend (const char *); static void append_seg (void); static void OP_indirE (int, int); static void print_operand_value (char *, int, bfd_vma); +static void print_displacement (char *, bfd_vma); static void OP_E (int, int); static void OP_G (int, int); static bfd_vma get64 (void); @@ -57,6 +60,7 @@ static bfd_signed_vma get32 (void); static bfd_signed_vma get32s (void); static int get16 (void); static void set_op (bfd_vma, int); +static void OP_Skip_MODRM (int, int); static void OP_REG (int, int); static void OP_IMREG (int, int); static void OP_I (int, int); @@ -83,21 +87,20 @@ static void OP_MXC (int,int); static void OP_MS (int, int); static void OP_XS (int, int); static void OP_M (int, int); -static void OP_VMX (int, int); -static void OP_0fae (int, int); static void OP_0f07 (int, int); +static void OP_Monitor (int, int); +static void OP_Mwait (int, int); static void NOP_Fixup1 (int, int); static void NOP_Fixup2 (int, int); static void OP_3DNowSuffix (int, int); static void OP_SIMD_Suffix (int, int); -static void SIMD_Fixup (int, int); -static void PNI_Fixup (int, int); static void SVME_Fixup (int, int); static void INVLPG_Fixup (int, int); static void BadOp (void); -static void VMX_Fixup (int, int); static void REP_Fixup (int, int); static void CMPXCHG8B_Fixup (int, int); +static void XMM_Fixup (int, int); +static void CRC32_Fixup (int, int); struct dis_private { /* Points to first byte not fetched. */ @@ -200,6 +203,9 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define Ed { OP_E, d_mode } #define Edq { OP_E, dq_mode } #define Edqw { OP_E, dqw_mode } +#define Edqb { OP_E, dqb_mode } +#define Edqd { OP_E, dqd_mode } +#define Eq { OP_E, q_mode } #define indirEv { OP_indirE, stack_v_mode } #define indirEp { OP_indirE, f_mode } #define stackEv { OP_E, stack_v_mode } @@ -207,6 +213,8 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define Ew { OP_E, w_mode } #define M { OP_M, 0 } /* lea, lgdt, etc. */ #define Ma { OP_M, v_mode } +#define Mb { OP_M, b_mode } +#define Md { OP_M, d_mode } #define Mp { OP_M, f_mode } /* 32 or 48 bit memory operand for LDS, LES etc */ #define Mq { OP_M, q_mode } #define Gb { OP_G, b_mode } @@ -229,6 +237,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define Cm { OP_C, m_mode } #define Dm { OP_D, m_mode } #define Td { OP_T, d_mode } +#define Skip_MODRM { OP_Skip_MODRM, 0 } #define RMeAX { OP_REG, eAX_reg } #define RMeBX { OP_REG, eBX_reg } @@ -301,14 +310,19 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define MX { OP_MMX, 0 } #define XM { OP_XMM, 0 } #define EM { OP_EM, v_mode } -#define EX { OP_EX, v_mode } +#define EMd { OP_EM, d_mode } +#define EMx { OP_EM, x_mode } +#define EXw { OP_EX, w_mode } +#define EXd { OP_EX, d_mode } +#define EXq { OP_EX, q_mode } +#define EXx { OP_EX, x_mode } #define MS { OP_MS, v_mode } #define XS { OP_XS, v_mode } -#define EMC { OP_EMC, v_mode } +#define EMCq { OP_EMC, q_mode } #define MXC { OP_MXC, 0 } -#define VM { OP_VMX, q_mode } #define OPSUF { OP_3DNowSuffix, 0 } #define OPSIMD { OP_SIMD_Suffix, 0 } +#define XMM0 { XMM_Fixup, 0 } /* Used handle "rep" prefix for string instructions. */ #define Xbr { REP_Fixup, eSI_reg } @@ -345,6 +359,8 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define stack_v_mode 15 /* v_mode for stack-related opcodes. */ #define z_mode 16 /* non-quad operand size depends on prefixes */ #define o_mode 17 /* 16-byte operand */ +#define dqb_mode 18 /* registers like dq_mode, memory like b_mode. */ +#define dqd_mode 19 /* registers like dq_mode, memory like d_mode. */ #define es_reg 100 #define cs_reg 101 @@ -397,6 +413,8 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define USE_PREFIX_USER_TABLE 3 #define X86_64_SPECIAL 4 #define IS_3BYTE_OPCODE 5 +#define USE_OPC_EXT_TABLE 6 +#define USE_OPC_EXT_RM_TABLE 7 #define FLOAT NULL, { { NULL, FLOATCODE } } @@ -468,6 +486,68 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define PREGRP36 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 36 } } #define PREGRP37 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 37 } } #define PREGRP38 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 38 } } +#define PREGRP39 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 39 } } +#define PREGRP40 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 40 } } +#define PREGRP41 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 41 } } +#define PREGRP42 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 42 } } +#define PREGRP43 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 43 } } +#define PREGRP44 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 44 } } +#define PREGRP45 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 45 } } +#define PREGRP46 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 46 } } +#define PREGRP47 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 47 } } +#define PREGRP48 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 48 } } +#define PREGRP49 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 49 } } +#define PREGRP50 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 50 } } +#define PREGRP51 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 51 } } +#define PREGRP52 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 52 } } +#define PREGRP53 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 53 } } +#define PREGRP54 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 54 } } +#define PREGRP55 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 55 } } +#define PREGRP56 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 56 } } +#define PREGRP57 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 57 } } +#define PREGRP58 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 58 } } +#define PREGRP59 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 59 } } +#define PREGRP60 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 60 } } +#define PREGRP61 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 61 } } +#define PREGRP62 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 62 } } +#define PREGRP63 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 63 } } +#define PREGRP64 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 64 } } +#define PREGRP65 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 65 } } +#define PREGRP66 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 66 } } +#define PREGRP67 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 67 } } +#define PREGRP68 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 68 } } +#define PREGRP69 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 69 } } +#define PREGRP70 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 70 } } +#define PREGRP71 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 71 } } +#define PREGRP72 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 72 } } +#define PREGRP73 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 73 } } +#define PREGRP74 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 74 } } +#define PREGRP75 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 75 } } +#define PREGRP76 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 76 } } +#define PREGRP77 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 77 } } +#define PREGRP78 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 78 } } +#define PREGRP79 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 79 } } +#define PREGRP80 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 80 } } +#define PREGRP81 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 81 } } +#define PREGRP82 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 82 } } +#define PREGRP83 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 83 } } +#define PREGRP84 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 84 } } +#define PREGRP85 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 85 } } +#define PREGRP86 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 86 } } +#define PREGRP87 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 87 } } +#define PREGRP88 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 88 } } +#define PREGRP89 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 89 } } +#define PREGRP90 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 90 } } +#define PREGRP91 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 91 } } +#define PREGRP92 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 92 } } +#define PREGRP93 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 93 } } +#define PREGRP94 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 94 } } +#define PREGRP95 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 95 } } +#define PREGRP96 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 96 } } +#define PREGRP97 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 97 } } +#define PREGRP98 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 98 } } +#define PREGRP99 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 99 } } +#define PREGRP100 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 100 } } #define X86_64_0 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 0 } } @@ -478,6 +558,51 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define THREE_BYTE_0 NULL, { { NULL, IS_3BYTE_OPCODE }, { NULL, 0 } } #define THREE_BYTE_1 NULL, { { NULL, IS_3BYTE_OPCODE }, { NULL, 1 } } +#define OPC_EXT_0 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 0 } } +#define OPC_EXT_1 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 1 } } +#define OPC_EXT_2 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 2 } } +#define OPC_EXT_3 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 3 } } +#define OPC_EXT_4 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 4 } } +#define OPC_EXT_5 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 5 } } +#define OPC_EXT_6 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 6 } } +#define OPC_EXT_7 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 7 } } +#define OPC_EXT_8 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 8 } } +#define OPC_EXT_9 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 9 } } +#define OPC_EXT_10 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 10 } } +#define OPC_EXT_11 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 11 } } +#define OPC_EXT_12 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 12 } } +#define OPC_EXT_13 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 13 } } +#define OPC_EXT_14 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 14 } } +#define OPC_EXT_15 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 15 } } +#define OPC_EXT_16 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 16 } } +#define OPC_EXT_17 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 17 } } +#define OPC_EXT_18 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 18 } } +#define OPC_EXT_19 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 19 } } +#define OPC_EXT_20 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 20 } } +#define OPC_EXT_21 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 21 } } +#define OPC_EXT_22 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 22 } } +#define OPC_EXT_23 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 23 } } +#define OPC_EXT_24 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 24 } } +#define OPC_EXT_25 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 25 } } +#define OPC_EXT_26 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 26 } } +#define OPC_EXT_27 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 27 } } +#define OPC_EXT_28 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 28 } } +#define OPC_EXT_29 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 29 } } +#define OPC_EXT_30 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 30 } } +#define OPC_EXT_31 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 31 } } +#define OPC_EXT_32 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 32 } } +#define OPC_EXT_33 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 33 } } +#define OPC_EXT_34 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 34 } } +#define OPC_EXT_35 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 35 } } +#define OPC_EXT_36 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 36 } } +#define OPC_EXT_37 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 37 } } + +#define OPC_EXT_RM_0 NULL, { { NULL, USE_OPC_EXT_RM_TABLE }, { NULL, 0 } } +#define OPC_EXT_RM_1 NULL, { { NULL, USE_OPC_EXT_RM_TABLE }, { NULL, 1 } } +#define OPC_EXT_RM_2 NULL, { { NULL, USE_OPC_EXT_RM_TABLE }, { NULL, 2 } } +#define OPC_EXT_RM_3 NULL, { { NULL, USE_OPC_EXT_RM_TABLE }, { NULL, 3 } } +#define OPC_EXT_RM_4 NULL, { { NULL, USE_OPC_EXT_RM_TABLE }, { NULL, 4 } } + typedef void (*op_rtn) (int bytemode, int sizeflag); struct dis386 { @@ -503,6 +628,7 @@ struct dis386 { 'I' => honor following macro letter even in Intel mode (implemented only . for some of the macro letters) 'J' => print 'l' + 'K' => print 'd' or 'q' if rex prefix is present. 'L' => print 'l' if suffix_always is true 'N' => print 'n' if instruction has no wait "prefix" 'O' => print 'd' or 'o' (or 'q' in Intel mode) @@ -689,7 +815,7 @@ static const struct dis386 dis386[] = { { "movB", { Gb, Eb } }, { "movS", { Gv, Ev } }, { "movD", { Sv, Sw } }, - { "leaS", { Gv, M } }, + { OPC_EXT_0 }, { "movD", { Sw, Sv } }, { GRP1a }, /* 90 */ @@ -751,8 +877,8 @@ static const struct dis386 dis386[] = { { GRP2S }, { "retT", { Iw } }, { "retT", { XX } }, - { "les{S|}", { Gv, Mp } }, - { "ldsS", { Gv, Mp } }, + { OPC_EXT_1 }, + { OPC_EXT_2 }, { GRP11_C6 }, { GRP11_C7 }, /* c8 */ @@ -843,11 +969,11 @@ static const struct dis386 dis386_twobyte[] = { { PREGRP8 }, { PREGRP9 }, { PREGRP30 }, - { "movlpX", { EX, XM, { SIMD_Fixup, 'h' } } }, - { "unpcklpX", { XM, EX } }, - { "unpckhpX", { XM, EX } }, + { OPC_EXT_34 }, + { "unpcklpX", { XM, EXq } }, + { "unpckhpX", { XM, EXq } }, { PREGRP31 }, - { "movhpX", { EX, XM, { SIMD_Fixup, 'l' } } }, + { OPC_EXT_35 }, /* 18 */ { GRP16 }, { "(bad)", { XX } }, @@ -867,14 +993,14 @@ static const struct dis386 dis386_twobyte[] = { { "movL", { Td, Rd } }, { "(bad)", { XX } }, /* 28 */ - { "movapX", { XM, EX } }, - { "movapX", { EX, XM } }, + { "movapX", { XM, EXx } }, + { "movapX", { EXx, XM } }, { PREGRP2 }, { PREGRP33 }, { PREGRP4 }, { PREGRP3 }, - { "ucomisX", { XM,EX } }, - { "comisX", { XM,EX } }, + { PREGRP93 }, + { PREGRP94 }, /* 30 */ { "wrmsr", { XX } }, { "rdtsc", { XX } }, @@ -916,10 +1042,10 @@ static const struct dis386 dis386_twobyte[] = { { PREGRP13 }, { PREGRP12 }, { PREGRP11 }, - { "andpX", { XM, EX } }, - { "andnpX", { XM, EX } }, - { "orpX", { XM, EX } }, - { "xorpX", { XM, EX } }, + { "andpX", { XM, EXx } }, + { "andnpX", { XM, EXx } }, + { "orpX", { XM, EXx } }, + { "xorpX", { XM, EXx } }, /* 58 */ { PREGRP0 }, { PREGRP10 }, @@ -930,9 +1056,9 @@ static const struct dis386 dis386_twobyte[] = { { PREGRP5 }, { PREGRP6 }, /* 60 */ - { "punpcklbw", { MX, EM } }, - { "punpcklwd", { MX, EM } }, - { "punpckldq", { MX, EM } }, + { PREGRP95 }, + { PREGRP96 }, + { PREGRP97 }, { "packsswb", { MX, EM } }, { "pcmpgtb", { MX, EM } }, { "pcmpgtw", { MX, EM } }, @@ -945,7 +1071,7 @@ static const struct dis386 dis386_twobyte[] = { { "packssdw", { MX, EM } }, { PREGRP26 }, { PREGRP24 }, - { "movd", { MX, Edq } }, + { "movK", { MX, Edq } }, { PREGRP19 }, /* 70 */ { PREGRP22 }, @@ -1022,10 +1148,10 @@ static const struct dis386 dis386_twobyte[] = { /* b0 */ { "cmpxchgB", { Eb, Gb } }, { "cmpxchgS", { Ev, Gv } }, - { "lssS", { Gv, Mp } }, + { OPC_EXT_3 }, { "btrS", { Ev, Gv } }, - { "lfsS", { Gv, Mp } }, - { "lgsS", { Gv, Mp } }, + { OPC_EXT_4 }, + { OPC_EXT_5 }, { "movz{bR|x|bR|x}", { Gv, Eb } }, { "movz{wR|x|wR|x}", { Gv, Ew } }, /* yes, there really is movzww ! */ /* b8 */ @@ -1044,7 +1170,7 @@ static const struct dis386 dis386_twobyte[] = { { "movntiS", { Ev, Gv } }, { "pinsrw", { MX, Edqw, Ib } }, { "pextrw", { Gdq, MS, Ib } }, - { "shufpX", { XM, EX, Ib } }, + { "shufpX", { XM, EXx, Ib } }, { GRP9 }, /* c8 */ { "bswap", { RMeAX } }, @@ -1157,231 +1283,23 @@ static const unsigned char twobyte_has_modrm[256] = { /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ }; -static const unsigned char twobyte_uses_DATA_prefix[256] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /* ------------------------------- */ - /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ - /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */ - /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 3f */ - /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ - /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */ - /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */ - /* 70 */ 1,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1, /* 7f */ - /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ - /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ - /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ - /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ - /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */ - /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 /* ff */ - /* ------------------------------- */ - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -}; - -static const unsigned char twobyte_uses_REPNZ_prefix[256] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /* ------------------------------- */ - /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ - /* 10 */ 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ - /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ - /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ - /* 50 */ 0,1,0,0,0,0,0,0,1,1,1,0,1,1,1,1, /* 5f */ - /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ - /* 70 */ 1,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0, /* 7f */ - /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ - /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ - /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ - /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ - /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */ - /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ - /* ------------------------------- */ - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -}; - -static const unsigned char twobyte_uses_REPZ_prefix[256] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /* ------------------------------- */ - /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ - /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */ - /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ - /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ - /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */ - /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, /* 6f */ - /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, /* 7f */ - /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ - /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ - /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ - /* b0 */ 0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, /* bf */ - /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */ - /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ - /* ------------------------------- */ - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -}; - -/* This is used to determine if opcode 0f 38 XX uses DATA prefix. */ -static const unsigned char threebyte_0x38_uses_DATA_prefix[256] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /* ------------------------------- */ - /* 00 */ 1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0, /* 0f */ - /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0, /* 1f */ - /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ - /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ - /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ - /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ - /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ - /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ - /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ - /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ - /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ - /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ - /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ - /* ------------------------------- */ - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -}; - -/* This is used to determine if opcode 0f 38 XX uses REPNZ prefix. */ -static const unsigned char threebyte_0x38_uses_REPNZ_prefix[256] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /* ------------------------------- */ - /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ - /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ - /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ - /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ - /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ - /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ - /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ - /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ - /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ - /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ - /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ - /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ - /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ - /* ------------------------------- */ - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -}; - -/* This is used to determine if opcode 0f 38 XX uses REPZ prefix. */ -static const unsigned char threebyte_0x38_uses_REPZ_prefix[256] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /* ------------------------------- */ - /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ - /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ - /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ - /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ - /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ - /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ - /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ - /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ - /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ - /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ - /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ - /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ - /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ - /* ------------------------------- */ - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -}; - -/* This is used to determine if opcode 0f 3a XX uses DATA prefix. */ -static const unsigned char threebyte_0x3a_uses_DATA_prefix[256] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /* ------------------------------- */ - /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, /* 0f */ - /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ - /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ - /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ - /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ - /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ - /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ - /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ - /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ - /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ - /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ - /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ - /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ - /* ------------------------------- */ - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -}; - -/* This is used to determine if opcode 0f 3a XX uses REPNZ prefix. */ -static const unsigned char threebyte_0x3a_uses_REPNZ_prefix[256] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /* ------------------------------- */ - /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ - /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ - /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ - /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ - /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ - /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ - /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ - /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ - /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ - /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ - /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ - /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ - /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ - /* ------------------------------- */ - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -}; - -/* This is used to determine if opcode 0f 3a XX uses REPZ prefix. */ -static const unsigned char threebyte_0x3a_uses_REPZ_prefix[256] = { - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ - /* ------------------------------- */ - /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ - /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ - /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */ - /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ - /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ - /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ - /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ - /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ - /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ - /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ - /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ - /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ - /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ - /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ - /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ - /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ - /* ------------------------------- */ - /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ -}; - static char obuf[100]; static char *obufp; static char scratchbuf[100]; static unsigned char *start_codep; static unsigned char *insn_codep; static unsigned char *codep; +static const char *lock_prefix; +static const char *data_prefix; +static const char *addr_prefix; +static const char *repz_prefix; +static const char *repnz_prefix; static disassemble_info *the_info; static struct { int mod; - int rm; int reg; + int rm; } modrm; static unsigned char need_modrm; @@ -1619,14 +1537,14 @@ static const struct dis386 grps[][8] = { }, /* GRP7 */ { - { "sgdt{Q|IQ||}", { { VMX_Fixup, 0 } } }, - { "sidt{Q|IQ||}", { { PNI_Fixup, 0 } } }, - { "lgdt{Q|Q||}", { M } }, + { OPC_EXT_6 }, + { OPC_EXT_7 }, + { OPC_EXT_8 }, { "lidt{Q|Q||}", { { SVME_Fixup, 0 } } }, { "smswD", { Sv } }, { "(bad)", { XX } }, { "lmsw", { Ew } }, - { "invlpg", { { INVLPG_Fixup, w_mode } } }, + { "invlpg", { { INVLPG_Fixup, 0 } } }, }, /* GRP8 */ { @@ -1647,8 +1565,8 @@ static const struct dis386 grps[][8] = { { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, - { "", { VM } }, /* See OP_VMX. */ - { "vmptrst", { Mq } }, + { OPC_EXT_9 }, + { OPC_EXT_10 }, }, /* GRP11_C6 */ { @@ -1676,56 +1594,56 @@ static const struct dis386 grps[][8] = { { { "(bad)", { XX } }, { "(bad)", { XX } }, - { "psrlw", { MS, Ib } }, + { OPC_EXT_11 }, { "(bad)", { XX } }, - { "psraw", { MS, Ib } }, + { OPC_EXT_12 }, { "(bad)", { XX } }, - { "psllw", { MS, Ib } }, + { OPC_EXT_13 }, { "(bad)", { XX } }, }, /* GRP13 */ { { "(bad)", { XX } }, { "(bad)", { XX } }, - { "psrld", { MS, Ib } }, + { OPC_EXT_14 }, { "(bad)", { XX } }, - { "psrad", { MS, Ib } }, + { OPC_EXT_15 }, { "(bad)", { XX } }, - { "pslld", { MS, Ib } }, + { OPC_EXT_16 }, { "(bad)", { XX } }, }, /* GRP14 */ { { "(bad)", { XX } }, { "(bad)", { XX } }, - { "psrlq", { MS, Ib } }, - { "psrldq", { MS, Ib } }, + { OPC_EXT_17 }, + { OPC_EXT_18 }, { "(bad)", { XX } }, { "(bad)", { XX } }, - { "psllq", { MS, Ib } }, - { "pslldq", { MS, Ib } }, + { OPC_EXT_19 }, + { OPC_EXT_20 }, }, /* GRP15 */ { - { "fxsave", { Ev } }, - { "fxrstor", { Ev } }, - { "ldmxcsr", { Ev } }, - { "stmxcsr", { Ev } }, - { "(bad)", { XX } }, - { "lfence", { { OP_0fae, 0 } } }, - { "mfence", { { OP_0fae, 0 } } }, - { "clflush", { { OP_0fae, 0 } } }, + { OPC_EXT_21 }, + { OPC_EXT_22 }, + { OPC_EXT_23 }, + { OPC_EXT_24 }, + { "(bad)", { XX } }, + { OPC_EXT_25 }, + { OPC_EXT_26 }, + { OPC_EXT_27 }, }, /* GRP16 */ { - { "prefetchnta", { Ev } }, - { "prefetcht0", { Ev } }, - { "prefetcht1", { Ev } }, - { "prefetcht2", { Ev } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { OPC_EXT_28 }, + { OPC_EXT_29 }, + { OPC_EXT_30 }, + { OPC_EXT_31 }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, }, /* GRPAMD */ { @@ -1765,178 +1683,178 @@ static const struct dis386 grps[][8] = { static const struct dis386 prefix_user_table[][4] = { /* PREGRP0 */ { - { "addps", { XM, EX } }, - { "addss", { XM, EX } }, - { "addpd", { XM, EX } }, - { "addsd", { XM, EX } }, + { "addps", { XM, EXx } }, + { "addss", { XM, EXd } }, + { "addpd", { XM, EXx } }, + { "addsd", { XM, EXq } }, }, /* PREGRP1 */ { - { "", { XM, EX, OPSIMD } }, /* See OP_SIMD_SUFFIX. */ - { "", { XM, EX, OPSIMD } }, - { "", { XM, EX, OPSIMD } }, - { "", { XM, EX, OPSIMD } }, + { "", { XM, EXx, OPSIMD } }, /* See OP_SIMD_SUFFIX. */ + { "", { XM, EXd, OPSIMD } }, + { "", { XM, EXx, OPSIMD } }, + { "", { XM, EXq, OPSIMD } }, }, /* PREGRP2 */ { - { "cvtpi2ps", { XM, EMC } }, + { "cvtpi2ps", { XM, EMCq } }, { "cvtsi2ssY", { XM, Ev } }, - { "cvtpi2pd", { XM, EMC } }, + { "cvtpi2pd", { XM, EMCq } }, { "cvtsi2sdY", { XM, Ev } }, }, /* PREGRP3 */ { - { "cvtps2pi", { MXC, EX } }, - { "cvtss2siY", { Gv, EX } }, - { "cvtpd2pi", { MXC, EX } }, - { "cvtsd2siY", { Gv, EX } }, + { "cvtps2pi", { MXC, EXq } }, + { "cvtss2siY", { Gv, EXd } }, + { "cvtpd2pi", { MXC, EXx } }, + { "cvtsd2siY", { Gv, EXq } }, }, /* PREGRP4 */ { - { "cvttps2pi", { MXC, EX } }, - { "cvttss2siY", { Gv, EX } }, - { "cvttpd2pi", { MXC, EX } }, - { "cvttsd2siY", { Gv, EX } }, + { "cvttps2pi", { MXC, EXq } }, + { "cvttss2siY", { Gv, EXd } }, + { "cvttpd2pi", { MXC, EXx } }, + { "cvttsd2siY", { Gv, EXq } }, }, /* PREGRP5 */ { - { "divps", { XM, EX } }, - { "divss", { XM, EX } }, - { "divpd", { XM, EX } }, - { "divsd", { XM, EX } }, + { "divps", { XM, EXx } }, + { "divss", { XM, EXd } }, + { "divpd", { XM, EXx } }, + { "divsd", { XM, EXq } }, }, /* PREGRP6 */ { - { "maxps", { XM, EX } }, - { "maxss", { XM, EX } }, - { "maxpd", { XM, EX } }, - { "maxsd", { XM, EX } }, + { "maxps", { XM, EXx } }, + { "maxss", { XM, EXd } }, + { "maxpd", { XM, EXx } }, + { "maxsd", { XM, EXq } }, }, /* PREGRP7 */ { - { "minps", { XM, EX } }, - { "minss", { XM, EX } }, - { "minpd", { XM, EX } }, - { "minsd", { XM, EX } }, + { "minps", { XM, EXx } }, + { "minss", { XM, EXd } }, + { "minpd", { XM, EXx } }, + { "minsd", { XM, EXq } }, }, /* PREGRP8 */ { - { "movups", { XM, EX } }, - { "movss", { XM, EX } }, - { "movupd", { XM, EX } }, - { "movsd", { XM, EX } }, + { "movups", { XM, EXx } }, + { "movss", { XM, EXd } }, + { "movupd", { XM, EXx } }, + { "movsd", { XM, EXq } }, }, /* PREGRP9 */ { - { "movups", { EX, XM } }, - { "movss", { EX, XM } }, - { "movupd", { EX, XM } }, - { "movsd", { EX, XM } }, + { "movups", { EXx, XM } }, + { "movss", { EXd, XM } }, + { "movupd", { EXx, XM } }, + { "movsd", { EXq, XM } }, }, /* PREGRP10 */ { - { "mulps", { XM, EX } }, - { "mulss", { XM, EX } }, - { "mulpd", { XM, EX } }, - { "mulsd", { XM, EX } }, + { "mulps", { XM, EXx } }, + { "mulss", { XM, EXd } }, + { "mulpd", { XM, EXx } }, + { "mulsd", { XM, EXq } }, }, /* PREGRP11 */ { - { "rcpps", { XM, EX } }, - { "rcpss", { XM, EX } }, - { "(bad)", { XM, EX } }, - { "(bad)", { XM, EX } }, + { "rcpps", { XM, EXx } }, + { "rcpss", { XM, EXd } }, + { "(bad)", { XM, EXx } }, + { "(bad)", { XM, EXx } }, }, /* PREGRP12 */ { - { "rsqrtps",{ XM, EX } }, - { "rsqrtss",{ XM, EX } }, - { "(bad)", { XM, EX } }, - { "(bad)", { XM, EX } }, + { "rsqrtps",{ XM, EXx } }, + { "rsqrtss",{ XM, EXd } }, + { "(bad)", { XM, EXx } }, + { "(bad)", { XM, EXx } }, }, /* PREGRP13 */ { - { "sqrtps", { XM, EX } }, - { "sqrtss", { XM, EX } }, - { "sqrtpd", { XM, EX } }, - { "sqrtsd", { XM, EX } }, + { "sqrtps", { XM, EXx } }, + { "sqrtss", { XM, EXd } }, + { "sqrtpd", { XM, EXx } }, + { "sqrtsd", { XM, EXq } }, }, /* PREGRP14 */ { - { "subps", { XM, EX } }, - { "subss", { XM, EX } }, - { "subpd", { XM, EX } }, - { "subsd", { XM, EX } }, + { "subps", { XM, EXx } }, + { "subss", { XM, EXd } }, + { "subpd", { XM, EXx } }, + { "subsd", { XM, EXq } }, }, /* PREGRP15 */ { - { "(bad)", { XM, EX } }, - { "cvtdq2pd", { XM, EX } }, - { "cvttpd2dq", { XM, EX } }, - { "cvtpd2dq", { XM, EX } }, + { "(bad)", { XM, EXx } }, + { "cvtdq2pd", { XM, EXq } }, + { "cvttpd2dq", { XM, EXx } }, + { "cvtpd2dq", { XM, EXx } }, }, /* PREGRP16 */ { - { "cvtdq2ps", { XM, EX } }, - { "cvttps2dq", { XM, EX } }, - { "cvtps2dq", { XM, EX } }, - { "(bad)", { XM, EX } }, + { "cvtdq2ps", { XM, EXx } }, + { "cvttps2dq", { XM, EXx } }, + { "cvtps2dq", { XM, EXx } }, + { "(bad)", { XM, EXx } }, }, /* PREGRP17 */ { - { "cvtps2pd", { XM, EX } }, - { "cvtss2sd", { XM, EX } }, - { "cvtpd2ps", { XM, EX } }, - { "cvtsd2ss", { XM, EX } }, + { "cvtps2pd", { XM, EXq } }, + { "cvtss2sd", { XM, EXd } }, + { "cvtpd2ps", { XM, EXx } }, + { "cvtsd2ss", { XM, EXq } }, }, /* PREGRP18 */ { { "maskmovq", { MX, MS } }, - { "(bad)", { XM, EX } }, + { "(bad)", { XM, EXx } }, { "maskmovdqu", { XM, XS } }, - { "(bad)", { XM, EX } }, + { "(bad)", { XM, EXx } }, }, /* PREGRP19 */ { { "movq", { MX, EM } }, - { "movdqu", { XM, EX } }, - { "movdqa", { XM, EX } }, - { "(bad)", { XM, EX } }, + { "movdqu", { XM, EXx } }, + { "movdqa", { XM, EXx } }, + { "(bad)", { XM, EXx } }, }, /* PREGRP20 */ { { "movq", { EM, MX } }, - { "movdqu", { EX, XM } }, - { "movdqa", { EX, XM } }, - { "(bad)", { EX, XM } }, + { "movdqu", { EXx, XM } }, + { "movdqa", { EXx, XM } }, + { "(bad)", { EXx, XM } }, }, /* PREGRP21 */ { - { "(bad)", { EX, XM } }, + { "(bad)", { EXx, XM } }, { "movq2dq",{ XM, MS } }, - { "movq", { EX, XM } }, + { "movq", { EXq, XM } }, { "movdq2q",{ MX, XS } }, }, /* PREGRP22 */ { { "pshufw", { MX, EM, Ib } }, - { "pshufhw",{ XM, EX, Ib } }, - { "pshufd", { XM, EX, Ib } }, - { "pshuflw",{ XM, EX, Ib } }, + { "pshufhw",{ XM, EXx, Ib } }, + { "pshufd", { XM, EXx, Ib } }, + { "pshuflw",{ XM, EXx, Ib } }, }, /* PREGRP23 */ { - { "movd", { Edq, MX } }, - { "movq", { XM, EX } }, - { "movd", { Edq, XM } }, + { "movK", { Edq, MX } }, + { "movq", { XM, EXq } }, + { "movK", { Edq, XM } }, { "(bad)", { Ed, XM } }, }, /* PREGRP24 */ { - { "(bad)", { MX, EX } }, - { "(bad)", { XM, EX } }, - { "punpckhqdq", { XM, EX } }, - { "(bad)", { XM, EX } }, + { "(bad)", { MX, EXx } }, + { "(bad)", { XM, EXx } }, + { "punpckhqdq", { XM, EXx } }, + { "(bad)", { XM, EXx } }, }, /* PREGRP25 */ { @@ -1947,59 +1865,59 @@ static const struct dis386 prefix_user_table[][4] = { }, /* PREGRP26 */ { - { "(bad)", { MX, EX } }, - { "(bad)", { XM, EX } }, - { "punpcklqdq", { XM, EX } }, - { "(bad)", { XM, EX } }, + { "(bad)", { MX, EXx } }, + { "(bad)", { XM, EXx } }, + { "punpcklqdq", { XM, EXx } }, + { "(bad)", { XM, EXx } }, }, /* PREGRP27 */ { - { "(bad)", { MX, EX } }, - { "(bad)", { XM, EX } }, - { "addsubpd", { XM, EX } }, - { "addsubps", { XM, EX } }, + { "(bad)", { MX, EXx } }, + { "(bad)", { XM, EXx } }, + { "addsubpd", { XM, EXx } }, + { "addsubps", { XM, EXx } }, }, /* PREGRP28 */ { - { "(bad)", { MX, EX } }, - { "(bad)", { XM, EX } }, - { "haddpd", { XM, EX } }, - { "haddps", { XM, EX } }, + { "(bad)", { MX, EXx } }, + { "(bad)", { XM, EXx } }, + { "haddpd", { XM, EXx } }, + { "haddps", { XM, EXx } }, }, /* PREGRP29 */ { - { "(bad)", { MX, EX } }, - { "(bad)", { XM, EX } }, - { "hsubpd", { XM, EX } }, - { "hsubps", { XM, EX } }, + { "(bad)", { MX, EXx } }, + { "(bad)", { XM, EXx } }, + { "hsubpd", { XM, EXx } }, + { "hsubps", { XM, EXx } }, }, /* PREGRP30 */ { - { "movlpX", { XM, EX, { SIMD_Fixup, 'h' } } }, /* really only 2 operands */ - { "movsldup", { XM, EX } }, - { "movlpd", { XM, EX } }, - { "movddup", { XM, EX } }, + { OPC_EXT_36 }, + { "movsldup", { XM, EXx } }, + { "movlpd", { XM, EXq } }, + { "movddup", { XM, EXq } }, }, /* PREGRP31 */ { - { "movhpX", { XM, EX, { SIMD_Fixup, 'l' } } }, - { "movshdup", { XM, EX } }, - { "movhpd", { XM, EX } }, - { "(bad)", { XM, EX } }, + { OPC_EXT_37 }, + { "movshdup", { XM, EXx } }, + { "movhpd", { XM, EXq } }, + { "(bad)", { XM, EXq } }, }, /* PREGRP32 */ { - { "(bad)", { XM, EX } }, - { "(bad)", { XM, EX } }, - { "(bad)", { XM, EX } }, - { "lddqu", { XM, M } }, + { "(bad)", { XM, EXx } }, + { "(bad)", { XM, EXx } }, + { "(bad)", { XM, EXx } }, + { OPC_EXT_32 }, }, /* PREGRP33 */ { {"movntps", { Ev, XM } }, - {"movntss", { Ev, XM } }, + {"movntss", { Ed, XM } }, {"movntpd", { Ev, XM } }, - {"movntsd", { Ev, XM } }, + {"movntsd", { Eq, XM } }, }, /* PREGRP34 */ @@ -2009,14 +1927,14 @@ static const struct dis386 prefix_user_table[][4] = { {"extrq", { XS, Ib, Ib } }, {"insertq", { XM, XS, Ib, Ib } }, }, - - /* PREGRP35 */ + + /* PREGRP35 */ { {"vmwrite", { Gm, Em } }, {"(bad)", { XX } }, {"extrq", { XM, XS } }, {"insertq", { XM, XS } }, - }, + }, /* PREGRP36 */ { @@ -2031,7 +1949,7 @@ static const struct dis386 prefix_user_table[][4] = { { "(bad)", { XX } }, { "popcntS", { Gv, Ev } }, { "(bad)", { XX } }, - { "(bad)", { XX } }, + { "(bad)", { XX } }, }, /* PREGRP38 */ @@ -2039,177 +1957,673 @@ static const struct dis386 prefix_user_table[][4] = { { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } } }, { "pause", { XX } }, { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } } }, - { "(bad)", { XX } }, + { "(bad)", { XX } }, }, -}; -static const struct dis386 x86_64_table[][2] = { + /* PREGRP39 */ { - { "pusha{P|}", { XX } }, - { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pblendvb", {XM, EXx, XMM0 } }, + { "(bad)", { XX } }, }, + + /* PREGRP40 */ { - { "popa{P|}", { XX } }, - { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "blendvps", {XM, EXx, XMM0 } }, + { "(bad)", { XX } }, }, + + /* PREGRP41 */ { - { "bound{S|}", { Gv, Ma } }, - { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "blendvpd", { XM, EXx, XMM0 } }, + { "(bad)", { XX } }, }, + + /* PREGRP42 */ { - { "arpl", { Ew, Gw } }, - { "movs{||lq|xd}", { Gv, Ed } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "ptest", { XM, EXx } }, + { "(bad)", { XX } }, }, -}; -static const struct dis386 three_byte_table[][256] = { - /* THREE_BYTE_0 */ + /* PREGRP43 */ { - /* 00 */ - { "pshufb", { MX, EM } }, - { "phaddw", { MX, EM } }, - { "phaddd", { MX, EM } }, - { "phaddsw", { MX, EM } }, - { "pmaddubsw", { MX, EM } }, - { "phsubw", { MX, EM } }, - { "phsubd", { MX, EM } }, - { "phsubsw", { MX, EM } }, - /* 08 */ - { "psignb", { MX, EM } }, - { "psignw", { MX, EM } }, - { "psignd", { MX, EM } }, - { "pmulhrsw", { MX, EM } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 10 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 18 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "pabsb", { MX, EM } }, - { "pabsw", { MX, EM } }, - { "pabsd", { MX, EM } }, - { "(bad)", { XX } }, - /* 20 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 28 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 30 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 38 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 40 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 48 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 50 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 58 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 60 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 68 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 70 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 78 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - /* 80 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovsxbw", { XM, EXq } }, + { "(bad)", { XX } }, + }, + + /* PREGRP44 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovsxbd", { XM, EXd } }, + { "(bad)", { XX } }, + }, + + /* PREGRP45 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovsxbq", { XM, EXw } }, + { "(bad)", { XX } }, + }, + + /* PREGRP46 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovsxwd", { XM, EXq } }, + { "(bad)", { XX } }, + }, + + /* PREGRP47 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovsxwq", { XM, EXd } }, + { "(bad)", { XX } }, + }, + + /* PREGRP48 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovsxdq", { XM, EXq } }, + { "(bad)", { XX } }, + }, + + /* PREGRP49 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmuldq", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP50 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pcmpeqq", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP51 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "movntdqa", { XM, EM } }, + { "(bad)", { XX } }, + }, + + /* PREGRP52 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "packusdw", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP53 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovzxbw", { XM, EXq } }, + { "(bad)", { XX } }, + }, + + /* PREGRP54 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovzxbd", { XM, EXd } }, + { "(bad)", { XX } }, + }, + + /* PREGRP55 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovzxbq", { XM, EXw } }, + { "(bad)", { XX } }, + }, + + /* PREGRP56 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovzxwd", { XM, EXq } }, + { "(bad)", { XX } }, + }, + + /* PREGRP57 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovzxwq", { XM, EXd } }, + { "(bad)", { XX } }, + }, + + /* PREGRP58 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovzxdq", { XM, EXq } }, + { "(bad)", { XX } }, + }, + + /* PREGRP59 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pminsb", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP60 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pminsd", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP61 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pminuw", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP62 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pminud", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP63 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmaxsb", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP64 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmaxsd", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP65 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmaxuw", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP66 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmaxud", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP67 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmulld", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP68 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "phminposuw", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP69 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "roundps", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP70 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "roundpd", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP71 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "roundss", { XM, EXd, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP72 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "roundsd", { XM, EXq, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP73 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "blendps", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP74 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "blendpd", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP75 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pblendw", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP76 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pextrb", { Edqb, XM, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP77 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pextrw", { Edqw, XM, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP78 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pextrK", { Edq, XM, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP79 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "extractps", { Edqd, XM, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP80 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pinsrb", { XM, Edqb, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP81 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "insertps", { XM, EXd, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP82 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pinsrK", { XM, Edq, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP83 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "dpps", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP84 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "dppd", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP85 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "mpsadbw", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP86 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pcmpgtq", { XM, EXx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP87 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "crc32", { Gdq, { CRC32_Fixup, b_mode } } }, + }, + + /* PREGRP88 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "crc32", { Gdq, { CRC32_Fixup, v_mode } } }, + }, + + /* PREGRP89 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pcmpestrm", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP90 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pcmpestri", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP91 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pcmpistrm", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP92 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pcmpistri", { XM, EXx, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP93 */ + { + { "ucomiss",{ XM, EXd } }, + { "(bad)", { XX } }, + { "ucomisd",{ XM, EXq } }, + { "(bad)", { XX } }, + }, + + /* PREGRP94 */ + { + { "comiss", { XM, EXd } }, + { "(bad)", { XX } }, + { "comisd", { XM, EXq } }, + { "(bad)", { XX } }, + }, + + /* PREGRP95 */ + { + { "punpcklbw",{ MX, EMd } }, + { "(bad)", { XX } }, + { "punpcklbw",{ MX, EMx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP96 */ + { + { "punpcklwd",{ MX, EMd } }, + { "(bad)", { XX } }, + { "punpcklwd",{ MX, EMx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP97 */ + { + { "punpckldq",{ MX, EMd } }, + { "(bad)", { XX } }, + { "punpckldq",{ MX, EMx } }, + { "(bad)", { XX } }, + }, + + /* PREGRP98 */ + { + { "vmptrld",{ Mq } }, + { "vmxon", { Mq } }, + { "vmclear",{ Mq } }, + { "(bad)", { XX } }, + }, + + /* PREGRP99 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "psrldq", { MS, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP100 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pslldq", { MS, Ib } }, + { "(bad)", { XX } }, + }, +}; + +static const struct dis386 x86_64_table[][2] = { + { + { "pusha{P|}", { XX } }, + { "(bad)", { XX } }, + }, + { + { "popa{P|}", { XX } }, + { "(bad)", { XX } }, + }, + { + { OPC_EXT_33 }, + { "(bad)", { XX } }, + }, + { + { "arpl", { Ew, Gw } }, + { "movs{||lq|xd}", { Gv, Ed } }, + }, +}; + +static const struct dis386 three_byte_table[][256] = { + /* THREE_BYTE_0 */ + { + /* 00 */ + { "pshufb", { MX, EM } }, + { "phaddw", { MX, EM } }, + { "phaddd", { MX, EM } }, + { "phaddsw", { MX, EM } }, + { "pmaddubsw", { MX, EM } }, + { "phsubw", { MX, EM } }, + { "phsubd", { MX, EM } }, + { "phsubsw", { MX, EM } }, + /* 08 */ + { "psignb", { MX, EM } }, + { "psignw", { MX, EM } }, + { "psignd", { MX, EM } }, + { "pmulhrsw", { MX, EM } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 10 */ + { PREGRP39 }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { PREGRP40 }, + { PREGRP41 }, + { "(bad)", { XX } }, + { PREGRP42 }, + /* 18 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pabsb", { MX, EM } }, + { "pabsw", { MX, EM } }, + { "pabsd", { MX, EM } }, + { "(bad)", { XX } }, + /* 20 */ + { PREGRP43 }, + { PREGRP44 }, + { PREGRP45 }, + { PREGRP46 }, + { PREGRP47 }, + { PREGRP48 }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 28 */ + { PREGRP49 }, + { PREGRP50 }, + { PREGRP51 }, + { PREGRP52 }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 30 */ + { PREGRP53 }, + { PREGRP54 }, + { PREGRP55 }, + { PREGRP56 }, + { PREGRP57 }, + { PREGRP58 }, + { "(bad)", { XX } }, + { PREGRP86 }, + /* 38 */ + { PREGRP59 }, + { PREGRP60 }, + { PREGRP61 }, + { PREGRP62 }, + { PREGRP63 }, + { PREGRP64 }, + { PREGRP65 }, + { PREGRP66 }, + /* 40 */ + { PREGRP67 }, + { PREGRP68 }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 48 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 50 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 58 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 60 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 68 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 70 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 78 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 80 */ { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, @@ -2336,8 +2750,8 @@ static const struct dis386 three_byte_table[][256] = { { "(bad)", { XX } }, { "(bad)", { XX } }, /* f0 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP87 }, + { PREGRP88 }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, @@ -2366,23 +2780,23 @@ static const struct dis386 three_byte_table[][256] = { { "(bad)", { XX } }, { "(bad)", { XX } }, /* 08 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP69 }, + { PREGRP70 }, + { PREGRP71 }, + { PREGRP72 }, + { PREGRP73 }, + { PREGRP74 }, + { PREGRP75 }, { "palignr", { MX, EM, Ib } }, /* 10 */ { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP76 }, + { PREGRP77 }, + { PREGRP78 }, + { PREGRP79 }, /* 18 */ { "(bad)", { XX } }, { "(bad)", { XX } }, @@ -2393,9 +2807,9 @@ static const struct dis386 three_byte_table[][256] = { { "(bad)", { XX } }, { "(bad)", { XX } }, /* 20 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP80 }, + { PREGRP81 }, + { PREGRP82 }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, @@ -2429,9 +2843,9 @@ static const struct dis386 three_byte_table[][256] = { { "(bad)", { XX } }, { "(bad)", { XX } }, /* 40 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP83 }, + { PREGRP84 }, + { PREGRP85 }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, @@ -2465,10 +2879,10 @@ static const struct dis386 three_byte_table[][256] = { { "(bad)", { XX } }, { "(bad)", { XX } }, /* 60 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP89 }, + { PREGRP90 }, + { PREGRP91 }, + { PREGRP92 }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, @@ -2647,6 +3061,257 @@ static const struct dis386 three_byte_table[][256] = { } }; +static const struct dis386 opc_ext_table[][2] = { + { + /* OPC_EXT_0 */ + { "leaS", { Gv, M } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_1 */ + { "les{S|}", { Gv, Mp } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_2 */ + { "ldsS", { Gv, Mp } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_3 */ + { "lssS", { Gv, Mp } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_4 */ + { "lfsS", { Gv, Mp } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_5 */ + { "lgsS", { Gv, Mp } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_6 */ + { "sgdt{Q|IQ||}", { M } }, + { OPC_EXT_RM_0 }, + }, + { + /* OPC_EXT_7 */ + { "sidt{Q|IQ||}", { M } }, + { OPC_EXT_RM_1 }, + }, + { + /* OPC_EXT_8 */ + { "lgdt{Q|Q||}", { M } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_9 */ + { PREGRP98 }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_10 */ + { "vmptrst", { Mq } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_11 */ + { "(bad)", { XX } }, + { "psrlw", { MS, Ib } }, + }, + { + /* OPC_EXT_12 */ + { "(bad)", { XX } }, + { "psraw", { MS, Ib } }, + }, + { + /* OPC_EXT_13 */ + { "(bad)", { XX } }, + { "psllw", { MS, Ib } }, + }, + { + /* OPC_EXT_14 */ + { "(bad)", { XX } }, + { "psrld", { MS, Ib } }, + }, + { + /* OPC_EXT_15 */ + { "(bad)", { XX } }, + { "psrad", { MS, Ib } }, + }, + { + /* OPC_EXT_16 */ + { "(bad)", { XX } }, + { "pslld", { MS, Ib } }, + }, + { + /* OPC_EXT_17 */ + { "(bad)", { XX } }, + { "psrlq", { MS, Ib } }, + }, + { + /* OPC_EXT_18 */ + { "(bad)", { XX } }, + { PREGRP99 }, + }, + { + /* OPC_EXT_19 */ + { "(bad)", { XX } }, + { "psllq", { MS, Ib } }, + }, + { + /* OPC_EXT_20 */ + { "(bad)", { XX } }, + { PREGRP100 }, + }, + { + /* OPC_EXT_21 */ + { "fxsave", { M } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_22 */ + { "fxrstor", { M } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_23 */ + { "ldmxcsr", { Md } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_24 */ + { "stmxcsr", { Md } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_25 */ + { "(bad)", { XX } }, + { OPC_EXT_RM_2 }, + }, + { + /* OPC_EXT_26 */ + { "(bad)", { XX } }, + { OPC_EXT_RM_3 }, + }, + { + /* OPC_EXT_27 */ + { "clflush", { Mb } }, + { OPC_EXT_RM_4 }, + }, + { + /* OPC_EXT_28 */ + { "prefetchnta", { Mb } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_29 */ + { "prefetcht0", { Mb } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_30 */ + { "prefetcht1", { Mb } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_31 */ + { "prefetcht2", { Mb } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_32 */ + { "lddqu", { XM, M } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_33 */ + { "bound{S|}", { Gv, Ma } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_34 */ + { "movlpX", { EXq, XM } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_35 */ + { "movhpX", { EXq, XM } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_36 */ + { "movlpX", { XM, EXq } }, + { "movhlpX", { XM, EXq } }, + }, + { + /* OPC_EXT_37 */ + { "movhpX", { XM, EXq } }, + { "movlhpX", { XM, EXq } }, + }, +}; + +static const struct dis386 opc_ext_rm_table[][8] = { + { + /* OPC_EXT_RM_0 */ + { "(bad)", { XX } }, + { "vmcall", { Skip_MODRM } }, + { "vmlaunch", { Skip_MODRM } }, + { "vmresume", { Skip_MODRM } }, + { "vmxoff", { Skip_MODRM } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_RM_1 */ + { "monitor", { { OP_Monitor, 0 } } }, + { "mwait", { { OP_Mwait, 0 } } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_RM_2 */ + { "lfence", { Skip_MODRM } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_RM_3 */ + { "mfence", { Skip_MODRM } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + }, + { + /* OPC_EXT_RM_4 */ + { "sfence", { Skip_MODRM } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + }, +}; + #define INTERNAL_DISASSEMBLER_ERROR _("") static void @@ -2891,6 +3556,79 @@ with the -M switch (multiple options should be separated by commas):\n")); fprintf (stream, _(" suffix Always display instruction suffix in AT&T syntax\n")); } +/* Get a pointer to struct dis386 with a valid name. */ + +static const struct dis386 * +get_valid_dis386 (const struct dis386 *dp) +{ + int index; + + if (dp->name != NULL) + return dp; + + switch (dp->op[0].bytemode) + { + case USE_GROUPS: + dp = &grps[dp->op[1].bytemode][modrm.reg]; + break; + + case USE_PREFIX_USER_TABLE: + index = 0; + used_prefixes |= (prefixes & PREFIX_REPZ); + if (prefixes & PREFIX_REPZ) + { + index = 1; + repz_prefix = NULL; + } + else + { + /* We should check PREFIX_REPNZ and PREFIX_REPZ before + PREFIX_DATA. */ + used_prefixes |= (prefixes & PREFIX_REPNZ); + if (prefixes & PREFIX_REPNZ) + { + index = 3; + repnz_prefix = NULL; + } + else + { + used_prefixes |= (prefixes & PREFIX_DATA); + if (prefixes & PREFIX_DATA) + { + index = 2; + data_prefix = NULL; + } + } + } + dp = &prefix_user_table[dp->op[1].bytemode][index]; + break; + + case X86_64_SPECIAL: + index = address_mode == mode_64bit ? 1 : 0; + dp = &x86_64_table[dp->op[1].bytemode][index]; + break; + + case USE_OPC_EXT_TABLE: + index = modrm.mod == 0x3 ? 1 : 0; + dp = &opc_ext_table[dp->op[1].bytemode][index]; + break; + + case USE_OPC_EXT_RM_TABLE: + index = modrm.rm; + dp = &opc_ext_rm_table[dp->op[1].bytemode][index]; + break; + + default: + oappend (INTERNAL_DISASSEMBLER_ERROR); + return NULL; + } + + if (dp->name != NULL) + return dp; + else + return get_valid_dis386 (dp); +} + static int print_insn (bfd_vma pc, disassemble_info *info) { @@ -2898,12 +3636,12 @@ print_insn (bfd_vma pc, disassemble_info *info) int i; char *op_txt[MAX_OPERANDS]; int needcomma; - unsigned char uses_DATA_prefix, uses_LOCK_prefix; - unsigned char uses_REPNZ_prefix, uses_REPZ_prefix; int sizeflag; const char *p; struct dis_private priv; unsigned char op; + char prefix_obuf[32]; + char *prefix_obufp; if (info->mach == bfd_mach_x86_64_intel_syntax || info->mach == bfd_mach_x86_64) @@ -3088,75 +3826,60 @@ print_insn (bfd_vma pc, disassemble_info *info) threebyte = *++codep; dp = &dis386_twobyte[threebyte]; need_modrm = twobyte_has_modrm[*codep]; - uses_DATA_prefix = twobyte_uses_DATA_prefix[*codep]; - uses_REPNZ_prefix = twobyte_uses_REPNZ_prefix[*codep]; - uses_REPZ_prefix = twobyte_uses_REPZ_prefix[*codep]; - uses_LOCK_prefix = (*codep & ~0x02) == 0x20; codep++; if (dp->name == NULL && dp->op[0].bytemode == IS_3BYTE_OPCODE) { FETCH_DATA (info, codep + 2); op = *codep++; - switch (threebyte) - { - case 0x38: - uses_DATA_prefix = threebyte_0x38_uses_DATA_prefix[op]; - uses_REPNZ_prefix = threebyte_0x38_uses_REPNZ_prefix[op]; - uses_REPZ_prefix = threebyte_0x38_uses_REPZ_prefix[op]; - break; - case 0x3a: - uses_DATA_prefix = threebyte_0x3a_uses_DATA_prefix[op]; - uses_REPNZ_prefix = threebyte_0x3a_uses_REPNZ_prefix[op]; - uses_REPZ_prefix = threebyte_0x3a_uses_REPZ_prefix[op]; - break; - default: - break; - } } } else { dp = &dis386[*codep]; need_modrm = onebyte_has_modrm[*codep]; - uses_DATA_prefix = 0; - uses_REPNZ_prefix = 0; - /* pause is 0xf3 0x90. */ - uses_REPZ_prefix = *codep == 0x90; - uses_LOCK_prefix = 0; codep++; } - - if (!uses_REPZ_prefix && (prefixes & PREFIX_REPZ)) + + if ((prefixes & PREFIX_REPZ)) { - oappend ("repz "); + repz_prefix = "repz "; used_prefixes |= PREFIX_REPZ; } - if (!uses_REPNZ_prefix && (prefixes & PREFIX_REPNZ)) + else + repz_prefix = NULL; + + if ((prefixes & PREFIX_REPNZ)) { - oappend ("repnz "); + repnz_prefix = "repnz "; used_prefixes |= PREFIX_REPNZ; } + else + repnz_prefix = NULL; - if (!uses_LOCK_prefix && (prefixes & PREFIX_LOCK)) + if ((prefixes & PREFIX_LOCK)) { - oappend ("lock "); + lock_prefix = "lock "; used_prefixes |= PREFIX_LOCK; } + else + lock_prefix = NULL; + addr_prefix = NULL; if (prefixes & PREFIX_ADDR) { sizeflag ^= AFLAG; if (dp->op[2].bytemode != loop_jcxz_mode || intel_syntax) { if ((sizeflag & AFLAG) || address_mode == mode_64bit) - oappend ("addr32 "); + addr_prefix = "addr32 "; else - oappend ("addr16 "); + addr_prefix = "addr16 "; used_prefixes |= PREFIX_ADDR; } } - if (!uses_DATA_prefix && (prefixes & PREFIX_DATA)) + data_prefix = NULL; + if ((prefixes & PREFIX_DATA)) { sizeflag ^= DFLAG; if (dp->op[2].bytemode == cond_jump_mode @@ -3164,9 +3887,9 @@ print_insn (bfd_vma pc, disassemble_info *info) && !intel_syntax) { if (sizeflag & DFLAG) - oappend ("data32 "); + data_prefix = "data32 "; else - oappend ("data16 "); + data_prefix = "data16 "; used_prefixes |= PREFIX_DATA; } } @@ -3192,53 +3915,12 @@ print_insn (bfd_vma pc, disassemble_info *info) } else { - int index; - if (dp->name == NULL) - { - switch (dp->op[0].bytemode) - { - case USE_GROUPS: - dp = &grps[dp->op[1].bytemode][modrm.reg]; - break; - - case USE_PREFIX_USER_TABLE: - index = 0; - used_prefixes |= (prefixes & PREFIX_REPZ); - if (prefixes & PREFIX_REPZ) - index = 1; - else - { - /* We should check PREFIX_REPNZ and PREFIX_REPZ - before PREFIX_DATA. */ - used_prefixes |= (prefixes & PREFIX_REPNZ); - if (prefixes & PREFIX_REPNZ) - index = 3; - else - { - used_prefixes |= (prefixes & PREFIX_DATA); - if (prefixes & PREFIX_DATA) - index = 2; - } - } - dp = &prefix_user_table[dp->op[1].bytemode][index]; - break; - - case X86_64_SPECIAL: - index = address_mode == mode_64bit ? 1 : 0; - dp = &x86_64_table[dp->op[1].bytemode][index]; - break; - - default: - oappend (INTERNAL_DISASSEMBLER_ERROR); - break; - } - } - - if (putop (dp->name, sizeflag) == 0) + dp = get_valid_dis386 (dp); + if (dp != NULL && putop (dp->name, sizeflag) == 0) { for (i = 0; i < MAX_OPERANDS; ++i) { - obufp = op_out[i]; + obufp = op_out[i]; op_ad = MAX_OPERANDS - 1 - i; if (dp->op[i].rtn) (*dp->op[i].rtn) (dp->op[i].bytemode, sizeflag); @@ -3269,8 +3951,24 @@ print_insn (bfd_vma pc, disassemble_info *info) (*info->fprintf_func) (info->stream, "%s ", name); } + prefix_obuf[0] = 0; + prefix_obufp = prefix_obuf; + if (lock_prefix) + prefix_obufp = stpcpy (prefix_obufp, lock_prefix); + if (repz_prefix) + prefix_obufp = stpcpy (prefix_obufp, repz_prefix); + if (repnz_prefix) + prefix_obufp = stpcpy (prefix_obufp, repnz_prefix); + if (addr_prefix) + prefix_obufp = stpcpy (prefix_obufp, addr_prefix); + if (data_prefix) + prefix_obufp = stpcpy (prefix_obufp, data_prefix); + + if (prefix_obuf[0] != 0) + (*info->fprintf_func) (info->stream, "%s", prefix_obuf); + obufp = obuf + strlen (obuf); - for (i = strlen (obuf); i < 6; i++) + for (i = strlen (obuf) + strlen (prefix_obuf); i < 6; i++) oappend (" "); oappend (" "); (*info->fprintf_func) (info->stream, "%s", obuf); @@ -3279,14 +3977,19 @@ print_insn (bfd_vma pc, disassemble_info *info) order as the intel book; everything else is printed in reverse order. */ if (intel_syntax || two_source_ops) { + bfd_vma riprel; + for (i = 0; i < MAX_OPERANDS; ++i) op_txt[i] = op_out[i]; - + for (i = 0; i < (MAX_OPERANDS >> 1); ++i) { op_ad = op_index[i]; op_index[i] = op_index[MAX_OPERANDS - 1 - i]; op_index[MAX_OPERANDS - 1 - i] = op_ad; + riprel = op_riprel[i]; + op_riprel[i] = op_riprel [MAX_OPERANDS - 1 - i]; + op_riprel[MAX_OPERANDS - 1 - i] = riprel; } } else @@ -3314,6 +4017,7 @@ print_insn (bfd_vma pc, disassemble_info *info) (*info->fprintf_func) (info->stream, " # "); (*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep + op_address[op_index[i]]), info); + break; } return codep - priv.the_buffer; } @@ -3634,6 +4338,15 @@ static char *fgrps[][8] = { }, }; +static void +OP_Skip_MODRM (int bytemode ATTRIBUTE_UNUSED, + int sizeflag ATTRIBUTE_UNUSED) +{ + /* Skip mod/rm byte. */ + MODRM_CHECK; + codep++; +} + static void dofloat (int sizeflag) { @@ -3839,6 +4552,13 @@ putop (const char *template, int sizeflag) break; *obufp++ = 'l'; break; + case 'K': + USED_REX (REX_W); + if (rex & REX_W) + *obufp++ = 'q'; + else + *obufp++ = 'd'; + break; case 'Z': if (intel_syntax) break; @@ -4122,12 +4842,57 @@ print_operand_value (char *buf, int hex, bfd_vma disp) } } +/* Put DISP in BUF as signed hex number. */ + +static void +print_displacement (char *buf, bfd_vma disp) +{ + bfd_signed_vma val = disp; + char tmp[30]; + int i, j = 0; + + if (val < 0) + { + buf[j++] = '-'; + val = -disp; + + /* Check for possible overflow. */ + if (val < 0) + { + switch (address_mode) + { + case mode_64bit: + strcpy (buf + j, "0x8000000000000000"); + break; + case mode_32bit: + strcpy (buf + j, "0x80000000"); + break; + case mode_16bit: + strcpy (buf + j, "0x8000"); + break; + } + return; + } + } + + buf[j++] = '0'; + buf[j++] = 'x'; + + sprintf_vma (tmp, val); + for (i = 0; tmp[i] == '0'; i++) + continue; + if (tmp[i] == '\0') + i--; + strcpy (buf + j, tmp + i); +} + static void intel_operand_size (int bytemode, int sizeflag) { switch (bytemode) { case b_mode: + case dqb_mode: oappend ("BYTE PTR "); break; case w_mode: @@ -4161,6 +4926,7 @@ intel_operand_size (int bytemode, int sizeflag) used_prefixes |= (prefixes & PREFIX_DATA); break; case d_mode: + case dqd_mode: oappend ("DWORD PTR "); break; case q_mode: @@ -4244,6 +5010,8 @@ OP_E (int bytemode, int sizeflag) /* FALLTHRU */ case v_mode: case dq_mode: + case dqb_mode: + case dqd_mode: case dqw_mode: USED_REX (REX_W); if (rex & REX_W) @@ -4268,8 +5036,10 @@ OP_E (int bytemode, int sizeflag) intel_operand_size (bytemode, sizeflag); append_seg (); - if ((sizeflag & AFLAG) || address_mode == mode_64bit) /* 32 bit address mode */ + if ((sizeflag & AFLAG) || address_mode == mode_64bit) { + /* 32/64 bit address mode */ + int havedisp; int havesib; int havebase; int base; @@ -4318,10 +5088,15 @@ OP_E (int bytemode, int sizeflag) break; } + havedisp = havebase || (havesib && (index != 4 || scale != 0)); + if (!intel_syntax) if (modrm.mod != 0 || (base & 7) == 5) { - print_operand_value (scratchbuf, !riprel, disp); + if (havedisp || riprel) + print_displacement (scratchbuf, disp); + else + print_operand_value (scratchbuf, 1, disp); oappend (scratchbuf); if (riprel) { @@ -4330,11 +5105,14 @@ OP_E (int bytemode, int sizeflag) } } - if (havebase || (havesib && (index != 4 || scale != 0))) + if (havedisp || (intel_syntax && riprel)) { *obufp++ = open_char; if (intel_syntax && riprel) - oappend ("rip + "); + { + set_op (disp, 1); + oappend ("rip"); + } *obufp = '\0'; if (havebase) oappend (address_mode == mode_64bit && (sizeflag & AFLAG) @@ -4359,9 +5137,10 @@ OP_E (int bytemode, int sizeflag) oappend (scratchbuf); } } - if (intel_syntax && disp) + if (intel_syntax + && (disp || modrm.mod != 0 || (base & 7) == 5)) { - if ((bfd_signed_vma) disp > 0) + if ((bfd_signed_vma) disp >= 0) { *obufp++ = '+'; *obufp = '\0'; @@ -4373,7 +5152,7 @@ OP_E (int bytemode, int sizeflag) disp = - (bfd_signed_vma) disp; } - print_operand_value (scratchbuf, modrm.mod != 1, disp); + print_displacement (scratchbuf, disp); oappend (scratchbuf); } @@ -4425,7 +5204,7 @@ OP_E (int bytemode, int sizeflag) if (!intel_syntax) if (modrm.mod != 0 || modrm.rm == 6) { - print_operand_value (scratchbuf, 0, disp); + print_displacement (scratchbuf, disp); oappend (scratchbuf); } @@ -4434,9 +5213,10 @@ OP_E (int bytemode, int sizeflag) *obufp++ = open_char; *obufp = '\0'; oappend (index16[modrm.rm]); - if (intel_syntax && disp) + if (intel_syntax + && (disp || modrm.mod != 0 || modrm.rm == 6)) { - if ((bfd_signed_vma) disp > 0) + if ((bfd_signed_vma) disp >= 0) { *obufp++ = '+'; *obufp = '\0'; @@ -4448,7 +5228,7 @@ OP_E (int bytemode, int sizeflag) disp = - (bfd_signed_vma) disp; } - print_operand_value (scratchbuf, modrm.mod != 1, disp); + print_displacement (scratchbuf, disp); oappend (scratchbuf); } @@ -4498,6 +5278,8 @@ OP_G (int bytemode, int sizeflag) break; case v_mode: case dq_mode: + case dqb_mode: + case dqd_mode: case dqw_mode: USED_REX (REX_W); if (rex & REX_W) @@ -5090,6 +5872,7 @@ OP_C (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) } else if (address_mode != mode_64bit && (prefixes & PREFIX_LOCK)) { + lock_prefix = NULL; used_prefixes |= PREFIX_LOCK; add = 8; } @@ -5187,10 +5970,10 @@ OP_EM (int bytemode, int sizeflag) oappend (scratchbuf + intel_syntax); } -/* cvt* are the only instructions in sse2 which have - both SSE and MMX operands and also have 0x66 prefix - in their opcode. 0x66 was originally used to differentiate - between SSE and MMX instruction(operands). So we have to handle the +/* cvt* are the only instructions in sse2 which have + both SSE and MMX operands and also have 0x66 prefix + in their opcode. 0x66 was originally used to differentiate + between SSE and MMX instruction(operands). So we have to handle the cvt* separately using OP_EMC and OP_MXC */ static void OP_EMC (int bytemode, int sizeflag) @@ -5205,7 +5988,7 @@ OP_EMC (int bytemode, int sizeflag) OP_E (bytemode, sizeflag); return; } - + /* Skip mod/rm byte. */ MODRM_CHECK; codep++; @@ -5228,17 +6011,6 @@ OP_EX (int bytemode, int sizeflag) int add = 0; if (modrm.mod != 3) { - if (intel_syntax && bytemode == v_mode) - { - switch (prefixes & (PREFIX_DATA|PREFIX_REPZ|PREFIX_REPNZ)) - { - case 0: bytemode = x_mode; break; - case PREFIX_REPZ: bytemode = d_mode; used_prefixes |= PREFIX_REPZ; break; - case PREFIX_DATA: bytemode = x_mode; used_prefixes |= PREFIX_DATA; break; - case PREFIX_REPNZ: bytemode = q_mode; used_prefixes |= PREFIX_REPNZ; break; - default: bytemode = 0; break; - } - } OP_E (bytemode, sizeflag); return; } @@ -5290,31 +6062,8 @@ OP_0f07 (int bytemode, int sizeflag) OP_E (bytemode, sizeflag); } -static void -OP_0fae (int bytemode, int sizeflag) -{ - if (modrm.mod == 3) - { - if (modrm.reg == 7) - strcpy (obuf + strlen (obuf) - sizeof ("clflush") + 1, "sfence"); - - if (modrm.reg < 5 || modrm.rm != 0) - { - BadOp (); /* bad sfence, mfence, or lfence */ - return; - } - } - else if (modrm.reg != 7) - { - BadOp (); /* bad clflush */ - return; - } - - OP_E (bytemode, sizeflag); -} - /* NOP is an alias of "xchg %ax,%ax" in 16bit mode, "xchg %eax,%eax" in - 32bit mode and "xchg %rax,%rax" in 64bit mode. */ + 32bit mode and "xchg %rax,%rax" in 64bit mode. */ static void NOP_Fixup1 (int bytemode, int sizeflag) @@ -5384,7 +6133,7 @@ static const char *const Suffix3DNow[] = { /* A8 */ NULL, NULL, "pfsubr", NULL, /* AC */ NULL, NULL, "pfacc", NULL, /* B0 */ "pfcmpeq", NULL, NULL, NULL, -/* B4 */ "pfmul", NULL, "pfrcpit2", "pfmulhrw", +/* B4 */ "pfmul", NULL, "pfrcpit2", "pmulhrw", /* B8 */ NULL, NULL, NULL, "pswapd", /* BC */ NULL, NULL, NULL, "pavgusb", /* C0 */ NULL, NULL, NULL, NULL, @@ -5482,83 +6231,53 @@ OP_SIMD_Suffix (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) } static void -SIMD_Fixup (int extrachar, int sizeflag ATTRIBUTE_UNUSED) +OP_Mwait (int bytemode ATTRIBUTE_UNUSED, + int sizeflag ATTRIBUTE_UNUSED) { - /* Change movlps/movhps to movhlps/movlhps for 2 register operand - forms of these instructions. */ - if (modrm.mod == 3) + /* mwait %eax,%ecx */ + if (!intel_syntax) { - char *p = obuf + strlen (obuf); - *(p + 1) = '\0'; - *p = *(p - 1); - *(p - 1) = *(p - 2); - *(p - 2) = *(p - 3); - *(p - 3) = extrachar; + const char **names = (address_mode == mode_64bit + ? names64 : names32); + strcpy (op_out[0], names[0]); + strcpy (op_out[1], names[1]); + two_source_ops = 1; } + /* Skip mod/rm byte. */ + MODRM_CHECK; + codep++; } static void -PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag) +OP_Monitor (int bytemode ATTRIBUTE_UNUSED, + int sizeflag ATTRIBUTE_UNUSED) { - if (modrm.mod == 3 && modrm.reg == 1 && modrm.rm <= 1) + /* monitor %eax,%ecx,%edx" */ + if (!intel_syntax) { - /* Override "sidt". */ - size_t olen = strlen (obuf); - char *p = obuf + olen - 4; + const char **op1_names; const char **names = (address_mode == mode_64bit ? names64 : names32); - /* We might have a suffix when disassembling with -Msuffix. */ - if (*p == 'i') - --p; - - /* Remove "addr16/addr32" if we aren't in Intel mode. */ - if (!intel_syntax - && (prefixes & PREFIX_ADDR) - && olen >= (4 + 7) - && *(p - 1) == ' ' - && CONST_STRNEQ (p - 7, "addr") - && (CONST_STRNEQ (p - 3, "16") - || CONST_STRNEQ (p - 3, "32"))) - p -= 7; - - if (modrm.rm) - { - /* mwait %eax,%ecx */ - strcpy (p, "mwait"); - if (!intel_syntax) - strcpy (op_out[0], names[0]); - } + if (!(prefixes & PREFIX_ADDR)) + op1_names = (address_mode == mode_16bit + ? names16 : names); else { - /* monitor %eax,%ecx,%edx" */ - strcpy (p, "monitor"); - if (!intel_syntax) - { - const char **op1_names; - if (!(prefixes & PREFIX_ADDR)) - op1_names = (address_mode == mode_16bit - ? names16 : names); - else - { - op1_names = (address_mode != mode_32bit - ? names32 : names16); - used_prefixes |= PREFIX_ADDR; - } - strcpy (op_out[0], op1_names[0]); - strcpy (op_out[2], names[2]); - } - } - if (!intel_syntax) - { - strcpy (op_out[1], names[1]); - two_source_ops = 1; + /* Remove "addr16/addr32". */ + addr_prefix = NULL; + op1_names = (address_mode != mode_32bit + ? names32 : names16); + used_prefixes |= PREFIX_ADDR; } - - codep++; + strcpy (op_out[0], op1_names[0]); + strcpy (op_out[1], names[1]); + strcpy (op_out[2], names[2]); + two_source_ops = 1; } - else - OP_M (0, sizeflag); + /* Skip mod/rm byte. */ + MODRM_CHECK; + codep++; } static void @@ -5661,109 +6380,13 @@ BadOp (void) oappend ("(bad)"); } -static void -VMX_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag) -{ - if (modrm.mod == 3 - && modrm.reg == 0 - && modrm.rm >=1 - && modrm.rm <= 4) - { - /* Override "sgdt". */ - char *p = obuf + strlen (obuf) - 4; - - /* We might have a suffix when disassembling with -Msuffix. */ - if (*p == 'g') - --p; - - switch (modrm.rm) - { - case 1: - strcpy (p, "vmcall"); - break; - case 2: - strcpy (p, "vmlaunch"); - break; - case 3: - strcpy (p, "vmresume"); - break; - case 4: - strcpy (p, "vmxoff"); - break; - } - - codep++; - } - else - OP_E (0, sizeflag); -} - -static void -OP_VMX (int bytemode, int sizeflag) -{ - used_prefixes |= (prefixes & (PREFIX_DATA | PREFIX_REPZ)); - if (prefixes & PREFIX_DATA) - strcpy (obuf, "vmclear"); - else if (prefixes & PREFIX_REPZ) - strcpy (obuf, "vmxon"); - else - strcpy (obuf, "vmptrld"); - OP_E (bytemode, sizeflag); -} - static void REP_Fixup (int bytemode, int sizeflag) { /* The 0xf3 prefix should be displayed as "rep" for ins, outs, movs, lods and stos. */ - size_t ilen = 0; - if (prefixes & PREFIX_REPZ) - switch (*insn_codep) - { - case 0x6e: /* outsb */ - case 0x6f: /* outsw/outsl */ - case 0xa4: /* movsb */ - case 0xa5: /* movsw/movsl/movsq */ - if (!intel_syntax) - ilen = 5; - else - ilen = 4; - break; - case 0xaa: /* stosb */ - case 0xab: /* stosw/stosl/stosq */ - case 0xac: /* lodsb */ - case 0xad: /* lodsw/lodsl/lodsq */ - if (!intel_syntax && (sizeflag & SUFFIX_ALWAYS)) - ilen = 5; - else - ilen = 4; - break; - case 0x6c: /* insb */ - case 0x6d: /* insl/insw */ - if (!intel_syntax) - ilen = 4; - else - ilen = 3; - break; - default: - abort (); - break; - } - - if (ilen != 0) - { - size_t olen; - char *p; - - olen = strlen (obuf); - p = obuf + olen - ilen - 1 - 4; - /* Handle "repz [addr16|addr32]". */ - if ((prefixes & PREFIX_ADDR)) - p -= 1 + 6; - - memmove (p + 3, p + 4, olen - (p + 3 - obuf)); - } + repz_prefix = "rep "; switch (bytemode) { @@ -5797,3 +6420,76 @@ CMPXCHG8B_Fixup (int bytemode, int sizeflag) } OP_M (bytemode, sizeflag); } + +static void +XMM_Fixup (int reg, int sizeflag ATTRIBUTE_UNUSED) +{ + sprintf (scratchbuf, "%%xmm%d", reg); + oappend (scratchbuf + intel_syntax); +} + +static void +CRC32_Fixup (int bytemode, int sizeflag) +{ + /* Add proper suffix to "crc32". */ + char *p = obuf + strlen (obuf); + + switch (bytemode) + { + case b_mode: + if (intel_syntax) + break; + + *p++ = 'b'; + break; + case v_mode: + if (intel_syntax) + break; + + USED_REX (REX_W); + if (rex & REX_W) + *p++ = 'q'; + else if (sizeflag & DFLAG) + *p++ = 'l'; + else + *p++ = 'w'; + used_prefixes |= (prefixes & PREFIX_DATA); + break; + default: + oappend (INTERNAL_DISASSEMBLER_ERROR); + break; + } + *p = '\0'; + + if (modrm.mod == 3) + { + int add; + + /* Skip mod/rm byte. */ + MODRM_CHECK; + codep++; + + USED_REX (REX_B); + add = (rex & REX_B) ? 8 : 0; + if (bytemode == b_mode) + { + USED_REX (0); + if (rex) + oappend (names8rex[modrm.rm + add]); + else + oappend (names8[modrm.rm + add]); + } + else + { + USED_REX (REX_W); + if (rex & REX_W) + oappend (names64[modrm.rm + add]); + else if ((prefixes & PREFIX_DATA)) + oappend (names16[modrm.rm + add]); + else + oappend (names32[modrm.rm + add]); + } + } + else + OP_E (bytemode, sizeflag); +}