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>
|
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
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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
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