X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=opcodes%2Fi386-dis.c;h=5cd0b8d0511d3239cffbc8ecb6da61cd6084553b;hb=798879259b7dc117b84d68ab8878cefd7ca15e3c;hp=526627afc9f8c5fb3ac0b89afec5c6330a978ee5;hpb=6f74c397defce90b9323316d756b32d9373b874c;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 526627afc9..5cd0b8d051 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -34,17 +34,10 @@ #include "dis-asm.h" #include "sysdep.h" #include "opintl.h" - -#define MAXLEN 15 +#include "opcode/i386.h" #include -#ifndef UNIXWARE_COMPAT -/* Set non-zero for broken, compatible instructions. Set to zero for - non-broken opcodes. */ -#define UNIXWARE_COMPAT 1 -#endif - static int fetch_data (struct disassemble_info *, bfd_byte *); static void ckprefix (void); static const char *prefix_name (int, int); @@ -57,6 +50,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); @@ -105,20 +99,18 @@ 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. */ bfd_byte *max_fetched; - bfd_byte the_buffer[MAXLEN]; + bfd_byte the_buffer[MAX_MNEM_SIZE]; bfd_vma insn_start; int orig_sizeflag; jmp_buf bailout; }; -/* The opcode for the fwait instruction, which we treat as a prefix - when we can. */ -#define FWAIT_OPCODE (0x9b) - enum address_mode { mode_16bit, @@ -135,10 +127,6 @@ static int prefixes; static int rex; /* Bits of REX we've already used. */ static int rex_used; -#define REX_MODE64 8 -#define REX_EXTX 4 -#define REX_EXTY 2 -#define REX_EXTZ 1 /* Mark parts used in the REX prefix. When we are testing for empty prefix (for 8bit register REX extension), just mask it out. Otherwise test for REX bit is excuse for existence of REX @@ -146,9 +134,12 @@ static int rex_used; #define USED_REX(value) \ { \ if (value) \ - rex_used |= (rex & value) ? (value) | 0x40 : 0; \ + { \ + if ((rex & value)) \ + rex_used |= (value) | REX_OPCODE; \ + } \ else \ - rex_used |= 0x40; \ + rex_used |= REX_OPCODE; \ } /* Flags for prefixes which we somehow handled when printing the @@ -183,7 +174,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) struct dis_private *priv = (struct dis_private *) info->private_data; bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); - if (addr <= priv->the_buffer + MAXLEN) + if (addr <= priv->the_buffer + MAX_MNEM_SIZE) status = (*info->read_memory_func) (start, priv->max_fetched, addr - priv->max_fetched, @@ -212,6 +203,8 @@ 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 indirEv { OP_indirE, stack_v_mode } #define indirEp { OP_indirE, f_mode } #define stackEv { OP_E, stack_v_mode } @@ -321,6 +314,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #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 } @@ -357,6 +351,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 @@ -412,33 +408,34 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define FLOAT NULL, { { NULL, FLOATCODE } } -#define GRP1b NULL, { { NULL, USE_GROUPS }, { NULL, 0 } } -#define GRP1S NULL, { { NULL, USE_GROUPS }, { NULL, 1 } } -#define GRP1Ss NULL, { { NULL, USE_GROUPS }, { NULL, 2 } } -#define GRP2b NULL, { { NULL, USE_GROUPS }, { NULL, 3 } } -#define GRP2S NULL, { { NULL, USE_GROUPS }, { NULL, 4 } } -#define GRP2b_one NULL, { { NULL, USE_GROUPS }, { NULL, 5 } } -#define GRP2S_one NULL, { { NULL, USE_GROUPS }, { NULL, 6 } } -#define GRP2b_cl NULL, { { NULL, USE_GROUPS }, { NULL, 7 } } -#define GRP2S_cl NULL, { { NULL, USE_GROUPS }, { NULL, 8 } } -#define GRP3b NULL, { { NULL, USE_GROUPS }, { NULL, 9 } } -#define GRP3S NULL, { { NULL, USE_GROUPS }, { NULL, 10 } } -#define GRP4 NULL, { { NULL, USE_GROUPS }, { NULL, 11 } } -#define GRP5 NULL, { { NULL, USE_GROUPS }, { NULL, 12 } } -#define GRP6 NULL, { { NULL, USE_GROUPS }, { NULL, 13 } } -#define GRP7 NULL, { { NULL, USE_GROUPS }, { NULL, 14 } } -#define GRP8 NULL, { { NULL, USE_GROUPS }, { NULL, 15 } } -#define GRP9 NULL, { { NULL, USE_GROUPS }, { NULL, 16 } } -#define GRP11_C6 NULL, { { NULL, USE_GROUPS }, { NULL, 17 } } -#define GRP11_C7 NULL, { { NULL, USE_GROUPS }, { NULL, 18 } } -#define GRP12 NULL, { { NULL, USE_GROUPS }, { NULL, 19 } } -#define GRP13 NULL, { { NULL, USE_GROUPS }, { NULL, 20 } } -#define GRP14 NULL, { { NULL, USE_GROUPS }, { NULL, 21 } } -#define GRP15 NULL, { { NULL, USE_GROUPS }, { NULL, 22 } } -#define GRP16 NULL, { { NULL, USE_GROUPS }, { NULL, 23 } } -#define GRPAMD NULL, { { NULL, USE_GROUPS }, { NULL, 24 } } -#define GRPPADLCK1 NULL, { { NULL, USE_GROUPS }, { NULL, 25 } } -#define GRPPADLCK2 NULL, { { NULL, USE_GROUPS }, { NULL, 26 } } +#define GRP1a NULL, { { NULL, USE_GROUPS }, { NULL, 0 } } +#define GRP1b NULL, { { NULL, USE_GROUPS }, { NULL, 1 } } +#define GRP1S NULL, { { NULL, USE_GROUPS }, { NULL, 2 } } +#define GRP1Ss NULL, { { NULL, USE_GROUPS }, { NULL, 3 } } +#define GRP2b NULL, { { NULL, USE_GROUPS }, { NULL, 4 } } +#define GRP2S NULL, { { NULL, USE_GROUPS }, { NULL, 5 } } +#define GRP2b_one NULL, { { NULL, USE_GROUPS }, { NULL, 6 } } +#define GRP2S_one NULL, { { NULL, USE_GROUPS }, { NULL, 7 } } +#define GRP2b_cl NULL, { { NULL, USE_GROUPS }, { NULL, 8 } } +#define GRP2S_cl NULL, { { NULL, USE_GROUPS }, { NULL, 9 } } +#define GRP3b NULL, { { NULL, USE_GROUPS }, { NULL, 10 } } +#define GRP3S NULL, { { NULL, USE_GROUPS }, { NULL, 11 } } +#define GRP4 NULL, { { NULL, USE_GROUPS }, { NULL, 12 } } +#define GRP5 NULL, { { NULL, USE_GROUPS }, { NULL, 13 } } +#define GRP6 NULL, { { NULL, USE_GROUPS }, { NULL, 14 } } +#define GRP7 NULL, { { NULL, USE_GROUPS }, { NULL, 15 } } +#define GRP8 NULL, { { NULL, USE_GROUPS }, { NULL, 16 } } +#define GRP9 NULL, { { NULL, USE_GROUPS }, { NULL, 17 } } +#define GRP11_C6 NULL, { { NULL, USE_GROUPS }, { NULL, 18 } } +#define GRP11_C7 NULL, { { NULL, USE_GROUPS }, { NULL, 19 } } +#define GRP12 NULL, { { NULL, USE_GROUPS }, { NULL, 20 } } +#define GRP13 NULL, { { NULL, USE_GROUPS }, { NULL, 21 } } +#define GRP14 NULL, { { NULL, USE_GROUPS }, { NULL, 22 } } +#define GRP15 NULL, { { NULL, USE_GROUPS }, { NULL, 23 } } +#define GRP16 NULL, { { NULL, USE_GROUPS }, { NULL, 24 } } +#define GRPAMD NULL, { { NULL, USE_GROUPS }, { NULL, 25 } } +#define GRPPADLCK1 NULL, { { NULL, USE_GROUPS }, { NULL, 26 } } +#define GRPPADLCK2 NULL, { { NULL, USE_GROUPS }, { NULL, 27 } } #define PREGRP0 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 0 } } #define PREGRP1 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 1 } } @@ -478,6 +475,61 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define PREGRP35 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 35 } } #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 X86_64_0 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 0 } } @@ -490,8 +542,6 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) typedef void (*op_rtn) (int bytemode, int sizeflag); -#define MAX_OPERANDS 4 - struct dis386 { const char *name; struct @@ -515,6 +565,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) @@ -703,9 +754,9 @@ static const struct dis386 dis386[] = { { "movD", { Sv, Sw } }, { "leaS", { Gv, M } }, { "movD", { Sw, Sv } }, - { "popU", { stackEv } }, + { GRP1a }, /* 90 */ - { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } } }, + { PREGRP38 }, { "xchgS", { RMeCX, eAX } }, { "xchgS", { RMeDX, eAX } }, { "xchgS", { RMeBX, eAX } }, @@ -1238,15 +1289,15 @@ 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 */ }; -/* This is used to determine if opcode 0f 38 XX uses DATA prefix. */ +/* 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 */ + /* 10 */ 1,0,0,0,1,1,0,1,0,0,0,0,1,1,1,0, /* 1f */ + /* 20 */ 1,1,1,1,1,1,0,0,1,1,1,1,0,0,0,0, /* 2f */ + /* 30 */ 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1, /* 3f */ + /* 40 */ 1,1,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 */ @@ -1262,7 +1313,7 @@ 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 */ }; -/* This is used to determine if opcode 0f 38 XX uses REPNZ prefix. */ +/* 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 */ /* ------------------------------- */ @@ -1281,12 +1332,12 @@ static const unsigned char threebyte_0x38_uses_REPNZ_prefix[256] = { /* 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 */ + /* f0 */ 1,1,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. */ +/* 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 */ /* ------------------------------- */ @@ -1310,17 +1361,17 @@ 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 */ }; -/* This is used to determine if opcode 0f 3a XX uses DATA prefix. */ +/* 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 */ + /* 00 */ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1, /* 0f */ + /* 10 */ 0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 1f */ + /* 20 */ 1,1,1,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 */ + /* 40 */ 1,1,1,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 */ + /* 60 */ 1,1,1,1,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 */ @@ -1334,7 +1385,7 @@ 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 */ }; -/* This is used to determine if opcode 0f 3a XX uses REPNZ prefix. */ +/* 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 */ /* ------------------------------- */ @@ -1358,7 +1409,7 @@ 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 */ }; -/* This is used to determine if opcode 0f 3a XX uses REPZ prefix. */ +/* 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 */ /* ------------------------------- */ @@ -1389,9 +1440,13 @@ static unsigned char *start_codep; static unsigned char *insn_codep; static unsigned char *codep; static disassemble_info *the_info; -static int mod; -static int rm; -static int reg; +static struct + { + int mod; + int reg; + int rm; + } +modrm; static unsigned char need_modrm; /* If we are accessing mod/rm/reg without need_modrm set, then the @@ -1460,6 +1515,17 @@ static const char *att_index16[] = { }; static const struct dis386 grps[][8] = { + /* GRP1a */ + { + { "popU", { stackEv } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + }, /* GRP1b */ { { "addA", { Eb, Ib } }, @@ -2006,14 +2072,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 */ { @@ -2028,7 +2094,447 @@ static const struct dis386 prefix_user_table[][4] = { { "(bad)", { XX } }, { "popcntS", { Gv, Ev } }, { "(bad)", { XX } }, - { "(bad)", { XX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP38 */ + { + { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } } }, + { "pause", { XX } }, + { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } } }, + { "(bad)", { XX } }, + }, + + /* PREGRP39 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pblendvb", {XM, EX, XMM0 } }, + { "(bad)", { XX } }, + }, + + /* PREGRP40 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "blendvps", {XM, EX, XMM0 } }, + { "(bad)", { XX } }, + }, + + /* PREGRP41 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "blendvpd", { XM, EX, XMM0 } }, + { "(bad)", { XX } }, + }, + + /* PREGRP42 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "ptest", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP43 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovsxbw", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP44 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovsxbd", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP45 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovsxbq", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP46 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovsxwd", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP47 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovsxwq", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP48 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovsxdq", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP49 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmuldq", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP50 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pcmpeqq", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP51 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "movntdqa", { XM, EM } }, + { "(bad)", { XX } }, + }, + + /* PREGRP52 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "packusdw", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP53 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovzxbw", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP54 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovzxbd", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP55 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovzxbq", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP56 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovzxwd", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP57 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovzxwq", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP58 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmovzxdq", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP59 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pminsb", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP60 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pminsd", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP61 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pminuw", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP62 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pminud", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP63 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmaxsb", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP64 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmaxsd", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP65 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmaxuw", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP66 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmaxud", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP67 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmulld", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP68 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "phminposuw", { XM, EX } }, + { "(bad)", { XX } }, + }, + + /* PREGRP69 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "roundps", { XM, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP70 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "roundpd", { XM, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP71 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "roundss", { XM, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP72 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "roundsd", { XM, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP73 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "blendps", { XM, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP74 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "blendpd", { XM, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP75 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pblendw", { XM, EX, 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, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP82 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pinsrK", { XM, Edq, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP83 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "dpps", { XM, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP84 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "dppd", { XM, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP85 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "mpsadbw", { XM, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP86 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pcmpgtq", { XM, EX } }, + { "(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, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP90 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pcmpestri", { XM, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP91 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pcmpistrm", { XM, EX, Ib } }, + { "(bad)", { XX } }, + }, + + /* PREGRP92 */ + { + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pcmpistri", { XM, EX, Ib } }, + { "(bad)", { XX } }, }, }; @@ -2073,14 +2579,14 @@ static const struct dis386 three_byte_table[][256] = { { "(bad)", { XX } }, { "(bad)", { XX } }, /* 10 */ + { PREGRP39 }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, + { PREGRP40 }, + { PREGRP41 }, { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP42 }, /* 18 */ { "(bad)", { XX } }, { "(bad)", { XX } }, @@ -2091,44 +2597,44 @@ static const struct dis386 three_byte_table[][256] = { { "pabsd", { MX, EM } }, { "(bad)", { XX } }, /* 20 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP43 }, + { PREGRP44 }, + { PREGRP45 }, + { PREGRP46 }, + { PREGRP47 }, + { PREGRP48 }, { "(bad)", { XX } }, { "(bad)", { XX } }, /* 28 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP49 }, + { PREGRP50 }, + { PREGRP51 }, + { PREGRP52 }, { "(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 } }, + { PREGRP53 }, + { PREGRP54 }, + { PREGRP55 }, + { PREGRP56 }, + { PREGRP57 }, + { PREGRP58 }, + { "(bad)", { XX } }, + { PREGRP86 }, /* 38 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP59 }, + { PREGRP60 }, + { PREGRP61 }, + { PREGRP62 }, + { PREGRP63 }, + { PREGRP64 }, + { PREGRP65 }, + { PREGRP66 }, /* 40 */ - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { PREGRP67 }, + { PREGRP68 }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, @@ -2325,8 +2831,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 } }, @@ -2355,23 +2861,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 } }, @@ -2382,9 +2888,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 } }, @@ -2418,9 +2924,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 } }, @@ -2454,10 +2960,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 } }, @@ -2739,41 +3245,46 @@ ckprefix (void) static const char * prefix_name (int pref, int sizeflag) { + static const char *rexes [16] = + { + "rex", /* 0x40 */ + "rex.B", /* 0x41 */ + "rex.X", /* 0x42 */ + "rex.XB", /* 0x43 */ + "rex.R", /* 0x44 */ + "rex.RB", /* 0x45 */ + "rex.RX", /* 0x46 */ + "rex.RXB", /* 0x47 */ + "rex.W", /* 0x48 */ + "rex.WB", /* 0x49 */ + "rex.WX", /* 0x4a */ + "rex.WXB", /* 0x4b */ + "rex.WR", /* 0x4c */ + "rex.WRB", /* 0x4d */ + "rex.WRX", /* 0x4e */ + "rex.WRXB", /* 0x4f */ + }; + switch (pref) { /* REX prefixes family. */ case 0x40: - return "rex"; case 0x41: - return "rexZ"; case 0x42: - return "rexY"; case 0x43: - return "rexYZ"; case 0x44: - return "rexX"; case 0x45: - return "rexXZ"; case 0x46: - return "rexXY"; case 0x47: - return "rexXYZ"; case 0x48: - return "rex64"; case 0x49: - return "rex64Z"; case 0x4a: - return "rex64Y"; case 0x4b: - return "rex64YZ"; case 0x4c: - return "rex64X"; case 0x4d: - return "rex64XZ"; case 0x4e: - return "rex64XY"; case 0x4f: - return "rex64XYZ"; + return rexes [pref - 0x40]; case 0xf3: return "repz"; case 0xf2: @@ -3104,11 +3615,12 @@ print_insn (bfd_vma pc, disassemble_info *info) need_modrm = onebyte_has_modrm[*codep]; uses_DATA_prefix = 0; uses_REPNZ_prefix = 0; - uses_REPZ_prefix = 0; + /* pause is 0xf3 0x90. */ + uses_REPZ_prefix = *codep == 0x90; uses_LOCK_prefix = 0; codep++; } - + if (!uses_REPZ_prefix && (prefixes & PREFIX_REPZ)) { oappend ("repz "); @@ -3157,16 +3669,16 @@ print_insn (bfd_vma pc, disassemble_info *info) if (dp->name == NULL && dp->op[0].bytemode == IS_3BYTE_OPCODE) { dp = &three_byte_table[dp->op[1].bytemode][op]; - mod = (*codep >> 6) & 3; - reg = (*codep >> 3) & 7; - rm = *codep & 7; + modrm.mod = (*codep >> 6) & 3; + modrm.reg = (*codep >> 3) & 7; + modrm.rm = *codep & 7; } else if (need_modrm) { FETCH_DATA (info, codep + 1); - mod = (*codep >> 6) & 3; - reg = (*codep >> 3) & 7; - rm = *codep & 7; + modrm.mod = (*codep >> 6) & 3; + modrm.reg = (*codep >> 3) & 7; + modrm.rm = *codep & 7; } if (dp->name == NULL && dp->op[0].bytemode == FLOATCODE) @@ -3181,7 +3693,7 @@ print_insn (bfd_vma pc, disassemble_info *info) switch (dp->op[0].bytemode) { case USE_GROUPS: - dp = &grps[dp->op[1].bytemode][reg]; + dp = &grps[dp->op[1].bytemode][modrm.reg]; break; case USE_PREFIX_USER_TABLE: @@ -3221,7 +3733,7 @@ print_insn (bfd_vma pc, disassemble_info *info) { 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); @@ -3262,14 +3774,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 @@ -3297,6 +3814,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; } @@ -3515,7 +4033,7 @@ static const struct dis386 float_reg[][8] = { { "fmul", { STi, ST } }, { "(bad)", { XX } }, { "(bad)", { XX } }, -#if UNIXWARE_COMPAT +#if SYSV386_COMPAT { "fsub", { STi, ST } }, { "fsubr", { STi, ST } }, { "fdiv", { STi, ST } }, @@ -3544,7 +4062,7 @@ static const struct dis386 float_reg[][8] = { { "fmulp", { STi, ST } }, { "(bad)", { XX } }, { FGRPde_3 }, -#if UNIXWARE_COMPAT +#if SYSV386_COMPAT { "fsubp", { STi, ST } }, { "fsubrp", { STi, ST } }, { "fdivp", { STi, ST } }, @@ -3625,9 +4143,9 @@ dofloat (int sizeflag) floatop = codep[-1]; - if (mod != 3) + if (modrm.mod != 3) { - int fp_indx = (floatop - 0xd8) * 8 + reg; + int fp_indx = (floatop - 0xd8) * 8 + modrm.reg; putop (float_mem[fp_indx], sizeflag); obufp = op_out[0]; @@ -3639,10 +4157,10 @@ dofloat (int sizeflag) MODRM_CHECK; codep++; - dp = &float_reg[floatop - 0xd8][reg]; + dp = &float_reg[floatop - 0xd8][modrm.reg]; if (dp->name == NULL) { - putop (fgrps[dp->op[0].bytemode][rm], sizeflag); + putop (fgrps[dp->op[0].bytemode][modrm.rm], sizeflag); /* Instruction fnstsw is only one with strange arg. */ if (floatop == 0xdf && codep[-1] == 0xe0) @@ -3673,7 +4191,7 @@ OP_ST (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) static void OP_STi (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) { - sprintf (scratchbuf, "%%st(%d)", rm); + sprintf (scratchbuf, "%%st(%d)", modrm.rm); oappend (scratchbuf + intel_syntax); } @@ -3729,7 +4247,7 @@ putop (const char *template, int sizeflag) case 'A': if (intel_syntax) break; - if (mod != 3 || (sizeflag & SUFFIX_ALWAYS)) + if (modrm.mod != 3 || (sizeflag & SUFFIX_ALWAYS)) *obufp++ = 'b'; break; case 'B': @@ -3753,10 +4271,10 @@ putop (const char *template, int sizeflag) case 'D': if (intel_syntax || !(sizeflag & SUFFIX_ALWAYS)) break; - USED_REX (REX_MODE64); - if (mod == 3) + USED_REX (REX_W); + if (modrm.mod == 3) { - if (rex & REX_MODE64) + if (rex & REX_W) *obufp++ = 'q'; else if (sizeflag & DFLAG) *obufp++ = intel_syntax ? 'd' : 'l'; @@ -3795,11 +4313,11 @@ putop (const char *template, int sizeflag) case 'G': if (intel_syntax || (obufp[-1] != 's' && !(sizeflag & SUFFIX_ALWAYS))) break; - if ((rex & REX_MODE64) || (sizeflag & DFLAG)) + if ((rex & REX_W) || (sizeflag & DFLAG)) *obufp++ = 'l'; else *obufp++ = 'w'; - if (!(rex & REX_MODE64)) + if (!(rex & REX_W)) used_prefixes |= (prefixes & PREFIX_DATA); break; case 'H': @@ -3822,6 +4340,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; @@ -3844,14 +4369,14 @@ putop (const char *template, int sizeflag) used_prefixes |= PREFIX_FWAIT; break; case 'O': - USED_REX (REX_MODE64); - if (rex & REX_MODE64) + USED_REX (REX_W); + if (rex & REX_W) *obufp++ = 'o'; else if (intel_syntax && (sizeflag & DFLAG)) *obufp++ = 'q'; else *obufp++ = 'd'; - if (!(rex & REX_MODE64)) + if (!(rex & REX_W)) used_prefixes |= (prefixes & PREFIX_DATA); break; case 'T': @@ -3867,11 +4392,11 @@ putop (const char *template, int sizeflag) if (intel_syntax) break; if ((prefixes & PREFIX_DATA) - || (rex & REX_MODE64) + || (rex & REX_W) || (sizeflag & SUFFIX_ALWAYS)) { - USED_REX (REX_MODE64); - if (rex & REX_MODE64) + USED_REX (REX_W); + if (rex & REX_W) *obufp++ = 'q'; else { @@ -3888,7 +4413,7 @@ putop (const char *template, int sizeflag) break; if (address_mode == mode_64bit && (sizeflag & DFLAG)) { - if (mod != 3 || (sizeflag & SUFFIX_ALWAYS)) + if (modrm.mod != 3 || (sizeflag & SUFFIX_ALWAYS)) *obufp++ = 'q'; break; } @@ -3896,10 +4421,10 @@ putop (const char *template, int sizeflag) case 'Q': if (intel_syntax && !alt) break; - USED_REX (REX_MODE64); - if (mod != 3 || (sizeflag & SUFFIX_ALWAYS)) + USED_REX (REX_W); + if (modrm.mod != 3 || (sizeflag & SUFFIX_ALWAYS)) { - if (rex & REX_MODE64) + if (rex & REX_W) *obufp++ = 'q'; else { @@ -3912,8 +4437,8 @@ putop (const char *template, int sizeflag) } break; case 'R': - USED_REX (REX_MODE64); - if (rex & REX_MODE64) + USED_REX (REX_W); + if (rex & REX_W) *obufp++ = 'q'; else if (sizeflag & DFLAG) { @@ -3925,9 +4450,9 @@ putop (const char *template, int sizeflag) else *obufp++ = 'w'; if (intel_syntax && !p[1] - && ((rex & REX_MODE64) || (sizeflag & DFLAG))) + && ((rex & REX_W) || (sizeflag & DFLAG))) *obufp++ = 'e'; - if (!(rex & REX_MODE64)) + if (!(rex & REX_W)) used_prefixes |= (prefixes & PREFIX_DATA); break; case 'V': @@ -3945,7 +4470,7 @@ putop (const char *template, int sizeflag) break; if (sizeflag & SUFFIX_ALWAYS) { - if (rex & REX_MODE64) + if (rex & REX_W) *obufp++ = 'q'; else { @@ -3967,17 +4492,17 @@ putop (const char *template, int sizeflag) case 'Y': if (intel_syntax) break; - if (rex & REX_MODE64) + if (rex & REX_W) { - USED_REX (REX_MODE64); + USED_REX (REX_W); *obufp++ = 'q'; } break; /* implicit operand size 'l' for i386 or 'q' for x86-64 */ case 'W': /* operand size flag for cwtl, cbtw */ - USED_REX (REX_MODE64); - if (rex & REX_MODE64) + USED_REX (REX_W); + if (rex & REX_W) { if (intel_syntax) *obufp++ = 'd'; @@ -3988,7 +4513,7 @@ putop (const char *template, int sizeflag) *obufp++ = 'w'; else *obufp++ = 'b'; - if (!(rex & REX_MODE64)) + if (!(rex & REX_W)) used_prefixes |= (prefixes & PREFIX_DATA); break; } @@ -4105,12 +4630,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: @@ -4127,8 +4697,8 @@ intel_operand_size (int bytemode, int sizeflag) /* FALLTHRU */ case v_mode: case dq_mode: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) + USED_REX (REX_W); + if (rex & REX_W) oappend ("QWORD PTR "); else if ((sizeflag & DFLAG) || bytemode == dq_mode) oappend ("DWORD PTR "); @@ -4137,13 +4707,14 @@ intel_operand_size (int bytemode, int sizeflag) used_prefixes |= (prefixes & PREFIX_DATA); break; case z_mode: - if ((rex & REX_MODE64) || (sizeflag & DFLAG)) + if ((rex & REX_W) || (sizeflag & DFLAG)) *obufp++ = 'D'; oappend ("WORD PTR "); - if (!(rex & REX_MODE64)) + if (!(rex & REX_W)) used_prefixes |= (prefixes & PREFIX_DATA); break; case d_mode: + case dqd_mode: oappend ("DWORD PTR "); break; case q_mode: @@ -4182,44 +4753,44 @@ OP_E (int bytemode, int sizeflag) bfd_vma disp; int add = 0; int riprel = 0; - USED_REX (REX_EXTZ); - if (rex & REX_EXTZ) + USED_REX (REX_B); + if (rex & REX_B) add += 8; /* Skip mod/rm byte. */ MODRM_CHECK; codep++; - if (mod == 3) + if (modrm.mod == 3) { switch (bytemode) { case b_mode: USED_REX (0); if (rex) - oappend (names8rex[rm + add]); + oappend (names8rex[modrm.rm + add]); else - oappend (names8[rm + add]); + oappend (names8[modrm.rm + add]); break; case w_mode: - oappend (names16[rm + add]); + oappend (names16[modrm.rm + add]); break; case d_mode: - oappend (names32[rm + add]); + oappend (names32[modrm.rm + add]); break; case q_mode: - oappend (names64[rm + add]); + oappend (names64[modrm.rm + add]); break; case m_mode: if (address_mode == mode_64bit) - oappend (names64[rm + add]); + oappend (names64[modrm.rm + add]); else - oappend (names32[rm + add]); + oappend (names32[modrm.rm + add]); break; case stack_v_mode: if (address_mode == mode_64bit && (sizeflag & DFLAG)) { - oappend (names64[rm + add]); + oappend (names64[modrm.rm + add]); used_prefixes |= (prefixes & PREFIX_DATA); break; } @@ -4227,14 +4798,16 @@ 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_MODE64); - if (rex & REX_MODE64) - oappend (names64[rm + add]); + USED_REX (REX_W); + if (rex & REX_W) + oappend (names64[modrm.rm + add]); else if ((sizeflag & DFLAG) || bytemode != v_mode) - oappend (names32[rm + add]); + oappend (names32[modrm.rm + add]); else - oappend (names16[rm + add]); + oappend (names16[modrm.rm + add]); used_prefixes |= (prefixes & PREFIX_DATA); break; case 0: @@ -4251,8 +4824,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; @@ -4261,7 +4836,7 @@ OP_E (int bytemode, int sizeflag) havesib = 0; havebase = 1; - base = rm; + base = modrm.rm; if (base == 4) { @@ -4272,14 +4847,14 @@ OP_E (int bytemode, int sizeflag) /* When INDEX == 0x4 in 32 bit mode, SCALE is ignored. */ scale = (*codep >> 6) & 3; base = *codep & 7; - USED_REX (REX_EXTY); - if (rex & REX_EXTY) + USED_REX (REX_X); + if (rex & REX_X) index += 8; codep++; } base += add; - switch (mod) + switch (modrm.mod) { case 0: if ((base & 7) == 5) @@ -4301,10 +4876,15 @@ OP_E (int bytemode, int sizeflag) break; } + havedisp = havebase || (havesib && (index != 4 || scale != 0)); + if (!intel_syntax) - if (mod != 0 || (base & 7) == 5) + 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) { @@ -4313,11 +4893,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) @@ -4342,21 +4925,22 @@ 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'; } - else if (mod != 1) + else if (modrm.mod != 1) { *obufp++ = '-'; *obufp = '\0'; disp = - (bfd_signed_vma) disp; } - print_operand_value (scratchbuf, mod != 1, disp); + print_displacement (scratchbuf, disp); oappend (scratchbuf); } @@ -4365,7 +4949,7 @@ OP_E (int bytemode, int sizeflag) } else if (intel_syntax) { - if (mod != 0 || (base & 7) == 5) + if (modrm.mod != 0 || (base & 7) == 5) { if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS | PREFIX_ES | PREFIX_FS | PREFIX_GS)) @@ -4382,10 +4966,10 @@ OP_E (int bytemode, int sizeflag) } else { /* 16 bit address mode */ - switch (mod) + switch (modrm.mod) { case 0: - if (rm == 6) + if (modrm.rm == 6) { disp = get16 (); if ((disp & 0x8000) != 0) @@ -4406,32 +4990,33 @@ OP_E (int bytemode, int sizeflag) } if (!intel_syntax) - if (mod != 0 || rm == 6) + if (modrm.mod != 0 || modrm.rm == 6) { - print_operand_value (scratchbuf, 0, disp); + print_displacement (scratchbuf, disp); oappend (scratchbuf); } - if (mod != 0 || rm != 6) + if (modrm.mod != 0 || modrm.rm != 6) { *obufp++ = open_char; *obufp = '\0'; - oappend (index16[rm]); - if (intel_syntax && disp) + oappend (index16[modrm.rm]); + 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'; } - else if (mod != 1) + else if (modrm.mod != 1) { *obufp++ = '-'; *obufp = '\0'; disp = - (bfd_signed_vma) disp; } - print_operand_value (scratchbuf, mod != 1, disp); + print_displacement (scratchbuf, disp); oappend (scratchbuf); } @@ -4458,44 +5043,46 @@ static void OP_G (int bytemode, int sizeflag) { int add = 0; - USED_REX (REX_EXTX); - if (rex & REX_EXTX) + USED_REX (REX_R); + if (rex & REX_R) add += 8; switch (bytemode) { case b_mode: USED_REX (0); if (rex) - oappend (names8rex[reg + add]); + oappend (names8rex[modrm.reg + add]); else - oappend (names8[reg + add]); + oappend (names8[modrm.reg + add]); break; case w_mode: - oappend (names16[reg + add]); + oappend (names16[modrm.reg + add]); break; case d_mode: - oappend (names32[reg + add]); + oappend (names32[modrm.reg + add]); break; case q_mode: - oappend (names64[reg + add]); + oappend (names64[modrm.reg + add]); break; case v_mode: case dq_mode: + case dqb_mode: + case dqd_mode: case dqw_mode: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) - oappend (names64[reg + add]); + USED_REX (REX_W); + if (rex & REX_W) + oappend (names64[modrm.reg + add]); else if ((sizeflag & DFLAG) || bytemode != v_mode) - oappend (names32[reg + add]); + oappend (names32[modrm.reg + add]); else - oappend (names16[reg + add]); + oappend (names16[modrm.reg + add]); used_prefixes |= (prefixes & PREFIX_DATA); break; case m_mode: if (address_mode == mode_64bit) - oappend (names64[reg + add]); + oappend (names64[modrm.reg + add]); else - oappend (names32[reg + add]); + oappend (names32[modrm.reg + add]); break; default: oappend (INTERNAL_DISASSEMBLER_ERROR); @@ -4590,8 +5177,8 @@ OP_REG (int code, int sizeflag) { const char *s; int add = 0; - USED_REX (REX_EXTZ); - if (rex & REX_EXTZ) + USED_REX (REX_B); + if (rex & REX_B) add = 8; switch (code) @@ -4623,8 +5210,8 @@ OP_REG (int code, int sizeflag) /* Fall through. */ case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg: case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) + USED_REX (REX_W); + if (rex & REX_W) s = names64[code - eAX_reg + add]; else if (sizeflag & DFLAG) s = names32[code - eAX_reg + add]; @@ -4670,8 +5257,8 @@ OP_IMREG (int code, int sizeflag) break; case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg: case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) + USED_REX (REX_W); + if (rex & REX_W) s = names64[code - eAX_reg]; else if (sizeflag & DFLAG) s = names32[code - eAX_reg]; @@ -4680,11 +5267,11 @@ OP_IMREG (int code, int sizeflag) used_prefixes |= (prefixes & PREFIX_DATA); break; case z_mode_ax_reg: - if ((rex & REX_MODE64) || (sizeflag & DFLAG)) + if ((rex & REX_W) || (sizeflag & DFLAG)) s = *names32; else s = *names16; - if (!(rex & REX_MODE64)) + if (!(rex & REX_W)) used_prefixes |= (prefixes & PREFIX_DATA); break; default: @@ -4715,8 +5302,8 @@ OP_I (int bytemode, int sizeflag) } /* Fall through. */ case v_mode: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) + USED_REX (REX_W); + if (rex & REX_W) op = get32s (); else if (sizeflag & DFLAG) { @@ -4770,8 +5357,8 @@ OP_I64 (int bytemode, int sizeflag) mask = 0xff; break; case v_mode: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) + USED_REX (REX_W); + if (rex & REX_W) op = get64 (); else if (sizeflag & DFLAG) { @@ -4817,8 +5404,8 @@ OP_sI (int bytemode, int sizeflag) mask = 0xffffffff; break; case v_mode: - USED_REX (REX_MODE64); - if (rex & REX_MODE64) + USED_REX (REX_W); + if (rex & REX_W) op = get32s (); else if (sizeflag & DFLAG) { @@ -4866,7 +5453,7 @@ OP_J (int bytemode, int sizeflag) disp -= 0x100; break; case v_mode: - if ((sizeflag & DFLAG) || (rex & REX_MODE64)) + if ((sizeflag & DFLAG) || (rex & REX_W)) disp = get32s (); else { @@ -4898,9 +5485,9 @@ static void OP_SEG (int bytemode, int sizeflag) { if (bytemode == w_mode) - oappend (names_seg[reg]); + oappend (names_seg[modrm.reg]); else - OP_E (mod == 3 ? bytemode : w_mode, sizeflag); + OP_E (modrm.mod == 3 ? bytemode : w_mode, sizeflag); } static void @@ -5066,9 +5653,9 @@ static void OP_C (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) { int add = 0; - if (rex & REX_EXTX) + if (rex & REX_R) { - USED_REX (REX_EXTX); + USED_REX (REX_R); add = 8; } else if (address_mode != mode_64bit && (prefixes & PREFIX_LOCK)) @@ -5076,7 +5663,7 @@ OP_C (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) used_prefixes |= PREFIX_LOCK; add = 8; } - sprintf (scratchbuf, "%%cr%d", reg + add); + sprintf (scratchbuf, "%%cr%d", modrm.reg + add); oappend (scratchbuf + intel_syntax); } @@ -5084,27 +5671,27 @@ static void OP_D (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) { int add = 0; - USED_REX (REX_EXTX); - if (rex & REX_EXTX) + USED_REX (REX_R); + if (rex & REX_R) add = 8; if (intel_syntax) - sprintf (scratchbuf, "db%d", reg + add); + sprintf (scratchbuf, "db%d", modrm.reg + add); else - sprintf (scratchbuf, "%%db%d", reg + add); + sprintf (scratchbuf, "%%db%d", modrm.reg + add); oappend (scratchbuf); } static void OP_T (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) { - sprintf (scratchbuf, "%%tr%d", reg); + sprintf (scratchbuf, "%%tr%d", modrm.reg); oappend (scratchbuf + intel_syntax); } static void OP_R (int bytemode, int sizeflag) { - if (mod == 3) + if (modrm.mod == 3) OP_E (bytemode, sizeflag); else BadOp (); @@ -5117,13 +5704,13 @@ OP_MMX (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) if (prefixes & PREFIX_DATA) { int add = 0; - USED_REX (REX_EXTX); - if (rex & REX_EXTX) + USED_REX (REX_R); + if (rex & REX_R) add = 8; - sprintf (scratchbuf, "%%xmm%d", reg + add); + sprintf (scratchbuf, "%%xmm%d", modrm.reg + add); } else - sprintf (scratchbuf, "%%mm%d", reg); + sprintf (scratchbuf, "%%mm%d", modrm.reg); oappend (scratchbuf + intel_syntax); } @@ -5131,17 +5718,17 @@ static void OP_XMM (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) { int add = 0; - USED_REX (REX_EXTX); - if (rex & REX_EXTX) + USED_REX (REX_R); + if (rex & REX_R) add = 8; - sprintf (scratchbuf, "%%xmm%d", reg + add); + sprintf (scratchbuf, "%%xmm%d", modrm.reg + add); oappend (scratchbuf + intel_syntax); } static void OP_EM (int bytemode, int sizeflag) { - if (mod != 3) + if (modrm.mod != 3) { if (intel_syntax && bytemode == v_mode) { @@ -5160,25 +5747,25 @@ OP_EM (int bytemode, int sizeflag) { int add = 0; - USED_REX (REX_EXTZ); - if (rex & REX_EXTZ) + USED_REX (REX_B); + if (rex & REX_B) add = 8; - sprintf (scratchbuf, "%%xmm%d", rm + add); + sprintf (scratchbuf, "%%xmm%d", modrm.rm + add); } else - sprintf (scratchbuf, "%%mm%d", rm); + sprintf (scratchbuf, "%%mm%d", modrm.rm); 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) { - if (mod != 3) + if (modrm.mod != 3) { if (intel_syntax && bytemode == v_mode) { @@ -5188,12 +5775,12 @@ OP_EMC (int bytemode, int sizeflag) OP_E (bytemode, sizeflag); return; } - + /* Skip mod/rm byte. */ MODRM_CHECK; codep++; used_prefixes |= (prefixes & PREFIX_DATA); - sprintf (scratchbuf, "%%mm%d", rm); + sprintf (scratchbuf, "%%mm%d", modrm.rm); oappend (scratchbuf + intel_syntax); } @@ -5201,7 +5788,7 @@ static void OP_MXC (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) { used_prefixes |= (prefixes & PREFIX_DATA); - sprintf (scratchbuf, "%%mm%d", reg); + sprintf (scratchbuf, "%%mm%d", modrm.reg); oappend (scratchbuf + intel_syntax); } @@ -5209,7 +5796,7 @@ static void OP_EX (int bytemode, int sizeflag) { int add = 0; - if (mod != 3) + if (modrm.mod != 3) { if (intel_syntax && bytemode == v_mode) { @@ -5225,21 +5812,21 @@ OP_EX (int bytemode, int sizeflag) OP_E (bytemode, sizeflag); return; } - USED_REX (REX_EXTZ); - if (rex & REX_EXTZ) + USED_REX (REX_B); + if (rex & REX_B) add = 8; /* Skip mod/rm byte. */ MODRM_CHECK; codep++; - sprintf (scratchbuf, "%%xmm%d", rm + add); + sprintf (scratchbuf, "%%xmm%d", modrm.rm + add); oappend (scratchbuf + intel_syntax); } static void OP_MS (int bytemode, int sizeflag) { - if (mod == 3) + if (modrm.mod == 3) OP_EM (bytemode, sizeflag); else BadOp (); @@ -5248,7 +5835,7 @@ OP_MS (int bytemode, int sizeflag) static void OP_XS (int bytemode, int sizeflag) { - if (mod == 3) + if (modrm.mod == 3) OP_EX (bytemode, sizeflag); else BadOp (); @@ -5257,7 +5844,7 @@ OP_XS (int bytemode, int sizeflag) static void OP_M (int bytemode, int sizeflag) { - if (mod == 3) + if (modrm.mod == 3) /* bad bound,lea,lds,les,lfs,lgs,lss,cmpxchg8b,vmptrst modrm */ BadOp (); else @@ -5267,7 +5854,7 @@ OP_M (int bytemode, int sizeflag) static void OP_0f07 (int bytemode, int sizeflag) { - if (mod != 3 || rm != 0) + if (modrm.mod != 3 || modrm.rm != 0) BadOp (); else OP_E (bytemode, sizeflag); @@ -5276,18 +5863,18 @@ OP_0f07 (int bytemode, int sizeflag) static void OP_0fae (int bytemode, int sizeflag) { - if (mod == 3) + if (modrm.mod == 3) { - if (reg == 7) + if (modrm.reg == 7) strcpy (obuf + strlen (obuf) - sizeof ("clflush") + 1, "sfence"); - if (reg < 5 || rm != 0) + if (modrm.reg < 5 || modrm.rm != 0) { BadOp (); /* bad sfence, mfence, or lfence */ return; } } - else if (reg != 7) + else if (modrm.reg != 7) { BadOp (); /* bad clflush */ return; @@ -5297,17 +5884,15 @@ OP_0fae (int bytemode, int 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. NOP with REPZ prefix - is called PAUSE. We display "xchg %ax,%ax" instead of "data16 nop". - */ + 32bit mode and "xchg %rax,%rax" in 64bit mode. */ static void NOP_Fixup1 (int bytemode, int sizeflag) { - if (prefixes == PREFIX_REPZ) - strcpy (obuf, "pause"); - else if (prefixes == PREFIX_DATA - || ((rex & REX_MODE64) && rex != 0x48)) + if ((prefixes & PREFIX_DATA) != 0 + || (rex != 0 + && rex != 0x48 + && address_mode == mode_64bit)) OP_REG (bytemode, sizeflag); else strcpy (obuf, "nop"); @@ -5316,8 +5901,10 @@ NOP_Fixup1 (int bytemode, int sizeflag) static void NOP_Fixup2 (int bytemode, int sizeflag) { - if (prefixes == PREFIX_DATA - || ((rex & REX_MODE64) && rex != 0x48)) + if ((prefixes & PREFIX_DATA) != 0 + || (rex != 0 + && rex != 0x48 + && address_mode == mode_64bit)) OP_IMREG (bytemode, sizeflag); } @@ -5367,7 +5954,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, @@ -5469,7 +6056,7 @@ SIMD_Fixup (int extrachar, int sizeflag ATTRIBUTE_UNUSED) { /* Change movlps/movhps to movhlps/movlhps for 2 register operand forms of these instructions. */ - if (mod == 3) + if (modrm.mod == 3) { char *p = obuf + strlen (obuf); *(p + 1) = '\0'; @@ -5483,7 +6070,7 @@ SIMD_Fixup (int extrachar, int sizeflag ATTRIBUTE_UNUSED) static void PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag) { - if (mod == 3 && reg == 1 && rm <= 1) + if (modrm.mod == 3 && modrm.reg == 1 && modrm.rm <= 1) { /* Override "sidt". */ size_t olen = strlen (obuf); @@ -5505,7 +6092,7 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag) || CONST_STRNEQ (p - 3, "32"))) p -= 7; - if (rm) + if (modrm.rm) { /* mwait %eax,%ecx */ strcpy (p, "mwait"); @@ -5647,7 +6234,10 @@ BadOp (void) static void VMX_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag) { - if (mod == 3 && reg == 0 && rm >=1 && rm <= 4) + if (modrm.mod == 3 + && modrm.reg == 0 + && modrm.rm >=1 + && modrm.rm <= 4) { /* Override "sgdt". */ char *p = obuf + strlen (obuf) - 4; @@ -5656,7 +6246,7 @@ VMX_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag) if (*p == 'g') --p; - switch (rm) + switch (modrm.rm) { case 1: strcpy (p, "vmcall"); @@ -5699,7 +6289,7 @@ REP_Fixup (int bytemode, int sizeflag) size_t ilen = 0; if (prefixes & PREFIX_REPZ) - switch (*insn_codep) + switch (*insn_codep) { case 0x6e: /* outsb */ case 0x6f: /* outsw/outsl */ @@ -5767,8 +6357,8 @@ REP_Fixup (int bytemode, int sizeflag) static void CMPXCHG8B_Fixup (int bytemode, int sizeflag) { - USED_REX (REX_MODE64); - if (rex & REX_MODE64) + USED_REX (REX_W); + if (rex & REX_W) { /* Change cmpxchg8b to cmpxchg16b. */ char *p = obuf + strlen (obuf) - 2; @@ -5777,3 +6367,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); +}