[v3,3/7] x86: re-work insn/suffix recognition
Checks
Commit Message
PR gas/29524
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).
PR gas/29525
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).
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?
---
v3: Limit xstrdup() to just the templates where a 2nd pass actually
makes sense (new Pass2 attribute).
Comments
On Wed, Oct 5, 2022 at 12:23 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> PR gas/29524
> 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).
>
> PR gas/29525
> 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).
>
> 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?
> ---
> 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;
> @@ -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,11 +4824,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++)
> @@ -4838,16 +4846,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. */
> @@ -4923,7 +4941,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)
> + {
> + 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
> @@ -5224,6 +5332,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;
> @@ -5393,8 +5502,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)
> {
> @@ -5442,7 +5553,8 @@ parse_insn (const char *line, char *mnem
>
> if (!current_templates)
> {
> - as_bad (_("no such instruction: `%s'"), token_start);
> + if (pass1)
> + as_bad (_("no such instruction: `%s'"), token_start);
> return NULL;
> }
> }
> @@ -6852,81 +6964,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;
> }
>
> @@ -11335,49 +11373,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)
> @@ -11528,17 +11523,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 ','
> @@ -11745,8 +11729,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+ <movs>:
> +[ ]*[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+ <movs>:
> +[ ]*[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|Pass2, { Reg8|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
> +movsw, 0xfbf, None, Cpu386, Modrm|No_bSuf|No_wSuf|No_sSuf|No_ldSuf|Pass2, { 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<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 +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, {}
> @@ -989,13 +973,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 +1143,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 +1168,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 }
>
Does the new assembler work on Linux kernel which has "rep movsd"?
On 06.10.2022 01:52, H.J. Lu wrote:
> Does the new assembler work on Linux kernel which has "rep movsd"?
No. And it shouldn't, as they should never have used MOVSD. The only valid
mnemonic (in AT&T syntax) is MOVSL. If you're meaning to suggest that we
continue to support MOVSD in AT&T mode, then this will - once again for
consistency - need extending to _all_ other D-suffixable insns the SDM
specifies. I can only repeat what I've said before: Consistency is a
requirement such that users can predict assembler behavior.
In the meantime I guess I'll make a patch for Linux.
Jan
On 06.10.2022 08:15, Jan Beulich via Binutils wrote:
> On 06.10.2022 01:52, H.J. Lu wrote:
>> Does the new assembler work on Linux kernel which has "rep movsd"?
>
> No. And it shouldn't, as they should never have used MOVSD. The only valid
> mnemonic (in AT&T syntax) is MOVSL. If you're meaning to suggest that we
> continue to support MOVSD in AT&T mode, then this will - once again for
> consistency - need extending to _all_ other D-suffixable insns the SDM
> specifies. I can only repeat what I've said before: Consistency is a
> requirement such that users can predict assembler behavior.
Note how Clang's integrated assembler doesn't even support CMPSD as a
string instruction - that's imo yet more odd behavior, and likely
attributed _solely_ to the goal of wanting to work around code wrongly
using such.
Jan
On Wed, Oct 5, 2022 at 11:58 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 06.10.2022 08:15, Jan Beulich via Binutils wrote:
> > On 06.10.2022 01:52, H.J. Lu wrote:
> >> Does the new assembler work on Linux kernel which has "rep movsd"?
> >
> > No. And it shouldn't, as they should never have used MOVSD. The only valid
> > mnemonic (in AT&T syntax) is MOVSL. If you're meaning to suggest that we
> > continue to support MOVSD in AT&T mode, then this will - once again for
> > consistency - need extending to _all_ other D-suffixable insns the SDM
> > specifies. I can only repeat what I've said before: Consistency is a
> > requirement such that users can predict assembler behavior.
>
> Note how Clang's integrated assembler doesn't even support CMPSD as a
> string instruction - that's imo yet more odd behavior, and likely
> attributed _solely_ to the goal of wanting to work around code wrongly
> using such.
I think we should avoid changing assembly sources if possible. Should we keep
CMPSD/MOVSD without any operands? This won't cause any confusion.
On 06.10.2022 17:28, H.J. Lu wrote:
> On Wed, Oct 5, 2022 at 11:58 PM Jan Beulich <jbeulich@suse.com> wrote:
>>
>> On 06.10.2022 08:15, Jan Beulich via Binutils wrote:
>>> On 06.10.2022 01:52, H.J. Lu wrote:
>>>> Does the new assembler work on Linux kernel which has "rep movsd"?
>>>
>>> No. And it shouldn't, as they should never have used MOVSD. The only valid
>>> mnemonic (in AT&T syntax) is MOVSL. If you're meaning to suggest that we
>>> continue to support MOVSD in AT&T mode, then this will - once again for
>>> consistency - need extending to _all_ other D-suffixable insns the SDM
>>> specifies. I can only repeat what I've said before: Consistency is a
>>> requirement such that users can predict assembler behavior.
>>
>> Note how Clang's integrated assembler doesn't even support CMPSD as a
>> string instruction - that's imo yet more odd behavior, and likely
>> attributed _solely_ to the goal of wanting to work around code wrongly
>> using such.
>
> I think we should avoid changing assembly sources if possible. Should we keep
> CMPSD/MOVSD without any operands? This won't cause any confusion.
Since Clang doesn't support CMPSD, I'd be (hesitantly) okay with keeping
just the single MOVSD template having no operands. I'm still be inclined
to warn if it ends up being used, so that people can correct their code.
If you can explain why you think CMPSD also needs retaining in a similar
way, I might be talked into keeping the operand-less form there as well.
But anything going beyond that would have me fall back to requiring
consistency throughout the mnemonics a D suffix might be used with as
per vendor documentation.
Jan
On Thu, Oct 6, 2022 at 9:12 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> On 06.10.2022 17:28, H.J. Lu wrote:
> > On Wed, Oct 5, 2022 at 11:58 PM Jan Beulich <jbeulich@suse.com> wrote:
> >>
> >> On 06.10.2022 08:15, Jan Beulich via Binutils wrote:
> >>> On 06.10.2022 01:52, H.J. Lu wrote:
> >>>> Does the new assembler work on Linux kernel which has "rep movsd"?
> >>>
> >>> No. And it shouldn't, as they should never have used MOVSD. The only valid
> >>> mnemonic (in AT&T syntax) is MOVSL. If you're meaning to suggest that we
> >>> continue to support MOVSD in AT&T mode, then this will - once again for
> >>> consistency - need extending to _all_ other D-suffixable insns the SDM
> >>> specifies. I can only repeat what I've said before: Consistency is a
> >>> requirement such that users can predict assembler behavior.
> >>
> >> Note how Clang's integrated assembler doesn't even support CMPSD as a
> >> string instruction - that's imo yet more odd behavior, and likely
> >> attributed _solely_ to the goal of wanting to work around code wrongly
> >> using such.
> >
> > I think we should avoid changing assembly sources if possible. Should we keep
> > CMPSD/MOVSD without any operands? This won't cause any confusion.
>
> Since Clang doesn't support CMPSD, I'd be (hesitantly) okay with keeping
> just the single MOVSD template having no operands. I'm still be inclined
> to warn if it ends up being used, so that people can correct their code.
> If you can explain why you think CMPSD also needs retaining in a similar
> way, I might be talked into keeping the operand-less form there as well.
> But anything going beyond that would have me fall back to requiring
> consistency throughout the mnemonics a D suffix might be used with as
> per vendor documentation.
Warning is fine with me. We should accept MOVSD and CMPSD without
operands.
On 06.10.2022 20:41, H.J. Lu wrote:
> On Thu, Oct 6, 2022 at 9:12 AM Jan Beulich <jbeulich@suse.com> wrote:
>>
>> On 06.10.2022 17:28, H.J. Lu wrote:
>>> On Wed, Oct 5, 2022 at 11:58 PM Jan Beulich <jbeulich@suse.com> wrote:
>>>>
>>>> On 06.10.2022 08:15, Jan Beulich via Binutils wrote:
>>>>> On 06.10.2022 01:52, H.J. Lu wrote:
>>>>>> Does the new assembler work on Linux kernel which has "rep movsd"?
>>>>>
>>>>> No. And it shouldn't, as they should never have used MOVSD. The only valid
>>>>> mnemonic (in AT&T syntax) is MOVSL. If you're meaning to suggest that we
>>>>> continue to support MOVSD in AT&T mode, then this will - once again for
>>>>> consistency - need extending to _all_ other D-suffixable insns the SDM
>>>>> specifies. I can only repeat what I've said before: Consistency is a
>>>>> requirement such that users can predict assembler behavior.
>>>>
>>>> Note how Clang's integrated assembler doesn't even support CMPSD as a
>>>> string instruction - that's imo yet more odd behavior, and likely
>>>> attributed _solely_ to the goal of wanting to work around code wrongly
>>>> using such.
>>>
>>> I think we should avoid changing assembly sources if possible. Should we keep
>>> CMPSD/MOVSD without any operands? This won't cause any confusion.
>>
>> Since Clang doesn't support CMPSD, I'd be (hesitantly) okay with keeping
>> just the single MOVSD template having no operands. I'm still be inclined
>> to warn if it ends up being used, so that people can correct their code.
>> If you can explain why you think CMPSD also needs retaining in a similar
>> way, I might be talked into keeping the operand-less form there as well.
>> But anything going beyond that would have me fall back to requiring
>> consistency throughout the mnemonics a D suffix might be used with as
>> per vendor documentation.
>
> Warning is fine with me. We should accept MOVSD and CMPSD without
> operands.
As it turns out, still dropping the two templates and adding a little bit
of code to parse_insn() is easier, especially for the purpose of emitting
a warning (which otherwise would need new code elsewhere, in a perhaps
less logical place).
Before I submit v4 - are there any comments on any of the other patches
in this series?
Jan
@@ -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,11 +4824,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++)
@@ -4838,16 +4846,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. */
@@ -4923,7 +4941,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)
+ {
+ 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
@@ -5224,6 +5332,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;
@@ -5393,8 +5502,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)
{
@@ -5442,7 +5553,8 @@ parse_insn (const char *line, char *mnem
if (!current_templates)
{
- as_bad (_("no such instruction: `%s'"), token_start);
+ if (pass1)
+ as_bad (_("no such instruction: `%s'"), token_start);
return NULL;
}
}
@@ -6852,81 +6964,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;
}
@@ -11335,49 +11373,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)
@@ -11528,17 +11523,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 ','
@@ -11745,8 +11729,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
@@ -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
@@ -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
@@ -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"
@@ -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
@@ -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
@@ -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
@@ -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+ <movs>:
+[ ]*[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
@@ -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+ <movs>:
+[ ]*[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
@@ -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
@@ -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
@@ -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]*[ ]*
@@ -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|Pass2, { Reg8|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+movsw, 0xfbf, None, Cpu386, Modrm|No_bSuf|No_wSuf|No_sSuf|No_ldSuf|Pass2, { 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<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 +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, {}
@@ -989,13 +973,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 +1143,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 +1168,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 }