mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-25 11:04:18 +08:00
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:
parent
8c8bd0babc
commit
8b65b8953a
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
1460
opcodes/i386-tbl.h
1460
opcodes/i386-tbl.h
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user