diff options
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r-- | opcodes/i386-dis.c | 1567 |
1 files changed, 1559 insertions, 8 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 0c7f77a..82b2bcb 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -37,6 +37,7 @@ #include "dis-asm.h" #include "opintl.h" #include "opcode/i386.h" +#include "libiberty.h" #include <setjmp.h> @@ -52,6 +53,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 OP_E_extended (int, int, int); static void print_displacement (char *, bfd_vma); static void OP_E (int, int); static void OP_G (int, int); @@ -99,6 +101,11 @@ static void REP_Fixup (int, int); static void CMPXCHG8B_Fixup (int, int); static void XMM_Fixup (int, int); static void CRC32_Fixup (int, int); +static void print_drex_arg (unsigned int, int, int); +static void OP_DREX4 (int, int); +static void OP_DREX3 (int, int); +static void OP_DREX_ICMP (int, int); +static void OP_DREX_FCMP (int, int); struct dis_private { /* Points to first byte not fetched. */ @@ -140,6 +147,20 @@ static int rex_used; rex_used |= REX_OPCODE; \ } +/* Special 'registers' for DREX handling */ +#define DREX_REG_UNKNOWN 1000 /* not initialized */ +#define DREX_REG_MEMORY 1001 /* use MODRM/SIB/OFFSET memory */ + +/* The DREX byte has the following fields: + Bits 7-4 -- DREX.Dest, xmm destination register + Bit 3 -- DREX.OC0, operand config bit defines operand order + Bit 2 -- DREX.R, equivalent to REX_R bit, to extend ModRM register + Bit 1 -- DREX.X, equivalent to REX_X bit, to extend SIB index field + Bit 0 -- DREX.W, equivalent to REX_B bit, to extend ModRM r/m field, + SIB base field, or opcode reg field. */ +#define DREX_XMM(drex) ((drex >> 4) & 0xf) +#define DREX_OC0(drex) ((drex >> 3) & 0x1) + /* Flags for prefixes which we somehow handled when printing the current instruction. */ static int used_prefixes; @@ -360,6 +381,11 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define dqb_mode 18 /* registers like dq_mode, memory like b_mode. */ #define dqd_mode 19 /* registers like dq_mode, memory like d_mode. */ +/* Flags that are OR'ed into the bytemode field to pass extra information. */ +#define DREX_OC1 0x4000 /* OC1 bit set */ +#define DREX_NO_OC0 0x2000 /* OC0 bit not used */ +#define DREX_MASK 0x6000 /* mask to delete */ + #define es_reg 100 #define cs_reg 101 #define ss_reg 102 @@ -555,6 +581,10 @@ 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 THREE_BYTE_SSE5_0F24 NULL, { { NULL, IS_3BYTE_OPCODE }, { NULL, 2 } } +#define THREE_BYTE_SSE5_0F25 NULL, { { NULL, IS_3BYTE_OPCODE }, { NULL, 3 } } +#define THREE_BYTE_SSE5_0F7A NULL, { { NULL, IS_3BYTE_OPCODE }, { NULL, 4 } } +#define THREE_BYTE_SSE5_0F7B NULL, { { NULL, IS_3BYTE_OPCODE }, { NULL, 5 } } #define OPC_EXT_0 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 0 } } #define OPC_EXT_1 NULL, { { NULL, USE_OPC_EXT_TABLE }, { NULL, 1 } } @@ -997,7 +1027,7 @@ static const struct dis386 dis386_twobyte[] = { { OPC_EXT_42 }, { OPC_EXT_43 }, { OPC_EXT_44 }, - { "(bad)", { XX } }, + { THREE_BYTE_SSE5_0F25 }, { OPC_EXT_45 }, { "(bad)", { XX } }, /* 28 */ @@ -1093,8 +1123,8 @@ static const struct dis386 dis386_twobyte[] = { /* 78 */ { PREGRP34 }, { PREGRP35 }, - { "(bad)", { XX } }, - { "(bad)", { XX } }, + { THREE_BYTE_SSE5_0F7A }, + { THREE_BYTE_SSE5_0F7B }, { PREGRP28 }, { PREGRP29 }, { PREGRP23 }, @@ -1273,12 +1303,12 @@ static const unsigned char twobyte_has_modrm[256] = { /* ------------------------------- */ /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */ /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1, /* 1f */ - /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */ + /* 20 */ 1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1, /* 2f */ /* 30 */ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 3f */ /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */ /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */ /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */ - /* 70 */ 1,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1, /* 7f */ + /* 70 */ 1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1, /* 7f */ /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */ /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */ @@ -3066,6 +3096,1170 @@ static const struct dis386 three_byte_table[][256] = { { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, + }, + /* THREE_BYTE_SSE5_0F24 */ + { + /* 00 */ + { "fmaddps", { { OP_DREX4, q_mode } } }, + { "fmaddpd", { { OP_DREX4, q_mode } } }, + { "fmaddss", { { OP_DREX4, w_mode } } }, + { "fmaddsd", { { OP_DREX4, d_mode } } }, + { "fmaddps", { { OP_DREX4, DREX_OC1 + q_mode } } }, + { "fmaddpd", { { OP_DREX4, DREX_OC1 + q_mode } } }, + { "fmaddss", { { OP_DREX4, DREX_OC1 + w_mode } } }, + { "fmaddsd", { { OP_DREX4, DREX_OC1 + d_mode } } }, + /* 08 */ + { "fmsubps", { { OP_DREX4, q_mode } } }, + { "fmsubpd", { { OP_DREX4, q_mode } } }, + { "fmsubss", { { OP_DREX4, w_mode } } }, + { "fmsubsd", { { OP_DREX4, d_mode } } }, + { "fmsubps", { { OP_DREX4, DREX_OC1 + q_mode } } }, + { "fmsubpd", { { OP_DREX4, DREX_OC1 + q_mode } } }, + { "fmsubss", { { OP_DREX4, DREX_OC1 + w_mode } } }, + { "fmsubsd", { { OP_DREX4, DREX_OC1 + d_mode } } }, + /* 10 */ + { "fnmaddps", { { OP_DREX4, q_mode } } }, + { "fnmaddpd", { { OP_DREX4, q_mode } } }, + { "fnmaddss", { { OP_DREX4, w_mode } } }, + { "fnmaddsd", { { OP_DREX4, d_mode } } }, + { "fnmaddps", { { OP_DREX4, DREX_OC1 + q_mode } } }, + { "fnmaddpd", { { OP_DREX4, DREX_OC1 + q_mode } } }, + { "fnmaddss", { { OP_DREX4, DREX_OC1 + w_mode } } }, + { "fnmaddsd", { { OP_DREX4, DREX_OC1 + d_mode } } }, + /* 18 */ + { "fnmsubps", { { OP_DREX4, q_mode } } }, + { "fnmsubpd", { { OP_DREX4, q_mode } } }, + { "fnmsubss", { { OP_DREX4, w_mode } } }, + { "fnmsubsd", { { OP_DREX4, d_mode } } }, + { "fnmsubps", { { OP_DREX4, DREX_OC1 + q_mode } } }, + { "fnmsubpd", { { OP_DREX4, DREX_OC1 + q_mode } } }, + { "fnmsubss", { { OP_DREX4, DREX_OC1 + w_mode } } }, + { "fnmsubsd", { { OP_DREX4, DREX_OC1 + d_mode } } }, + /* 20 */ + { "permps", { { OP_DREX4, q_mode } } }, + { "permpd", { { OP_DREX4, q_mode } } }, + { "pcmov", { { OP_DREX4, q_mode } } }, + { "pperm", { { OP_DREX4, q_mode } } }, + { "permps", { { OP_DREX4, DREX_OC1 + q_mode } } }, + { "permpd", { { OP_DREX4, DREX_OC1 + q_mode } } }, + { "pcmov", { { OP_DREX4, DREX_OC1 + w_mode } } }, + { "pperm", { { OP_DREX4, DREX_OC1 + d_mode } } }, + /* 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 */ + { "protb", { { OP_DREX3, q_mode } } }, + { "protw", { { OP_DREX3, q_mode } } }, + { "protd", { { OP_DREX3, q_mode } } }, + { "protq", { { OP_DREX3, q_mode } } }, + { "pshlb", { { OP_DREX3, q_mode } } }, + { "pshlw", { { OP_DREX3, q_mode } } }, + { "pshld", { { OP_DREX3, q_mode } } }, + { "pshlq", { { OP_DREX3, q_mode } } }, + /* 48 */ + { "pshab", { { OP_DREX3, q_mode } } }, + { "pshaw", { { OP_DREX3, q_mode } } }, + { "pshad", { { OP_DREX3, q_mode } } }, + { "pshaq", { { OP_DREX3, q_mode } } }, + { "(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 } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmacssww", { { OP_DREX4, DREX_OC1 + DREX_NO_OC0 + q_mode } } }, + { "pmacsswd", { { OP_DREX4, DREX_OC1 + DREX_NO_OC0 + q_mode } } }, + { "pmacssdql", { { OP_DREX4, DREX_OC1 + DREX_NO_OC0 + q_mode } } }, + /* 88 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmacssdd", { { OP_DREX4, DREX_OC1 + DREX_NO_OC0 + q_mode } } }, + { "pmacssdqh", { { OP_DREX4, DREX_OC1 + DREX_NO_OC0 + q_mode } } }, + /* 90 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmacsww", { { OP_DREX4, DREX_OC1 + DREX_NO_OC0 + q_mode } } }, + { "pmacswd", { { OP_DREX4, DREX_OC1 + DREX_NO_OC0 + q_mode } } }, + { "pmacsdql", { { OP_DREX4, DREX_OC1 + DREX_NO_OC0 + q_mode } } }, + /* 98 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmacsdd", { { OP_DREX4, DREX_OC1 + DREX_NO_OC0 + q_mode } } }, + { "pmacsdqh", { { OP_DREX4, DREX_OC1 + DREX_NO_OC0 + q_mode } } }, + /* a0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmadcsswd", { { OP_DREX4, DREX_OC1 + DREX_NO_OC0 + q_mode } } }, + { "(bad)", { XX } }, + /* a8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* b0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "pmadcswd", { { OP_DREX4, DREX_OC1 + DREX_NO_OC0 + q_mode } } }, + { "(bad)", { XX } }, + /* b8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* c0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* c8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* d0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* d8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* e0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* e8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* f0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* f8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + }, + /* THREE_BYTE_SSE5_0F25 */ + { + /* 00 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 08 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(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 } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(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 } }, + { "comps", { { OP_DREX3, q_mode }, { OP_DREX_FCMP, b_mode } } }, + { "compd", { { OP_DREX3, q_mode }, { OP_DREX_FCMP, b_mode } } }, + { "comss", { { OP_DREX3, w_mode }, { OP_DREX_FCMP, b_mode } } }, + { "comsd", { { OP_DREX3, d_mode }, { OP_DREX_FCMP, b_mode } } }, + /* 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 } }, + { "pcomb", { { OP_DREX3, q_mode }, { OP_DREX_ICMP, b_mode } } }, + { "pcomw", { { OP_DREX3, q_mode }, { OP_DREX_ICMP, b_mode } } }, + { "pcomd", { { OP_DREX3, q_mode }, { OP_DREX_ICMP, b_mode } } }, + { "pcomq", { { OP_DREX3, q_mode }, { OP_DREX_ICMP, b_mode } } }, + /* 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 } }, + { "pcomub", { { OP_DREX3, q_mode }, { OP_DREX_ICMP, b_mode } } }, + { "pcomuw", { { OP_DREX3, q_mode }, { OP_DREX_ICMP, b_mode } } }, + { "pcomud", { { OP_DREX3, q_mode }, { OP_DREX_ICMP, b_mode } } }, + { "pcomuq", { { OP_DREX3, q_mode }, { OP_DREX_ICMP, b_mode } } }, + /* 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 } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 88 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 90 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 98 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* a0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* a8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* b0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* b8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* c0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* c8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* d0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* d8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* e0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* e8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* f0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* f8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + }, + /* THREE_BYTE_SSE5_0F7A */ + { + /* 00 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 08 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 10 */ + { "frczps", { XM, EXq } }, + { "frczpd", { XM, EXq } }, + { "frczss", { XM, EXq } }, + { "frczsd", { XM, EXq } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 18 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 20 */ + { "ptest", { 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 */ + { "cvtph2ps", { XM, EXd } }, + { "cvtps2ph", { EXd, XM } }, + { "(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 } }, + { "phaddbw", { XM, EXq } }, + { "phaddbd", { XM, EXq } }, + { "phaddbq", { XM, EXq } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "phaddwd", { XM, EXq } }, + { "phaddwq", { XM, EXq } }, + /* 48 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "phadddq", { XM, EXq } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 50 */ + { "(bad)", { XX } }, + { "phaddubw", { XM, EXq } }, + { "phaddubd", { XM, EXq } }, + { "phaddubq", { XM, EXq } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "phadduwd", { XM, EXq } }, + { "phadduwq", { XM, EXq } }, + /* 58 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "phaddudq", { XM, EXq } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 60 */ + { "(bad)", { XX } }, + { "phsubbw", { XM, EXq } }, + { "phsubbd", { XM, EXq } }, + { "phsubbq", { XM, EXq } }, + { "(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 } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 88 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 90 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 98 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* a0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* a8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* b0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* b8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* c0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* c8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* d0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* d8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* e0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* e8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* f0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* f8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + }, + /* THREE_BYTE_SSE5_0F7B */ + { + /* 00 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 08 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(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 } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(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 */ + { "protb", { XM, EXq, Ib } }, + { "protw", { XM, EXq, Ib } }, + { "protd", { XM, EXq, Ib } }, + { "protq", { XM, EXq, Ib } }, + { "pshlb", { XM, EXq, Ib } }, + { "pshlw", { XM, EXq, Ib } }, + { "pshld", { XM, EXq, Ib } }, + { "pshlq", { XM, EXq, Ib } }, + /* 48 */ + { "pshab", { XM, EXq, Ib } }, + { "pshaw", { XM, EXq, Ib } }, + { "pshad", { XM, EXq, Ib } }, + { "pshaq", { XM, EXq, Ib } }, + { "(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 } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 88 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 90 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* 98 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* a0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* a8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* b0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* b8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* c0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* c8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* d0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* d8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* e0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* e8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* f0 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + /* f8 */ + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, + { "(bad)", { XX } }, } }; @@ -3292,7 +4486,7 @@ static const struct dis386 opc_ext_table[][2] = { }, { /* OPC_EXT_44 */ - { "(bad)", { XX } }, + { THREE_BYTE_SSE5_0F24 }, { "movL", { Rd, Td } }, }, { @@ -5027,7 +6221,7 @@ intel_operand_size (int bytemode, int sizeflag) } static void -OP_E (int bytemode, int sizeflag) +OP_E_extended (int bytemode, int sizeflag, int has_drex) { bfd_vma disp; int add = 0; @@ -5133,6 +6327,14 @@ OP_E (int bytemode, int sizeflag) } base += add; + /* If we have a DREX byte, skip it now + (it has already been handled) */ + if (has_drex) + { + FETCH_DATA (the_info, codep + 1); + codep++; + } + switch (modrm.mod) { case 0: @@ -5193,7 +6395,8 @@ OP_E (int bytemode, int sizeflag) *obufp++ = separator_char; *obufp = '\0'; } - oappend (address_mode == mode_64bit && (sizeflag & AFLAG) + oappend (address_mode == mode_64bit + && (sizeflag & AFLAG) ? names64[index] : names32[index]); } if (scale != 0 || (!intel_syntax && index != 4)) @@ -5319,6 +6522,13 @@ OP_E (int bytemode, int sizeflag) } static void +OP_E (int bytemode, int sizeflag) +{ + OP_E_extended (bytemode, sizeflag, 0); +} + + +static void OP_G (int bytemode, int sizeflag) { int add = 0; @@ -6468,3 +7678,344 @@ CRC32_Fixup (int bytemode, int sizeflag) else OP_E (bytemode, sizeflag); } + +/* Print a DREX argument as either a register or memory operation. */ +static void +print_drex_arg (unsigned int reg, int bytemode, int sizeflag) +{ + if (reg == DREX_REG_UNKNOWN) + BadOp (); + + else if (reg != DREX_REG_MEMORY) + { + sprintf (scratchbuf, "%%xmm%d", reg); + oappend (scratchbuf + intel_syntax); + } + + else + OP_E_extended (bytemode, sizeflag, 1); +} + +/* SSE5 instructions that have 4 arguments are encoded as: + 0f 24 <sub-opcode> <modrm> <optional-sib> <drex> <offset>. + + The <sub-opcode> byte has 1 bit (0x4) that is combined with 1 bit in + the DREX field (0x8) to determine how the arguments are laid out. + The destination register must be the same register as one of the + inputs, and it is encoded in the DREX byte. No REX prefix is used + for these instructions, since the DREX field contains the 3 extension + bits provided by the REX prefix. + + The bytemode argument adds 2 extra bits for passing extra information: + DREX_OC1 -- Set the OC1 bit to indicate dest == 1st arg + DREX_NO_OC0 -- OC0 in DREX is invalid + (but pretend it is set). */ + +static void +OP_DREX4 (int flag_bytemode, int sizeflag) +{ + unsigned int drex_byte; + unsigned int regs[4]; + unsigned int modrm_regmem; + unsigned int modrm_reg; + unsigned int drex_reg; + int bytemode; + int rex_save = rex; + int rex_used_save = rex_used; + int has_sib = 0; + int oc1 = (flag_bytemode & DREX_OC1) ? 2 : 0; + int oc0; + int i; + + bytemode = flag_bytemode & ~ DREX_MASK; + + for (i = 0; i < 4; i++) + regs[i] = DREX_REG_UNKNOWN; + + /* Determine if we have a SIB byte in addition to MODRM before the + DREX byte. */ + if (((sizeflag & AFLAG) || address_mode == mode_64bit) + && (modrm.mod != 3) + && (modrm.rm == 4)) + has_sib = 1; + + /* Get the DREX byte. */ + FETCH_DATA (the_info, codep + 2 + has_sib); + drex_byte = codep[has_sib+1]; + drex_reg = DREX_XMM (drex_byte); + modrm_reg = modrm.reg + ((drex_byte & REX_R) ? 8 : 0); + + /* Is OC0 legal? If not, hardwire oc0 == 1. */ + if (flag_bytemode & DREX_NO_OC0) + { + oc0 = 1; + if (DREX_OC0 (drex_byte)) + BadOp (); + } + else + oc0 = DREX_OC0 (drex_byte); + + if (modrm.mod == 3) + { + /* regmem == register */ + modrm_regmem = modrm.rm + ((drex_byte & REX_B) ? 8 : 0); + rex = rex_used = 0; + /* skip modrm/drex since we don't call OP_E_extended */ + codep += 2; + } + else + { + /* regmem == memory, fill in appropriate REX bits */ + modrm_regmem = DREX_REG_MEMORY; + rex = drex_byte & (REX_B | REX_X | REX_R); + if (rex) + rex |= REX_OPCODE; + rex_used = rex; + } + + /* Based on the OC1/OC0 bits, lay out the arguments in the correct + order. */ + switch (oc0 + oc1) + { + default: + BadOp (); + return; + + case 0: + regs[0] = modrm_regmem; + regs[1] = modrm_reg; + regs[2] = drex_reg; + regs[3] = drex_reg; + break; + + case 1: + regs[0] = modrm_reg; + regs[1] = modrm_regmem; + regs[2] = drex_reg; + regs[3] = drex_reg; + break; + + case 2: + regs[0] = drex_reg; + regs[1] = modrm_regmem; + regs[2] = modrm_reg; + regs[3] = drex_reg; + break; + + case 3: + regs[0] = drex_reg; + regs[1] = modrm_reg; + regs[2] = modrm_regmem; + regs[3] = drex_reg; + break; + } + + /* Print out the arguments. */ + for (i = 0; i < 4; i++) + { + int j = (intel_syntax) ? 3 - i : i; + if (i > 0) + { + *obufp++ = ','; + *obufp = '\0'; + } + + print_drex_arg (regs[j], bytemode, sizeflag); + } + + rex = rex_save; + rex_used = rex_used_save; +} + +/* SSE5 instructions that have 3 arguments, and are encoded as: + 0f 24 <sub-opcode> <modrm> <optional-sib> <drex> <offset> (or) + 0f 25 <sub-opcode> <modrm> <optional-sib> <drex> <offset> <cmp-byte> + + The DREX field has 1 bit (0x8) to determine how the arguments are + laid out. The destination register is encoded in the DREX byte. + No REX prefix is used for these instructions, since the DREX field + contains the 3 extension bits provided by the REX prefix. */ + +static void +OP_DREX3 (int flag_bytemode, int sizeflag) +{ + unsigned int drex_byte; + unsigned int regs[3]; + unsigned int modrm_regmem; + unsigned int modrm_reg; + unsigned int drex_reg; + int bytemode; + int rex_save = rex; + int rex_used_save = rex_used; + int has_sib = 0; + int oc0; + int i; + + bytemode = flag_bytemode & ~ DREX_MASK; + + for (i = 0; i < 3; i++) + regs[i] = DREX_REG_UNKNOWN; + + /* Determine if we have a SIB byte in addition to MODRM before the + DREX byte. */ + if (((sizeflag & AFLAG) || address_mode == mode_64bit) + && (modrm.mod != 3) + && (modrm.rm == 4)) + has_sib = 1; + + /* Get the DREX byte. */ + FETCH_DATA (the_info, codep + 2 + has_sib); + drex_byte = codep[has_sib+1]; + drex_reg = DREX_XMM (drex_byte); + modrm_reg = modrm.reg + ((drex_byte & REX_R) ? 8 : 0); + + /* Is OC0 legal? If not, hardwire oc0 == 0 */ + oc0 = DREX_OC0 (drex_byte); + if ((flag_bytemode & DREX_NO_OC0) && oc0) + BadOp (); + + if (modrm.mod == 3) + { + /* regmem == register */ + modrm_regmem = modrm.rm + ((drex_byte & REX_B) ? 8 : 0); + rex = rex_used = 0; + /* skip modrm/drex since we don't call OP_E_extended. */ + codep += 2; + } + else + { + /* regmem == memory, fill in appropriate REX bits. */ + modrm_regmem = DREX_REG_MEMORY; + rex = drex_byte & (REX_B | REX_X | REX_R); + if (rex) + rex |= REX_OPCODE; + rex_used = rex; + } + + /* Based on the OC1/OC0 bits, lay out the arguments in the correct + order. */ + switch (oc0) + { + default: + BadOp (); + return; + + case 0: + regs[0] = modrm_regmem; + regs[1] = modrm_reg; + regs[2] = drex_reg; + break; + + case 1: + regs[0] = modrm_reg; + regs[1] = modrm_regmem; + regs[2] = drex_reg; + break; + } + + /* Print out the arguments. */ + for (i = 0; i < 3; i++) + { + int j = (intel_syntax) ? 2 - i : i; + if (i > 0) + { + *obufp++ = ','; + *obufp = '\0'; + } + + print_drex_arg (regs[j], bytemode, sizeflag); + } + + rex = rex_save; + rex_used = rex_used_save; +} + +/* Emit a floating point comparison for comp<xx> instructions. */ + +static void +OP_DREX_FCMP (int bytemode ATTRIBUTE_UNUSED, + int sizeflag ATTRIBUTE_UNUSED) +{ + unsigned char byte; + + static const char *const cmp_test[] = { + "eq", + "lt", + "le", + "unord", + "ne", + "nlt", + "nle", + "ord", + "ueq", + "ult", + "ule", + "false", + "une", + "unlt", + "unle", + "true" + }; + + FETCH_DATA (the_info, codep + 1); + byte = *codep & 0xff; + + if (byte >= ARRAY_SIZE (cmp_test) + || obuf[0] != 'c' + || obuf[1] != 'o' + || obuf[2] != 'm') + { + /* The instruction isn't one we know about, so just append the + extension byte as a numeric value. */ + OP_I (b_mode, 0); + } + + else + { + sprintf (scratchbuf, "com%s%s", cmp_test[byte], obuf+3); + strcpy (obuf, scratchbuf); + codep++; + } +} + +/* Emit an integer point comparison for pcom<xx> instructions, + rewriting the instruction to have the test inside of it. */ + +static void +OP_DREX_ICMP (int bytemode ATTRIBUTE_UNUSED, + int sizeflag ATTRIBUTE_UNUSED) +{ + unsigned char byte; + + static const char *const cmp_test[] = { + "lt", + "le", + "gt", + "ge", + "eq", + "ne", + "false", + "true" + }; + + FETCH_DATA (the_info, codep + 1); + byte = *codep & 0xff; + + if (byte >= ARRAY_SIZE (cmp_test) + || obuf[0] != 'p' + || obuf[1] != 'c' + || obuf[2] != 'o' + || obuf[3] != 'm') + { + /* The instruction isn't one we know about, so just print the + comparison test byte as a numeric value. */ + OP_I (b_mode, 0); + } + + else + { + sprintf (scratchbuf, "pcom%s%s", cmp_test[byte], obuf+4); + strcpy (obuf, scratchbuf); + codep++; + } +} |