x86: Remove the prefix byte from non-VEX/EVEX base_opcode

Replace the prefix byte in non-VEX/EVEX base_opcode with PREFIX_0X66,
PREFIX_0XF2 or PREFIX_0XF3.

gas/

	* config/tc-i386.c (load_insn_p): Check opcodeprefix == 0 for
	base_opcode == 0xfc7.
	(match_template): Likewise.
	(process_suffix): Check opcodeprefix == PREFIX_0XF2 for CRC32.
	(check_byte_reg): Likewise.
	(output_insn): Don't add the 0xf3 prefix twice for PadLock
	instructions.  Don't add prefix from non-VEX/EVEX base_opcode.

opcodes/

	* i386-gen.c (process_i386_opcode_modifier): Return 1 for
	non-VEX/EVEX/prefix encoding.
	(output_i386_opcode): Fail if non-VEX/EVEX/prefix base_opcode
	has a prefix byte.
	* i386-opc.tbl: Replace the prefix byte in non-VEX/EVEX
	base_opcode with PREFIX_0X66, PREFIX_0XF2 or PREFIX_0XF3.
	* i386-tbl.h: Regenerated.
This commit is contained in:
H.J. Lu 2020-10-14 04:17:54 -07:00
parent 8c8bd0babc
commit 8b65b8953a
6 changed files with 1165 additions and 1101 deletions

View File

@ -1,3 +1,13 @@
2020-10-14 H.J. Lu <hongjiu.lu@intel.com>
* config/tc-i386.c (load_insn_p): Check opcodeprefix == 0 for
base_opcode == 0xfc7.
(match_template): Likewise.
(process_suffix): Check opcodeprefix == PREFIX_0XF2 for CRC32.
(check_byte_reg): Likewise.
(output_insn): Don't add the 0xf3 prefix twice for PadLock
instructions. Don't add prefix from non-VEX/EVEX base_opcode.
2020-10-13 H.J. Lu <hongjiu.lu@intel.com>
* config/tc-i386.c (build_vex_prefix): Replace vexopcode with

View File

@ -4434,6 +4434,7 @@ load_insn_p (void)
/* cmpxchg8b, cmpxchg16b, xrstors. */
if (i.tm.base_opcode == 0xfc7
&& i.tm.opcode_modifier.opcodeprefix == 0
&& (i.tm.extension_opcode == 1 || i.tm.extension_opcode == 3))
return 1;
@ -4453,6 +4454,7 @@ load_insn_p (void)
/* vmptrld */
if (i.tm.base_opcode == 0xfc7
&& i.tm.opcode_modifier.opcodeprefix == 0
&& i.tm.extension_opcode == 6)
return 1;
@ -6313,8 +6315,9 @@ match_template (char mnem_suffix)
j = i.imm_operands + (t->operands > i.imm_operands + 1);
if (((i.suffix == QWORD_MNEM_SUFFIX
&& flag_code != CODE_64BIT
&& (t->base_opcode != 0x0fc7
|| t->extension_opcode != 1 /* cmpxchg8b */))
&& !(t->base_opcode == 0xfc7
&& i.tm.opcode_modifier.opcodeprefix == 0
&& t->extension_opcode == 1) /* cmpxchg8b */)
|| (i.suffix == LONG_MNEM_SUFFIX
&& !cpu_arch_flags.bitfield.cpui386))
&& (intel_syntax
@ -6759,6 +6762,8 @@ check_string (void)
static int
process_suffix (void)
{
bfd_boolean is_crc32 = FALSE;
/* If matched instruction specifies an explicit instruction mnemonic
suffix, use it. */
if (i.tm.opcode_modifier.size == SIZE16)
@ -6772,6 +6777,9 @@ process_suffix (void)
&& !i.tm.opcode_modifier.addrprefixopreg)
{
unsigned int numop = i.operands;
/* CRC32 */
is_crc32 = (i.tm.base_opcode == 0xf38f0
&& i.tm.opcode_modifier.opcodeprefix == PREFIX_0XF2);
/* movsx/movzx want only their source operand considered here, for the
ambiguity checking below. The suffix will be replaced afterwards
@ -6781,8 +6789,7 @@ process_suffix (void)
--i.operands;
/* crc32 needs REX.W set regardless of suffix / source operand size. */
if (i.tm.base_opcode == 0xf20f38f0
&& i.tm.operand_types[1].bitfield.qword)
if (is_crc32 && i.tm.operand_types[1].bitfield.qword)
i.rex |= REX_W;
/* If there's no instruction mnemonic suffix we try to invent one
@ -6793,7 +6800,7 @@ process_suffix (void)
Destination register type is more significant than source
register type. crc32 in SSE4.2 prefers source register
type. */
unsigned int op = i.tm.base_opcode != 0xf20f38f0 ? i.operands : 1;
unsigned int op = is_crc32 ? 1 : i.operands;
while (op--)
if (i.tm.operand_types[op].bitfield.instance == InstanceNone
@ -7143,7 +7150,7 @@ process_suffix (void)
|| i.tm.operand_types[0].bitfield.instance == RegD
|| i.tm.operand_types[1].bitfield.instance == RegD
/* CRC32 */
|| i.tm.base_opcode == 0xf20f38f0))))
|| is_crc32))))
i.tm.base_opcode |= 1;
break;
}
@ -7257,7 +7264,9 @@ check_byte_reg (void)
continue;
/* crc32 only wants its source operand checked here. */
if (i.tm.base_opcode == 0xf20f38f0 && op)
if (i.tm.base_opcode == 0xf38f0
&& i.tm.opcode_modifier.opcodeprefix == PREFIX_0XF2
&& op != 0)
continue;
/* Any other register is bad. */
@ -9302,7 +9311,6 @@ output_insn (void)
char *p;
unsigned char *q;
unsigned int j;
unsigned int prefix;
enum mf_cmp_kind mf_cmp;
if (avoid_fence
@ -9382,28 +9390,15 @@ output_insn (void)
add_prefix (0xf2);
break;
case PREFIX_0XF3:
add_prefix (0xf3);
if (!i.tm.cpu_flags.bitfield.cpupadlock
|| (i.prefix[REP_PREFIX] != 0xf3))
add_prefix (0xf3);
break;
case PREFIX_NONE:
switch (i.tm.opcode_length)
{
case 3:
if (i.tm.base_opcode & 0xff000000)
{
prefix = (i.tm.base_opcode >> 24) & 0xff;
if (!i.tm.cpu_flags.bitfield.cpupadlock
|| prefix != REPE_PREFIX_OPCODE
|| (i.prefix[REP_PREFIX] != REPE_PREFIX_OPCODE))
add_prefix (prefix);
}
break;
case 2:
if ((i.tm.base_opcode & 0xff0000) != 0)
{
prefix = (i.tm.base_opcode >> 16) & 0xff;
add_prefix (prefix);
}
break;
case 1:
break;
case 0:

View File

@ -1,3 +1,13 @@
2020-10-14 H.J. Lu <hongjiu.lu@intel.com>
* i386-gen.c (process_i386_opcode_modifier): Return 1 for
non-VEX/EVEX/prefix encoding.
(output_i386_opcode): Fail if non-VEX/EVEX/prefix base_opcode
has a prefix byte.
* i386-opc.tbl: Replace the prefix byte in non-VEX/EVEX
base_opcode with PREFIX_0X66, PREFIX_0XF2 or PREFIX_0XF3.
* i386-tbl.h: Regenerated.
2020-10-13 H.J. Lu <hongjiu.lu@intel.com>
* i386-gen.c (opcode_modifiers): Replace VexOpcode with

View File

@ -1161,11 +1161,12 @@ adjust_broadcast_modifier (char **opnd)
return bcst_type;
}
static void
static int
process_i386_opcode_modifier (FILE *table, char *mod, char **opnd, int lineno)
{
char *str, *next, *last;
bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
unsigned int regular_encoding = 1;
active_isstring = 0;
@ -1184,9 +1185,22 @@ process_i386_opcode_modifier (FILE *table, char *mod, char **opnd, int lineno)
{
int val = 1;
if (strcasecmp(str, "Broadcast") == 0)
{
val = adjust_broadcast_modifier (opnd);
regular_encoding = 0;
}
else if (strcasecmp(str, "Vex") == 0
|| strncasecmp(str, "Vex=", 4) == 0
|| strcasecmp(str, "EVex") == 0
|| strncasecmp(str, "EVex=", 5) == 0
|| strncasecmp(str, "Disp8MemShift=", 14) == 0
|| strncasecmp(str, "Masking=", 8) == 0
|| strcasecmp(str, "SAE") == 0
|| strcasecmp(str, "IsPrefix") == 0)
regular_encoding = 0;
set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
lineno);
lineno);
if (strcasecmp(str, "IsString") == 0)
active_isstring = 1;
@ -1215,6 +1229,8 @@ process_i386_opcode_modifier (FILE *table, char *mod, char **opnd, int lineno)
filename, lineno);
}
output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
return regular_encoding;
}
enum stage {
@ -1396,7 +1412,40 @@ output_i386_opcode (FILE *table, const char *name, char *str,
process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno);
process_i386_opcode_modifier (table, opcode_modifier, operand_types, lineno);
if (process_i386_opcode_modifier (table, opcode_modifier,
operand_types, lineno))
{
char *end;
unsigned long int length = strtoul (opcode_length, &end, 0);
unsigned long int opcode = strtoul (base_opcode, &end, 0);
switch (length)
{
case 3:
if ((opcode >> 24) != 0)
fail (_("%s: %s: (base_opcode >> 24) != 0: %s\n"),
filename, name, base_opcode);
break;
case 2:
if ((opcode >> 16) != 0)
fail (_("%s: %s: (base_opcode >> 16) != 0: %s\n"),
filename, name, base_opcode);
break;
case 1:
if ((opcode >> 8) != 0)
fail (_("%s: %s: (base_opcode >> 8) != 0: %s\n"),
filename, name, base_opcode);
break;
case 0:
if (opcode != 0)
fail (_("%s: %s: base_opcode != 0: %s\n"),
filename, name, base_opcode);
break;
default:
fail (_("%s: %s: invalid opcode length: %s\n"),
filename, name, opcode_length);
break;
}
}
fprintf (table, " { ");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff