summaryrefslogtreecommitdiff
path: root/opcodes
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2021-07-22 13:07:27 +0200
committerJan Beulich <jbeulich@suse.com>2021-07-22 13:07:27 +0200
commit54ca11a48eba11788445247b16bc77637e3aa84a (patch)
treef6467dee62f9e4d9dc98a2c5059ada62abb9c724 /opcodes
parent4454883ff0ee338b1f6aab7f65ab1081af307e7c (diff)
downloadbinutils-gdb-54ca11a48eba11788445247b16bc77637e3aa84a.tar.gz
x86: correct EVEX.V' handling outside of 64-bit mode
Unlike the high bit of VEX.vvvv / EVEX.vvvv, EVEX.V' is not ignored outside of 64-bit mode. Oddly enough there already are tests for these cases, but their expectations were wrong. (This may have been based on an old SDM version, where the restriction wasn't properly spelled out.)
Diffstat (limited to 'opcodes')
-rw-r--r--opcodes/i386-dis.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index ddb659fb041..267d58d535e 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -9316,7 +9316,6 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
/* In 16/32-bit mode silently ignore following bits. */
rex &= ~REX_B;
vex.r = 1;
- vex.v = 1;
}
need_vex = 1;
@@ -11718,8 +11717,13 @@ OP_E_memory (int bytemode, int sizeflag)
*obufp = '\0';
}
if (haveindex)
- oappend (address_mode == mode_64bit && !addr32flag
- ? indexes64[vindex] : indexes32[vindex]);
+ {
+ if (address_mode == mode_64bit || vindex < 16)
+ oappend (address_mode == mode_64bit && !addr32flag
+ ? indexes64[vindex] : indexes32[vindex]);
+ else
+ oappend ("(bad)");
+ }
else
oappend (address_mode == mode_64bit && !addr32flag
? index64 : index32);
@@ -13256,7 +13260,15 @@ OP_VEX (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
reg = vex.register_specifier;
vex.register_specifier = 0;
if (address_mode != mode_64bit)
- reg &= 7;
+ {
+ if (vex.evex && !vex.v)
+ {
+ oappend ("(bad)");
+ return;
+ }
+
+ reg &= 7;
+ }
else if (vex.evex && !vex.v)
reg += 16;