diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2020-10-14 04:17:54 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2020-10-14 04:20:55 -0700 |
commit | 8b65b8953af2d49ae1d2d7fcc5b49c5308febbc1 (patch) | |
tree | 6787d9d057850f28f7fd940774843b80871ab90b /gas | |
parent | 8c8bd0babc6039a4cef7d60d57b1b68e7a7f2e70 (diff) | |
download | fsf-binutils-gdb-8b65b8953af2d49ae1d2d7fcc5b49c5308febbc1.zip fsf-binutils-gdb-8b65b8953af2d49ae1d2d7fcc5b49c5308febbc1.tar.gz fsf-binutils-gdb-8b65b8953af2d49ae1d2d7fcc5b49c5308febbc1.tar.bz2 |
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.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 10 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 43 |
2 files changed, 29 insertions, 24 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 76b65df..ae54f17 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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 diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index b1e8f7c..80b96d0 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -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: |