aboutsummaryrefslogtreecommitdiff
path: root/opcodes
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2021-07-23 08:03:21 +0200
committerJan Beulich <jbeulich@suse.com>2021-07-23 08:03:21 +0200
commit0e4cc77316732e67cff33e493eff2aa7feed4587 (patch)
treee1e3a9830a91012c0b7a49a4ed6610793e34bcb3 /opcodes
parent9234efeee5f47807f0e08769983ac439d5ffefde (diff)
downloadgdb-0e4cc77316732e67cff33e493eff2aa7feed4587.zip
gdb-0e4cc77316732e67cff33e493eff2aa7feed4587.tar.gz
gdb-0e4cc77316732e67cff33e493eff2aa7feed4587.tar.bz2
x86: express unduly set rounding control bits in disassembly
While EVEX.L'L are indeed ignored when EVEX.b stands for just SAE, EVEX.b itself is not ignored when an insn permits neither rounding control nor SAE. While changing this aspect of EVEX.b handling, also alter unduly set embedded broadcast: Don't call BadOp(), screwing up subsequent disassembly, but emit "{bad}" instead.
Diffstat (limited to 'opcodes')
-rw-r--r--opcodes/i386-dis.c90
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}");
}