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> 2020-10-13 H.J. Lu <hongjiu.lu@intel.com>
* config/tc-i386.c (build_vex_prefix): Replace vexopcode with * config/tc-i386.c (build_vex_prefix): Replace vexopcode with

View File

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

View File

@ -1161,11 +1161,12 @@ adjust_broadcast_modifier (char **opnd)
return bcst_type; return bcst_type;
} }
static void static int
process_i386_opcode_modifier (FILE *table, char *mod, char **opnd, int lineno) process_i386_opcode_modifier (FILE *table, char *mod, char **opnd, int lineno)
{ {
char *str, *next, *last; char *str, *next, *last;
bitfield modifiers [ARRAY_SIZE (opcode_modifiers)]; bitfield modifiers [ARRAY_SIZE (opcode_modifiers)];
unsigned int regular_encoding = 1;
active_isstring = 0; active_isstring = 0;
@ -1184,9 +1185,22 @@ process_i386_opcode_modifier (FILE *table, char *mod, char **opnd, int lineno)
{ {
int val = 1; int val = 1;
if (strcasecmp(str, "Broadcast") == 0) if (strcasecmp(str, "Broadcast") == 0)
{
val = adjust_broadcast_modifier (opnd); 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), set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers),
lineno); lineno);
if (strcasecmp(str, "IsString") == 0) if (strcasecmp(str, "IsString") == 0)
active_isstring = 1; active_isstring = 1;
@ -1215,6 +1229,8 @@ process_i386_opcode_modifier (FILE *table, char *mod, char **opnd, int lineno)
filename, lineno); filename, lineno);
} }
output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers)); output_opcode_modifier (table, modifiers, ARRAY_SIZE (modifiers));
return regular_encoding;
} }
enum stage { 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_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, " { "); fprintf (table, " { ");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff