diff options
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r-- | opcodes/i386-dis.c | 242 |
1 files changed, 171 insertions, 71 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 66fd388..b5cc638 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -193,16 +193,19 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define Eb OP_E, b_mode #define Ev OP_E, v_mode #define Ed OP_E, d_mode +#define Eq OP_E, q_mode #define Edq OP_E, dq_mode -#define indirEb OP_indirE, b_mode +#define Edqw OP_E, dqw_mode #define indirEv OP_indirE, v_mode +#define indirEp OP_indirE, f_mode #define Ew OP_E, w_mode #define Ma OP_E, v_mode #define M OP_M, 0 /* lea, lgdt, etc. */ -#define Mp OP_M, 0 /* 32 or 48 bit memory operand for LDS, LES etc */ +#define Mp OP_M, f_mode /* 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 Gdq OP_G, dq_mode #define Gw OP_G, w_mode #define Rd OP_Rd, d_mode #define Rm OP_Rd, m_mode @@ -212,6 +215,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define Iq OP_I, q_mode #define Iv64 OP_I64, v_mode #define Iw OP_I, w_mode +#define I1 OP_I, const_1_mode #define Jb OP_J, b_mode #define Jv OP_J, v_mode #define Cm OP_C, m_mode @@ -308,11 +312,15 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr) #define w_mode 3 /* word operand */ #define d_mode 4 /* double word operand */ #define q_mode 5 /* quad word operand */ -#define x_mode 6 /* 80 bit float operand */ -#define m_mode 7 /* d_mode in 32bit, q_mode in 64bit mode. */ -#define cond_jump_mode 8 -#define loop_jcxz_mode 9 -#define dq_mode 10 /* operand size depends on REX prefixes. */ +#define t_mode 6 /* ten-byte operand */ +#define x_mode 7 /* 16-byte XMM operand */ +#define m_mode 8 /* d_mode in 32bit, q_mode in 64bit mode. */ +#define cond_jump_mode 9 +#define loop_jcxz_mode 10 +#define dq_mode 11 /* operand size depends on REX prefixes. */ +#define dqw_mode 12 /* registers like dq_mode, memory like w_mode. */ +#define f_mode 13 /* 4- or 6-byte pointer operand */ +#define const_1_mode 14 #define es_reg 100 #define cs_reg 101 @@ -443,9 +451,14 @@ struct dis386 { /* Upper case letters in the instruction names here are macros. 'A' => print 'b' if no register operands or suffix_always is true 'B' => print 'b' if suffix_always is true + 'C' => print 's' or 'l' ('w' or 'd' in Intel mode) depending on operand + . size prefix 'E' => print 'e' if 32-bit form of jcxz 'F' => print 'w' or 'l' depending on address size prefix (loop insns) 'H' => print ",pt" or ",pn" branch hint + 'I' => honor following macro letter even in Intel mode (implemented only + . for some of the macro letters) + 'J' => print 'l' 'L' => print 'l' if suffix_always is true 'N' => print 'n' if instruction has no wait "prefix" 'O' => print 'd', or 'o' @@ -457,8 +470,8 @@ struct dis386 { 'S' => print 'w', 'l' or 'q' if suffix_always is true 'T' => print 'q' in 64bit mode and behave as 'P' otherwise 'U' => print 'q' in 64bit mode and behave as 'Q' otherwise - 'X' => print 's', 'd' depending on data16 prefix (for XMM) 'W' => print 'b' or 'w' ("w" or "de" in intel mode) + 'X' => print 's', 'd' depending on data16 prefix (for XMM) 'Y' => 'q' if instruction has an REX 64bit overwrite prefix Many of the above letters print nothing in Intel mode. See "putop" @@ -645,7 +658,7 @@ static const struct dis386 dis386[] = { /* 98 */ { "cW{tR||tR|}", XX, XX, XX }, { "cR{tO||tO|}", XX, XX, XX }, - { "lcall{T|}", Ap, XX, XX }, + { "Jcall{T|}", Ap, XX, XX }, { "(bad)", XX, XX, XX }, /* fwait */ { "pushfT", XX, XX, XX }, { "popfT", XX, XX, XX }, @@ -735,7 +748,7 @@ static const struct dis386 dis386[] = { /* e8 */ { "callT", Jv, XX, XX }, { "jmpT", Jv, XX, XX }, - { "ljmp{T|}", Ap, XX, XX }, + { "Jjmp{T|}", Ap, XX, XX }, { "jmp", Jb, XX, XX }, { "inB", AL, indirDX, XX }, { "inS", eAX, indirDX, XX }, @@ -853,7 +866,7 @@ static const struct dis386 dis386_twobyte[] = { { "cmovle", Gv, Ev, XX }, { "cmovg", Gv, Ev, XX }, /* 50 */ - { "movmskpX", Gd, XS, XX }, + { "movmskpX", Gdq, XS, XX }, { PREGRP13 }, { PREGRP12 }, { PREGRP11 }, @@ -983,8 +996,8 @@ static const struct dis386 dis386_twobyte[] = { { "xaddS", Ev, Gv, XX }, { PREGRP1 }, { "movntiS", Ev, Gv, XX }, - { "pinsrw", MX, Ed, Ib }, - { "pextrw", Gd, MS, Ib }, + { "pinsrw", MX, Edqw, Ib }, + { "pextrw", Gdq, MS, Ib }, { "shufpX", XM, EX, Ib }, { GRP9 }, /* c8 */ @@ -1004,7 +1017,7 @@ static const struct dis386 dis386_twobyte[] = { { "paddq", MX, EM, XX }, { "pmullw", MX, EM, XX }, { PREGRP21 }, - { "pmovmskb", Gd, MS, XX }, + { "pmovmskb", Gdq, MS, XX }, /* d8 */ { "psubusb", MX, EM, XX }, { "psubusw", MX, EM, XX }, @@ -1256,25 +1269,25 @@ static const struct dis386 grps[][8] = { }, /* GRP2b_one */ { - { "rolA", Eb, XX, XX }, - { "rorA", Eb, XX, XX }, - { "rclA", Eb, XX, XX }, - { "rcrA", Eb, XX, XX }, - { "shlA", Eb, XX, XX }, - { "shrA", Eb, XX, XX }, + { "rolA", Eb, I1, XX }, + { "rorA", Eb, I1, XX }, + { "rclA", Eb, I1, XX }, + { "rcrA", Eb, I1, XX }, + { "shlA", Eb, I1, XX }, + { "shrA", Eb, I1, XX }, { "(bad)", XX, XX, XX }, - { "sarA", Eb, XX, XX }, + { "sarA", Eb, I1, XX }, }, /* GRP2S_one */ { - { "rolQ", Ev, XX, XX }, - { "rorQ", Ev, XX, XX }, - { "rclQ", Ev, XX, XX }, - { "rcrQ", Ev, XX, XX }, - { "shlQ", Ev, XX, XX }, - { "shrQ", Ev, XX, XX }, + { "rolQ", Ev, I1, XX }, + { "rorQ", Ev, I1, XX }, + { "rclQ", Ev, I1, XX }, + { "rcrQ", Ev, I1, XX }, + { "shlQ", Ev, I1, XX }, + { "shrQ", Ev, I1, XX }, { "(bad)", XX, XX, XX}, - { "sarQ", Ev, XX, XX }, + { "sarQ", Ev, I1, XX }, }, /* GRP2b_cl */ { @@ -1336,9 +1349,9 @@ static const struct dis386 grps[][8] = { { "incQ", Ev, XX, XX }, { "decQ", Ev, XX, XX }, { "callT", indirEv, XX, XX }, - { "lcallT", indirEv, XX, XX }, + { "JcallT", indirEp, XX, XX }, { "jmpT", indirEv, XX, XX }, - { "ljmpT", indirEv, XX, XX }, + { "JjmpT", indirEp, XX, XX }, { "pushU", Ev, XX, XX }, { "(bad)", XX, XX, XX }, }, @@ -1355,10 +1368,10 @@ static const struct dis386 grps[][8] = { }, /* GRP7 */ { - { "sgdtQ", M, XX, XX }, - { "sidtQ", PNI_Fixup, 0, XX, XX }, - { "lgdtQ", M, XX, XX }, - { "lidtQ", M, XX, XX }, + { "sgdtIQ", M, XX, XX }, + { "sidtIQ", PNI_Fixup, 0, XX, XX }, + { "lgdt{Q|Q||}", M, XX, XX }, + { "lidt{Q|Q||}", M, XX, XX }, { "smswQ", Ev, XX, XX }, { "(bad)", XX, XX, XX }, { "lmsw", Ew, XX, XX }, @@ -1378,7 +1391,7 @@ static const struct dis386 grps[][8] = { /* GRP9 */ { { "(bad)", XX, XX, XX }, - { "cmpxchg8b", Ev, XX, XX }, + { "cmpxchg8b", Eq, XX, XX }, { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, { "(bad)", XX, XX, XX }, @@ -1654,10 +1667,10 @@ static const struct dis386 prefix_user_table[][4] = { }, /* PREGRP25 */ { - { "movntq", Ev, MX, XX }, - { "(bad)", Ev, XM, XX }, - { "movntdq", Ev, XM, XX }, - { "(bad)", Ev, XM, XX }, + { "movntq", EM, MX, XX }, + { "(bad)", EM, XM, XX }, + { "movntdq", EM, XM, XX }, + { "(bad)", EM, XM, XX }, }, /* PREGRP26 */ { @@ -2339,9 +2352,9 @@ static const char *float_mem[] = { "(bad)", "fst{s||s|}", "fstp{s||s|}", - "fldenv", + "fldenvIC", "fldcw", - "fNstenv", + "fNstenvIC", "fNstcw", /* da */ "fiadd{l||l|}", @@ -2375,9 +2388,9 @@ static const char *float_mem[] = { "fisttp{ll||ll|}", "fst{l||l|}", "fstp{l||l|}", - "frstor", + "frstorIC", "(bad)", - "fNsave", + "fNsaveIC", "fNstsw", /* de */ "fiadd", @@ -2433,9 +2446,9 @@ static const unsigned char float_mem_mode[] = { d_mode, d_mode, 0, - x_mode, + t_mode, 0, - x_mode, + t_mode, /* dc */ q_mode, q_mode, @@ -2468,9 +2481,9 @@ static const unsigned char float_mem_mode[] = { w_mode, w_mode, w_mode, - x_mode, + t_mode, q_mode, - x_mode, + t_mode, q_mode }; @@ -2701,7 +2714,7 @@ static int putop (const char *template, int sizeflag) { const char *p; - int alt; + int alt = 0; for (p = template; *p; p++) { @@ -2732,7 +2745,10 @@ putop (const char *template, int sizeflag) } alt--; } - break; + /* Fall through. */ + case 'I': + alt = 1; + continue; case '|': while (*++p != '}') { @@ -2754,6 +2770,18 @@ putop (const char *template, int sizeflag) if (sizeflag & SUFFIX_ALWAYS) *obufp++ = 'b'; break; + case 'C': + if (intel_syntax && !alt) + break; + if ((prefixes & PREFIX_DATA) || (sizeflag & SUFFIX_ALWAYS)) + { + if (sizeflag & DFLAG) + *obufp++ = intel_syntax ? 'd' : 'l'; + else + *obufp++ = intel_syntax ? 'w' : 's'; + used_prefixes |= (prefixes & PREFIX_DATA); + } + break; case 'E': /* For jcxz/jecxz */ if (mode_64bit) { @@ -2794,6 +2822,11 @@ putop (const char *template, int sizeflag) *obufp++ = 'n'; } break; + case 'J': + if (intel_syntax) + break; + *obufp++ = 'l'; + break; case 'L': if (intel_syntax) break; @@ -2852,7 +2885,7 @@ putop (const char *template, int sizeflag) } /* Fall through. */ case 'Q': - if (intel_syntax) + if (intel_syntax && !alt) break; USED_REX (REX_MODE64); if (mod != 3 || (sizeflag & SUFFIX_ALWAYS)) @@ -2862,7 +2895,7 @@ putop (const char *template, int sizeflag) else { if (sizeflag & DFLAG) - *obufp++ = 'l'; + *obufp++ = intel_syntax ? 'd' : 'l'; else *obufp++ = 'w'; used_prefixes |= (prefixes & PREFIX_DATA); @@ -2965,6 +2998,7 @@ putop (const char *template, int sizeflag) used_prefixes |= (prefixes & PREFIX_DATA); break; } + alt = 0; } *obufp = 0; return 0; @@ -3119,10 +3153,11 @@ OP_E (int bytemode, int sizeflag) break; case v_mode: case dq_mode: + case dqw_mode: USED_REX (REX_MODE64); if (rex & REX_MODE64) oappend (names64[rm + add]); - else if ((sizeflag & DFLAG) || bytemode == dq_mode) + else if ((sizeflag & DFLAG) || bytemode != v_mode) oappend (names32[rm + add]); else oappend (names16[rm + add]); @@ -3212,13 +3247,19 @@ OP_E (int bytemode, int sizeflag) oappend ("BYTE PTR "); break; case w_mode: + case dqw_mode: oappend ("WORD PTR "); break; case v_mode: - if (sizeflag & DFLAG) + case dq_mode: + USED_REX (REX_MODE64); + if (rex & REX_MODE64) + oappend ("QWORD PTR "); + else if ((sizeflag & DFLAG) || bytemode == dq_mode) oappend ("DWORD PTR "); else oappend ("WORD PTR "); + used_prefixes |= (prefixes & PREFIX_DATA); break; case d_mode: oappend ("DWORD PTR "); @@ -3228,17 +3269,29 @@ OP_E (int bytemode, int sizeflag) break; case m_mode: if (mode_64bit) + oappend ("QWORD PTR "); + else oappend ("DWORD PTR "); + break; + case f_mode: + if (sizeflag & DFLAG) + { + used_prefixes |= (prefixes & PREFIX_DATA); + oappend ("FWORD PTR "); + } else - oappend ("QWORD PTR "); + oappend ("DWORD PTR "); + break; + case t_mode: + oappend ("TBYTE PTR "); break; case x_mode: - oappend ("XWORD PTR "); + oappend ("XMMWORD PTR "); break; default: break; } - } + } *obufp++ = open_char; if (intel_syntax && riprel) oappend ("rip + "); @@ -3253,22 +3306,13 @@ OP_E (int bytemode, int sizeflag) { if (index != 4) { - if (intel_syntax) + if (!intel_syntax || havebase) { - if (havebase) - { - *obufp++ = separator_char; - *obufp = '\0'; - } - sprintf (scratchbuf, "%s", - mode_64bit && (sizeflag & AFLAG) - ? names64[index] : names32[index]); + *obufp++ = separator_char; + *obufp = '\0'; } - else - sprintf (scratchbuf, ",%s", - mode_64bit && (sizeflag & AFLAG) - ? names64[index] : names32[index]); - oappend (scratchbuf); + oappend (mode_64bit && (sizeflag & AFLAG) + ? names64[index] : names32[index]); } if (scale != 0 || (!intel_syntax && index != 4)) { @@ -3384,10 +3428,12 @@ OP_G (int bytemode, int sizeflag) oappend (names64[reg + add]); break; case v_mode: + case dq_mode: + case dqw_mode: USED_REX (REX_MODE64); if (rex & REX_MODE64) oappend (names64[reg + add]); - else if (sizeflag & DFLAG) + else if ((sizeflag & DFLAG) || bytemode != v_mode) oappend (names32[reg + add]); else oappend (names16[reg + add]); @@ -3628,6 +3674,10 @@ OP_I (int bytemode, int sizeflag) mask = 0xfffff; op = get16 (); break; + case const_1_mode: + if (intel_syntax) + oappend ("1"); + return; default: oappend (INTERNAL_DISASSEMBLER_ERROR); return; @@ -3884,6 +3934,23 @@ ptr_reg (int code, int sizeflag) static void OP_ESreg (int code, int sizeflag) { + if (intel_syntax) + { + if (codep[-1] & 1) + { + USED_REX (REX_MODE64); + used_prefixes |= (prefixes & PREFIX_DATA); + if (rex & REX_MODE64) + oappend ("QWORD PTR "); + else if ((sizeflag & DFLAG)) + oappend ("DWORD PTR "); + else + oappend ("WORD PTR "); + } + else + oappend ("BYTE PTR "); + } + oappend ("%es:" + intel_syntax); ptr_reg (code, sizeflag); } @@ -3891,6 +3958,23 @@ OP_ESreg (int code, int sizeflag) static void OP_DSreg (int code, int sizeflag) { + if (intel_syntax) + { + if (codep[-1] != 0xd7 && (codep[-1] & 1)) + { + USED_REX (REX_MODE64); + used_prefixes |= (prefixes & PREFIX_DATA); + if (rex & REX_MODE64) + oappend ("QWORD PTR "); + else if ((sizeflag & DFLAG)) + oappend ("DWORD PTR "); + else + oappend ("WORD PTR "); + } + else + oappend ("BYTE PTR "); + } + if ((prefixes & (PREFIX_CS | PREFIX_DS @@ -3977,6 +4061,11 @@ OP_EM (int bytemode, int sizeflag) { if (mod != 3) { + if (intel_syntax && bytemode == v_mode) + { + bytemode = (prefixes & PREFIX_DATA) ? x_mode : q_mode; + used_prefixes |= (prefixes & PREFIX_DATA); + } OP_E (bytemode, sizeflag); return; } @@ -4005,6 +4094,17 @@ OP_EX (int bytemode, int sizeflag) int add = 0; if (mod != 3) { + if (intel_syntax && bytemode == v_mode) + { + switch (prefixes & (PREFIX_DATA|PREFIX_REPZ|PREFIX_REPNZ)) + { + case 0: bytemode = x_mode; break; + case PREFIX_REPZ: bytemode = d_mode; used_prefixes |= PREFIX_REPZ; break; + case PREFIX_DATA: bytemode = x_mode; used_prefixes |= PREFIX_DATA; break; + case PREFIX_REPNZ: bytemode = q_mode; used_prefixes |= PREFIX_REPNZ; break; + default: bytemode = 0; break; + } + } OP_E (bytemode, sizeflag); return; } |