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.
diff --git a/gas/testsuite/gas/i386/avx512f-nondef.d b/gas/testsuite/gas/i386/avx512f-nondef.d
index f19edce..07ffe60 100644
--- a/gas/testsuite/gas/i386/avx512f-nondef.d
+++ b/gas/testsuite/gas/i386/avx512f-nondef.d
@@ -10,12 +10,11 @@
0+ <.text>:
[ ]*[a-f0-9]+: 62 f3 d5 1f 0b f4 7b vrndscalesd \$0x7b,\{sae\},%xmm4,%xmm5,%xmm6\{%k7\}
[ ]*[a-f0-9]+: 62 f3 d5 5f 0b f4 7b vrndscalesd \$0x7b,\{sae\},%xmm4,%xmm5,%xmm6\{%k7\}
-[ ]*[a-f0-9]+: 62 f2 55 1f 3b f4 vpminud %zmm4,%zmm5,%zmm6\{%k7\}
-[ ]*[a-f0-9]+: 62 c2 55 1f 3b f4 vpminud %zmm4,%zmm5,%zmm6\{%k7\}
+[ ]*[a-f0-9]+: 62 f2 55 4f 3b f4 vpminud %zmm4,%zmm5,%zmm6\{%k7\}
+[ ]*[a-f0-9]+: 62 c2 55 4f 3b f4 vpminud %zmm4,%zmm5,%zmm6\{%k7\}
+[ ]*[a-f0-9]+: 62 f2 55 1f 3b f4 vpminud \{rn-bad\},%zmm4,%zmm5,%zmm6\{%k7\}
[ ]*[a-f0-9]+: 62 f2 7e 48 31 72 7f vpmovdb %zmm6,0x7f0\(%edx\)
-[ ]*[a-f0-9]+: 62 vpmovdb %zmm6,\(bad\)
-[ ]*[a-f0-9]+: f2 7e 58 bnd jle (0x7d|7d <.text\+0x7d>)
-[ ]*[a-f0-9]+: 31 72 7f xor %esi,0x7f\(%edx\)
+[ ]*[a-f0-9]+: 62 f2 7e 58 31 72 7f vpmovdb %zmm6,0x7f0\(%edx\)\{bad\}
[ ]*[a-f0-9]+: 62 f1 7c 88 58 \(bad\)
[ ]*[a-f0-9]+: c3 ret *
[ ]*[a-f0-9]+: 62 f2 7d 4f 92 01 vgatherdps \(bad\),%zmm0\{%k7\}
diff --git a/gas/testsuite/gas/i386/avx512f-nondef.s b/gas/testsuite/gas/i386/avx512f-nondef.s
index 676c4e0..96d0466 100644
--- a/gas/testsuite/gas/i386/avx512f-nondef.s
+++ b/gas/testsuite/gas/i386/avx512f-nondef.s
@@ -5,13 +5,15 @@
.byte 0x62, 0xf3, 0xd5, 0x1f, 0x0b, 0xf4, 0x7b
# vrndscalesd {sae}, $123, %xmm4, %xmm5, %xmm6{%k7} # with not-null RC
.byte 0x62, 0xf3, 0xd5, 0x5f, 0x0b, 0xf4, 0x7b
-# vpminud %zmm4, %zmm5, %zmm6{%k7} # with 111 REX
+# vpminud %zmm4, %zmm5, %zmm6{%k7} # with 11 EVEX.{B,R'}
+.byte 0x62, 0xf2, 0x55, 0x4f, 0x3b, 0xf4
+# vpminud %zmm4, %zmm5, %zmm6{%k7} # with not-11 EVEX.{B,R'}
+.byte 0x62, 0xc2, 0x55, 0x4f, 0x3b, 0xf4
+# vpminud %zmm4, %zmm5, %zmm6{%k7} # with set EVEX.b bit
.byte 0x62, 0xf2, 0x55, 0x1f, 0x3b, 0xf4
-# vpminud %zmm4, %zmm5, %zmm6{%k7} # with not-111 REX
-.byte 0x62, 0xc2, 0x55, 0x1f, 0x3b, 0xf4
-# vpmovdb %zmm6, 2032(%rdx) # with unset EVEX.B bit
+# vpmovdb %zmm6, 2032(%rdx) # with unset EVEX.b bit
.byte 0x62, 0xf2, 0x7e, 0x48, 0x31, 0x72, 0x7f
-# vpmovdb %zmm6, 2032(%rdx) # with set EVEX.B bit - we should get (bad) operand
+# vpmovdb %zmm6, 2032(%rdx) # with set EVEX.b bit - we should get (bad) operand
.byte 0x62, 0xf2, 0x7e, 0x58, 0x31, 0x72, 0x7f
# vaddps xmm0, xmm0, xmm3 # with EVEX.z set
.byte 0x62, 0xf1, 0x7c, 0x88, 0x58, 0xc3
diff --git a/gas/testsuite/gas/i386/evex.d b/gas/testsuite/gas/i386/evex.d
index 367b2eb..4afcc6d 100644
--- a/gas/testsuite/gas/i386/evex.d
+++ b/gas/testsuite/gas/i386/evex.d
@@ -8,14 +8,14 @@
0+ <_start>:
+[a-f0-9]+: 62 f1 d6 38 2a f0 vcvtsi2ssl %eax,\{rd-sae\},%xmm5,%xmm6
- +[a-f0-9]+: 62 f1 57 38 2a f0 vcvtsi2sdl %eax,\(bad\),%xmm5,%xmm6
- +[a-f0-9]+: 62 f1 d7 38 2a f0 vcvtsi2sdl %eax,\(bad\),%xmm5,%xmm6
+ +[a-f0-9]+: 62 f1 57 38 2a f0 vcvtsi2sdl %eax,\{rd-bad\},%xmm5,%xmm6
+ +[a-f0-9]+: 62 f1 d7 38 2a f0 vcvtsi2sdl %eax,\{rd-bad\},%xmm5,%xmm6
+[a-f0-9]+: 62 f1 d6 08 7b f0 vcvtusi2ssl %eax,%xmm5,%xmm6
+[a-f0-9]+: 62 f1 57 08 7b f0 vcvtusi2sdl %eax,%xmm5,%xmm6
+[a-f0-9]+: 62 f1 d7 08 7b f0 vcvtusi2sdl %eax,%xmm5,%xmm6
+[a-f0-9]+: 62 f1 d6 38 7b f0 vcvtusi2ssl %eax,\{rd-sae\},%xmm5,%xmm6
- +[a-f0-9]+: 62 f1 57 38 7b f0 vcvtusi2sdl %eax,\(bad\),%xmm5,%xmm6
- +[a-f0-9]+: 62 f1 d7 38 7b f0 vcvtusi2sdl %eax,\(bad\),%xmm5,%xmm6
+ +[a-f0-9]+: 62 f1 57 38 7b f0 vcvtusi2sdl %eax,\{rd-bad\},%xmm5,%xmm6
+ +[a-f0-9]+: 62 f1 d7 38 7b f0 vcvtusi2sdl %eax,\{rd-bad\},%xmm5,%xmm6
+[a-f0-9]+: 62 e1 7e 08 2d c0 vcvtss2si %xmm0,%eax
+[a-f0-9]+: 62 e1 7c 08 c2 c0 00 vcmpeqps %xmm0,%xmm0,%k0
#pass
diff --git a/gas/testsuite/gas/i386/x86-64-avx512f-nondef.d b/gas/testsuite/gas/i386/x86-64-avx512f-nondef.d
index bce2d80..e8ddfd5 100644
--- a/gas/testsuite/gas/i386/x86-64-avx512f-nondef.d
+++ b/gas/testsuite/gas/i386/x86-64-avx512f-nondef.d
@@ -10,10 +10,9 @@
0+ <.text>:
[ ]*[a-f0-9]+: 62 f3 d5 1f 0b f4 7b vrndscalesd \$0x7b,\{sae\},%xmm4,%xmm5,%xmm6\{%k7\}
[ ]*[a-f0-9]+: 62 f3 d5 5f 0b f4 7b vrndscalesd \$0x7b,\{sae\},%xmm4,%xmm5,%xmm6\{%k7\}
-[ ]*[a-f0-9]+: 62 f2 55 1f 3b f4 vpminud %zmm4,%zmm5,%zmm6\{%k7\}
-[ ]*[a-f0-9]+: 62 c2 55 1f 3b f4 vpminud %zmm12,%zmm5,%zmm22\{%k7\}
+[ ]*[a-f0-9]+: 62 f2 55 4f 3b f4 vpminud %zmm4,%zmm5,%zmm6\{%k7\}
+[ ]*[a-f0-9]+: 62 c2 55 4f 3b f4 vpminud %zmm12,%zmm5,%zmm22\{%k7\}
+[ ]*[a-f0-9]+: 62 f2 55 1f 3b f4 vpminud \{rn-bad\},%zmm4,%zmm5,%zmm6\{%k7\}
[ ]*[a-f0-9]+: 62 f2 7e 48 31 72 7f vpmovdb %zmm6,0x7f0\(%rdx\)
-[ ]*[a-f0-9]+: 62 vpmovdb %zmm6,\(bad\)
-[ ]*[a-f0-9]+: f2 7e 58 bnd jle (0x7d|7d <.text\+0x7d>)
-[ ]*[a-f0-9]+: 31 72 7f xor %esi,0x7f\(%rdx\)
+[ ]*[a-f0-9]+: 62 f2 7e 58 31 72 7f vpmovdb %zmm6,0x7f0\(%rdx\)\{bad\}
#pass
diff --git a/gas/testsuite/gas/i386/x86-64-avx512f-nondef.s b/gas/testsuite/gas/i386/x86-64-avx512f-nondef.s
index 255d2c9..952f2db 100644
--- a/gas/testsuite/gas/i386/x86-64-avx512f-nondef.s
+++ b/gas/testsuite/gas/i386/x86-64-avx512f-nondef.s
@@ -5,11 +5,13 @@
.byte 0x62, 0xf3, 0xd5, 0x1f, 0x0b, 0xf4, 0x7b
# vrndscalesd {sae}, $123, %xmm4, %xmm5, %xmm6{%k7} # with not-null RC
.byte 0x62, 0xf3, 0xd5, 0x5f, 0x0b, 0xf4, 0x7b
-# vpminud %zmm4, %zmm5, %zmm6{%k7} # with 111 REX
+# vpminud %zmm4, %zmm5, %zmm6{%k7} # with 11 EVEX.{B,R'}
+.byte 0x62, 0xf2, 0x55, 0x4f, 0x3b, 0xf4
+# vpminud %zmm4, %zmm5, %zmm6{%k7} # with not-11 EVEX.{B,R'}
+.byte 0x62, 0xc2, 0x55, 0x4f, 0x3b, 0xf4
+# vpminud %zmm4, %zmm5, %zmm6{%k7} # with set EVEX.b bit
.byte 0x62, 0xf2, 0x55, 0x1f, 0x3b, 0xf4
-# vpminud %zmm4, %zmm5, %zmm6{%k7} # with not-111 REX
-.byte 0x62, 0xc2, 0x55, 0x1f, 0x3b, 0xf4
-# vpmovdb %zmm6, 2032(%rdx) # with unset EVEX.B bit
+# vpmovdb %zmm6, 2032(%rdx) # with unset EVEX.b bit
.byte 0x62, 0xf2, 0x7e, 0x48, 0x31, 0x72, 0x7f
-# vpmovdb %zmm6, 2032(%rdx) # with set EVEX.B bit - we should get (bad) operand
+# vpmovdb %zmm6, 2032(%rdx) # with set EVEX.b bit - we should get (bad) operand
.byte 0x62, 0xf2, 0x7e, 0x58, 0x31, 0x72, 0x7f
diff --git a/gas/testsuite/gas/i386/x86-64-evex.d b/gas/testsuite/gas/i386/x86-64-evex.d
index 3a7b48e..041747d 100644
--- a/gas/testsuite/gas/i386/x86-64-evex.d
+++ b/gas/testsuite/gas/i386/x86-64-evex.d
@@ -9,13 +9,13 @@
0+ <_start>:
+[a-f0-9]+: 62 f1 d6 38 2a f0 vcvtsi2ss %rax,\{rd-sae\},%xmm5,%xmm6
- +[a-f0-9]+: 62 f1 57 38 2a f0 vcvtsi2sd %eax,\(bad\),%xmm5,%xmm6
+ +[a-f0-9]+: 62 f1 57 38 2a f0 vcvtsi2sd %eax,\{rd-bad\},%xmm5,%xmm6
+[a-f0-9]+: 62 f1 d7 38 2a f0 vcvtsi2sd %rax,\{rd-sae\},%xmm5,%xmm6
+[a-f0-9]+: 62 f1 d6 08 7b f0 vcvtusi2ss %rax,%xmm5,%xmm6
+[a-f0-9]+: 62 f1 57 08 7b f0 vcvtusi2sd %eax,%xmm5,%xmm6
+[a-f0-9]+: 62 f1 d7 08 7b f0 vcvtusi2sd %rax,%xmm5,%xmm6
+[a-f0-9]+: 62 f1 d6 38 7b f0 vcvtusi2ss %rax,\{rd-sae\},%xmm5,%xmm6
- +[a-f0-9]+: 62 f1 57 38 7b f0 vcvtusi2sd %eax,\(bad\),%xmm5,%xmm6
+ +[a-f0-9]+: 62 f1 57 38 7b f0 vcvtusi2sd %eax,\{rd-bad\},%xmm5,%xmm6
+[a-f0-9]+: 62 f1 d7 38 7b f0 vcvtusi2sd %rax,\{rd-sae\},%xmm5,%xmm6
+[a-f0-9]+: 62 e1 7e 08 2d c0 vcvtss2si %xmm0,\(bad\)
+[a-f0-9]+: 62 e1 7c 08 c2 c0 00 vcmpeqps %xmm0,%xmm0,\(bad\)
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 @@
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 @@
"%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 @@
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 @@
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 @@
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 @@
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 @@
abort ();
}
}
- else
+ else if (bytemode == x_mode)
{
switch (vex.length)
{
@@ -11803,6 +11815,9 @@
abort ();
}
}
+ else
+ /* If operand doesn't allow broadcast, vex.b should be 0. */
+ oappend ("{bad}");
}
}
@@ -13495,24 +13510,25 @@
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}");
}