x86: Print {bad} on invalid broadcast in OP_E_memory

Don't print broadcast for scalar_mode, and print {bad} for invalid broadcast.

gas/

	PR binutils/28381
	* testsuite/gas/i386/bad-bcast.s: Add a new testcase.
	* testsuite/gas/i386/bad-bcast.d: Likewise.
	* testsuite/gas/i386/bad-bcast-intel.d: New.

opcodes/

	PR binutils/28381
	* i386-dis.c (static struct): Add no_broadcast.
	(OP_E_memory): Mark invalid broadcast with no_broadcast=1 and Print "{bad}"for it.
	(intel_operand_size): mark invalid broadcast with no_broadcast=1.
	(OP_XMM): Mark scalar_mode with no_broadcast=1.
This commit is contained in:
Cui,Lili 2021-09-28 11:13:33 +08:00
parent 901b98215e
commit 2c02075a8e
5 changed files with 105 additions and 80 deletions

View File

@ -0,0 +1,15 @@
#source: bad-bcast.s
#objdump: -dw -Mintel
#name: Disassemble bad broadcast (Intel mode)
.*: +file format .*
Disassembly of section .text:
0+ <.text>:
[ ]*[a-f0-9]+:[ ]*62 c3 8c 1d 66\s*\(bad\)
[ ]*[a-f0-9]+:[ ]*90\s*nop
[ ]*[a-f0-9]+:[ ]*66 90\s*xchg ax,ax
[ ]*[a-f0-9]+:[ ]*66 90\s*xchg ax,ax
[ ]*[a-f0-9]+:[ ]*62 c1 ff 38 2a 20\s*vcvtsi2sd xmm4,xmm0,\[eax\]{bad}
#pass

View File

@ -7,8 +7,8 @@
Disassembly of section .text: Disassembly of section .text:
0+ <.text>: 0+ <.text>:
+[a-f0-9]+: 62 .byte 0x62 +[a-f0-9]+: 62 c3 8c 1d 66\s+\(bad\)
+[a-f0-9]+: c3 ret +[a-f0-9]+: 90\s+nop
+[a-f0-9]+: 8c 1d 66 90 66 90 mov %ds,0x90669066 +[a-f0-9]+: 66 90\s+xchg %ax,%ax
+[a-f0-9]+: 66 90 xchg %ax,%ax +[a-f0-9]+: 66 90\s+xchg %ax,%ax
#pass +[a-f0-9]+: 62 c1 ff 38 2a 20\s+vcvtsi2sd \(%eax\){bad},%xmm0,%xmm4

View File

@ -1,3 +1,5 @@
.text .text
# Invalid 16-bit broadcast with EVEX.W == 1. # Invalid 16-bit broadcast with EVEX.W == 1.
.byte 0x62, 0xc3, 0x8c, 0x1d, 0x66, 0x90, 0x66, 0x90, 0x66, 0x90 .byte 0x62, 0xc3, 0x8c, 0x1d, 0x66, 0x90, 0x66, 0x90, 0x66, 0x90
# Invalid vcvtsi2sd with EVEX.b == 1.
.byte 0x62,0xc1,0xff,0x38,0x2a,0x20

View File

@ -646,6 +646,7 @@ if [gas_32_check] then {
run_dump_test "dw2-compress-2" run_dump_test "dw2-compress-2"
run_dump_test "dw2-compressed-2" run_dump_test "dw2-compressed-2"
run_dump_test "bad-bcast-intel"
run_dump_test "bad-bcast" run_dump_test "bad-bcast"
run_dump_test "bad-size" run_dump_test "bad-size"

View File

@ -2422,6 +2422,7 @@ static struct
int zeroing; int zeroing;
int ll; int ll;
int b; int b;
int no_broadcast;
} }
vex; vex;
static unsigned char need_vex; static unsigned char need_vex;
@ -11059,23 +11060,25 @@ intel_operand_size (int bytemode, int sizeflag)
{ {
if (vex.b) if (vex.b)
{ {
switch (bytemode) if (!vex.no_broadcast)
{ switch (bytemode)
case x_mode: {
case evex_half_bcst_xmmq_mode: case x_mode:
if (vex.w) case evex_half_bcst_xmmq_mode:
oappend ("QWORD PTR "); if (vex.w)
else oappend ("QWORD PTR ");
oappend ("DWORD PTR "); else
break; oappend ("DWORD PTR ");
case xh_mode: break;
case evex_half_bcst_xmmqh_mode: case xh_mode:
case evex_half_bcst_xmmqdh_mode: case evex_half_bcst_xmmqh_mode:
oappend ("WORD PTR "); case evex_half_bcst_xmmqdh_mode:
break; oappend ("WORD PTR ");
default: break;
abort (); default:
} vex.no_broadcast = 1;
break;
}
return; return;
} }
switch (bytemode) switch (bytemode)
@ -11908,69 +11911,71 @@ OP_E_memory (int bytemode, int sizeflag)
if (vex.b) if (vex.b)
{ {
evex_used |= EVEX_b_used; evex_used |= EVEX_b_used;
if (bytemode == xh_mode) if (!vex.no_broadcast)
{ {
if (vex.w) if (bytemode == xh_mode)
{ {
oappend ("{bad}"); if (vex.w)
} oappend ("{bad}");
else else
{ {
switch (vex.length) switch (vex.length)
{ {
case 128: case 128:
oappend ("{1to8}"); oappend ("{1to8}");
break; break;
case 256: case 256:
oappend ("{1to16}"); oappend ("{1to16}");
break; break;
case 512: case 512:
oappend ("{1to32}"); oappend ("{1to32}");
break; break;
default: default:
abort ();
}
}
}
else if (vex.w
|| bytemode == evex_half_bcst_xmmqdh_mode
|| bytemode == evex_half_bcst_xmmq_mode)
{
switch (vex.length)
{
case 128:
oappend ("{1to2}");
break;
case 256:
oappend ("{1to4}");
break;
case 512:
oappend ("{1to8}");
break;
default:
abort (); abort ();
} }
}
}
else if (vex.w
|| bytemode == evex_half_bcst_xmmqdh_mode
|| bytemode == evex_half_bcst_xmmq_mode)
{
switch (vex.length)
{
case 128:
oappend ("{1to2}");
break;
case 256:
oappend ("{1to4}");
break;
case 512:
oappend ("{1to8}");
break;
default:
abort ();
} }
} else if (bytemode == x_mode
else if (bytemode == x_mode || bytemode == evex_half_bcst_xmmqh_mode)
|| bytemode == evex_half_bcst_xmmqh_mode)
{
switch (vex.length)
{ {
case 128: switch (vex.length)
oappend ("{1to4}"); {
break; case 128:
case 256: oappend ("{1to4}");
oappend ("{1to8}"); break;
break; case 256:
case 512: oappend ("{1to8}");
oappend ("{1to16}"); break;
break; case 512:
default: oappend ("{1to16}");
abort (); break;
default:
abort ();
}
} }
else
vex.no_broadcast = 1;
} }
else if (vex.no_broadcast)
/* If operand doesn't allow broadcast, vex.b should be 0. */
oappend ("{bad}"); oappend ("{bad}");
} }
} }
@ -12685,6 +12690,8 @@ OP_XMM (int bytemode, int sizeflag ATTRIBUTE_UNUSED)
if (bytemode == tmm_mode) if (bytemode == tmm_mode)
modrm.reg = reg; modrm.reg = reg;
else if (bytemode == scalar_mode)
vex.no_broadcast = 1;
print_vector_reg (reg, bytemode); print_vector_reg (reg, bytemode);
} }