From: "H.J. Lu" <hjl.tools@gmail.com>
To: Jan Beulich <jbeulich@suse.com>
Cc: Binutils <binutils@sourceware.org>
Subject: Re: [PATCH v5 3/8] x86: re-work insn/suffix recognition
Date: Thu, 27 Oct 2022 10:21:07 -0700 [thread overview]
Message-ID: <CAMe9rOpz7cYqta86qCTVogfEk9sgFD_2OGAkN8v80ph7qdk+bw@mail.gmail.com> (raw)
In-Reply-To: <7250dab9-e218-e6dd-4c74-23da9f611ab4@suse.com>
On Tue, Oct 25, 2022 at 12:26 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> Having templates with a suffix explicitly present has always been
> quirky. Introduce a 2nd matching pass in case the 1st one couldn't find
> a suitable template _and_ didn't itself already need to trim off a
> suffix to find a match at all. This requires error reporting adjustments
> (albeit luckily fewer than I was afraid might be necessary), as errors
> previously reported during matching now need deferring until after the
> 2nd pass (because, obviously, we must not emit any error if the 2nd pass
> succeeds). While also related to PR gas/29524, it was requested that
> move-with-sign-extend be left as broken as it always was.
>
> PR gas/29525
> Note that with the dropped CMPSD and MOVSD Intel Syntax string insn
> templates taking operands, mixed IsString/non-IsString template groups
> (with memory operands) cannot occur anymore. With that
> maybe_adjust_templates() becomes unnecessary (and is hence being
> removed).
>
> PR gas/29526
> Note further that while the additions to the intel16 testcase aren't
> really proper Intel syntax, we've been permitting all of those except
> for the MOVD variant. The test therefore is to avoid re-introducing such
> an inconsistency.
> ---
> To limit code churn I'm using "goto" for the retry loop, but I'd be
> happy to make this a proper loop either right here or in a follow-on
> change doing just the necessary re-indentation.
>
> The "too many memory references" errors which are being deleted weren't
> fully consistent anyway - even the majority of IsString insns accepts
> only a single memory operand. If we wanted to retain that, it would need
> re-introducing in md_assemble(), latching the error into i.error just
> like match_template() does.
>
> Why is "MOVQ $imm64, %reg64" being optimized but "MOVABS $imm64, %reg64"
> is not?
> ---
> v5: Split off move-with-sign-extend changes.
> v4: Retain support for operand-less MOVSD and CMPSD.
> v3: Limit xstrdup() to just the templates where a 2nd pass actually
> makes sense (new Pass2 attribute).
>
> --- a/gas/config/tc-i386.c
> +++ b/gas/config/tc-i386.c
> @@ -297,9 +297,6 @@ struct _i386_insn
> explicit segment overrides are given. */
> const reg_entry *seg[2];
>
> - /* Copied first memory operand string, for re-checking. */
> - char *memop1_string;
> -
> /* PREFIX holds all the given prefix opcodes (usually null).
> PREFIXES is the number of prefix opcodes. */
> unsigned int prefixes;
> @@ -4272,7 +4269,20 @@ optimize_encoding (void)
> movq $imm31, %r64 -> movl $imm31, %r32
> movq $imm32, %r64 -> movl $imm32, %r32
> */
> - i.tm.opcode_modifier.norex64 = 1;
> + i.tm.opcode_modifier.size = SIZE32;
> + if (i.imm_operands)
> + {
> + i.types[0].bitfield.imm32 = 1;
> + i.types[0].bitfield.imm32s = 0;
> + i.types[0].bitfield.imm64 = 0;
> + }
> + else
> + {
> + i.types[0].bitfield.dword = 1;
> + i.types[0].bitfield.qword = 0;
> + }
> + i.types[1].bitfield.dword = 1;
> + i.types[1].bitfield.qword = 0;
> if (i.tm.base_opcode == 0xb8 || (i.tm.base_opcode | 1) == 0xc7)
> {
> /* Handle
> @@ -4282,11 +4292,6 @@ optimize_encoding (void)
> i.tm.operand_types[0].bitfield.imm32 = 1;
> i.tm.operand_types[0].bitfield.imm32s = 0;
> i.tm.operand_types[0].bitfield.imm64 = 0;
> - i.types[0].bitfield.imm32 = 1;
> - i.types[0].bitfield.imm32s = 0;
> - i.types[0].bitfield.imm64 = 0;
> - i.types[1].bitfield.dword = 1;
> - i.types[1].bitfield.qword = 0;
> if ((i.tm.base_opcode | 1) == 0xc7)
> {
> /* Handle
> @@ -4818,11 +4823,14 @@ void
> md_assemble (char *line)
> {
> unsigned int j;
> - char mnemonic[MAX_MNEM_SIZE], mnem_suffix;
> - const char *end;
> + char mnemonic[MAX_MNEM_SIZE], mnem_suffix, *copy = NULL;
> + const char *end, *pass1_mnem = NULL;
> + enum i386_error pass1_err = 0;
> const insn_template *t;
>
> /* Initialize globals. */
> + current_templates = NULL;
> + retry:
> memset (&i, '\0', sizeof (i));
> i.rounding.type = rc_none;
> for (j = 0; j < MAX_OPERANDS; j++)
> @@ -4837,16 +4845,26 @@ md_assemble (char *line)
>
> end = parse_insn (line, mnemonic);
> if (end == NULL)
> - return;
> + {
> + if (pass1_mnem != NULL)
> + goto match_error;
> + return;
> + }
> + if (current_templates->start->opcode_modifier.pass2)
> + {
> + /* Make a copy of the full line in case we need to retry. */
> + copy = xstrdup (line);
> + }
> line += end - line;
> mnem_suffix = i.suffix;
>
> line = parse_operands (line, mnemonic);
> this_operand = -1;
> - xfree (i.memop1_string);
> - i.memop1_string = NULL;
> if (line == NULL)
> - return;
> + {
> + free (copy);
> + return;
> + }
>
> /* Now we've parsed the mnemonic into a set of templates, and have the
> operands at hand. */
> @@ -4922,7 +4940,97 @@ md_assemble (char *line)
> with the template operand types. */
>
> if (!(t = match_template (mnem_suffix)))
> - return;
> + {
> + const char *err_msg;
> +
> + if (copy && !mnem_suffix)
> + {
> + line = copy;
> + copy = NULL;
> + pass1_err = i.error;
> + pass1_mnem = current_templates->start->name;
> + goto retry;
> + }
> + free (copy);
> + match_error:
> + switch (pass1_mnem ? pass1_err : i.error)
> + {
> + default:
> + abort ();
> + case operand_size_mismatch:
> + err_msg = _("operand size mismatch");
> + break;
> + case operand_type_mismatch:
> + err_msg = _("operand type mismatch");
> + break;
> + case register_type_mismatch:
> + err_msg = _("register type mismatch");
> + break;
> + case number_of_operands_mismatch:
> + err_msg = _("number of operands mismatch");
> + break;
> + case invalid_instruction_suffix:
> + err_msg = _("invalid instruction suffix");
> + break;
> + case bad_imm4:
> + err_msg = _("constant doesn't fit in 4 bits");
> + break;
> + case unsupported_with_intel_mnemonic:
> + err_msg = _("unsupported with Intel mnemonic");
> + break;
> + case unsupported_syntax:
> + err_msg = _("unsupported syntax");
> + break;
> + case unsupported:
> + as_bad (_("unsupported instruction `%s'"),
> + pass1_mnem ? pass1_mnem : current_templates->start->name);
> + return;
> + case invalid_sib_address:
> + err_msg = _("invalid SIB address");
> + break;
> + case invalid_vsib_address:
> + err_msg = _("invalid VSIB address");
> + break;
> + case invalid_vector_register_set:
> + err_msg = _("mask, index, and destination registers must be distinct");
> + break;
> + case invalid_tmm_register_set:
> + err_msg = _("all tmm registers must be distinct");
> + break;
> + case invalid_dest_and_src_register_set:
> + err_msg = _("destination and source registers must be distinct");
> + break;
> + case unsupported_vector_index_register:
> + err_msg = _("unsupported vector index register");
> + break;
> + case unsupported_broadcast:
> + err_msg = _("unsupported broadcast");
> + break;
> + case broadcast_needed:
> + err_msg = _("broadcast is needed for operand of such type");
> + break;
> + case unsupported_masking:
> + err_msg = _("unsupported masking");
> + break;
> + case mask_not_on_destination:
> + err_msg = _("mask not on destination operand");
> + break;
> + case no_default_mask:
> + err_msg = _("default mask isn't allowed");
> + break;
> + case unsupported_rc_sae:
> + err_msg = _("unsupported static rounding/sae");
> + break;
> + case invalid_register_operand:
> + err_msg = _("invalid register operand");
> + break;
> + }
> + as_bad (_("%s for `%s'"), err_msg,
> + pass1_mnem ? pass1_mnem : current_templates->start->name);
> + return;
> + }
> +
> + free (copy);
>
> if (sse_check != check_none
> /* The opcode space check isn't strictly needed; it's there only to
> @@ -5223,6 +5331,7 @@ parse_insn (const char *line, char *mnem
> {
> const char *l = line, *token_start = l;
> char *mnem_p;
> + bool pass1 = !current_templates;
> int supported;
> const insn_template *t;
> char *dot_p = NULL;
> @@ -5392,8 +5501,10 @@ parse_insn (const char *line, char *mnem
> current_templates = (const templates *) str_hash_find (op_hash, mnemonic);
> }
>
> - if (!current_templates)
> + if (!current_templates || !pass1)
> {
> + current_templates = NULL;
> +
> check_suffix:
> if (mnem_p > mnemonic)
> {
> @@ -5435,13 +5546,39 @@ parse_insn (const char *line, char *mnem
> current_templates
> = (const templates *) str_hash_find (op_hash, mnemonic);
> }
> + /* For compatibility reasons accept MOVSD and CMPSD without
> + operands even in AT&T mode. */
> + else if (*l == END_OF_INSN
> + || (is_space_char (*l) && l[1] == END_OF_INSN))
> + {
> + mnem_p[-1] = '\0';
> + current_templates
> + = (const templates *) str_hash_find (op_hash, mnemonic);
> + if (current_templates != NULL
> + /* MOVS or CMPS */
> + && (current_templates->start->base_opcode | 2) == 0xa6
> + && current_templates->start->opcode_modifier.opcodespace
> + == SPACE_BASE
> + && mnem_p[-2] == 's')
> + {
> + as_warn (_("found `%sd'; assuming `%sl' was meant"),
> + mnemonic, mnemonic);
> + i.suffix = LONG_MNEM_SUFFIX;
> + }
> + else
> + {
> + current_templates = NULL;
> + mnem_p[-1] = 'd';
> + }
> + }
> break;
> }
> }
>
> if (!current_templates)
> {
> - as_bad (_("no such instruction: `%s'"), token_start);
> + if (pass1)
> + as_bad (_("no such instruction: `%s'"), token_start);
> return NULL;
> }
> }
> @@ -6845,81 +6982,7 @@ match_template (char mnem_suffix)
> if (t == current_templates->end)
> {
> /* We found no match. */
> - const char *err_msg;
> - switch (specific_error)
> - {
> - default:
> - abort ();
> - case operand_size_mismatch:
> - err_msg = _("operand size mismatch");
> - break;
> - case operand_type_mismatch:
> - err_msg = _("operand type mismatch");
> - break;
> - case register_type_mismatch:
> - err_msg = _("register type mismatch");
> - break;
> - case number_of_operands_mismatch:
> - err_msg = _("number of operands mismatch");
> - break;
> - case invalid_instruction_suffix:
> - err_msg = _("invalid instruction suffix");
> - break;
> - case bad_imm4:
> - err_msg = _("constant doesn't fit in 4 bits");
> - break;
> - case unsupported_with_intel_mnemonic:
> - err_msg = _("unsupported with Intel mnemonic");
> - break;
> - case unsupported_syntax:
> - err_msg = _("unsupported syntax");
> - break;
> - case unsupported:
> - as_bad (_("unsupported instruction `%s'"),
> - current_templates->start->name);
> - return NULL;
> - case invalid_sib_address:
> - err_msg = _("invalid SIB address");
> - break;
> - case invalid_vsib_address:
> - err_msg = _("invalid VSIB address");
> - break;
> - case invalid_vector_register_set:
> - err_msg = _("mask, index, and destination registers must be distinct");
> - break;
> - case invalid_tmm_register_set:
> - err_msg = _("all tmm registers must be distinct");
> - break;
> - case invalid_dest_and_src_register_set:
> - err_msg = _("destination and source registers must be distinct");
> - break;
> - case unsupported_vector_index_register:
> - err_msg = _("unsupported vector index register");
> - break;
> - case unsupported_broadcast:
> - err_msg = _("unsupported broadcast");
> - break;
> - case broadcast_needed:
> - err_msg = _("broadcast is needed for operand of such type");
> - break;
> - case unsupported_masking:
> - err_msg = _("unsupported masking");
> - break;
> - case mask_not_on_destination:
> - err_msg = _("mask not on destination operand");
> - break;
> - case no_default_mask:
> - err_msg = _("default mask isn't allowed");
> - break;
> - case unsupported_rc_sae:
> - err_msg = _("unsupported static rounding/sae");
> - break;
> - case invalid_register_operand:
> - err_msg = _("invalid register operand");
> - break;
> - }
> - as_bad (_("%s for `%s'"), err_msg,
> - current_templates->start->name);
> + i.error = specific_error;
> return NULL;
> }
>
> @@ -11328,49 +11391,6 @@ RC_SAE_immediate (const char *imm_start)
> return 1;
> }
>
> -/* Only string instructions can have a second memory operand, so
> - reduce current_templates to just those if it contains any. */
> -static int
> -maybe_adjust_templates (void)
> -{
> - const insn_template *t;
> -
> - gas_assert (i.mem_operands == 1);
> -
> - for (t = current_templates->start; t < current_templates->end; ++t)
> - if (t->opcode_modifier.isstring)
> - break;
> -
> - if (t < current_templates->end)
> - {
> - static templates aux_templates;
> - bool recheck;
> -
> - aux_templates.start = t;
> - for (; t < current_templates->end; ++t)
> - if (!t->opcode_modifier.isstring)
> - break;
> - aux_templates.end = t;
> -
> - /* Determine whether to re-check the first memory operand. */
> - recheck = (aux_templates.start != current_templates->start
> - || t != current_templates->end);
> -
> - current_templates = &aux_templates;
> -
> - if (recheck)
> - {
> - i.mem_operands = 0;
> - if (i.memop1_string != NULL
> - && i386_index_check (i.memop1_string) == 0)
> - return 0;
> - i.mem_operands = 1;
> - }
> - }
> -
> - return 1;
> -}
> -
> static INLINE bool starts_memory_operand (char c)
> {
> return ISDIGIT (c)
> @@ -11521,17 +11541,6 @@ i386_att_operand (char *operand_string)
> char *displacement_string_end;
>
> do_memory_reference:
> - if (i.mem_operands == 1 && !maybe_adjust_templates ())
> - return 0;
> - if ((i.mem_operands == 1
> - && !current_templates->start->opcode_modifier.isstring)
> - || i.mem_operands == 2)
> - {
> - as_bad (_("too many memory references for `%s'"),
> - current_templates->start->name);
> - return 0;
> - }
> -
> /* Check for base index form. We detect the base index form by
> looking for an ')' at the end of the operand, searching
> for the '(' matching it, and finding a REGISTER_PREFIX or ','
> @@ -11738,8 +11747,6 @@ i386_att_operand (char *operand_string)
> if (i386_index_check (operand_string) == 0)
> return 0;
> i.flags[this_operand] |= Operand_Mem;
> - if (i.mem_operands == 0)
> - i.memop1_string = xstrdup (operand_string);
> i.mem_operands++;
> }
> else
> --- a/gas/config/tc-i386-intel.c
> +++ b/gas/config/tc-i386-intel.c
> @@ -993,10 +993,7 @@ i386_intel_operand (char *operand_string
> || intel_state.is_mem)
> {
> /* Memory operand. */
> - if (i.mem_operands == 1 && !maybe_adjust_templates ())
> - return 0;
> - if ((int) i.mem_operands
> - >= 2 - !current_templates->start->opcode_modifier.isstring)
> + if (i.mem_operands)
> {
> /* Handle
>
> @@ -1041,10 +1038,6 @@ i386_intel_operand (char *operand_string
> }
> }
> }
> -
> - as_bad (_("too many memory references for `%s'"),
> - current_templates->start->name);
> - return 0;
> }
>
> /* Swap base and index in 16-bit memory operands like
> @@ -1158,8 +1151,6 @@ i386_intel_operand (char *operand_string
> return 0;
>
> i.flags[this_operand] |= Operand_Mem;
> - if (i.mem_operands == 0)
> - i.memop1_string = xstrdup (operand_string);
> ++i.mem_operands;
> }
> else
> --- a/gas/testsuite/gas/i386/code16.d
> +++ b/gas/testsuite/gas/i386/code16.d
> @@ -1,5 +1,6 @@
> #objdump: -drw -mi8086
> #name: i386 with .code16
> +#warning_output: code16.e
>
> .*: +file format .*
>
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/code16.e
> @@ -0,0 +1,3 @@
> +.*: Assembler messages:
> +.*:3: Warning: .* `movsd'.*`movsl'.*
> +.*:4: Warning: .* `cmpsd'.*`cmpsl'.*
> --- a/gas/testsuite/gas/i386/code16.s
> +++ b/gas/testsuite/gas/i386/code16.s
> @@ -2,8 +2,8 @@
> .code16
> rep; movsd
> rep; cmpsd
> - rep movsd %ds:(%si),%es:(%di)
> - rep cmpsd %es:(%di),%ds:(%si)
> + rep movsl %ds:(%si),%es:(%di)
> + rep cmpsl %es:(%di),%ds:(%si)
>
> mov %cr2, %ecx
> mov %ecx, %cr2
> --- a/gas/testsuite/gas/i386/intel16.d
> +++ b/gas/testsuite/gas/i386/intel16.d
> @@ -20,4 +20,12 @@ Disassembly of section .text:
> 2c: 8d 02 [ ]*lea \(%bp,%si\),%ax
> 2e: 8d 01 [ ]*lea \(%bx,%di\),%ax
> 30: 8d 03 [ ]*lea \(%bp,%di\),%ax
> - ...
> +[ ]*[0-9a-f]+: 67 f7 13[ ]+notw[ ]+\(%ebx\)
> +[ ]*[0-9a-f]+: 66 f7 17[ ]+notl[ ]+\(%bx\)
> +[ ]*[0-9a-f]+: 67 0f 1f 03[ ]+nopw[ ]+\(%ebx\)
> +[ ]*[0-9a-f]+: 66 0f 1f 07[ ]+nopl[ ]+\(%bx\)
> +[ ]*[0-9a-f]+: 67 83 03 05[ ]+addw[ ]+\$0x5,\(%ebx\)
> +[ ]*[0-9a-f]+: 66 83 07 05[ ]+addl[ ]+\$0x5,\(%bx\)
> +[ ]*[0-9a-f]+: 67 c7 03 05 00[ ]+movw[ ]+\$0x5,\(%ebx\)
> +[ ]*[0-9a-f]+: 66 c7 07 05 00 00 00[ ]+movl[ ]+\$0x5,\(%bx\)
> +#pass
> --- a/gas/testsuite/gas/i386/intel16.s
> +++ b/gas/testsuite/gas/i386/intel16.s
> @@ -18,4 +18,14 @@
> lea ax, [di][bx]
> lea ax, [di][bp]
>
> - .p2align 4,0
> + notw [ebx]
> + notd [bx]
> +
> + nopw [ebx]
> + nopd [bx]
> +
> + addw [ebx], 5
> + addd [bx], 5
> +
> + movw [ebx], 5
> + movd [bx], 5
> --- a/opcodes/i386-opc.tbl
> +++ b/opcodes/i386-opc.tbl
> @@ -135,34 +135,27 @@
> mov, 0xa0, None, CpuNo64, D|W|No_sSuf|No_qSuf|No_ldSuf, { Disp16|Disp32|Unspecified|Byte|Word|Dword, Acc|Byte|Word|Dword }
> mov, 0xa0, None, Cpu64, D|W|No_sSuf|No_ldSuf, { Disp64|Unspecified|Byte|Word|Dword|Qword, Acc|Byte|Word|Dword|Qword }
> movabs, 0xa0, None, Cpu64, D|W|No_sSuf|No_ldSuf, { Disp64|Unspecified|Byte|Word|Dword|Qword, Acc|Byte|Word|Dword|Qword }
> -movq, 0xa1, None, Cpu64, D|Size64|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Disp64|Unspecified|Qword, Acc|Qword }
> mov, 0x88, None, 0, D|W|CheckRegSize|Modrm|No_sSuf|No_ldSuf|HLEPrefixRelease, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Byte|Word|Dword|Qword|Unspecified|BaseIndex }
> -movq, 0x89, None, Cpu64, D|Modrm|Size64|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|HLEPrefixRelease, { Reg64, Reg64|Unspecified|Qword|BaseIndex }
> // In the 64bit mode the short form mov immediate is redefined to have
> // 64bit value.
> mov, 0xb0, None, 0, W|No_sSuf|No_qSuf|No_ldSuf, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32 }
> mov, 0xc6, 0, 0, W|Modrm|No_sSuf|No_ldSuf|HLEPrefixRelease|Optimize, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Byte|Word|Dword|Qword|Unspecified|BaseIndex }
> -movq, 0xc7, 0, Cpu64, Modrm|Size64|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|HLEPrefixRelease|Optimize, { Imm32S, Reg64|Qword|Unspecified|BaseIndex }
> mov, 0xb8, None, Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_ldSuf|Optimize, { Imm64, Reg64 }
> movabs, 0xb8, None, Cpu64, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_ldSuf, { Imm64, Reg64 }
> -movq, 0xb8, None, Cpu64, Size64|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|Optimize, { Imm64, Reg64 }
> // The segment register moves accept WordReg so that a segment register
> // can be copied to a 32 bit register, and vice versa, without using a
> // size prefix. When moving to a 32 bit register, the upper 16 bits
> // are set to an implementation defined value (on the Pentium Pro, the
> // implementation defined value is zero).
> -mov, 0x8c, None, 0, RegMem|No_bSuf|No_sSuf|No_qSuf|No_ldSuf|NoRex64, { SReg, Reg16|Reg32|Reg64 }
> +mov, 0x8c, None, 0, RegMem|No_bSuf|No_sSuf|No_ldSuf|NoRex64, { SReg, Reg16|Reg32|Reg64 }
> mov, 0x8c, None, 0, D|Modrm|IgnoreSize|No_bSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { SReg, Word|Unspecified|BaseIndex }
> -movq, 0x8c, None, Cpu64, D|RegMem|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|NoRex64, { SReg, Reg64 }
> -mov, 0x8e, None, 0, Modrm|IgnoreSize|No_bSuf|No_sSuf|No_qSuf|No_ldSuf|NoRex64, { Reg16|Reg32|Reg64, SReg }
> +mov, 0x8e, None, 0, Modrm|IgnoreSize|No_bSuf|No_sSuf|No_ldSuf|NoRex64, { Reg16|Reg32|Reg64, SReg }
> // Move to/from control debug registers. In the 16 or 32bit modes
> // they are 32bit. In the 64bit mode they are 64bit.
> mov, 0xf20, None, Cpu386|CpuNo64, D|RegMem|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_ldSuf, { Control, Reg32 }
> mov, 0xf20, None, Cpu64, D|RegMem|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_ldSuf|NoRex64, { Control, Reg64 }
> -movq, 0xf20, None, Cpu64, D|RegMem|Size64|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|NoRex64, { Control, Reg64 }
> mov, 0xf21, None, Cpu386|CpuNo64, D|RegMem|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_ldSuf, { Debug, Reg32 }
> mov, 0xf21, None, Cpu64, D|RegMem|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_ldSuf|NoRex64, { Debug, Reg64 }
> -movq, 0xf21, None, Cpu64, D|RegMem|Size64|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|NoRex64, { Debug, Reg64 }
> mov, 0xf24, None, Cpu386|CpuNo64, D|RegMem|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_ldSuf, { Test, Reg32 }
>
> // Move after swapping the bytes
> @@ -492,9 +485,6 @@ set<cc>, 0xf9<cc:opc>, 0, Cpu386, Modrm|
> // String manipulation.
> cmps, 0xa6, None, 0, W|No_sSuf|No_ldSuf|IsString|RepPrefixOk, {}
> cmps, 0xa6, None, 0, W|No_sSuf|No_ldSuf|IsStringEsOp0|RepPrefixOk, { Byte|Word|Dword|Qword|Unspecified|BaseIndex, Byte|Word|Dword|Qword|Unspecified|BaseIndex }
> -// Intel mode string compare.
> -cmpsd, 0xa7, None, Cpu386, Size32|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsString|RepPrefixOk, {}
> -cmpsd, 0xa7, None, Cpu386, Size32|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsStringEsOp0|RepPrefixOk, { Dword|Unspecified|BaseIndex, Dword|Unspecified|BaseIndex }
> scmp, 0xa6, None, 0, W|No_sSuf|No_ldSuf|IsString|RepPrefixOk, {}
> scmp, 0xa6, None, 0, W|No_sSuf|No_ldSuf|IsStringEsOp0|RepPrefixOk, { Byte|Word|Dword|Qword|Unspecified|BaseIndex, Byte|Word|Dword|Qword|Unspecified|BaseIndex }
> ins, 0x6c, None, Cpu186, W|No_sSuf|No_qSuf|No_ldSuf|IsString|RepPrefixOk, {}
> @@ -509,9 +499,6 @@ slod, 0xac, None, 0, W|No_sSuf|No_ldSuf|
> slod, 0xac, None, 0, W|No_sSuf|No_ldSuf|IsString|RepPrefixOk, { Byte|Word|Dword|Qword|Unspecified|BaseIndex, Acc|Byte|Word|Dword|Qword }
> movs, 0xa4, None, 0, W|No_sSuf|No_ldSuf|IsString|RepPrefixOk, {}
> movs, 0xa4, None, 0, W|No_sSuf|No_ldSuf|IsStringEsOp1|RepPrefixOk, { Byte|Word|Dword|Qword|Unspecified|BaseIndex, Byte|Word|Dword|Qword|Unspecified|BaseIndex }
> -// Intel mode string move.
> -movsd, 0xa5, None, Cpu386, Size32|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsString|RepPrefixOk, {}
> -movsd, 0xa5, None, Cpu386, Size32|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsStringEsOp1|RepPrefixOk, { Dword|Unspecified|BaseIndex, Dword|Unspecified|BaseIndex }
> smov, 0xa4, None, 0, W|No_sSuf|No_ldSuf|IsString|RepPrefixOk, {}
> smov, 0xa4, None, 0, W|No_sSuf|No_ldSuf|IsStringEsOp1|RepPrefixOk, { Byte|Word|Dword|Qword|Unspecified|BaseIndex, Byte|Word|Dword|Qword|Unspecified|BaseIndex }
> scas, 0xae, None, 0, W|No_sSuf|No_ldSuf|IsString|RepPrefixOk, {}
> @@ -989,13 +976,13 @@ emms, 0xf77, None, CpuMMX, No_bSuf|No_wS
> // copying between Reg64/Mem64 and RegXMM/RegMMX, as is mandated by Intel's
> // spec). AMD's spec, having been in existence for much longer, failed to
> // recognize that and specified movd for 32- and 64-bit operations.
> -movd, 0x666e, None, CpuAVX, D|Modrm|Vex128|Space0F|VexW0|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX, { Reg32|Unspecified|BaseIndex, RegXMM }
> +movd, 0x666e, None, CpuAVX, D|Modrm|Vex128|Space0F|VexW0|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX|Pass2, { Reg32|Unspecified|BaseIndex, RegXMM }
> movd, 0x666e, None, CpuAVX|Cpu64, D|Modrm|Vex=1|Space0F|VexW1|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|Size64|SSE2AVX, { Reg64|BaseIndex, RegXMM }
> movd, 0x660f6e, None, CpuSSE2, D|Modrm|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg32|Unspecified|BaseIndex, RegXMM }
> movd, 0x660f6e, None, CpuSSE2|Cpu64, D|Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|Size64, { Reg64|BaseIndex, RegXMM }
> movd, 0xf6e, None, CpuMMX, D|Modrm|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg32|Unspecified|BaseIndex, RegMMX }
> movd, 0xf6e, None, CpuMMX|Cpu64, D|Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|Size64, { Reg64|BaseIndex, RegMMX }
> -movq, 0xf37e, None, CpuAVX, Load|Modrm|Vex=1|Space0F|VexWIG|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX, { Qword|Unspecified|BaseIndex|RegXMM, RegXMM }
> +movq, 0xf37e, None, CpuAVX, Load|Modrm|Vex=1|Space0F|VexWIG|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX|Pass2, { Qword|Unspecified|BaseIndex|RegXMM, RegXMM }
> movq, 0x66d6, None, CpuAVX, Modrm|Vex=1|Space0F|VexWIG|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX, { RegXMM, Qword|Unspecified|BaseIndex|RegXMM }
> movq, 0x666e, None, CpuAVX|Cpu64, D|Modrm|Vex=1|Space0F|VexW1|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|Size64|SSE2AVX, { Reg64|Unspecified|BaseIndex, RegXMM }
> movq, 0xf30f7e, None, CpuSSE2, Load|Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Unspecified|Qword|BaseIndex|RegXMM, RegXMM }
> @@ -1159,7 +1146,7 @@ andpd<sse2>, 0x660f54, None, <sse2:cpu>,
> cmp<frel>pd<sse2>, 0x660fc2, <frel:imm>, <sse2:cpu>, Modrm|<sse2:attr>|<sse2:vvvv>|<frel:comm>|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { RegXMM|Unspecified|BaseIndex, RegXMM }
> cmp<frel>sd<sse2>, 0xf20fc2, <frel:imm>, <sse2:cpu>, Modrm|<sse2:scal>|<sse2:vvvv>|<frel:comm>|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { RegXMM|Qword|Unspecified|BaseIndex, RegXMM }
> cmppd<sse2>, 0x660fc2, None, <sse2:cpu>, Modrm|<sse2:attr>|<sse2:vvvv>|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Imm8, RegXMM|Unspecified|BaseIndex, RegXMM }
> -cmpsd<sse2>, 0xf20fc2, None, <sse2:cpu>, Modrm|<sse2:scal>|<sse2:vvvv>|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Imm8, Qword|Unspecified|BaseIndex|RegXMM, RegXMM }
> +cmpsd<sse2>, 0xf20fc2, None, <sse2:cpu>, Modrm|<sse2:scal>|<sse2:vvvv>|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|Pass2, { Imm8, Qword|Unspecified|BaseIndex|RegXMM, RegXMM }
> comisd<sse2>, 0x660f2f, None, <sse2:cpu>, Modrm|<sse2:scal>|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Qword|Unspecified|BaseIndex|RegXMM, RegXMM }
> cvtpi2pd, 0x660f2a, None, CpuSSE2, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegMMX, RegXMM }
> cvtpi2pd, 0xf3e6, None, CpuAVX, Modrm|Vex|Space0F|VexW0|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX, { Qword|Unspecified|BaseIndex, RegXMM }
> @@ -1184,7 +1171,7 @@ movlpd, 0x6613, None, CpuAVX, Modrm|Vex|
> movlpd, 0x660f12, None, CpuSSE2, D|Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Qword|Unspecified|BaseIndex, RegXMM }
> movmskpd<sse2>, 0x660f50, None, <sse2:cpu>, Modrm|<sse2:attr>|IgnoreSize|No_bSuf|No_wSuf|No_sSuf|No_ldSuf|NoRex64, { RegXMM, Reg32|Reg64 }
> movntpd<sse2>, 0x660f2b, None, <sse2:cpu>, Modrm|<sse2:attr>|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegXMM, Xmmword|Unspecified|BaseIndex }
> -movsd, 0xf210, None, CpuAVX, D|Modrm|VexLIG|Space0F|VexW0|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX, { Qword|Unspecified|BaseIndex, RegXMM }
> +movsd, 0xf210, None, CpuAVX, D|Modrm|VexLIG|Space0F|VexW0|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX|Pass2, { Qword|Unspecified|BaseIndex, RegXMM }
> movsd, 0xf210, None, CpuAVX, D|Modrm|Vex=3|Space0F|VexVVVV=1|VexW=1|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX, { RegXMM, RegXMM }
> movsd, 0xf20f10, None, CpuSSE2, D|Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Qword|Unspecified|BaseIndex|RegXMM, RegXMM }
> movupd<sse2>, 0x660f10, None, <sse2:cpu>, D|Modrm|<sse2:attr>|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegXMM|Unspecified|BaseIndex, RegXMM }
>
All these instructions with Pass2 have a vector register operand. Can you
use it instead?
--
H.J.
next prev parent reply other threads:[~2022-10-27 17:21 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-25 7:23 [PATCH v5 0/8] x86: suffix handling changes Jan Beulich
2022-10-25 7:24 ` [PATCH v5 1/8] x86: constify parse_insn()'s input Jan Beulich
2022-10-25 7:25 ` [PATCH v5 1/8] x86: introduce Pass2 insn attribute Jan Beulich
2022-10-25 7:30 ` [PATCH v5 2/8] " Jan Beulich
2022-10-25 7:26 ` [PATCH v5 3/8] x86: re-work insn/suffix recognition Jan Beulich
2022-10-27 17:21 ` H.J. Lu [this message]
2022-10-28 9:00 ` Jan Beulich
2022-10-28 16:12 ` H.J. Lu
2022-10-31 11:40 ` Jan Beulich
2022-10-31 16:59 ` H.J. Lu
2022-10-25 7:26 ` [PATCH v5 4/8] ix86: don't recognize/derive Q suffix in the common case Jan Beulich
2022-10-25 7:27 ` [PATCH v5 5/8] x86-64: allow HLE store of accumulator to absolute 32-bit address Jan Beulich
2022-10-25 7:27 ` [PATCH v5 6/8] x86: move bad-use-of-TLS-reloc check Jan Beulich
2022-10-25 7:28 ` [PATCH v5 7/8] x86: drop (now) stray IsString Jan Beulich
2022-10-25 7:29 ` [PATCH v5 8/8] x86: further re-work insn/suffix recognition to also cover MOVSX Jan Beulich
2022-10-25 17:10 ` H.J. Lu
2022-10-26 9:07 ` Jan Beulich
2022-10-27 0:11 ` H.J. Lu
2022-10-27 6:31 ` Jan Beulich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAMe9rOpz7cYqta86qCTVogfEk9sgFD_2OGAkN8v80ph7qdk+bw@mail.gmail.com \
--to=hjl.tools@gmail.com \
--cc=binutils@sourceware.org \
--cc=jbeulich@suse.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).