Check invalid mask registers

In 32-bit, the REX_B bit in the 3-byte VEX prefix is ignored and the
the highest bit in VEX.vvvv is either 1 or ignored.  In 64-bit, we
need to check invalid mask registers.

gas/

	PR binutis/20705
	* testsuite/gas/i386/i386.exp: Run x86-64-opcode-bad.
	* testsuite/gas/i386/x86-64-opcode-bad.d: New file.
	* testsuite/gas/i386/x86-64-opcode-bad.s: Likewise.

opcodes/

	PR binutis/20705
	* i386-dis.c (get_valid_dis386): Ignore the REX_B bit and
	the highest bit in VEX.vvvv for the 3-byte VEX prefix in
	32-bit mode.  Don't check vex.register_specifier in 32-bit
	mode.
	(OP_E_register): Check invalid mask registers.
	(OP_G): Likewise.
	(OP_VEX): Likewise.
This commit is contained in:
H.J. Lu 2016-10-20 15:07:42 -07:00
parent f90fd8c2f1
commit 9889cbb14e
6 changed files with 73 additions and 17 deletions

View File

@ -1,3 +1,10 @@
2016-10-20 H.J. Lu <hongjiu.lu@intel.com>
PR binutis/20705
* testsuite/gas/i386/i386.exp: Run x86-64-opcode-bad.
* testsuite/gas/i386/x86-64-opcode-bad.d: New file.
* testsuite/gas/i386/x86-64-opcode-bad.s: Likewise.
2016-10-19 Renlin Li <renlin.li@arm.com>
* config/tc-arm.c (encode_arm_shift): Generate unpredictable warning

View File

@ -776,6 +776,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t
run_dump_test "x86-64-pr20141"
run_list_test "x86-64-avx512vl-1" "-al"
run_list_test "x86-64-avx512vl-2" "-al"
run_dump_test "x86-64-opcode-bad"
if { ![istarget "*-*-aix*"]
&& ![istarget "*-*-beos*"]

View File

@ -0,0 +1,12 @@
#as: --64
#objdump: -dw
#name: 64bit bad opcodes
.*: +file format .*
Disassembly of section .text:
0+ <.text>:
+[a-f0-9]+: c5 ac 46 f5 kxnorw %k5,\(bad\),%k6
+[a-f0-9]+: c5 2c 46 f5 kxnorw %k5,\(bad\),\(bad\)
#pass

View File

@ -0,0 +1,10 @@
.text
# All the followings are bad opcodes for x86-64.
.byte 0xc5
.byte 0xac
.byte 0x46
.byte 0xf5
.byte 0xc5
.byte 0x2c
.byte 0x46
.byte 0xf5

View File

@ -1,3 +1,12 @@
2016-10-20 H.J. Lu <hongjiu.lu@intel.com>
PR binutis/20705
* i386-dis.c (get_valid_dis386): Ignore the REX_B bit and
the highest bit in VEX.vvvv for the 3-byte VEX prefix in
32-bit mode. Don't check vex.register_specifier in 32-bit
mode.
(OP_VEX): Check for invalid mask registers.
2016-10-18 H.J. Lu <hongjiu.lu@intel.com>
PR binutis/20699

View File

@ -13022,17 +13022,20 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
}
codep++;
vex.w = *codep & 0x80;
if (vex.w && address_mode == mode_64bit)
rex |= REX_W;
vex.register_specifier = (~(*codep >> 3)) & 0xf;
if (address_mode != mode_64bit
&& vex.register_specifier > 0x7)
if (address_mode == mode_64bit)
{
dp = &bad_opcode;
return dp;
if (vex.w)
rex |= REX_W;
vex.register_specifier = (~(*codep >> 3)) & 0xf;
}
else
{
/* For the 3-byte VEX prefix in 32-bit mode, the REX_B bit
is ignored, other REX bits are 0 and the highest bit in
VEX.vvvv is also ignored. */
rex = 0;
vex.register_specifier = (~(*codep >> 3)) & 0x7;
}
vex.length = (*codep & 0x4) ? 256 : 128;
switch ((*codep & 0x3))
{
@ -13072,16 +13075,10 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
rex_ignored = rex;
rex = (*codep & 0x80) ? 0 : REX_R;
/* For the 2-byte VEX prefix in 32-bit mode, the highest bit in
VEX.vvvv is 1. */
vex.register_specifier = (~(*codep >> 3)) & 0xf;
if (address_mode != mode_64bit
&& vex.register_specifier > 0x7)
{
dp = &bad_opcode;
return dp;
}
vex.w = 0;
vex.length = (*codep & 0x4) ? 256 : 128;
switch ((*codep & 0x3))
{
@ -15266,6 +15263,11 @@ OP_E_register (int bytemode, int sizeflag)
break;
case mask_bd_mode:
case mask_mode:
if (reg > 0x7)
{
oappend ("(bad)");
return;
}
names = names_mask;
break;
case 0:
@ -15795,6 +15797,11 @@ OP_G (int bytemode, int sizeflag)
break;
case mask_bd_mode:
case mask_mode:
if ((modrm.reg + add) > 0x7)
{
oappend ("(bad)");
return;
}
oappend (names_mask[modrm.reg + add]);
break;
default:
@ -17225,6 +17232,11 @@ OP_VEX (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
break;
case mask_bd_mode:
case mask_mode:
if (reg > 0x7)
{
oappend ("(bad)");
return;
}
names = names_mask;
break;
default:
@ -17245,6 +17257,11 @@ OP_VEX (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
break;
case mask_bd_mode:
case mask_mode:
if (reg > 0x7)
{
oappend ("(bad)");
return;
}
names = names_mask;
break;
default: