summaryrefslogtreecommitdiffstats
path: root/contrib/binutils/opcodes/i386-dis.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/binutils/opcodes/i386-dis.c')
-rw-r--r--contrib/binutils/opcodes/i386-dis.c258
1 files changed, 164 insertions, 94 deletions
diff --git a/contrib/binutils/opcodes/i386-dis.c b/contrib/binutils/opcodes/i386-dis.c
index 61ec71e..5621d8a 100644
--- a/contrib/binutils/opcodes/i386-dis.c
+++ b/contrib/binutils/opcodes/i386-dis.c
@@ -149,15 +149,14 @@ fetch_data (info, addr)
#define Ev OP_E, v_mode
#define Ed OP_E, d_mode
#define indirEb OP_indirE, b_mode
-#define Gb OP_G, b_mode
-#define Ev OP_E, v_mode
-#define Ed OP_E, d_mode
#define indirEv OP_indirE, v_mode
#define Ew OP_E, w_mode
#define Ma OP_E, v_mode
#define M OP_E, 0 /* lea */
#define Mp OP_E, 0 /* 32 or 48 bit memory operand for LDS, LES etc */
+#define Gb OP_G, b_mode
#define Gv OP_G, v_mode
+#define Gd OP_G, d_mode
#define Gw OP_G, w_mode
#define Rd OP_Rd, d_mode
#define Rm OP_Rd, m_mode
@@ -246,10 +245,14 @@ fetch_data (info, addr)
#define EM OP_EM, v_mode
#define EX OP_EX, v_mode
#define MS OP_MS, v_mode
+#define XS OP_XS, v_mode
#define None OP_E, 0
#define OPSUF OP_3DNowSuffix, 0
#define OPSIMD OP_SIMD_Suffix, 0
+#define cond_jump_flag NULL, cond_jump_mode
+#define loop_jcxz_flag NULL, loop_jcxz_mode
+
/* bits in sizeflag */
#if 0 /* leave undefined until someone adds the extra flag to objdump */
#define SUFFIX_ALWAYS 4
@@ -287,6 +290,7 @@ static void OP_XMM PARAMS ((int, int));
static void OP_EM PARAMS ((int, int));
static void OP_EX PARAMS ((int, int));
static void OP_MS PARAMS ((int, int));
+static void OP_XS PARAMS ((int, int));
static void OP_3DNowSuffix PARAMS ((int, int));
static void OP_SIMD_Suffix PARAMS ((int, int));
static void SIMD_Fixup PARAMS ((int, int));
@@ -311,6 +315,8 @@ static void BadOp PARAMS ((void));
#define q_mode 5 /* quad word operand */
#define x_mode 6
#define m_mode 7 /* d_mode in 32bit, q_mode in 64bit mode. */
+#define cond_jump_mode 8
+#define loop_jcxz_mode 9
#define es_reg 100
#define cs_reg 101
@@ -429,6 +435,7 @@ struct dis386 {
'A' => print 'b' if no register operands or suffix_always is true
'B' => print 'b' if suffix_always is true
'E' => print 'e' if 32-bit form of jcxz
+ 'F' => print 'w' or 'l' depending on address size prefix (loop insns)
'L' => print 'l' if suffix_always is true
'N' => print 'n' if instruction has no wait "prefix"
'O' => print 'd', or 'o'
@@ -573,23 +580,23 @@ static const struct dis386 dis386_att[] = {
{ "outsb", indirDX, Xb, XX },
{ "outsR", indirDX, Xv, XX },
/* 70 */
- { "jo", Jb, XX, XX },
- { "jno", Jb, XX, XX },
- { "jb", Jb, XX, XX },
- { "jae", Jb, XX, XX },
- { "je", Jb, XX, XX },
- { "jne", Jb, XX, XX },
- { "jbe", Jb, XX, XX },
- { "ja", Jb, XX, XX },
+ { "jo", Jb, cond_jump_flag, XX },
+ { "jno", Jb, cond_jump_flag, XX },
+ { "jb", Jb, cond_jump_flag, XX },
+ { "jae", Jb, cond_jump_flag, XX },
+ { "je", Jb, cond_jump_flag, XX },
+ { "jne", Jb, cond_jump_flag, XX },
+ { "jbe", Jb, cond_jump_flag, XX },
+ { "ja", Jb, cond_jump_flag, XX },
/* 78 */
- { "js", Jb, XX, XX },
- { "jns", Jb, XX, XX },
- { "jp", Jb, XX, XX },
- { "jnp", Jb, XX, XX },
- { "jl", Jb, XX, XX },
- { "jge", Jb, XX, XX },
- { "jle", Jb, XX, XX },
- { "jg", Jb, XX, XX },
+ { "js", Jb, cond_jump_flag, XX },
+ { "jns", Jb, cond_jump_flag, XX },
+ { "jp", Jb, cond_jump_flag, XX },
+ { "jnp", Jb, cond_jump_flag, XX },
+ { "jl", Jb, cond_jump_flag, XX },
+ { "jge", Jb, cond_jump_flag, XX },
+ { "jle", Jb, cond_jump_flag, XX },
+ { "jg", Jb, cond_jump_flag, XX },
/* 80 */
{ GRP1b },
{ GRP1S },
@@ -700,10 +707,10 @@ static const struct dis386 dis386_att[] = {
{ FLOAT },
{ FLOAT },
/* e0 */
- { "loopne", Jb, XX, XX },
- { "loope", Jb, XX, XX },
- { "loop", Jb, XX, XX },
- { "jEcxz", Jb, XX, XX },
+ { "loopneF", Jb, loop_jcxz_flag, XX },
+ { "loopeF", Jb, loop_jcxz_flag, XX },
+ { "loopF", Jb, loop_jcxz_flag, XX },
+ { "jEcxz", Jb, loop_jcxz_flag, XX },
{ "inB", AL, Ib, XX },
{ "inS", eAX, Ib, XX },
{ "outB", Ib, AL, XX },
@@ -1159,23 +1166,23 @@ static const struct dis386 disx86_64_att[] = {
{ "outsb", indirDX, Xb, XX },
{ "outsR", indirDX, Xv, XX },
/* 70 */
- { "jo", Jb, XX, XX },
- { "jno", Jb, XX, XX },
- { "jb", Jb, XX, XX },
- { "jae", Jb, XX, XX },
- { "je", Jb, XX, XX },
- { "jne", Jb, XX, XX },
- { "jbe", Jb, XX, XX },
- { "ja", Jb, XX, XX },
+ { "jo", Jb, cond_jump_flag, XX },
+ { "jno", Jb, cond_jump_flag, XX },
+ { "jb", Jb, cond_jump_flag, XX },
+ { "jae", Jb, cond_jump_flag, XX },
+ { "je", Jb, cond_jump_flag, XX },
+ { "jne", Jb, cond_jump_flag, XX },
+ { "jbe", Jb, cond_jump_flag, XX },
+ { "ja", Jb, cond_jump_flag, XX },
/* 78 */
- { "js", Jb, XX, XX },
- { "jns", Jb, XX, XX },
- { "jp", Jb, XX, XX },
- { "jnp", Jb, XX, XX },
- { "jl", Jb, XX, XX },
- { "jge", Jb, XX, XX },
- { "jle", Jb, XX, XX },
- { "jg", Jb, XX, XX },
+ { "js", Jb, cond_jump_flag, XX },
+ { "jns", Jb, cond_jump_flag, XX },
+ { "jp", Jb, cond_jump_flag, XX },
+ { "jnp", Jb, cond_jump_flag, XX },
+ { "jl", Jb, cond_jump_flag, XX },
+ { "jge", Jb, cond_jump_flag, XX },
+ { "jle", Jb, cond_jump_flag, XX },
+ { "jg", Jb, cond_jump_flag, XX },
/* 80 */
{ GRP1b },
{ GRP1S },
@@ -1286,10 +1293,10 @@ static const struct dis386 disx86_64_att[] = {
{ FLOAT },
{ FLOAT },
/* e0 */
- { "loopne", Jb, XX, XX },
- { "loope", Jb, XX, XX },
- { "loop", Jb, XX, XX },
- { "jEcxz", Jb, XX, XX },
+ { "loopneF", Jb, loop_jcxz_flag, XX },
+ { "loopeF", Jb, loop_jcxz_flag, XX },
+ { "loopF", Jb, loop_jcxz_flag, XX },
+ { "jEcxz", Jb, loop_jcxz_flag, XX },
{ "inB", AL, Ib, XX },
{ "inS", eAX, Ib, XX },
{ "outB", Ib, AL, XX },
@@ -1708,7 +1715,7 @@ static const struct dis386 dis386_twobyte_att[] = {
{ "cmovle", Gv, Ev, XX },
{ "cmovg", Gv, Ev, XX },
/* 50 */
- { "movmskpX", Gv, EX, XX },
+ { "movmskpX", Gd, XS, XX },
{ PREGRP13 },
{ PREGRP12 },
{ PREGRP11 },
@@ -1762,23 +1769,23 @@ static const struct dis386 dis386_twobyte_att[] = {
{ PREGRP23 },
{ PREGRP20 },
/* 80 */
- { "jo", Jv, XX, XX },
- { "jno", Jv, XX, XX },
- { "jb", Jv, XX, XX },
- { "jae", Jv, XX, XX },
- { "je", Jv, XX, XX },
- { "jne", Jv, XX, XX },
- { "jbe", Jv, XX, XX },
- { "ja", Jv, XX, XX },
+ { "jo", Jv, cond_jump_flag, XX },
+ { "jno", Jv, cond_jump_flag, XX },
+ { "jb", Jv, cond_jump_flag, XX },
+ { "jae", Jv, cond_jump_flag, XX },
+ { "je", Jv, cond_jump_flag, XX },
+ { "jne", Jv, cond_jump_flag, XX },
+ { "jbe", Jv, cond_jump_flag, XX },
+ { "ja", Jv, cond_jump_flag, XX },
/* 88 */
- { "js", Jv, XX, XX },
- { "jns", Jv, XX, XX },
- { "jp", Jv, XX, XX },
- { "jnp", Jv, XX, XX },
- { "jl", Jv, XX, XX },
- { "jge", Jv, XX, XX },
- { "jle", Jv, XX, XX },
- { "jg", Jv, XX, XX },
+ { "js", Jv, cond_jump_flag, XX },
+ { "jns", Jv, cond_jump_flag, XX },
+ { "jp", Jv, cond_jump_flag, XX },
+ { "jnp", Jv, cond_jump_flag, XX },
+ { "jl", Jv, cond_jump_flag, XX },
+ { "jge", Jv, cond_jump_flag, XX },
+ { "jle", Jv, cond_jump_flag, XX },
+ { "jg", Jv, cond_jump_flag, XX },
/* 90 */
{ "seto", Eb, XX, XX },
{ "setno", Eb, XX, XX },
@@ -1838,8 +1845,8 @@ static const struct dis386 dis386_twobyte_att[] = {
{ "xaddS", Ev, Gv, XX },
{ PREGRP1 },
{ "movntiS", Ev, Gv, XX },
- { "pinsrw", MX, Ev, Ib },
- { "pextrw", Ev, MX, Ib },
+ { "pinsrw", MX, Ed, Ib },
+ { "pextrw", Gd, MS, Ib },
{ "shufpX", XM, EX, Ib },
{ GRP9 },
/* c8 */
@@ -1859,7 +1866,7 @@ static const struct dis386 dis386_twobyte_att[] = {
{ "paddq", MX, EM, XX },
{ "pmullw", MX, EM, XX },
{ PREGRP21 },
- { "pmovmskb", Ev, MX, XX },
+ { "pmovmskb", Gd, MS, XX },
/* d8 */
{ "psubusb", MX, EM, XX },
{ "psubusw", MX, EM, XX },
@@ -1927,8 +1934,8 @@ static const struct dis386 dis386_twobyte_intel[] = {
{ "femms" , XX, XX, XX},
{ "", MX, EM, OPSUF }, /* See OP_3DNowSuffix */
/* 10 */
- { PREGRP8 },
- { PREGRP9 },
+ { PREGRP8 },
+ { PREGRP9 },
{ "movlpX", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */
{ "movlpX", EX, XM, SIMD_Fixup, 'h' },
{ "unpcklpX", XM, EX, XX },
@@ -2000,7 +2007,7 @@ static const struct dis386 dis386_twobyte_intel[] = {
{ "cmovle", Gv, Ev, XX },
{ "cmovg", Gv, Ev, XX },
/* 50 */
- { "movmskpX", Gv, EX, XX },
+ { "movmskpX", Gd, XS, XX },
{ PREGRP13 },
{ PREGRP12 },
{ PREGRP11 },
@@ -2130,8 +2137,8 @@ static const struct dis386 dis386_twobyte_intel[] = {
{ "xadd", Ev, Gv, XX },
{ PREGRP1 },
{ "movnti", Ev, Gv, XX },
- { "pinsrw", MX, Ev, Ib },
- { "pextrw", Ev, MX, Ib },
+ { "pinsrw", MX, Ed, Ib },
+ { "pextrw", Gd, MS, Ib },
{ "shufpX", XM, EX, Ib },
{ GRP9 },
/* c8 */
@@ -2151,7 +2158,7 @@ static const struct dis386 dis386_twobyte_intel[] = {
{ "paddq", MX, EM, XX },
{ "pmullw", MX, EM, XX },
{ PREGRP21 },
- { "pmovmskb", Ev, MX, XX },
+ { "pmovmskb", Gd, MS, XX },
/* d8 */
{ "psubusb", MX, EM, XX },
{ "psubusw", MX, EM, XX },
@@ -2227,20 +2234,20 @@ 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,0, /* 1f */
- /* 20 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 2f */
+ /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */
/* 30 */ 0,0,0,0,0,0,0,0,0,0,0,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,0,0,1,1,1,1, /* 5f */
- /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1, /* 6f */
+ /* 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,0,0,0,0,0,0,1,1, /* 7f */
/* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
/* 90 */ 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 */
+ /* a0 */ 0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1, /* af */
/* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
/* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
- /* d0 */ 0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1, /* df */
- /* e0 */ 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1, /* ef */
- /* f0 */ 0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0 /* ff */
+ /* d0 */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
+ /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */
+ /* f0 */ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* ff */
/* ------------------------------- */
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
};
@@ -2278,8 +2285,14 @@ static disassemble_info *the_info;
static int mod;
static int rm;
static int reg;
+static unsigned char need_modrm;
static void oappend PARAMS ((const char *s));
+/* If we are accessing mod/rm/reg without need_modrm set, then the
+ values are stale. Hitting this abort likely indicates that you
+ need to update onebyte_has_modrm or twobyte_has_modrm. */
+#define MODRM_CHECK if (!need_modrm) abort ()
+
static const char *names64[] = {
"%rax","%rcx","%rdx","%rbx", "%rsp","%rbp","%rsi","%rdi",
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
@@ -2296,7 +2309,7 @@ static const char *names8[] = {
"%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
};
static const char *names8rex[] = {
- "%al","%cl","%dl","%bl","%spl", "%bpl", "%sil", "%dil",
+ "%al","%cl","%dl","%bl","%spl", "%bpl", "%sil", "%dil",
"%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
};
static const char *names_seg[] = {
@@ -2693,7 +2706,7 @@ static const struct dis386 prefix_user_table[][4] = {
},
/* PREGRP18 */
{
- { "maskmovq", MX, EM, XX },
+ { "maskmovq", MX, MS, XX },
{ "(bad)", XM, EX, XX },
{ "maskmovdqu", XM, EX, XX },
{ "(bad)", XM, EX, XX },
@@ -2715,9 +2728,9 @@ static const struct dis386 prefix_user_table[][4] = {
/* PREGRP21 */
{
{ "(bad)", EX, XM, XX },
- { "movq2dq", EX, EM, XX },
+ { "movq2dq", XM, MS, XX },
{ "movq", EX, XM, XX },
- { "movdq2q", EM, MX, XX },
+ { "movdq2q", MX, XS, XX },
},
/* PREGRP22 */
{
@@ -2729,7 +2742,7 @@ static const struct dis386 prefix_user_table[][4] = {
/* PREGRP23 */
{
{ "movd", Ed, MX, XX },
- { "movq", Ed, XM, XX },
+ { "movq", XM, EX, XX },
{ "movd", Ed, XM, XX },
{ "(bad)", Ed, XM, XX },
},
@@ -2988,7 +3001,6 @@ print_insn_i386 (pc, info)
int two_source_ops;
char *first, *second, *third;
int needcomma;
- unsigned char need_modrm;
unsigned char uses_SSE_prefix;
VOLATILE int sizeflag;
VOLATILE int orig_sizeflag;
@@ -3120,17 +3132,44 @@ print_insn_i386 (pc, info)
used_prefixes |= PREFIX_LOCK;
}
- if (!uses_SSE_prefix && (prefixes & PREFIX_DATA))
- sizeflag ^= DFLAG;
-
if (prefixes & PREFIX_ADDR)
{
sizeflag ^= AFLAG;
- if (sizeflag & AFLAG)
- oappend ("addr32 ");
- else
- oappend ("addr16 ");
- used_prefixes |= PREFIX_ADDR;
+ if (dp->bytemode2 != loop_jcxz_mode)
+ {
+ if (sizeflag & AFLAG)
+ oappend ("addr32 ");
+ else
+ oappend ("addr16 ");
+ used_prefixes |= PREFIX_ADDR;
+ }
+ }
+
+ if (!uses_SSE_prefix && (prefixes & PREFIX_DATA))
+ {
+ sizeflag ^= DFLAG;
+ if (dp->bytemode2 == cond_jump_mode && dp->bytemode1 == v_mode)
+ {
+ if (sizeflag & DFLAG)
+ oappend ("data32 ");
+ else
+ oappend ("data16 ");
+ used_prefixes |= PREFIX_DATA;
+ }
+ }
+
+ if (dp->bytemode2 == cond_jump_mode || dp->bytemode2 == loop_jcxz_mode)
+ {
+ if ((prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_CS)
+ {
+ oappend ("cs ");
+ used_prefixes |= PREFIX_CS;
+ }
+ if ((prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_DS)
+ {
+ oappend ("ds ");
+ used_prefixes |= PREFIX_DS;
+ }
}
if (need_modrm)
@@ -3170,7 +3209,6 @@ print_insn_i386 (pc, info)
used_prefixes |= (prefixes & PREFIX_REPNZ);
if (prefixes & PREFIX_REPNZ)
index = 3;
-
}
}
dp = &prefix_user_table[dp->bytemode1][index];
@@ -3540,7 +3578,7 @@ static const struct dis386 float_reg[][8] = {
},
/* df */
{
- { "(bad)", XX, XX, XX },
+ { "ffreep", STi, XX, XX },
{ "(bad)", XX, XX, XX },
{ "(bad)", XX, XX, XX },
{ "(bad)", XX, XX, XX },
@@ -3624,6 +3662,8 @@ dofloat (sizeflag)
OP_E (v_mode, sizeflag);
return;
}
+ /* skip mod/rm byte */
+ MODRM_CHECK;
codep++;
dp = &float_reg[floatop - 0xd8][reg];
@@ -3704,6 +3744,21 @@ putop (template, sizeflag)
case 'E': /* For jcxz/jecxz */
if (sizeflag & AFLAG)
*obufp++ = 'e';
+ used_prefixes |= (prefixes & PREFIX_ADDR);
+ break;
+ case 'F':
+ if ((prefixes & PREFIX_ADDR)
+#ifdef SUFFIX_ALWAYS
+ || (sizeflag & SUFFIX_ALWAYS)
+#endif
+ )
+ {
+ if (sizeflag & AFLAG)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ used_prefixes |= (prefixes & PREFIX_ADDR);
+ }
break;
case 'I':
if (intel_syntax)
@@ -3760,7 +3815,7 @@ putop (template, sizeflag)
USED_REX (REX_MODE64);
if (rex & REX_MODE64)
*obufp++ = 'q';
- else
+ else
{
if (sizeflag & DFLAG)
*obufp++ = 'l';
@@ -4038,6 +4093,7 @@ OP_E (bytemode, sizeflag)
add += 8;
/* skip mod/rm byte */
+ MODRM_CHECK;
codep++;
if (mod == 3)
@@ -4689,7 +4745,6 @@ OP_J (bytemode, sizeflag)
displacement is added! */
mask = 0xffff;
}
- used_prefixes |= (prefixes & PREFIX_DATA);
break;
default:
oappend (INTERNAL_DISASSEMBLER_ERROR);
@@ -4927,6 +4982,8 @@ OP_EM (bytemode, sizeflag)
if (rex & REX_EXTZ)
add = 8;
+ /* skip mod/rm byte */
+ MODRM_CHECK;
codep++;
used_prefixes |= (prefixes & PREFIX_DATA);
if (prefixes & PREFIX_DATA)
@@ -4951,6 +5008,8 @@ OP_EX (bytemode, sizeflag)
if (rex & REX_EXTZ)
add = 8;
+ /* skip mod/rm byte */
+ MODRM_CHECK;
codep++;
sprintf (scratchbuf, "%%xmm%d", rm + add);
oappend (scratchbuf);
@@ -4967,6 +5026,17 @@ OP_MS (bytemode, sizeflag)
BadOp();
}
+static void
+OP_XS (bytemode, sizeflag)
+ int bytemode;
+ int sizeflag;
+{
+ if (mod == 3)
+ OP_EX (bytemode, sizeflag);
+ else
+ BadOp();
+}
+
static const char *Suffix3DNow[] = {
/* 00 */ NULL, NULL, NULL, NULL,
/* 04 */ NULL, NULL, NULL, NULL,
OpenPOWER on IntegriCloud