diff options
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r-- | opcodes/i386-dis.c | 90 |
1 files changed, 53 insertions, 37 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 521d689..b25a9f3 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -159,6 +159,11 @@ static int rex_used; current instruction. */ static int used_prefixes; +/* Flags for EVEX bits which we somehow handled when printing the + current instruction. */ +#define EVEX_b_used 1 +static int evex_used; + /* Flags stored in PREFIXES. */ #define PREFIX_REPZ 1 #define PREFIX_REPNZ 2 @@ -2524,12 +2529,12 @@ static const char *att_names_mask[] = { "%k0", "%k1", "%k2", "%k3", "%k4", "%k5", "%k6", "%k7" }; -static const char *names_rounding[] = +static const char *const names_rounding[] = { - "{rn-sae}", - "{rd-sae}", - "{ru-sae}", - "{rz-sae}" + "{rn-", + "{rd-", + "{ru-", + "{rz-" }; static const struct dis386 reg_table[][8] = { @@ -8578,6 +8583,7 @@ ckprefix (void) prefixes = 0; used_prefixes = 0; rex_used = 0; + evex_used = 0; last_lock_prefix = -1; last_repz_prefix = -1; last_repnz_prefix = -1; @@ -9661,6 +9667,21 @@ print_insn (bfd_vma pc, disassemble_info *info) oappend ("/(bad)"); } } + + /* Check whether rounding control was enabled for an insn not + supporting it. */ + if (modrm.mod == 3 && vex.b && !(evex_used & EVEX_b_used)) + { + for (i = 0; i < MAX_OPERANDS; ++i) + { + obufp = op_out[i]; + if (*obufp) + continue; + oappend (names_rounding[vex.ll]); + oappend ("bad}"); + break; + } + } } } @@ -11316,14 +11337,6 @@ OP_E_memory (int bytemode, int sizeflag) if (vex.evex) { - /* In EVEX, if operand doesn't allow broadcast, vex.b should be 0. */ - if (vex.b - && bytemode != x_mode - && bytemode != evex_half_bcst_xmmq_mode) - { - BadOp (); - return; - } switch (bytemode) { case dw_mode: @@ -11764,10 +11777,9 @@ OP_E_memory (int bytemode, int sizeflag) oappend (scratchbuf); } } - if (vex.b - && (bytemode == x_mode - || bytemode == evex_half_bcst_xmmq_mode)) + if (vex.b) { + evex_used |= EVEX_b_used; if (vex.w || bytemode == evex_half_bcst_xmmq_mode) { @@ -11786,7 +11798,7 @@ OP_E_memory (int bytemode, int sizeflag) abort (); } } - else + else if (bytemode == x_mode) { switch (vex.length) { @@ -11803,6 +11815,9 @@ OP_E_memory (int bytemode, int sizeflag) abort (); } } + else + /* If operand doesn't allow broadcast, vex.b should be 0. */ + oappend ("{bad}"); } } @@ -13495,24 +13510,25 @@ MOVSXD_Fixup (int bytemode, int sizeflag) static void OP_Rounding (int bytemode, int sizeflag ATTRIBUTE_UNUSED) { - if (modrm.mod == 3 && vex.b) - switch (bytemode) - { - case evex_rounding_64_mode: - if (address_mode != mode_64bit || !vex.w) - { - oappend ("(bad)"); - break; - } - /* Fall through. */ - case evex_rounding_mode: - oappend (names_rounding[vex.ll]); - break; - case evex_sae_mode: - oappend ("{sae}"); - break; - default: - abort (); - break; - } + if (modrm.mod != 3 || !vex.b) + return; + + switch (bytemode) + { + case evex_rounding_64_mode: + if (address_mode != mode_64bit || !vex.w) + return; + /* Fall through. */ + case evex_rounding_mode: + evex_used |= EVEX_b_used; + oappend (names_rounding[vex.ll]); + break; + case evex_sae_mode: + evex_used |= EVEX_b_used; + oappend ("{"); + break; + default: + abort (); + } + oappend ("sae}"); } |