diff options
Diffstat (limited to 'contrib/binutils/opcodes/i386-dis.c')
-rw-r--r-- | contrib/binutils/opcodes/i386-dis.c | 258 |
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, |