Loading disas/i386.c +132 −14 Original line number Diff line number Diff line Loading @@ -171,6 +171,7 @@ static void print_operand_value (char *buf, size_t bufsize, int hex, bfd_vma dis static void print_displacement (char *, bfd_vma); static void OP_E (int, int); static void OP_G (int, int); static void OP_vvvv (int, int); static bfd_vma get64 (void); static bfd_signed_vma get32 (void); static bfd_signed_vma get32s (void); Loading Loading @@ -264,6 +265,9 @@ static int rex_used; current instruction. */ static int used_prefixes; /* The VEX.vvvv register, unencoded. */ static int vex_reg; /* Flags stored in PREFIXES. */ #define PREFIX_REPZ 1 #define PREFIX_REPNZ 2 Loading @@ -278,6 +282,10 @@ static int used_prefixes; #define PREFIX_ADDR 0x400 #define PREFIX_FWAIT 0x800 #define PREFIX_VEX_0F 0x1000 #define PREFIX_VEX_0F38 0x2000 #define PREFIX_VEX_0F3A 0x4000 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) to ADDR (exclusive) are valid. Returns 1 for success, longjmps on error. */ Loading Loading @@ -323,6 +331,7 @@ fetch_data(struct disassemble_info *info, bfd_byte *addr) #define XX { NULL, 0 } #define Bv { OP_vvvv, v_mode } #define Eb { OP_E, b_mode } #define Ev { OP_E, v_mode } #define Ed { OP_E, d_mode } Loading Loading @@ -671,7 +680,8 @@ fetch_data(struct disassemble_info *info, bfd_byte *addr) #define PREGRP102 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 102 } } #define PREGRP103 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 103 } } #define PREGRP104 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 104 } } #define PREGRP105 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 105 } } #define PREGRP106 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 106 } } #define X86_64_0 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 0 } } #define X86_64_1 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 1 } } Loading Loading @@ -1449,7 +1459,7 @@ static const unsigned char threebyte_0x38_uses_DATA_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,1,1,1,1,1, /* 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 */ 0,0,0,0,0,0,0,1,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 */ }; Loading @@ -1473,7 +1483,7 @@ 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 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ /* f0 */ 1,1,0,0,0,0,0,1,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 */ }; Loading @@ -1497,7 +1507,7 @@ static const unsigned char threebyte_0x38_uses_REPZ_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 */ 0,0,0,0,0,0,0,1,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 */ }; Loading Loading @@ -2774,6 +2784,22 @@ static const struct dis386 prefix_user_table[][4] = { { "(bad)", { XX } }, }, /* PREGRP105 */ { { "andnS", { Gv, Bv, Ev } }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, }, /* PREGRP106 */ { { "bextrS", { Gv, Ev, Bv } }, { "sarxS", { Gv, Ev, Bv } }, { "shlxS", { Gv, Ev, Bv } }, { "shrxS", { Gv, Ev, Bv } }, }, }; static const struct dis386 x86_64_table[][2] = { Loading Loading @@ -3071,12 +3097,12 @@ static const struct dis386 three_byte_table[][256] = { /* f0 */ { PREGRP87 }, { PREGRP88 }, { PREGRP105 }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, { PREGRP106 }, /* f8 */ { "(bad)", { XX } }, { "(bad)", { XX } }, Loading Loading @@ -3477,6 +3503,74 @@ ckprefix (void) } } static void ckvexprefix (void) { int op, vex2, vex3, newrex = 0, newpfx = prefixes; if (address_mode == mode_16bit) { return; } fetch_data(the_info, codep + 1); op = *codep; if (op != 0xc4 && op != 0xc5) { return; } fetch_data(the_info, codep + 2); vex2 = codep[1]; if (address_mode == mode_32bit && (vex2 & 0xc0) != 0xc0) { return; } if (op == 0xc4) { /* Three byte VEX prefix. */ fetch_data(the_info, codep + 3); vex3 = codep[2]; newrex |= (vex2 & 0x80 ? 0 : REX_R); newrex |= (vex2 & 0x40 ? 0 : REX_X); newrex |= (vex2 & 0x20 ? 0 : REX_B); newrex |= (vex3 & 0x80 ? REX_W : 0); switch (vex2 & 0x1f) { /* VEX.m-mmmm */ case 1: newpfx |= PREFIX_VEX_0F; break; case 2: newpfx |= PREFIX_VEX_0F | PREFIX_VEX_0F38; break; case 3: newpfx |= PREFIX_VEX_0F | PREFIX_VEX_0F3A; break; } vex2 = vex3; codep += 3; } else { /* Two byte VEX prefix. */ newrex |= (vex2 & 0x80 ? 0 : REX_R); codep += 2; } vex_reg = (~vex2 >> 3) & 15; /* VEX.vvvv */ switch (vex2 & 3) { /* VEX.pp */ case 1: newpfx |= PREFIX_DATA; /* 0x66 */ break; case 2: newpfx |= PREFIX_REPZ; /* 0xf3 */ break; case 3: newpfx |= PREFIX_REPNZ; /* 0xf2 */ break; } rex = newrex; prefixes = newpfx; } /* Return the name of the prefix byte PREF, or NULL if PREF is not a prefix byte. */ Loading Loading @@ -3598,6 +3692,7 @@ print_insn (bfd_vma pc, disassemble_info *info) const char *p; struct dis_private priv; unsigned char op; unsigned char threebyte; if (info->mach == bfd_mach_x86_64_intel_syntax || info->mach == bfd_mach_x86_64) Loading Loading @@ -3752,6 +3847,7 @@ print_insn (bfd_vma pc, disassemble_info *info) obufp = obuf; ckprefix (); ckvexprefix (); insn_codep = codep; sizeflag = priv.orig_sizeflag; Loading @@ -3775,18 +3871,29 @@ print_insn (bfd_vma pc, disassemble_info *info) } op = 0; if (prefixes & PREFIX_VEX_0F) { used_prefixes |= PREFIX_VEX_0F | PREFIX_VEX_0F38 | PREFIX_VEX_0F3A; if (prefixes & PREFIX_VEX_0F38) threebyte = 0x38; else if (prefixes & PREFIX_VEX_0F3A) threebyte = 0x3a; else threebyte = *codep++; goto vex_opcode; } if (*codep == 0x0f) { unsigned char threebyte; fetch_data(info, codep + 2); threebyte = *++codep; threebyte = codep[1]; codep += 2; vex_opcode: dp = &dis386_twobyte[threebyte]; need_modrm = twobyte_has_modrm[*codep]; uses_DATA_prefix = twobyte_uses_DATA_prefix[*codep]; uses_REPNZ_prefix = twobyte_uses_REPNZ_prefix[*codep]; uses_REPZ_prefix = twobyte_uses_REPZ_prefix[*codep]; uses_LOCK_prefix = (*codep & ~0x02) == 0x20; codep++; need_modrm = twobyte_has_modrm[threebyte]; uses_DATA_prefix = twobyte_uses_DATA_prefix[threebyte]; uses_REPNZ_prefix = twobyte_uses_REPNZ_prefix[threebyte]; uses_REPZ_prefix = twobyte_uses_REPZ_prefix[threebyte]; uses_LOCK_prefix = (threebyte & ~0x02) == 0x20; if (dp->name == NULL && dp->op[0].bytemode == IS_3BYTE_OPCODE) { fetch_data(info, codep + 2); Loading Loading @@ -5291,6 +5398,17 @@ OP_G (int bytemode, int sizeflag) } } static void OP_vvvv (int bytemode, int sizeflags) { USED_REX (REX_W); if (rex & REX_W) { oappend(names64[vex_reg]); } else { oappend(names32[vex_reg]); } } static bfd_vma get64 (void) { Loading Loading
disas/i386.c +132 −14 Original line number Diff line number Diff line Loading @@ -171,6 +171,7 @@ static void print_operand_value (char *buf, size_t bufsize, int hex, bfd_vma dis static void print_displacement (char *, bfd_vma); static void OP_E (int, int); static void OP_G (int, int); static void OP_vvvv (int, int); static bfd_vma get64 (void); static bfd_signed_vma get32 (void); static bfd_signed_vma get32s (void); Loading Loading @@ -264,6 +265,9 @@ static int rex_used; current instruction. */ static int used_prefixes; /* The VEX.vvvv register, unencoded. */ static int vex_reg; /* Flags stored in PREFIXES. */ #define PREFIX_REPZ 1 #define PREFIX_REPNZ 2 Loading @@ -278,6 +282,10 @@ static int used_prefixes; #define PREFIX_ADDR 0x400 #define PREFIX_FWAIT 0x800 #define PREFIX_VEX_0F 0x1000 #define PREFIX_VEX_0F38 0x2000 #define PREFIX_VEX_0F3A 0x4000 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) to ADDR (exclusive) are valid. Returns 1 for success, longjmps on error. */ Loading Loading @@ -323,6 +331,7 @@ fetch_data(struct disassemble_info *info, bfd_byte *addr) #define XX { NULL, 0 } #define Bv { OP_vvvv, v_mode } #define Eb { OP_E, b_mode } #define Ev { OP_E, v_mode } #define Ed { OP_E, d_mode } Loading Loading @@ -671,7 +680,8 @@ fetch_data(struct disassemble_info *info, bfd_byte *addr) #define PREGRP102 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 102 } } #define PREGRP103 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 103 } } #define PREGRP104 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 104 } } #define PREGRP105 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 105 } } #define PREGRP106 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 106 } } #define X86_64_0 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 0 } } #define X86_64_1 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 1 } } Loading Loading @@ -1449,7 +1459,7 @@ static const unsigned char threebyte_0x38_uses_DATA_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,1,1,1,1,1, /* 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 */ 0,0,0,0,0,0,0,1,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 */ }; Loading @@ -1473,7 +1483,7 @@ 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 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ /* f0 */ 1,1,0,0,0,0,0,1,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 */ }; Loading @@ -1497,7 +1507,7 @@ static const unsigned char threebyte_0x38_uses_REPZ_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 */ 0,0,0,0,0,0,0,1,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 */ }; Loading Loading @@ -2774,6 +2784,22 @@ static const struct dis386 prefix_user_table[][4] = { { "(bad)", { XX } }, }, /* PREGRP105 */ { { "andnS", { Gv, Bv, Ev } }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, }, /* PREGRP106 */ { { "bextrS", { Gv, Ev, Bv } }, { "sarxS", { Gv, Ev, Bv } }, { "shlxS", { Gv, Ev, Bv } }, { "shrxS", { Gv, Ev, Bv } }, }, }; static const struct dis386 x86_64_table[][2] = { Loading Loading @@ -3071,12 +3097,12 @@ static const struct dis386 three_byte_table[][256] = { /* f0 */ { PREGRP87 }, { PREGRP88 }, { PREGRP105 }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, { "(bad)", { XX } }, { PREGRP106 }, /* f8 */ { "(bad)", { XX } }, { "(bad)", { XX } }, Loading Loading @@ -3477,6 +3503,74 @@ ckprefix (void) } } static void ckvexprefix (void) { int op, vex2, vex3, newrex = 0, newpfx = prefixes; if (address_mode == mode_16bit) { return; } fetch_data(the_info, codep + 1); op = *codep; if (op != 0xc4 && op != 0xc5) { return; } fetch_data(the_info, codep + 2); vex2 = codep[1]; if (address_mode == mode_32bit && (vex2 & 0xc0) != 0xc0) { return; } if (op == 0xc4) { /* Three byte VEX prefix. */ fetch_data(the_info, codep + 3); vex3 = codep[2]; newrex |= (vex2 & 0x80 ? 0 : REX_R); newrex |= (vex2 & 0x40 ? 0 : REX_X); newrex |= (vex2 & 0x20 ? 0 : REX_B); newrex |= (vex3 & 0x80 ? REX_W : 0); switch (vex2 & 0x1f) { /* VEX.m-mmmm */ case 1: newpfx |= PREFIX_VEX_0F; break; case 2: newpfx |= PREFIX_VEX_0F | PREFIX_VEX_0F38; break; case 3: newpfx |= PREFIX_VEX_0F | PREFIX_VEX_0F3A; break; } vex2 = vex3; codep += 3; } else { /* Two byte VEX prefix. */ newrex |= (vex2 & 0x80 ? 0 : REX_R); codep += 2; } vex_reg = (~vex2 >> 3) & 15; /* VEX.vvvv */ switch (vex2 & 3) { /* VEX.pp */ case 1: newpfx |= PREFIX_DATA; /* 0x66 */ break; case 2: newpfx |= PREFIX_REPZ; /* 0xf3 */ break; case 3: newpfx |= PREFIX_REPNZ; /* 0xf2 */ break; } rex = newrex; prefixes = newpfx; } /* Return the name of the prefix byte PREF, or NULL if PREF is not a prefix byte. */ Loading Loading @@ -3598,6 +3692,7 @@ print_insn (bfd_vma pc, disassemble_info *info) const char *p; struct dis_private priv; unsigned char op; unsigned char threebyte; if (info->mach == bfd_mach_x86_64_intel_syntax || info->mach == bfd_mach_x86_64) Loading Loading @@ -3752,6 +3847,7 @@ print_insn (bfd_vma pc, disassemble_info *info) obufp = obuf; ckprefix (); ckvexprefix (); insn_codep = codep; sizeflag = priv.orig_sizeflag; Loading @@ -3775,18 +3871,29 @@ print_insn (bfd_vma pc, disassemble_info *info) } op = 0; if (prefixes & PREFIX_VEX_0F) { used_prefixes |= PREFIX_VEX_0F | PREFIX_VEX_0F38 | PREFIX_VEX_0F3A; if (prefixes & PREFIX_VEX_0F38) threebyte = 0x38; else if (prefixes & PREFIX_VEX_0F3A) threebyte = 0x3a; else threebyte = *codep++; goto vex_opcode; } if (*codep == 0x0f) { unsigned char threebyte; fetch_data(info, codep + 2); threebyte = *++codep; threebyte = codep[1]; codep += 2; vex_opcode: dp = &dis386_twobyte[threebyte]; need_modrm = twobyte_has_modrm[*codep]; uses_DATA_prefix = twobyte_uses_DATA_prefix[*codep]; uses_REPNZ_prefix = twobyte_uses_REPNZ_prefix[*codep]; uses_REPZ_prefix = twobyte_uses_REPZ_prefix[*codep]; uses_LOCK_prefix = (*codep & ~0x02) == 0x20; codep++; need_modrm = twobyte_has_modrm[threebyte]; uses_DATA_prefix = twobyte_uses_DATA_prefix[threebyte]; uses_REPNZ_prefix = twobyte_uses_REPNZ_prefix[threebyte]; uses_REPZ_prefix = twobyte_uses_REPZ_prefix[threebyte]; uses_LOCK_prefix = (threebyte & ~0x02) == 0x20; if (dp->name == NULL && dp->op[0].bytemode == IS_3BYTE_OPCODE) { fetch_data(info, codep + 2); Loading Loading @@ -5291,6 +5398,17 @@ OP_G (int bytemode, int sizeflag) } } static void OP_vvvv (int bytemode, int sizeflags) { USED_REX (REX_W); if (rex & REX_W) { oappend(names64[vex_reg]); } else { oappend(names32[vex_reg]); } } static bfd_vma get64 (void) { Loading