x86: ignore high register select bit(s) in 32- and 16-bit modes
While commits9889cbb14e
("Check invalid mask registers") andabfcb414b9
("X86: Ignore REX_B bit for 32-bit XOP instructions") went a bit into the right direction, this wasn't quite enough: - VEX.vvvv has its high bit ignored - EVEX.vvvv has its high bit ignored together with EVEX.v' - the high bits of {,E}VEX.vvvv should not be prematurely zapped, to allow proper checking of them when the fields has to hold al ones - when the high bits of an immediate specify a register, bit 7 is ignored
This commit is contained in:
parent
968a13f836
commit
5f847646ee
|
@ -1,3 +1,9 @@
|
|||
2017-11-16 Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
* testsuite/gas/i386/noextreg.s: Add tests with register index
|
||||
bit 3 set.
|
||||
* testsuite/gas/i386/noextreg.d: Adjust expectations.
|
||||
|
||||
2017-11-16 Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
* config/tc-i386.c (process_suffix): Ignore .no_qsuf outside of
|
||||
|
|
|
@ -6,13 +6,48 @@
|
|||
Disassembly of section .text:
|
||||
|
||||
0+ <ix86>:
|
||||
[ ]*[a-f0-9]+: c5 f9 db c0 vpand %xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 c1 79 db c0 vpand %xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 c1 39 db c0 vpand %xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: 62 f1 7d 08 db c0 vpandd %xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: 62 d1 7d 08 db c0 vpandd %xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: 62 f1 3d 08 db c0 vpandd %xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: 62 f1 7d 00 db c0 vpandd %xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 e3 79 4c c0 00 vpblendvb %xmm0,%xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 c3 79 4c c0 00 vpblendvb %xmm0,%xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 e3 39 4c c0 00 vpblendvb %xmm0,%xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 e3 79 4c c0 80 vpblendvb %xmm0,%xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: 62 f2 7d 0f 90 0c 00 vpgatherdd \(%eax,%xmm0,1\),%xmm1\{%k7\}
|
||||
[ ]*[a-f0-9]+: 62 d2 7d 0f 90 0c 00 vpgatherdd \(%eax,%xmm0,1\),%xmm1\{%k7\}
|
||||
[ ]*[a-f0-9]+: 62 f2 7d 07 90 0c 00 vpgatherdd \(%eax,%xmm0,1\),%xmm1\{%k7\}
|
||||
[ ]*[a-f0-9]+: c4 e2 78 f2 00 andn \(%eax\),%eax,%eax
|
||||
[ ]*[a-f0-9]+: c4 e2 38 f2 00 andn \(%eax\),%eax,%eax
|
||||
[ ]*[a-f0-9]+: c4 c2 78 f2 00 andn \(%eax\),%eax,%eax
|
||||
[ ]*[a-f0-9]+: c4 e2 f8 f2 00 andn \(%eax\),%eax,%eax
|
||||
[ ]*[a-f0-9]+: 8f e9 78 01 20 tzmsk \(%eax\),%eax
|
||||
[ ]*[a-f0-9]+: 8f c9 78 01 20 tzmsk \(%eax\),%eax
|
||||
[ ]*[a-f0-9]+: 8f e9 38 01 20 tzmsk \(%eax\),%eax
|
||||
[ ]*[a-f0-9]+: 8f e9 f8 01 20 tzmsk \(%eax\),%eax
|
||||
[ ]*[a-f0-9]+: 8f e9 78 12 c0 llwpcb %eax
|
||||
[ ]*[a-f0-9]+: 8f c9 78 12 c0 llwpcb %eax
|
||||
[ ]*[a-f0-9]+: 8f e9 f8 12 c0 llwpcb %eax
|
||||
[ ]*[a-f0-9]+: 8f e8 78 c0 c0 01 vprotb \$0x1,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: 8f c8 78 c0 c0 01 vprotb \$0x1,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: 8f e8 78 c0 00 01 vprotb \$0x1,\(%eax\),%xmm0
|
||||
[ ]*[a-f0-9]+: 8f c8 78 c0 00 01 vprotb \$0x1,\(%eax\),%xmm0
|
||||
[ ]*[a-f0-9]+: 8f e9 78 90 c0 vprotb %xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: 8f c9 b8 90 c0 vprotb %xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: 8f e9 38 90 c0 vprotb %xmm0,%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: 8f e9 78 90 00 vprotb %xmm0,\(%eax\),%xmm0
|
||||
[ ]*[a-f0-9]+: 8f c9 78 90 00 vprotb %xmm0,\(%eax\),%xmm0
|
||||
[ ]*[a-f0-9]+: 8f e9 f8 90 00 vprotb \(%eax\),%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: 8f c9 f8 90 00 vprotb \(%eax\),%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 e3 79 68 00 00 vfmaddps %xmm0,\(%eax\),%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 e3 39 68 00 00 vfmaddps %xmm0,\(%eax\),%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 e3 79 68 00 80 vfmaddps %xmm0,\(%eax\),%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 e3 79 68 00 0f vfmaddps %xmm0,\(%eax\),%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 e3 79 48 00 00 vpermil2ps \$0x0,%xmm0,\(%eax\),%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 e3 39 48 00 00 vpermil2ps \$0x0,%xmm0,\(%eax\),%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c4 e3 79 48 00 80 vpermil2ps \$0x0,%xmm0,\(%eax\),%xmm0,%xmm0
|
||||
[ ]*[a-f0-9]+: c3 ret[ ]*
|
||||
#pass
|
||||
|
|
|
@ -1,20 +1,57 @@
|
|||
.intel_syntax noprefix
|
||||
.text
|
||||
ix86:
|
||||
vpand xmm0, xmm0, xmm0
|
||||
.byte 0xc4, 0xc1, 0x79, 0xdb, 0xc0
|
||||
.byte 0xc4, 0xc1, 0x39, 0xdb, 0xc0
|
||||
|
||||
vpandd xmm0, xmm0, xmm0
|
||||
.byte 0x62, 0xd1, 0x7d, 0x08, 0xdb, 0xc0
|
||||
.byte 0x62, 0xf1, 0x3d, 0x08, 0xdb, 0xc0
|
||||
.byte 0x62, 0xf1, 0x7d, 0x00, 0xdb, 0xc0
|
||||
|
||||
vpblendvb xmm0, xmm0, xmm0, xmm0
|
||||
.byte 0xc4, 0xc3, 0x79, 0x4c, 0xc0, 0x00
|
||||
.byte 0xc4, 0xe3, 0x39, 0x4c, 0xc0, 0x00
|
||||
.byte 0xc4, 0xe3, 0x79, 0x4c, 0xc0, 0x80
|
||||
|
||||
vpgatherdd xmm1{k7}, [eax+xmm0]
|
||||
.byte 0x62, 0xd2, 0x7d, 0x0f, 0x90, 0x0c, 0x00
|
||||
.byte 0x62, 0xf2, 0x7d, 0x07, 0x90, 0x0c, 0x00
|
||||
|
||||
andn eax, eax, [eax]
|
||||
# andn rax, rax, [rax]
|
||||
.byte 0xc4, 0xe2, 0x38, 0xf2, 0x00
|
||||
.byte 0xc4, 0xc2, 0x78, 0xf2, 0x00
|
||||
.byte 0xc4, 0xe2, 0xf8, 0xf2, 0x00
|
||||
|
||||
tzmsk eax, [eax]
|
||||
# tzmsk rax, [rax]
|
||||
.byte 0x8f, 0xc9, 0x78, 0x01, 0x20
|
||||
.byte 0x8f, 0xe9, 0x38, 0x01, 0x20
|
||||
.byte 0x8f, 0xe9, 0xf8, 0x01, 0x20
|
||||
|
||||
llwpcb eax
|
||||
# llwpcb rax
|
||||
.byte 0x8f, 0xc9, 0x78, 0x12, 0xc0
|
||||
.byte 0x8f, 0xe9, 0xf8, 0x12, 0xc0
|
||||
|
||||
vprotb xmm0, xmm0, 1
|
||||
.byte 0x8f, 0xc8, 0x78, 0xc0, 0xc0, 0x01
|
||||
vprotb xmm0, [eax], 1
|
||||
.byte 0x8f, 0xc8, 0x78, 0xc0, 0x00, 0x01
|
||||
vprotb xmm0, xmm0, xmm0
|
||||
.byte 0x8f, 0xc9, 0xb8, 0x90, 0xc0
|
||||
.byte 0x8f, 0xe9, 0x38, 0x90, 0xc0
|
||||
vprotb xmm0, [eax], xmm0
|
||||
.byte 0x8f, 0xc9, 0x78, 0x90, 0x00
|
||||
vprotb xmm0, xmm0, [eax]
|
||||
.byte 0x8f, 0xc9, 0xf8, 0x90, 0x00
|
||||
|
||||
vfmaddps xmm0, xmm0, [eax], xmm0
|
||||
# vfmaddps xmm0, xmm0, [eax], xmm0
|
||||
.byte 0xc4, 0xe3, 0x39, 0x68, 0x00, 0x00
|
||||
.byte 0xc4, 0xe3, 0x79, 0x68, 0x00, 0x80
|
||||
.byte 0xc4, 0xe3, 0x79, 0x68, 0x00, 0x0f
|
||||
|
||||
vpermil2ps xmm0, xmm0, [eax], xmm0, 0
|
||||
.byte 0xc4, 0xe3, 0x39, 0x48, 0x00, 0x00
|
||||
.byte 0xc4, 0xe3, 0x79, 0x48, 0x00, 0x80
|
||||
|
||||
ret
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
2017-11-16 Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
(get_valid_dis386): Never flag bad opcode when
|
||||
vex.register_specifier is beyond 7. Always store all four
|
||||
bits of it. Move 16-/32-bit override in EVEX handling after
|
||||
all to be overridden bits have been set.
|
||||
(OP_VEX): Mask vex.register_specifier outside of 64-bit mode.
|
||||
Use rex to determine GPR register set.
|
||||
(OP_EX_VexReg, OP_Vex_2src_1, OP_Vex_2src_2, OP_REG_VexI4,
|
||||
OP_LWP_E): Mask vex.register_specifier outside of 64-bit mode.
|
||||
|
||||
2017-11-15 Jan Beulich <jbeulich@suse.com>
|
||||
|
||||
* i386-dis.c (OP_VEX, OP_LWPCB_E, OP_LWP_E): Use rex to
|
||||
|
|
|
@ -12809,11 +12809,6 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
|
|||
{
|
||||
/* In 16/32-bit mode REX_B is silently ignored. */
|
||||
rex &= ~REX_B;
|
||||
if (vex.register_specifier > 0x7)
|
||||
{
|
||||
dp = &bad_opcode;
|
||||
return dp;
|
||||
}
|
||||
}
|
||||
|
||||
vex.length = (*codep & 0x4) ? 256 : 128;
|
||||
|
@ -12872,16 +12867,15 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
|
|||
{
|
||||
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. */
|
||||
VEX.vvvv is also ignored (but we mustn't clear it here). */
|
||||
rex = 0;
|
||||
vex.register_specifier = (~(*codep >> 3)) & 0x7;
|
||||
}
|
||||
vex.register_specifier = (~(*codep >> 3)) & 0xf;
|
||||
vex.length = (*codep & 0x4) ? 256 : 128;
|
||||
switch ((*codep & 0x3))
|
||||
{
|
||||
|
@ -12996,14 +12990,6 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
|
|||
rex |= REX_W;
|
||||
|
||||
vex.register_specifier = (~(*codep >> 3)) & 0xf;
|
||||
if (address_mode != mode_64bit)
|
||||
{
|
||||
/* In 16/32-bit mode silently ignore following bits. */
|
||||
rex &= ~REX_B;
|
||||
vex.r = 1;
|
||||
vex.v = 1;
|
||||
vex.register_specifier &= 0x7;
|
||||
}
|
||||
|
||||
/* The U bit. */
|
||||
if (!(*codep & 0x4))
|
||||
|
@ -13036,6 +13022,14 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
|
|||
vex.mask_register_specifier = *codep & 0x7;
|
||||
vex.zeroing = *codep & 0x80;
|
||||
|
||||
if (address_mode != mode_64bit)
|
||||
{
|
||||
/* In 16/32-bit mode silently ignore following bits. */
|
||||
rex &= ~REX_B;
|
||||
vex.r = 1;
|
||||
vex.v = 1;
|
||||
}
|
||||
|
||||
need_vex = 1;
|
||||
need_vex_reg = 1;
|
||||
codep++;
|
||||
|
@ -17098,11 +17092,10 @@ OP_VEX (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
|
|||
return;
|
||||
|
||||
reg = vex.register_specifier;
|
||||
if (vex.evex)
|
||||
{
|
||||
if (!vex.v)
|
||||
reg += 16;
|
||||
}
|
||||
if (address_mode != mode_64bit)
|
||||
reg &= 7;
|
||||
else if (vex.evex && !vex.v)
|
||||
reg += 16;
|
||||
|
||||
if (bytemode == vex_scalar_mode)
|
||||
{
|
||||
|
@ -17287,8 +17280,8 @@ OP_EX_VexReg (int bytemode, int sizeflag, int reg)
|
|||
if (rex & REX_B)
|
||||
reg += 8;
|
||||
}
|
||||
else if (reg > 7 && address_mode != mode_64bit)
|
||||
BadOp ();
|
||||
if (address_mode != mode_64bit)
|
||||
reg &= 7;
|
||||
}
|
||||
|
||||
switch (vex.length)
|
||||
|
@ -17380,7 +17373,13 @@ OP_Vex_2src_1 (int bytemode, int sizeflag)
|
|||
}
|
||||
|
||||
if (vex.w)
|
||||
oappend (names_xmm[vex.register_specifier]);
|
||||
{
|
||||
unsigned int reg = vex.register_specifier;
|
||||
|
||||
if (address_mode != mode_64bit)
|
||||
reg &= 7;
|
||||
oappend (names_xmm[reg]);
|
||||
}
|
||||
else
|
||||
OP_Vex_2src (bytemode, sizeflag);
|
||||
}
|
||||
|
@ -17391,7 +17390,13 @@ OP_Vex_2src_2 (int bytemode, int sizeflag)
|
|||
if (vex.w)
|
||||
OP_Vex_2src (bytemode, sizeflag);
|
||||
else
|
||||
oappend (names_xmm[vex.register_specifier]);
|
||||
{
|
||||
unsigned int reg = vex.register_specifier;
|
||||
|
||||
if (address_mode != mode_64bit)
|
||||
reg &= 7;
|
||||
oappend (names_xmm[reg]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -17434,8 +17439,8 @@ OP_REG_VexI4 (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
|
|||
abort ();
|
||||
|
||||
reg >>= 4;
|
||||
if (reg > 7 && address_mode != mode_64bit)
|
||||
BadOp ();
|
||||
if (address_mode != mode_64bit)
|
||||
reg &= 7;
|
||||
|
||||
switch (vex.length)
|
||||
{
|
||||
|
@ -17775,13 +17780,16 @@ static void
|
|||
OP_LWP_E (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
|
||||
{
|
||||
const char **names;
|
||||
unsigned int reg = vex.register_specifier;
|
||||
|
||||
if (rex & REX_W)
|
||||
names = names64;
|
||||
else
|
||||
names = names32;
|
||||
|
||||
oappend (names[vex.register_specifier]);
|
||||
if (address_mode != mode_64bit)
|
||||
reg &= 7;
|
||||
oappend (names[reg]);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in New Issue