From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-qt1-x82a.google.com (mail-qt1-x82a.google.com [IPv6:2607:f8b0:4864:20::82a]) by sourceware.org (Postfix) with ESMTPS id 94EDF3858D1E for ; Wed, 17 Aug 2022 20:29:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 94EDF3858D1E Received: by mail-qt1-x82a.google.com with SMTP id s11so11266201qtx.6 for ; Wed, 17 Aug 2022 13:29:49 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc; bh=uTI6LReNL0J80yNUOcKhGD1TLA3VlYzhaf3lvAojvUs=; b=qQAr/nm0Q8wHQEkCoX09aGmn6c3PLMCOfId7A67a8dOqIu6mEgnc8nLved4ku9SQNM PGwlw3Tk/RcXzHK72/y1MX6JiEwmmrBqAdSnQU1ajbY629vagdHA+GZ2OaLinugArT7I QaSC8XQ7dC7jIFWheyNShpBXdtB95mkq/fyCCtg4X3B8IPut6b3Uz17JZsa0maNT8Ytk 21R/AriyfXjwn/E/4asGg2TQzwIO2T9mhTDT5z1R31dfBwUEuy5Hmq+ZFFjlmvz6Q+yB vg7GIsOvtIyjT975OAXJ3iWh6GAHV0r4jffVn+8fbZfTCIdPbCJ/YqOXr0tVSbJM2nQb saqQ== X-Gm-Message-State: ACgBeo3yAjAEyL7u9/UiOjsrOF17BErcS4qUoiJzGOroiu1xBrrgiGoo 90ppLanvU2GzUPjLTEUjf7bOehLDSxyjIcJxJYjWm8a9 X-Google-Smtp-Source: AA6agR4Q+ngeB5tBT18+j8lXEKWEbikLuBxVlLINFGUxvlee+m8Ep3cLJwFX3tP8Bp3a4TNZPGHDNqs7BV3iQJO2C9g= X-Received: by 2002:a05:622a:1989:b0:344:52ff:66e6 with SMTP id u9-20020a05622a198900b0034452ff66e6mr18672272qtc.76.1660768188602; Wed, 17 Aug 2022 13:29:48 -0700 (PDT) MIME-Version: 1.0 References: <32216291-fd1f-4579-87de-d24cb7190894@suse.com> In-Reply-To: From: "H.J. Lu" Date: Wed, 17 Aug 2022 13:29:12 -0700 Message-ID: Subject: Re: [PATCH 5/7] x86: re-work insn/suffix recognition To: Jan Beulich Cc: Binutils Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-3018.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 17 Aug 2022 20:29:53 -0000 On Tue, Aug 16, 2022 at 12:32 AM Jan Beulich wrote: > > x86: re-work insn/suffix recognition > > Having templates with a suffix explicitly present has always been > quirky. Introduce a 2nd matching pass in case the 1st one couldn't find I don't like the second pass. What problem does it solve? > 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). > > Note that with the dropped CMPSD and MOVSD Intel Syntax string insn > templates, mixed IsString/non-IsString template groups cannot occur > anymore. With that maybe_adjust_templates() becomes unnecessary (and is > hence being removed). > > 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 want 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? > > --- 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; > @@ -4273,7 +4270,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 > @@ -4283,11 +4293,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 > @@ -4819,10 +4824,17 @@ void > md_assemble (char *line) > { > unsigned int j; > - char mnemonic[MAX_MNEM_SIZE], mnem_suffix; > + char mnemonic[MAX_MNEM_SIZE], mnem_suffix, *copy; > + const char *pass1_mnem = NULL; > + enum i386_error pass1_err = 0; > const insn_template *t; > > + /* Make a copy of the full line in case we need to retry. */ > + copy = xstrdup (line); > + > /* Initialize globals. */ > + current_templates = NULL; > + retry: > memset (&i, '\0', sizeof (i)); > i.rounding.type = rc_none; > for (j = 0; j < MAX_OPERANDS; j++) > @@ -4837,15 +4849,21 @@ md_assemble (char *line) > > line = parse_insn (line, mnemonic); > if (line == NULL) > - return; > + { > + if (!copy) > + goto match_error; > + free (copy); > + return; > + } > 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. */ > @@ -4921,7 +4939,97 @@ md_assemble (char *line) > with the template operand types. */ > > if (!(t = match_template (mnem_suffix))) > - return; > + { > + const char *err_msg; > + > + if (!mnem_suffix) > + { > + pass1_err = i.error; > + pass1_mnem = current_templates->start->name; > + line = copy; > + copy = NULL; > + 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 (char *line, char *mnemonic) > char *l = line; > char *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 (char *line, char *mnemonic) > 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) > { > @@ -5441,7 +5552,8 @@ parse_insn (char *line, char *mnemonic) > > if (!current_templates) > { > - as_bad (_("no such instruction: `%s'"), token_start); > + if (pass1) > + as_bad (_("no such instruction: `%s'"), token_start); > return NULL; > } > } > @@ -6851,81 +6963,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; > } > > @@ -11334,49 +11372,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) > @@ -11527,17 +11522,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 ',' > @@ -11737,8 +11721,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.s > +++ b/gas/testsuite/gas/i386/code16.s > @@ -1,9 +1,9 @@ > .text > .code16 > - rep; movsd > - rep; cmpsd > - rep movsd %ds:(%si),%es:(%di) > - rep cmpsd %es:(%di),%ds:(%si) > + rep; movsl > + rep; cmpsl > + rep movsl %ds:(%si),%es:(%di) > + rep cmpsl %es:(%di),%ds:(%si) > > mov %cr2, %ecx > mov %ecx, %cr2 > --- a/gas/testsuite/gas/i386/i386.exp > +++ b/gas/testsuite/gas/i386/i386.exp > @@ -73,6 +73,7 @@ if [gas_32_check] then { > run_dump_test "amd" > run_dump_test "katmai" > run_dump_test "jump" > + run_dump_test "movs32" > run_dump_test "movz32" > run_dump_test "relax-1" > run_dump_test "relax-2" > @@ -806,6 +807,7 @@ if [gas_64_check] then { > run_dump_test "x86-64-segovr" > run_list_test "x86-64-inval-seg" "-al" > run_dump_test "x86-64-branch" > + run_dump_test "movs64" > run_dump_test "movz64" > run_dump_test "x86-64-relax-1" > run_dump_test "svme64" > --- 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 > --- /dev/null > +++ b/gas/testsuite/gas/i386/movs.s > @@ -0,0 +1,33 @@ > + .text > +movs: > + movsb %al,%ax > + movsb (%eax),%ax > + movsb %al,%eax > + movsb (%eax),%eax > +.ifdef x86_64 > + movsb %al,%rax > + movsb (%rax),%rax > +.endif > + > + movsbw %al,%ax > + movsbw (%eax),%ax > + movsbl %al,%eax > + movsbl (%eax),%eax > +.ifdef x86_64 > + movsbq %al,%rax > + movsbq (%rax),%rax > +.endif > + > + movsw %ax,%eax > + movsw (%eax),%eax > +.ifdef x86_64 > + movsw %ax,%rax > + movsw (%rax),%rax > +.endif > + > + movswl %ax,%eax > + movswl (%eax),%eax > +.ifdef x86_64 > + movswq %ax,%rax > + movswq (%rax),%rax > +.endif > --- /dev/null > +++ b/gas/testsuite/gas/i386/movs32.d > @@ -0,0 +1,22 @@ > +#objdump: -dw > +#source: movs.s > +#name: x86 mov with sign-extend (32-bit object) > + > +.*: +file format .* > + > +Disassembly of section .text: > + > +0+ : > +[ ]*[a-f0-9]+: 66 0f be c0 * movsbw %al,%ax > +[ ]*[a-f0-9]+: 66 0f be 00 * movsbw \(%eax\),%ax > +[ ]*[a-f0-9]+: 0f be c0 * movsbl %al,%eax > +[ ]*[a-f0-9]+: 0f be 00 * movsbl \(%eax\),%eax > +[ ]*[a-f0-9]+: 66 0f be c0 * movsbw %al,%ax > +[ ]*[a-f0-9]+: 66 0f be 00 * movsbw \(%eax\),%ax > +[ ]*[a-f0-9]+: 0f be c0 * movsbl %al,%eax > +[ ]*[a-f0-9]+: 0f be 00 * movsbl \(%eax\),%eax > +[ ]*[a-f0-9]+: 0f bf c0 * movswl %ax,%eax > +[ ]*[a-f0-9]+: 0f bf 00 * movswl \(%eax\),%eax > +[ ]*[a-f0-9]+: 0f bf c0 * movswl %ax,%eax > +[ ]*[a-f0-9]+: 0f bf 00 * movswl \(%eax\),%eax > +#pass > --- /dev/null > +++ b/gas/testsuite/gas/i386/movs64.d > @@ -0,0 +1,30 @@ > +#objdump: -dw > +#source: movs.s > +#name: x86 mov with sign-extend (64-bit object) > + > +.*: +file format .* > + > +Disassembly of section .text: > + > +0+ : > +[ ]*[a-f0-9]+: 66 0f be c0 * movsbw %al,%ax > +[ ]*[a-f0-9]+: 67 66 0f be 00 * movsbw \(%eax\),%ax > +[ ]*[a-f0-9]+: 0f be c0 * movsbl %al,%eax > +[ ]*[a-f0-9]+: 67 0f be 00 * movsbl \(%eax\),%eax > +[ ]*[a-f0-9]+: 48 0f be c0 * movsbq %al,%rax > +[ ]*[a-f0-9]+: 48 0f be 00 * movsbq \(%rax\),%rax > +[ ]*[a-f0-9]+: 66 0f be c0 * movsbw %al,%ax > +[ ]*[a-f0-9]+: 67 66 0f be 00 * movsbw \(%eax\),%ax > +[ ]*[a-f0-9]+: 0f be c0 * movsbl %al,%eax > +[ ]*[a-f0-9]+: 67 0f be 00 * movsbl \(%eax\),%eax > +[ ]*[a-f0-9]+: 48 0f be c0 * movsbq %al,%rax > +[ ]*[a-f0-9]+: 48 0f be 00 * movsbq \(%rax\),%rax > +[ ]*[a-f0-9]+: 0f bf c0 * movswl %ax,%eax > +[ ]*[a-f0-9]+: 67 0f bf 00 * movswl \(%eax\),%eax > +[ ]*[a-f0-9]+: 48 0f bf c0 * movswq %ax,%rax > +[ ]*[a-f0-9]+: 48 0f bf 00 * movswq \(%rax\),%rax > +[ ]*[a-f0-9]+: 0f bf c0 * movswl %ax,%eax > +[ ]*[a-f0-9]+: 67 0f bf 00 * movswl \(%eax\),%eax > +[ ]*[a-f0-9]+: 48 0f bf c0 * movswq %ax,%rax > +[ ]*[a-f0-9]+: 48 0f bf 00 * movswq \(%rax\),%rax > +#pass > --- a/gas/testsuite/gas/i386/movx16.l > +++ b/gas/testsuite/gas/i386/movx16.l > @@ -41,11 +41,11 @@ > [ ]*[1-9][0-9]*[ ]+movsb %ax, %cl > [ ]*[1-9][0-9]*[ ]+movsb %eax, %cl > [ ]*[1-9][0-9]*[ ]* > -[ ]*[1-9][0-9]*[ ]+movsb %al, %cx > +[ ]*[1-9][0-9]* \?\?\?\? 0FBEC8[ ]+movsb %al, %cx > [ ]*[1-9][0-9]*[ ]+movsb %ax, %cx > [ ]*[1-9][0-9]*[ ]+movsb %eax, %cx > [ ]*[1-9][0-9]*[ ]* > -[ ]*[1-9][0-9]*[ ]+movsb %al, %ecx > +[ ]*[1-9][0-9]* \?\?\?\? 660FBEC8[ ]+movsb %al, %ecx > [ ]*[1-9][0-9]*[ ]+movsb %ax, %ecx > [ ]*[1-9][0-9]*[ ]+movsb %eax, %ecx > [ ]*[1-9][0-9]*[ ]* > @@ -82,7 +82,7 @@ > [ ]*[1-9][0-9]*[ ]+movsw %eax, %cx > [ ]*[1-9][0-9]*[ ]* > [ ]*[1-9][0-9]*[ ]+movsw %al, %ecx > -[ ]*[1-9][0-9]*[ ]+movsw %ax, %ecx > +[ ]*[1-9][0-9]* \?\?\?\? 660FBFC8[ ]+movsw %ax, %ecx > [ ]*[1-9][0-9]*[ ]+movsw %eax, %ecx > [ ]*[1-9][0-9]*[ ]* > [ ]*[1-9][0-9]*[ ]+movswl %al, %cl > --- a/gas/testsuite/gas/i386/movx32.l > +++ b/gas/testsuite/gas/i386/movx32.l > @@ -41,11 +41,11 @@ > [ ]*[1-9][0-9]*[ ]+movsb %ax, %cl > [ ]*[1-9][0-9]*[ ]+movsb %eax, %cl > [ ]*[1-9][0-9]*[ ]* > -[ ]*[1-9][0-9]*[ ]+movsb %al, %cx > +[ ]*[1-9][0-9]* \?\?\?\? 660FBEC8[ ]+movsb %al, %cx > [ ]*[1-9][0-9]*[ ]+movsb %ax, %cx > [ ]*[1-9][0-9]*[ ]+movsb %eax, %cx > [ ]*[1-9][0-9]*[ ]* > -[ ]*[1-9][0-9]*[ ]+movsb %al, %ecx > +[ ]*[1-9][0-9]* \?\?\?\? 0FBEC8[ ]+movsb %al, %ecx > [ ]*[1-9][0-9]*[ ]+movsb %ax, %ecx > [ ]*[1-9][0-9]*[ ]+movsb %eax, %ecx > [ ]*[1-9][0-9]*[ ]* > @@ -82,7 +82,7 @@ > [ ]*[1-9][0-9]*[ ]+movsw %eax, %cx > [ ]*[1-9][0-9]*[ ]* > [ ]*[1-9][0-9]*[ ]+movsw %al, %ecx > -[ ]*[1-9][0-9]*[ ]+movsw %ax, %ecx > +[ ]*[1-9][0-9]* \?\?\?\? 0FBFC8[ ]+movsw %ax, %ecx > [ ]*[1-9][0-9]*[ ]+movsw %eax, %ecx > [ ]*[1-9][0-9]*[ ]* > [ ]*[1-9][0-9]*[ ]+movswl %al, %cl > --- a/gas/testsuite/gas/i386/movx64.l > +++ b/gas/testsuite/gas/i386/movx64.l > @@ -106,17 +106,17 @@ > [ ]*[1-9][0-9]*[ ]+movsb %eax, %cl > [ ]*[1-9][0-9]*[ ]+movsb %rax, %cl > [ ]*[1-9][0-9]*[ ]* > -[ ]*[1-9][0-9]*[ ]+movsb %al, %cx > +[ ]*[1-9][0-9]* \?\?\?\? 660FBEC8[ ]+movsb %al, %cx > [ ]*[1-9][0-9]*[ ]+movsb %ax, %cx > [ ]*[1-9][0-9]*[ ]+movsb %eax, %cx > [ ]*[1-9][0-9]*[ ]+movsb %rax, %cx > [ ]*[1-9][0-9]*[ ]* > -[ ]*[1-9][0-9]*[ ]+movsb %al, %ecx > +[ ]*[1-9][0-9]* \?\?\?\? 0FBEC8[ ]+movsb %al, %ecx > [ ]*[1-9][0-9]*[ ]+movsb %ax, %ecx > [ ]*[1-9][0-9]*[ ]+movsb %eax, %ecx > [ ]*[1-9][0-9]*[ ]+movsb %rax, %ecx > [ ]*[1-9][0-9]*[ ]* > -[ ]*[1-9][0-9]*[ ]+movsb %al, %rcx > +[ ]*[1-9][0-9]* \?\?\?\? 480FBEC8[ ]+movsb %al, %rcx > [ ]*[1-9][0-9]*[ ]+movsb %ax, %rcx > [ ]*[1-9][0-9]*[ ]+movsb %eax, %rcx > [ ]*[1-9][0-9]*[ ]+movsb %rax, %rcx > @@ -192,12 +192,12 @@ > [ ]*[1-9][0-9]*[ ]+movsw %rax, %cx > [ ]*[1-9][0-9]*[ ]* > [ ]*[1-9][0-9]*[ ]+movsw %al, %ecx > -[ ]*[1-9][0-9]*[ ]+movsw %ax, %ecx > +[ ]*[1-9][0-9]* \?\?\?\? 0FBFC8[ ]+movsw %ax, %ecx > [ ]*[1-9][0-9]*[ ]+movsw %eax, %ecx > [ ]*[1-9][0-9]*[ ]+movsw %rax, %ecx > [ ]*[1-9][0-9]*[ ]* > [ ]*[1-9][0-9]*[ ]+movsw %al, %rcx > -[ ]*[1-9][0-9]*[ ]+movsw %ax, %rcx > +[ ]*[1-9][0-9]* \?\?\?\? 480FBFC8[ ]+movsw %ax, %rcx > [ ]*[1-9][0-9]*[ ]+movsw %eax, %rcx > [ ]*[1-9][0-9]*[ ]+movsw %rax, %rcx > [ ]*[1-9][0-9]*[ ]* > --- a/opcodes/i386-opc.tbl > +++ b/opcodes/i386-opc.tbl > @@ -135,47 +135,37 @@ > 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 > movbe, 0x0f38f0, None, CpuMovbe, D|Modrm|No_bSuf|No_sSuf|No_ldSuf, { Word|Dword|Qword|Unspecified|BaseIndex, Reg16|Reg32|Reg64 } > > // Move with sign extend. > -// "movsbl" & "movsbw" must not be unified into "movsb" to avoid > -// conflict with the "movs" string move instruction. > -movsbl, 0xfbe, None, Cpu386, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg8|Byte|Unspecified|BaseIndex, Reg32 } > -movsbw, 0xfbe, None, Cpu386, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg8|Byte|Unspecified|BaseIndex, Reg16 } > -movswl, 0xfbf, None, Cpu386, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg16|Word|Unspecified|BaseIndex, Reg32 } > -movsbq, 0xfbe, None, Cpu64, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|Size64, { Reg8|Byte|Unspecified|BaseIndex, Reg64 } > -movswq, 0xfbf, None, Cpu64, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|Size64, { Reg16|Word|Unspecified|BaseIndex, Reg64 } > +movsb, 0xfbe, None, Cpu386, Modrm|No_bSuf|No_sSuf|No_ldSuf, { Reg8|Unspecified|BaseIndex, Reg16|Reg32|Reg64 } > +movsw, 0xfbf, None, Cpu386, Modrm|No_bSuf|No_wSuf|No_sSuf|No_ldSuf, { Reg16|Unspecified|BaseIndex, Reg32|Reg64 } > +// "movslq" must not be converted into "movsl" to avoid conflict with the > +// "movsl" string move instruction. > movslq, 0x63, None, Cpu64, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|Size64, { Reg32|Dword|Unspecified|BaseIndex, Reg64 } > movsx, 0xfbe, None, Cpu386, W|Modrm|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg8|Reg16|Unspecified|BaseIndex, Reg16|Reg32|Reg64 } > movsx, 0x63, None, Cpu64, Modrm|No_bSuf|No_wSuf|No_sSuf|No_qSuf|No_ldSuf, { Reg32|Unspecified|BaseIndex, Reg32|Reg64 } > @@ -492,9 +482,6 @@ set, 0xf9, 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 +496,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, {} > -- H.J.