public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] gas/x86-64: properly distinguish low and high register ranges
@ 2012-07-24 14:14 Jan Beulich
       [not found] ` <CAMe9rOrY+ECKpfYM23heJB4Ma1BT9aFd2+-z1oVdhq3EiXwdRQ@mail.gmail.com>
  0 siblings, 1 reply; 9+ messages in thread
From: Jan Beulich @ 2012-07-24 14:14 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 4805 bytes --]

There were several cases where the registers in the REX encoded range
got treated identically to the ones in the base range, due to not
paying attention to the fact that reg_entry's reg_num field doesn't
fully specify the register number (reg_flags also needs to be checked
for RegRex). This patch introduces and uses a new (inline) function to
obtain the full register number, and uses it to fix all those cases.

2012-07-24  Jan Beulich <jbeulich@suse.com>

	* config/tc-i386.c (register_number): New function.
	(build_vex_prefix, process_immext, process_operands,
	build_modrm_byte, i386_index_check): Use it.

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1758,6 +1758,17 @@ operand_type_register_match (i386_operan
 }
 
 static INLINE unsigned int
+register_number (const reg_entry *r)
+{
+  unsigned int nr = r->reg_num;
+
+  if (r->reg_flags & RegRex)
+    nr += 8;
+
+  return nr;
+}
+
+static INLINE unsigned int
 mode_from_disp_size (i386_operand_type t)
 {
   if (t.bitfield.disp8)
@@ -2830,12 +2841,7 @@ build_vex_prefix (const insn_template *t
 
   /* Check register specifier.  */
   if (i.vex.register_specifier)
-    {
-      register_specifier = i.vex.register_specifier->reg_num;
-      if ((i.vex.register_specifier->reg_flags & RegRex))
-	register_specifier += 8;
-      register_specifier = ~register_specifier & 0xf;
-    }
+    register_specifier = ~register_number (i.vex.register_specifier) & 0xf;
   else
     register_specifier = 0xf;
 
@@ -2976,14 +2982,13 @@ process_immext (void)
 
   if (i.tm.cpu_flags.bitfield.cpusse3 && i.operands > 0)
     {
-      /* SSE3 Instructions have the fixed operands with an opcode
-	 suffix which is coded in the same place as an 8-bit immediate
-	 field would be.  Here we check those operands and remove them
-	 afterwards.  */
+      /* MONITOR/MWAIT have fixed operands with an opcode suffix which
+	 is coded in the same place as an 8-bit immediate field would be.
+	 Here we check those operands and remove them afterwards.  */
       unsigned int x;
 
       for (x = 0; x < i.operands; x++)
-	if (i.op[x].regs->reg_num != x)
+	if (register_number (i.op[x].regs) != x)
 	  as_bad (_("can't use register '%s%s' as operand %d in '%s'."),
 		  register_prefix, i.op[x].regs->reg_name, x + 1,
 		  i.tm.name);
@@ -5075,7 +5080,7 @@ process_operands (void)
 	{
 	  /* The first operand is implicit and must be xmm0.  */
 	  gas_assert (operand_type_equal (&i.types[0], &regxmm));
-	  if (i.op[0].regs->reg_num != 0)
+	  if (register_number (i.op[0].regs) != 0)
 	    return bad_implicit_operand (1);
 
 	  if (i.tm.opcode_modifier.vexsources == VEX3SOURCES)
@@ -5149,7 +5154,7 @@ duplicate:
       gas_assert (i.reg_operands
 		  && (operand_type_equal (&i.types[0], &regxmm)
 		      || operand_type_equal (&i.types[0], &regymm)));
-      if (i.op[0].regs->reg_num != 0)
+      if (register_number (i.op[0].regs) != 0)
 	return bad_implicit_operand (i.types[0].bitfield.regxmm);
 
       for (j = 1; j < i.operands; j++)
@@ -5352,10 +5357,7 @@ build_modrm_byte (void)
                       || operand_type_equal (&i.tm.operand_types[reg_slot],
                                              &regymm));
           exp->X_op = O_constant;
-          exp->X_add_number
-              = ((i.op[reg_slot].regs->reg_num
-                  + ((i.op[reg_slot].regs->reg_flags & RegRex) ? 8 : 0))
-		 << 4);
+          exp->X_add_number = register_number (i.op[reg_slot].regs) << 4;
         }
       else
         {
@@ -5399,9 +5401,7 @@ build_modrm_byte (void)
 		      || operand_type_equal (&i.tm.operand_types[reg_slot],
 					     &regymm));
           i.op[imm_slot].imms->X_add_number
-              |= ((i.op[reg_slot].regs->reg_num
-                   + ((i.op[reg_slot].regs->reg_flags & RegRex) ? 8 : 0))
-		  << 4);
+              |= register_number (i.op[reg_slot].regs) << 4;
         }
 
       gas_assert (operand_type_equal (&i.tm.operand_types[nds], &regxmm)
@@ -7314,7 +7314,7 @@ i386_index_check (const char *operand_st
 		   ? i.base_reg->reg_type.bitfield.reg32
 		   : i.base_reg->reg_type.bitfield.reg16))
 	ok = 0;
-      else if (i.base_reg->reg_num != expected)
+      else if (register_number (i.base_reg) != expected)
 	ok = -1;
 
       if (ok < 0)
@@ -7329,7 +7329,7 @@ i386_index_check (const char *operand_st
 		 : (flag_code == CODE_16BIT) ^ !i.prefix[ADDR_PREFIX]
 		   ? i386_regtab[j].reg_type.bitfield.reg32
 		   : i386_regtab[j].reg_type.bitfield.reg16)
-		&& i386_regtab[j].reg_num == expected)
+		&& register_number(i386_regtab + j) == expected)
 	      break;
 	  gas_assert (j < i386_regtab_size);
 	  as_warn (_("`%s' is not valid here (expected `%c%s%s%c')"),



[-- Attachment #2: binutils-mainline-x86-register-number.patch --]
[-- Type: text/plain, Size: 4801 bytes --]

There were several cases where the registers in the REX encoded range
got treated identically to the ones in the base range, due to not
paying attention to the fact that reg_entry's reg_num field doesn't
fully specify the register number (reg_flags also needs to be checked
for RegRex). This patch introduces and uses a new (inline) function to
obtain the full register number, and uses it to fix all those cases.

2012-07-24  Jan Beulich <jbeulich@suse.com>

	* config/tc-i386.c (register_number): New function.
	(build_vex_prefix, process_immext, process_operands,
	build_modrm_byte, i386_index_check): Use it.

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1758,6 +1758,17 @@ operand_type_register_match (i386_operan
 }
 
 static INLINE unsigned int
+register_number (const reg_entry *r)
+{
+  unsigned int nr = r->reg_num;
+
+  if (r->reg_flags & RegRex)
+    nr += 8;
+
+  return nr;
+}
+
+static INLINE unsigned int
 mode_from_disp_size (i386_operand_type t)
 {
   if (t.bitfield.disp8)
@@ -2830,12 +2841,7 @@ build_vex_prefix (const insn_template *t
 
   /* Check register specifier.  */
   if (i.vex.register_specifier)
-    {
-      register_specifier = i.vex.register_specifier->reg_num;
-      if ((i.vex.register_specifier->reg_flags & RegRex))
-	register_specifier += 8;
-      register_specifier = ~register_specifier & 0xf;
-    }
+    register_specifier = ~register_number (i.vex.register_specifier) & 0xf;
   else
     register_specifier = 0xf;
 
@@ -2976,14 +2982,13 @@ process_immext (void)
 
   if (i.tm.cpu_flags.bitfield.cpusse3 && i.operands > 0)
     {
-      /* SSE3 Instructions have the fixed operands with an opcode
-	 suffix which is coded in the same place as an 8-bit immediate
-	 field would be.  Here we check those operands and remove them
-	 afterwards.  */
+      /* MONITOR/MWAIT have fixed operands with an opcode suffix which
+	 is coded in the same place as an 8-bit immediate field would be.
+	 Here we check those operands and remove them afterwards.  */
       unsigned int x;
 
       for (x = 0; x < i.operands; x++)
-	if (i.op[x].regs->reg_num != x)
+	if (register_number (i.op[x].regs) != x)
 	  as_bad (_("can't use register '%s%s' as operand %d in '%s'."),
 		  register_prefix, i.op[x].regs->reg_name, x + 1,
 		  i.tm.name);
@@ -5075,7 +5080,7 @@ process_operands (void)
 	{
 	  /* The first operand is implicit and must be xmm0.  */
 	  gas_assert (operand_type_equal (&i.types[0], &regxmm));
-	  if (i.op[0].regs->reg_num != 0)
+	  if (register_number (i.op[0].regs) != 0)
 	    return bad_implicit_operand (1);
 
 	  if (i.tm.opcode_modifier.vexsources == VEX3SOURCES)
@@ -5149,7 +5154,7 @@ duplicate:
       gas_assert (i.reg_operands
 		  && (operand_type_equal (&i.types[0], &regxmm)
 		      || operand_type_equal (&i.types[0], &regymm)));
-      if (i.op[0].regs->reg_num != 0)
+      if (register_number (i.op[0].regs) != 0)
 	return bad_implicit_operand (i.types[0].bitfield.regxmm);
 
       for (j = 1; j < i.operands; j++)
@@ -5352,10 +5357,7 @@ build_modrm_byte (void)
                       || operand_type_equal (&i.tm.operand_types[reg_slot],
                                              &regymm));
           exp->X_op = O_constant;
-          exp->X_add_number
-              = ((i.op[reg_slot].regs->reg_num
-                  + ((i.op[reg_slot].regs->reg_flags & RegRex) ? 8 : 0))
-		 << 4);
+          exp->X_add_number = register_number (i.op[reg_slot].regs) << 4;
         }
       else
         {
@@ -5399,9 +5401,7 @@ build_modrm_byte (void)
 		      || operand_type_equal (&i.tm.operand_types[reg_slot],
 					     &regymm));
           i.op[imm_slot].imms->X_add_number
-              |= ((i.op[reg_slot].regs->reg_num
-                   + ((i.op[reg_slot].regs->reg_flags & RegRex) ? 8 : 0))
-		  << 4);
+              |= register_number (i.op[reg_slot].regs) << 4;
         }
 
       gas_assert (operand_type_equal (&i.tm.operand_types[nds], &regxmm)
@@ -7314,7 +7314,7 @@ i386_index_check (const char *operand_st
 		   ? i.base_reg->reg_type.bitfield.reg32
 		   : i.base_reg->reg_type.bitfield.reg16))
 	ok = 0;
-      else if (i.base_reg->reg_num != expected)
+      else if (register_number (i.base_reg) != expected)
 	ok = -1;
 
       if (ok < 0)
@@ -7329,7 +7329,7 @@ i386_index_check (const char *operand_st
 		 : (flag_code == CODE_16BIT) ^ !i.prefix[ADDR_PREFIX]
 		   ? i386_regtab[j].reg_type.bitfield.reg32
 		   : i386_regtab[j].reg_type.bitfield.reg16)
-		&& i386_regtab[j].reg_num == expected)
+		&& register_number(i386_regtab + j) == expected)
 	      break;
 	  gas_assert (j < i386_regtab_size);
 	  as_warn (_("`%s' is not valid here (expected `%c%s%s%c')"),

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] gas/x86-64: properly distinguish low and high register ranges
       [not found] ` <CAMe9rOrY+ECKpfYM23heJB4Ma1BT9aFd2+-z1oVdhq3EiXwdRQ@mail.gmail.com>
@ 2012-07-25  6:56   ` Jan Beulich
  2012-07-30 16:05     ` H.J. Lu
  0 siblings, 1 reply; 9+ messages in thread
From: Jan Beulich @ 2012-07-25  6:56 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

>>> On 24.07.12 at 16:16, "H.J. Lu" <hjl.tools@gmail.com> wrote:
> Can you add some testcases?

I knew you would ask this, but sorry, this makes no sense - if test
cases would are desirable here, they shouldn't be testing just the
things that this patch fixes, but also any other invalid operand
combinations. As an example - why would testing that "xlat [r11]"
isn't accepted be needed, but not e.g. "xlat [ecx]"?

Furthermore, this fixes actually broken behavior, so accepting
the change shouldn't be dependent upon test case availability.

Jan

> On Jul 24, 2012 6:14 AM, "Jan Beulich" <JBeulich@suse.com> wrote:
> 
>> There were several cases where the registers in the REX encoded range
>> got treated identically to the ones in the base range, due to not
>> paying attention to the fact that reg_entry's reg_num field doesn't
>> fully specify the register number (reg_flags also needs to be checked
>> for RegRex). This patch introduces and uses a new (inline) function to
>> obtain the full register number, and uses it to fix all those cases.
>>
>> 2012-07-24  Jan Beulich <jbeulich@suse.com>
>>
>>         * config/tc-i386.c (register_number): New function.
>>         (build_vex_prefix, process_immext, process_operands,
>>         build_modrm_byte, i386_index_check): Use it.
>>
>> --- a/gas/config/tc-i386.c
>> +++ b/gas/config/tc-i386.c
>> @@ -1758,6 +1758,17 @@ operand_type_register_match (i386_operan
>>  }
>>
>>  static INLINE unsigned int
>> +register_number (const reg_entry *r)
>> +{
>> +  unsigned int nr = r->reg_num;
>> +
>> +  if (r->reg_flags & RegRex)
>> +    nr += 8;
>> +
>> +  return nr;
>> +}
>> +
>> +static INLINE unsigned int
>>  mode_from_disp_size (i386_operand_type t)
>>  {
>>    if (t.bitfield.disp8)
>> @@ -2830,12 +2841,7 @@ build_vex_prefix (const insn_template *t
>>
>>    /* Check register specifier.  */
>>    if (i.vex.register_specifier)
>> -    {
>> -      register_specifier = i.vex.register_specifier->reg_num;
>> -      if ((i.vex.register_specifier->reg_flags & RegRex))
>> -       register_specifier += 8;
>> -      register_specifier = ~register_specifier & 0xf;
>> -    }
>> +    register_specifier = ~register_number (i.vex.register_specifier) &
>> 0xf;
>>    else
>>      register_specifier = 0xf;
>>
>> @@ -2976,14 +2982,13 @@ process_immext (void)
>>
>>    if (i.tm.cpu_flags.bitfield.cpusse3 && i.operands > 0)
>>      {
>> -      /* SSE3 Instructions have the fixed operands with an opcode
>> -        suffix which is coded in the same place as an 8-bit immediate
>> -        field would be.  Here we check those operands and remove them
>> -        afterwards.  */
>> +      /* MONITOR/MWAIT have fixed operands with an opcode suffix which
>> +        is coded in the same place as an 8-bit immediate field would be.
>> +        Here we check those operands and remove them afterwards.  */
>>        unsigned int x;
>>
>>        for (x = 0; x < i.operands; x++)
>> -       if (i.op[x].regs->reg_num != x)
>> +       if (register_number (i.op[x].regs) != x)
>>           as_bad (_("can't use register '%s%s' as operand %d in '%s'."),
>>                   register_prefix, i.op[x].regs->reg_name, x + 1,
>>                   i.tm.name);
>> @@ -5075,7 +5080,7 @@ process_operands (void)
>>         {
>>           /* The first operand is implicit and must be xmm0.  */
>>           gas_assert (operand_type_equal (&i.types[0], &regxmm));
>> -         if (i.op[0].regs->reg_num != 0)
>> +         if (register_number (i.op[0].regs) != 0)
>>             return bad_implicit_operand (1);
>>
>>           if (i.tm.opcode_modifier.vexsources == VEX3SOURCES)
>> @@ -5149,7 +5154,7 @@ duplicate:
>>        gas_assert (i.reg_operands
>>                   && (operand_type_equal (&i.types[0], &regxmm)
>>                       || operand_type_equal (&i.types[0], &regymm)));
>> -      if (i.op[0].regs->reg_num != 0)
>> +      if (register_number (i.op[0].regs) != 0)
>>         return bad_implicit_operand (i.types[0].bitfield.regxmm);
>>
>>        for (j = 1; j < i.operands; j++)
>> @@ -5352,10 +5357,7 @@ build_modrm_byte (void)
>>                        || operand_type_equal
>> (&i.tm.operand_types[reg_slot],
>>                                               &regymm));
>>            exp->X_op = O_constant;
>> -          exp->X_add_number
>> -              = ((i.op[reg_slot].regs->reg_num
>> -                  + ((i.op[reg_slot].regs->reg_flags & RegRex) ? 8 : 0))
>> -                << 4);
>> +          exp->X_add_number = register_number (i.op[reg_slot].regs) << 4;
>>          }
>>        else
>>          {
>> @@ -5399,9 +5401,7 @@ build_modrm_byte (void)
>>                       || operand_type_equal (&i.tm.operand_types[reg_slot],
>>                                              &regymm));
>>            i.op[imm_slot].imms->X_add_number
>> -              |= ((i.op[reg_slot].regs->reg_num
>> -                   + ((i.op[reg_slot].regs->reg_flags & RegRex) ? 8 : 0))
>> -                 << 4);
>> +              |= register_number (i.op[reg_slot].regs) << 4;
>>          }
>>
>>        gas_assert (operand_type_equal (&i.tm.operand_types[nds], &regxmm)
>> @@ -7314,7 +7314,7 @@ i386_index_check (const char *operand_st
>>                    ? i.base_reg->reg_type.bitfield.reg32
>>                    : i.base_reg->reg_type.bitfield.reg16))
>>         ok = 0;
>> -      else if (i.base_reg->reg_num != expected)
>> +      else if (register_number (i.base_reg) != expected)
>>         ok = -1;
>>
>>        if (ok < 0)
>> @@ -7329,7 +7329,7 @@ i386_index_check (const char *operand_st
>>                  : (flag_code == CODE_16BIT) ^ !i.prefix[ADDR_PREFIX]
>>                    ? i386_regtab[j].reg_type.bitfield.reg32
>>                    : i386_regtab[j].reg_type.bitfield.reg16)
>> -               && i386_regtab[j].reg_num == expected)
>> +               && register_number(i386_regtab + j) == expected)
>>               break;
>>           gas_assert (j < i386_regtab_size);
>>           as_warn (_("`%s' is not valid here (expected `%c%s%s%c')"),
>>
>>
>>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] gas/x86-64: properly distinguish low and high register ranges
  2012-07-25  6:56   ` Jan Beulich
@ 2012-07-30 16:05     ` H.J. Lu
  2012-07-31  6:24       ` Jan Beulich
  0 siblings, 1 reply; 9+ messages in thread
From: H.J. Lu @ 2012-07-30 16:05 UTC (permalink / raw)
  To: Jan Beulich; +Cc: binutils

On Tue, Jul 24, 2012 at 11:56 PM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 24.07.12 at 16:16, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>> Can you add some testcases?
>
> I knew you would ask this, but sorry, this makes no sense - if test
> cases would are desirable here, they shouldn't be testing just the
> things that this patch fixes, but also any other invalid operand
> combinations. As an example - why would testing that "xlat [r11]"
> isn't accepted be needed, but not e.g. "xlat [ecx]"?
>
> Furthermore, this fixes actually broken behavior, so accepting
> the change shouldn't be dependent upon test case availability.
>

What broken behavior does this change fix? Why hasn't it been
tested in the testsuite?


-- 
H.J.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] gas/x86-64: properly distinguish low and high register ranges
  2012-07-30 16:05     ` H.J. Lu
@ 2012-07-31  6:24       ` Jan Beulich
  2012-07-31 15:49         ` H.J. Lu
  0 siblings, 1 reply; 9+ messages in thread
From: Jan Beulich @ 2012-07-31  6:24 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

>>> On 30.07.12 at 18:04, "H.J. Lu" <hjl.tools@gmail.com> wrote:
> On Tue, Jul 24, 2012 at 11:56 PM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>> On 24.07.12 at 16:16, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>>> Can you add some testcases?
>>
>> I knew you would ask this, but sorry, this makes no sense - if test
>> cases would are desirable here, they shouldn't be testing just the
>> things that this patch fixes, but also any other invalid operand
>> combinations. As an example - why would testing that "xlat [r11]"
>> isn't accepted be needed, but not e.g. "xlat [ecx]"?
>>
>> Furthermore, this fixes actually broken behavior, so accepting
>> the change shouldn't be dependent upon test case availability.
> 
> What broken behavior does this change fix?

I gave an example above - xlat [r11]. Other similar examples
involve other string instructions requiring fixed registers as
well as the one or two instructions requiring xmm0/ymm0 as
their first/last operand.

> Why hasn't it been tested in the testsuite?

Don't know.

Jan

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] gas/x86-64: properly distinguish low and high register ranges
  2012-07-31  6:24       ` Jan Beulich
@ 2012-07-31 15:49         ` H.J. Lu
  2012-07-31 16:28           ` Jan Beulich
  0 siblings, 1 reply; 9+ messages in thread
From: H.J. Lu @ 2012-07-31 15:49 UTC (permalink / raw)
  To: Jan Beulich; +Cc: binutils

On Mon, Jul 30, 2012 at 11:25 PM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 30.07.12 at 18:04, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>> On Tue, Jul 24, 2012 at 11:56 PM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>>> On 24.07.12 at 16:16, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>>>> Can you add some testcases?
>>>
>>> I knew you would ask this, but sorry, this makes no sense - if test
>>> cases would are desirable here, they shouldn't be testing just the
>>> things that this patch fixes, but also any other invalid operand
>>> combinations. As an example - why would testing that "xlat [r11]"
>>> isn't accepted be needed, but not e.g. "xlat [ecx]"?
>>>
>>> Furthermore, this fixes actually broken behavior, so accepting
>>> the change shouldn't be dependent upon test case availability.
>>
>> What broken behavior does this change fix?
>
> I gave an example above - xlat [r11]. Other similar examples
> involve other string instructions requiring fixed registers as
> well as the one or two instructions requiring xmm0/ymm0 as
> their first/last operand.
>

Please open a bug report for broken behaviors.

Thanks.

-- 
H.J.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] gas/x86-64: properly distinguish low and high register ranges
  2012-07-31 15:49         ` H.J. Lu
@ 2012-07-31 16:28           ` Jan Beulich
  2012-07-31 18:45             ` H.J. Lu
  0 siblings, 1 reply; 9+ messages in thread
From: Jan Beulich @ 2012-07-31 16:28 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

>>> On 31.07.12 at 17:48, "H.J. Lu" <hjl.tools@gmail.com> wrote:
> On Mon, Jul 30, 2012 at 11:25 PM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>> On 30.07.12 at 18:04, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>>> On Tue, Jul 24, 2012 at 11:56 PM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>>>> On 24.07.12 at 16:16, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>>>>> Can you add some testcases?
>>>>
>>>> I knew you would ask this, but sorry, this makes no sense - if test
>>>> cases would are desirable here, they shouldn't be testing just the
>>>> things that this patch fixes, but also any other invalid operand
>>>> combinations. As an example - why would testing that "xlat [r11]"
>>>> isn't accepted be needed, but not e.g. "xlat [ecx]"?
>>>>
>>>> Furthermore, this fixes actually broken behavior, so accepting
>>>> the change shouldn't be dependent upon test case availability.
>>>
>>> What broken behavior does this change fix?
>>
>> I gave an example above - xlat [r11]. Other similar examples
>> involve other string instructions requiring fixed registers as
>> well as the one or two instructions requiring xmm0/ymm0 as
>> their first/last operand.
>>
> 
> Please open a bug report for broken behaviors.

That's bureaucracy that doesn't get us anywhere. I'd really
like to know whether the patch is okay; entering bug reports
is meaningful if one _can't_ fix a problem right away.

Jan

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] gas/x86-64: properly distinguish low and high register ranges
  2012-07-31 16:28           ` Jan Beulich
@ 2012-07-31 18:45             ` H.J. Lu
  2012-08-07 10:29               ` [PATCH, v2] " Jan Beulich
  0 siblings, 1 reply; 9+ messages in thread
From: H.J. Lu @ 2012-07-31 18:45 UTC (permalink / raw)
  To: Jan Beulich; +Cc: binutils

On Tue, Jul 31, 2012 at 9:28 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 31.07.12 at 17:48, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>> On Mon, Jul 30, 2012 at 11:25 PM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>>> On 30.07.12 at 18:04, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>>>> On Tue, Jul 24, 2012 at 11:56 PM, Jan Beulich <JBeulich@suse.com> wrote:
>>>>>>>> On 24.07.12 at 16:16, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>>>>>> Can you add some testcases?
>>>>>
>>>>> I knew you would ask this, but sorry, this makes no sense - if test
>>>>> cases would are desirable here, they shouldn't be testing just the
>>>>> things that this patch fixes, but also any other invalid operand
>>>>> combinations. As an example - why would testing that "xlat [r11]"
>>>>> isn't accepted be needed, but not e.g. "xlat [ecx]"?
>>>>>
>>>>> Furthermore, this fixes actually broken behavior, so accepting
>>>>> the change shouldn't be dependent upon test case availability.
>>>>
>>>> What broken behavior does this change fix?
>>>
>>> I gave an example above - xlat [r11]. Other similar examples
>>> involve other string instructions requiring fixed registers as
>>> well as the one or two instructions requiring xmm0/ymm0 as
>>> their first/last operand.
>>>
>>
>> Please open a bug report for broken behaviors.
>
> That's bureaucracy that doesn't get us anywhere. I'd really
> like to know whether the patch is okay; entering bug reports
> is meaningful if one _can't_ fix a problem right away.
>

I'd like to see the impact of broken behaviors and verify that
the change fixes them.


-- 
H.J.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH, v2] gas/x86-64: properly distinguish low and high register ranges
  2012-07-31 18:45             ` H.J. Lu
@ 2012-08-07 10:29               ` Jan Beulich
  2012-08-07 14:02                 ` H.J. Lu
  0 siblings, 1 reply; 9+ messages in thread
From: Jan Beulich @ 2012-08-07 10:29 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 24214 bytes --]

>>> On 31.07.12 at 20:45, "H.J. Lu" <hjl.tools@gmail.com> wrote:
> I'd like to see the impact of broken behaviors and verify that
> the change fixes them.

Here you go.

Jan

There were several cases where the registers in the REX encoded range
got treated identically to the ones in the base range, due to not
paying attention to the fact that reg_entry's reg_num field doesn't
fully specify the register number (reg_flags also needs to be checked
for RegRex). This patch introduces and uses a new (inline) function to
obtain the full register number, and uses it to fix all those cases.

It additionally adds the missing operand checks for SVME instructions
(which match the monitor/mwait ones).

gas/
2012-08-07  Jan Beulich <jbeulich@suse.com>

	* config/tc-i386.c (register_number): New function.
	(build_vex_prefix, process_immext, process_operands,
	build_modrm_byte, i386_index_check): Use it.

gas/testsuite/
2012-08-07  Jan Beulich <jbeulich@suse.com>

	* gas/i386/x86-64-specific-reg.{s,l}: New.
	* gas/i386/i386.exp: Run new test.

opcodes/
2012-08-07  Jan Beulich <jbeulich@suse.com>

	* i386-opc.tbl: Remove "FIXME" comments from SVME instructions.

--- 2012-08-07/gas/config/tc-i386.c	2012-07-31 09:45:03.000000000 +0200
+++ 2012-08-07/gas/config/tc-i386.c	2012-08-07 11:37:29.000000000 +0200
@@ -1758,6 +1758,17 @@ operand_type_register_match (i386_operan
 }
 
 static INLINE unsigned int
+register_number (const reg_entry *r)
+{
+  unsigned int nr = r->reg_num;
+
+  if (r->reg_flags & RegRex)
+    nr += 8;
+
+  return nr;
+}
+
+static INLINE unsigned int
 mode_from_disp_size (i386_operand_type t)
 {
   if (t.bitfield.disp8)
@@ -2830,12 +2841,7 @@ build_vex_prefix (const insn_template *t
 
   /* Check register specifier.  */
   if (i.vex.register_specifier)
-    {
-      register_specifier = i.vex.register_specifier->reg_num;
-      if ((i.vex.register_specifier->reg_flags & RegRex))
-	register_specifier += 8;
-      register_specifier = ~register_specifier & 0xf;
-    }
+    register_specifier = ~register_number (i.vex.register_specifier) & 0xf;
   else
     register_specifier = 0xf;
 
@@ -2974,16 +2980,15 @@ process_immext (void)
 {
   expressionS *exp;
 
-  if (i.tm.cpu_flags.bitfield.cpusse3 && i.operands > 0)
+  if ((i.tm.cpu_flags.bitfield.cpusse3 || i.tm.cpu_flags.bitfield.cpusvme)
+      && i.operands > 0)
     {
-      /* SSE3 Instructions have the fixed operands with an opcode
-	 suffix which is coded in the same place as an 8-bit immediate
-	 field would be.  Here we check those operands and remove them
-	 afterwards.  */
+      /* MONITOR/MWAIT as well as SVME instructions have fixed operands.
+	 Here we check those operands and remove them afterwards.  */
       unsigned int x;
 
       for (x = 0; x < i.operands; x++)
-	if (i.op[x].regs->reg_num != x)
+	if (register_number (i.op[x].regs) != x)
 	  as_bad (_("can't use register '%s%s' as operand %d in '%s'."),
 		  register_prefix, i.op[x].regs->reg_name, x + 1,
 		  i.tm.name);
@@ -5071,7 +5076,7 @@ process_operands (void)
 	{
 	  /* The first operand is implicit and must be xmm0.  */
 	  gas_assert (operand_type_equal (&i.types[0], &regxmm));
-	  if (i.op[0].regs->reg_num != 0)
+	  if (register_number (i.op[0].regs) != 0)
 	    return bad_implicit_operand (1);
 
 	  if (i.tm.opcode_modifier.vexsources == VEX3SOURCES)
@@ -5145,7 +5150,7 @@ duplicate:
       gas_assert (i.reg_operands
 		  && (operand_type_equal (&i.types[0], &regxmm)
 		      || operand_type_equal (&i.types[0], &regymm)));
-      if (i.op[0].regs->reg_num != 0)
+      if (register_number (i.op[0].regs) != 0)
 	return bad_implicit_operand (i.types[0].bitfield.regxmm);
 
       for (j = 1; j < i.operands; j++)
@@ -5348,10 +5353,7 @@ build_modrm_byte (void)
                       || operand_type_equal (&i.tm.operand_types[reg_slot],
                                              &regymm));
           exp->X_op = O_constant;
-          exp->X_add_number
-              = ((i.op[reg_slot].regs->reg_num
-                  + ((i.op[reg_slot].regs->reg_flags & RegRex) ? 8 : 0))
-		 << 4);
+          exp->X_add_number = register_number (i.op[reg_slot].regs) << 4;
         }
       else
         {
@@ -5395,9 +5397,7 @@ build_modrm_byte (void)
 		      || operand_type_equal (&i.tm.operand_types[reg_slot],
 					     &regymm));
           i.op[imm_slot].imms->X_add_number
-              |= ((i.op[reg_slot].regs->reg_num
-                   + ((i.op[reg_slot].regs->reg_flags & RegRex) ? 8 : 0))
-		  << 4);
+              |= register_number (i.op[reg_slot].regs) << 4;
         }
 
       gas_assert (operand_type_equal (&i.tm.operand_types[nds], &regxmm)
@@ -7310,7 +7310,7 @@ i386_index_check (const char *operand_st
 		   ? i.base_reg->reg_type.bitfield.reg32
 		   : i.base_reg->reg_type.bitfield.reg16))
 	ok = 0;
-      else if (i.base_reg->reg_num != expected)
+      else if (register_number (i.base_reg) != expected)
 	ok = -1;
 
       if (ok < 0)
@@ -7325,7 +7325,7 @@ i386_index_check (const char *operand_st
 		 : (flag_code == CODE_16BIT) ^ !i.prefix[ADDR_PREFIX]
 		   ? i386_regtab[j].reg_type.bitfield.reg32
 		   : i386_regtab[j].reg_type.bitfield.reg16)
-		&& i386_regtab[j].reg_num == expected)
+		&& register_number(i386_regtab + j) == expected)
 	      break;
 	  gas_assert (j < i386_regtab_size);
 	  as_warn (_("`%s' is not valid here (expected `%c%s%s%c')"),
--- 2012-08-07/gas/testsuite/gas/i386/i386.exp	2012-07-24 14:52:59.000000000 +0200
+++ 2012-08-07/gas/testsuite/gas/i386/i386.exp	2012-08-07 11:37:29.000000000 +0200
@@ -374,6 +374,7 @@ if [expr ([istarget "i*86-*-*"] || [ista
     run_dump_test "x86-64-disp-intel"
     run_dump_test "x86-64-disp32"
     run_dump_test "rexw"
+    run_list_test "x86-64-specific-reg"
     run_dump_test "x86-64-fxsave"
     run_dump_test "x86-64-fxsave-intel"
     run_dump_test "x86-64-arch-1"
--- 2012-08-07/gas/testsuite/gas/i386/x86-64-specific-reg.l	1970-01-01 01:00:00.000000000 +0100
+++ 2012-08-07/gas/testsuite/gas/i386/x86-64-specific-reg.l	2012-08-03 15:48:54.000000000 +0200
@@ -0,0 +1,376 @@
+.*: Assembler messages:
+.*:[0-9]*: Warning: .*rax.*rsi.*
+.*:[0-9]*: Warning: .*rax.*rdi.*
+.*:[0-9]*: Warning: .*rax.*rdi.*
+.*:[0-9]*: Warning: .*rax.*rdi.*
+.*:[0-9]*: Warning: .*rax.*rsi.*
+.*:[0-9]*: Warning: .*rax.*rbx.*
+.*:[0-9]*: Warning: .*rax.*rsi.*
+.*:[0-9]*: Warning: .*rax.*rdi.*
+.*:[0-9]*: Warning: .*rax.*rdi.*
+.*:[0-9]*: Warning: .*rax.*rsi.*
+.*:[0-9]*: Error: .*rax.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rax.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rax.* 3 .*monitor.*
+.*:[0-9]*: Error: .*eax.* 2 .*invlpga.*
+.*:[0-9]*: Warning: .*rcx.*rsi.*
+.*:[0-9]*: Warning: .*rcx.*rdi.*
+.*:[0-9]*: Warning: .*rcx.*rdi.*
+.*:[0-9]*: Warning: .*rcx.*rdi.*
+.*:[0-9]*: Warning: .*rcx.*rsi.*
+.*:[0-9]*: Warning: .*rcx.*rbx.*
+.*:[0-9]*: Warning: .*rcx.*rsi.*
+.*:[0-9]*: Warning: .*rcx.*rdi.*
+.*:[0-9]*: Warning: .*rcx.*rdi.*
+.*:[0-9]*: Warning: .*rcx.*rsi.*
+.*:[0-9]*: Error: .*rcx.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rcx.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rcx.* 3 .*monitor.*
+.*:[0-9]*: Error: .*rcx.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rcx.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rcx.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rcx.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*ecx.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*rdx.*rsi.*
+.*:[0-9]*: Warning: .*rdx.*rdi.*
+.*:[0-9]*: Warning: .*rdx.*rdi.*
+.*:[0-9]*: Warning: .*rdx.*rdi.*
+.*:[0-9]*: Warning: .*rdx.*rsi.*
+.*:[0-9]*: Warning: .*rdx.*rbx.*
+.*:[0-9]*: Warning: .*rdx.*rsi.*
+.*:[0-9]*: Warning: .*rdx.*rdi.*
+.*:[0-9]*: Warning: .*rdx.*rdi.*
+.*:[0-9]*: Warning: .*rdx.*rsi.*
+.*:[0-9]*: Error: .*rdx.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rdx.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rdx.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rdx.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rdx.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rdx.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rdx.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rdx.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*edx.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*edx.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*rbx.*rsi.*
+.*:[0-9]*: Warning: .*rbx.*rdi.*
+.*:[0-9]*: Warning: .*rbx.*rdi.*
+.*:[0-9]*: Warning: .*rbx.*rdi.*
+.*:[0-9]*: Warning: .*rbx.*rsi.*
+.*:[0-9]*: Warning: .*rbx.*rsi.*
+.*:[0-9]*: Warning: .*rbx.*rdi.*
+.*:[0-9]*: Warning: .*rbx.*rdi.*
+.*:[0-9]*: Warning: .*rbx.*rsi.*
+.*:[0-9]*: Error: .*rbx.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rbx.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rbx.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rbx.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rbx.* 3 .*monitor.*
+.*:[0-9]*: Error: .*rbx.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rbx.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rbx.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rbx.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*ebx.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*ebx.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*rsp.*rsi.*
+.*:[0-9]*: Warning: .*rsp.*rdi.*
+.*:[0-9]*: Warning: .*rsp.*rdi.*
+.*:[0-9]*: Warning: .*rsp.*rdi.*
+.*:[0-9]*: Warning: .*rsp.*rsi.*
+.*:[0-9]*: Warning: .*rsp.*rbx.*
+.*:[0-9]*: Warning: .*rsp.*rsi.*
+.*:[0-9]*: Warning: .*rsp.*rdi.*
+.*:[0-9]*: Warning: .*rsp.*rdi.*
+.*:[0-9]*: Warning: .*rsp.*rsi.*
+.*:[0-9]*: Error: .*rsp.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rsp.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rsp.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rsp.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rsp.* 3 .*monitor.*
+.*:[0-9]*: Error: .*rsp.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rsp.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rsp.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rsp.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*esp.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*esp.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*rbp.*rsi.*
+.*:[0-9]*: Warning: .*rbp.*rdi.*
+.*:[0-9]*: Warning: .*rbp.*rdi.*
+.*:[0-9]*: Warning: .*rbp.*rdi.*
+.*:[0-9]*: Warning: .*rbp.*rsi.*
+.*:[0-9]*: Warning: .*rbp.*rbx.*
+.*:[0-9]*: Warning: .*rbp.*rsi.*
+.*:[0-9]*: Warning: .*rbp.*rdi.*
+.*:[0-9]*: Warning: .*rbp.*rdi.*
+.*:[0-9]*: Warning: .*rbp.*rsi.*
+.*:[0-9]*: Error: .*rbp.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rbp.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rbp.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rbp.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rbp.* 3 .*monitor.*
+.*:[0-9]*: Error: .*rbp.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rbp.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rbp.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rbp.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*ebp.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*ebp.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*rsi.*rdi.*
+.*:[0-9]*: Warning: .*rsi.*rdi.*
+.*:[0-9]*: Warning: .*rsi.*rdi.*
+.*:[0-9]*: Warning: .*rsi.*rbx.*
+.*:[0-9]*: Warning: .*rsi.*rdi.*
+.*:[0-9]*: Warning: .*rsi.*rdi.*
+.*:[0-9]*: Error: .*rsi.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rsi.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rsi.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rsi.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rsi.* 3 .*monitor.*
+.*:[0-9]*: Error: .*rsi.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rsi.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rsi.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rsi.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*esi.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*esi.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*rdi.*rsi.*
+.*:[0-9]*: Warning: .*rdi.*rsi.*
+.*:[0-9]*: Warning: .*rdi.*rbx.*
+.*:[0-9]*: Warning: .*rdi.*rsi.*
+.*:[0-9]*: Warning: .*rdi.*rsi.*
+.*:[0-9]*: Error: .*rdi.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rdi.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rdi.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rdi.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rdi.* 3 .*monitor.*
+.*:[0-9]*: Error: .*rdi.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rdi.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rdi.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rdi.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*edi.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*edi.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r8.*rsi.*
+.*:[0-9]*: Warning: .*r8.*rdi.*
+.*:[0-9]*: Warning: .*r8.*rdi.*
+.*:[0-9]*: Warning: .*r8.*rdi.*
+.*:[0-9]*: Warning: .*r8.*rsi.*
+.*:[0-9]*: Warning: .*r8.*rbx.*
+.*:[0-9]*: Warning: .*r8.*rsi.*
+.*:[0-9]*: Warning: .*r8.*rdi.*
+.*:[0-9]*: Warning: .*r8.*rdi.*
+.*:[0-9]*: Warning: .*r8.*rsi.*
+.*:[0-9]*: Error: .*r8.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r8.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r8.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r8.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r8.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r8.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r8.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r8.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r8.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r8.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r8.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r9.*rsi.*
+.*:[0-9]*: Warning: .*r9.*rdi.*
+.*:[0-9]*: Warning: .*r9.*rdi.*
+.*:[0-9]*: Warning: .*r9.*rdi.*
+.*:[0-9]*: Warning: .*r9.*rsi.*
+.*:[0-9]*: Warning: .*r9.*rbx.*
+.*:[0-9]*: Warning: .*r9.*rsi.*
+.*:[0-9]*: Warning: .*r9.*rdi.*
+.*:[0-9]*: Warning: .*r9.*rdi.*
+.*:[0-9]*: Warning: .*r9.*rsi.*
+.*:[0-9]*: Error: .*r9.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r9.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r9.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r9.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r9.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r9.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r9.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r9.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r9.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r9.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r9.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r10.*rsi.*
+.*:[0-9]*: Warning: .*r10.*rdi.*
+.*:[0-9]*: Warning: .*r10.*rdi.*
+.*:[0-9]*: Warning: .*r10.*rdi.*
+.*:[0-9]*: Warning: .*r10.*rsi.*
+.*:[0-9]*: Warning: .*r10.*rbx.*
+.*:[0-9]*: Warning: .*r10.*rsi.*
+.*:[0-9]*: Warning: .*r10.*rdi.*
+.*:[0-9]*: Warning: .*r10.*rdi.*
+.*:[0-9]*: Warning: .*r10.*rsi.*
+.*:[0-9]*: Error: .*r10.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r10.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r10.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r10.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r10.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r10.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r10.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r10.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r10.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r10.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r10.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r11.*rsi.*
+.*:[0-9]*: Warning: .*r11.*rdi.*
+.*:[0-9]*: Warning: .*r11.*rdi.*
+.*:[0-9]*: Warning: .*r11.*rdi.*
+.*:[0-9]*: Warning: .*r11.*rsi.*
+.*:[0-9]*: Warning: .*r11.*rbx.*
+.*:[0-9]*: Warning: .*r11.*rsi.*
+.*:[0-9]*: Warning: .*r11.*rdi.*
+.*:[0-9]*: Warning: .*r11.*rdi.*
+.*:[0-9]*: Warning: .*r11.*rsi.*
+.*:[0-9]*: Error: .*r11.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r11.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r11.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r11.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r11.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r11.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r11.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r11.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r11.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r11.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r11.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r12.*rsi.*
+.*:[0-9]*: Warning: .*r12.*rdi.*
+.*:[0-9]*: Warning: .*r12.*rdi.*
+.*:[0-9]*: Warning: .*r12.*rdi.*
+.*:[0-9]*: Warning: .*r12.*rsi.*
+.*:[0-9]*: Warning: .*r12.*rbx.*
+.*:[0-9]*: Warning: .*r12.*rsi.*
+.*:[0-9]*: Warning: .*r12.*rdi.*
+.*:[0-9]*: Warning: .*r12.*rdi.*
+.*:[0-9]*: Warning: .*r12.*rsi.*
+.*:[0-9]*: Error: .*r12.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r12.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r12.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r12.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r12.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r12.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r12.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r12.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r12.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r12.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r12.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r13.*rsi.*
+.*:[0-9]*: Warning: .*r13.*rdi.*
+.*:[0-9]*: Warning: .*r13.*rdi.*
+.*:[0-9]*: Warning: .*r13.*rdi.*
+.*:[0-9]*: Warning: .*r13.*rsi.*
+.*:[0-9]*: Warning: .*r13.*rbx.*
+.*:[0-9]*: Warning: .*r13.*rsi.*
+.*:[0-9]*: Warning: .*r13.*rdi.*
+.*:[0-9]*: Warning: .*r13.*rdi.*
+.*:[0-9]*: Warning: .*r13.*rsi.*
+.*:[0-9]*: Error: .*r13.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r13.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r13.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r13.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r13.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r13.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r13.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r13.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r13.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r13.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r13.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r14.*rsi.*
+.*:[0-9]*: Warning: .*r14.*rdi.*
+.*:[0-9]*: Warning: .*r14.*rdi.*
+.*:[0-9]*: Warning: .*r14.*rdi.*
+.*:[0-9]*: Warning: .*r14.*rsi.*
+.*:[0-9]*: Warning: .*r14.*rbx.*
+.*:[0-9]*: Warning: .*r14.*rsi.*
+.*:[0-9]*: Warning: .*r14.*rdi.*
+.*:[0-9]*: Warning: .*r14.*rdi.*
+.*:[0-9]*: Warning: .*r14.*rsi.*
+.*:[0-9]*: Error: .*r14.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r14.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r14.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r14.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r14.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r14.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r14.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r14.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r14.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r14.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r14.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r15.*rsi.*
+.*:[0-9]*: Warning: .*r15.*rdi.*
+.*:[0-9]*: Warning: .*r15.*rdi.*
+.*:[0-9]*: Warning: .*r15.*rdi.*
+.*:[0-9]*: Warning: .*r15.*rsi.*
+.*:[0-9]*: Warning: .*r15.*rbx.*
+.*:[0-9]*: Warning: .*r15.*rsi.*
+.*:[0-9]*: Warning: .*r15.*rdi.*
+.*:[0-9]*: Warning: .*r15.*rdi.*
+.*:[0-9]*: Warning: .*r15.*rsi.*
+.*:[0-9]*: Error: .*r15.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r15.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r15.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r15.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r15.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r15.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r15.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r15.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r15.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r15.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r15.* 1 .*skinit.*
+# xmm1
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm2
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm3
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm4
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm5
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm6
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm7
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm8
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm9
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm10
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm11
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm12
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm13
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm14
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm15
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
--- 2012-08-07/gas/testsuite/gas/i386/x86-64-specific-reg.s	1970-01-01 01:00:00.000000000 +0100
+++ 2012-08-07/gas/testsuite/gas/i386/x86-64-specific-reg.s	2012-08-03 15:49:41.000000000 +0200
@@ -0,0 +1,90 @@
+# 64bit insns with special register requirements
+
+	.text
+special:
+.irp reg1, ax, cx, dx, bx, sp, bp, si, di
+	lodsb	%ds:(%r\reg1)
+
+	stosb	%es:(%r\reg1)
+
+	scasb	%es:(%r\reg1)
+
+	insb	%dx, %es:(%r\reg1)
+
+	outsb	%ds:(%r\reg1), %dx
+
+	xlatb	%ds:(%r\reg1)
+
+	movsb	%ds:(%r\reg1), %es:(%rdi)
+	movsb	%ds:(%rsi), %es:(%r\reg1)
+
+	cmpsb	%es:(%r\reg1), %ds:(%rsi)
+	cmpsb	%es:(%rdi), %ds:(%r\reg1)
+
+	mwait	%r\reg1, %rcx
+	mwait	%rax, %r\reg1
+
+	monitor	%r\reg1, %rcx, %rdx
+	monitor	%rax, %r\reg1, %rdx
+	monitor	%rax, %rcx, %r\reg1
+
+# FIXME: Need to ensure only "vmload %[re]ax" is accepted.
+	vmload	%r\reg1
+
+# FIXME: Need to ensure only "vmrun %[re]ax" is accepted.
+	vmrun	%r\reg1
+
+# FIXME: Need to ensure only "vmsave %[re]ax" is accepted.
+	vmsave	%r\reg1
+
+# FIXME: Need to ensure only "invlpga %[re]ax,%ecx" is accepted.
+	invlpga	%r\reg1, %ecx
+	invlpga	%rax, %e\reg1
+
+# FIXME: Need to ensure only "skinit %eax" is accepted.
+	skinit	%e\reg1
+.endr
+
+.irp reg1, 8, 9, 10, 11, 12, 13, 14, 15
+	lodsb	%ds:(%r\reg1)
+
+	stosb	%es:(%r\reg1)
+
+	scasb	%es:(%r\reg1)
+
+	insb	%dx, %es:(%r\reg1)
+
+	outsb	%ds:(%r\reg1), %dx
+
+	xlatb	%ds:(%r\reg1)
+
+	movsb	%ds:(%r\reg1), %es:(%rdi)
+	movsb	%ds:(%rsi), %es:(%r\reg1)
+
+	cmpsb	%es:(%r\reg1), %ds:(%rsi)
+	cmpsb	%es:(%rdi), %ds:(%r\reg1)
+
+	mwait	%r\reg1, %rcx
+	mwait	%rax, %r\reg1
+
+	monitor	%r\reg1, %rcx, %rdx
+	monitor	%rax, %r\reg1, %rdx
+	monitor	%rax, %rcx, %r\reg1
+
+	vmload	%r\reg1
+
+	vmrun	%r\reg1
+
+	vmsave	%r\reg1
+
+	invlpga	%r\reg1, %ecx
+	invlpga	%rax, %r\reg1\(d)
+
+	skinit	%r\reg1\(d)
+.endr
+
+.irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+	blendvpd %xmm\n, %xmm\n, %xmm\n
+	blendvps %xmm\n, %xmm\n, %xmm\n
+	pblendvb %xmm\n, %xmm\n, %xmm\n
+.endr
--- 2012-08-07/opcodes/i386-opc.tbl	2012-07-31 09:37:43.000000000 +0200
+++ 2012-08-07/opcodes/i386-opc.tbl	2012-08-07 11:37:29.000000000 +0200
@@ -3004,21 +3004,16 @@ rdtscp, 0, 0xf01, 0xf9, 2, CpuRdtscp, No
 // AMD Pacifica additions.
 clgi, 0, 0xf01, 0xdd, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
 invlpga, 0, 0xf01, 0xdf, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
-// FIXME: Need to ensure only "invlpga %[re]ax,%ecx" is accepted.
 invlpga, 2, 0xf01, 0xdf, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt|AddrPrefixOp0|NoRex64, { Reg32|Reg64, Reg32 }
 skinit, 0, 0xf01, 0xde, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
-// FIXME: Need to ensure only "skinit %eax" is accepted.
 skinit, 1, 0xf01, 0xde, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { Reg32 }
 stgi, 0, 0xf01, 0xdc, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
 vmload, 0, 0xf01, 0xda, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
-// FIXME: Need to ensure only "vmload %[re]ax" is accepted.
 vmload, 1, 0xf01, 0xda, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt|AddrPrefixOp0|NoRex64, { Reg32|Reg64 }
 vmmcall, 0, 0xf01, 0xd9, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
 vmrun, 0, 0xf01, 0xd8, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
-// FIXME: Need to ensure only "vmrun %[re]ax" is accepted.
 vmrun, 1, 0xf01, 0xd8, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt|AddrPrefixOp0|NoRex64, { Reg32|Reg64 }
 vmsave, 0, 0xf01, 0xdb, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
-// FIXME: Need to ensure only "vmsave %[re]ax" is accepted.
 vmsave, 1, 0xf01, 0xdb, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt|AddrPrefixOp0|NoRex64, { Reg32|Reg64 }
 
 



[-- Attachment #2: binutils-mainline-x86_64-register-number.patch --]
[-- Type: text/plain, Size: 24027 bytes --]

There were several cases where the registers in the REX encoded range
got treated identically to the ones in the base range, due to not
paying attention to the fact that reg_entry's reg_num field doesn't
fully specify the register number (reg_flags also needs to be checked
for RegRex). This patch introduces and uses a new (inline) function to
obtain the full register number, and uses it to fix all those cases.

It additionally adds the missing operand checks for SVME instructions
(which match the monitor/mwait ones).

gas/
2012-08-07  Jan Beulich <jbeulich@suse.com>

	* config/tc-i386.c (register_number): New function.
	(build_vex_prefix, process_immext, process_operands,
	build_modrm_byte, i386_index_check): Use it.

gas/testsuite/
2012-08-07  Jan Beulich <jbeulich@suse.com>

	* gas/i386/x86-64-specific-reg.{s,l}: New.
	* gas/i386/i386.exp: Run new test.

opcodes/
2012-08-07  Jan Beulich <jbeulich@suse.com>

	* i386-opc.tbl: Remove "FIXME" comments from SVME instructions.

--- 2012-08-07/gas/config/tc-i386.c	2012-07-31 09:45:03.000000000 +0200
+++ 2012-08-07/gas/config/tc-i386.c	2012-08-07 11:37:29.000000000 +0200
@@ -1758,6 +1758,17 @@ operand_type_register_match (i386_operan
 }
 
 static INLINE unsigned int
+register_number (const reg_entry *r)
+{
+  unsigned int nr = r->reg_num;
+
+  if (r->reg_flags & RegRex)
+    nr += 8;
+
+  return nr;
+}
+
+static INLINE unsigned int
 mode_from_disp_size (i386_operand_type t)
 {
   if (t.bitfield.disp8)
@@ -2830,12 +2841,7 @@ build_vex_prefix (const insn_template *t
 
   /* Check register specifier.  */
   if (i.vex.register_specifier)
-    {
-      register_specifier = i.vex.register_specifier->reg_num;
-      if ((i.vex.register_specifier->reg_flags & RegRex))
-	register_specifier += 8;
-      register_specifier = ~register_specifier & 0xf;
-    }
+    register_specifier = ~register_number (i.vex.register_specifier) & 0xf;
   else
     register_specifier = 0xf;
 
@@ -2974,16 +2980,15 @@ process_immext (void)
 {
   expressionS *exp;
 
-  if (i.tm.cpu_flags.bitfield.cpusse3 && i.operands > 0)
+  if ((i.tm.cpu_flags.bitfield.cpusse3 || i.tm.cpu_flags.bitfield.cpusvme)
+      && i.operands > 0)
     {
-      /* SSE3 Instructions have the fixed operands with an opcode
-	 suffix which is coded in the same place as an 8-bit immediate
-	 field would be.  Here we check those operands and remove them
-	 afterwards.  */
+      /* MONITOR/MWAIT as well as SVME instructions have fixed operands.
+	 Here we check those operands and remove them afterwards.  */
       unsigned int x;
 
       for (x = 0; x < i.operands; x++)
-	if (i.op[x].regs->reg_num != x)
+	if (register_number (i.op[x].regs) != x)
 	  as_bad (_("can't use register '%s%s' as operand %d in '%s'."),
 		  register_prefix, i.op[x].regs->reg_name, x + 1,
 		  i.tm.name);
@@ -5071,7 +5076,7 @@ process_operands (void)
 	{
 	  /* The first operand is implicit and must be xmm0.  */
 	  gas_assert (operand_type_equal (&i.types[0], &regxmm));
-	  if (i.op[0].regs->reg_num != 0)
+	  if (register_number (i.op[0].regs) != 0)
 	    return bad_implicit_operand (1);
 
 	  if (i.tm.opcode_modifier.vexsources == VEX3SOURCES)
@@ -5145,7 +5150,7 @@ duplicate:
       gas_assert (i.reg_operands
 		  && (operand_type_equal (&i.types[0], &regxmm)
 		      || operand_type_equal (&i.types[0], &regymm)));
-      if (i.op[0].regs->reg_num != 0)
+      if (register_number (i.op[0].regs) != 0)
 	return bad_implicit_operand (i.types[0].bitfield.regxmm);
 
       for (j = 1; j < i.operands; j++)
@@ -5348,10 +5353,7 @@ build_modrm_byte (void)
                       || operand_type_equal (&i.tm.operand_types[reg_slot],
                                              &regymm));
           exp->X_op = O_constant;
-          exp->X_add_number
-              = ((i.op[reg_slot].regs->reg_num
-                  + ((i.op[reg_slot].regs->reg_flags & RegRex) ? 8 : 0))
-		 << 4);
+          exp->X_add_number = register_number (i.op[reg_slot].regs) << 4;
         }
       else
         {
@@ -5395,9 +5397,7 @@ build_modrm_byte (void)
 		      || operand_type_equal (&i.tm.operand_types[reg_slot],
 					     &regymm));
           i.op[imm_slot].imms->X_add_number
-              |= ((i.op[reg_slot].regs->reg_num
-                   + ((i.op[reg_slot].regs->reg_flags & RegRex) ? 8 : 0))
-		  << 4);
+              |= register_number (i.op[reg_slot].regs) << 4;
         }
 
       gas_assert (operand_type_equal (&i.tm.operand_types[nds], &regxmm)
@@ -7310,7 +7310,7 @@ i386_index_check (const char *operand_st
 		   ? i.base_reg->reg_type.bitfield.reg32
 		   : i.base_reg->reg_type.bitfield.reg16))
 	ok = 0;
-      else if (i.base_reg->reg_num != expected)
+      else if (register_number (i.base_reg) != expected)
 	ok = -1;
 
       if (ok < 0)
@@ -7325,7 +7325,7 @@ i386_index_check (const char *operand_st
 		 : (flag_code == CODE_16BIT) ^ !i.prefix[ADDR_PREFIX]
 		   ? i386_regtab[j].reg_type.bitfield.reg32
 		   : i386_regtab[j].reg_type.bitfield.reg16)
-		&& i386_regtab[j].reg_num == expected)
+		&& register_number(i386_regtab + j) == expected)
 	      break;
 	  gas_assert (j < i386_regtab_size);
 	  as_warn (_("`%s' is not valid here (expected `%c%s%s%c')"),
--- 2012-08-07/gas/testsuite/gas/i386/i386.exp	2012-07-24 14:52:59.000000000 +0200
+++ 2012-08-07/gas/testsuite/gas/i386/i386.exp	2012-08-07 11:37:29.000000000 +0200
@@ -374,6 +374,7 @@ if [expr ([istarget "i*86-*-*"] || [ista
     run_dump_test "x86-64-disp-intel"
     run_dump_test "x86-64-disp32"
     run_dump_test "rexw"
+    run_list_test "x86-64-specific-reg"
     run_dump_test "x86-64-fxsave"
     run_dump_test "x86-64-fxsave-intel"
     run_dump_test "x86-64-arch-1"
--- 2012-08-07/gas/testsuite/gas/i386/x86-64-specific-reg.l	1970-01-01 01:00:00.000000000 +0100
+++ 2012-08-07/gas/testsuite/gas/i386/x86-64-specific-reg.l	2012-08-03 15:48:54.000000000 +0200
@@ -0,0 +1,376 @@
+.*: Assembler messages:
+.*:[0-9]*: Warning: .*rax.*rsi.*
+.*:[0-9]*: Warning: .*rax.*rdi.*
+.*:[0-9]*: Warning: .*rax.*rdi.*
+.*:[0-9]*: Warning: .*rax.*rdi.*
+.*:[0-9]*: Warning: .*rax.*rsi.*
+.*:[0-9]*: Warning: .*rax.*rbx.*
+.*:[0-9]*: Warning: .*rax.*rsi.*
+.*:[0-9]*: Warning: .*rax.*rdi.*
+.*:[0-9]*: Warning: .*rax.*rdi.*
+.*:[0-9]*: Warning: .*rax.*rsi.*
+.*:[0-9]*: Error: .*rax.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rax.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rax.* 3 .*monitor.*
+.*:[0-9]*: Error: .*eax.* 2 .*invlpga.*
+.*:[0-9]*: Warning: .*rcx.*rsi.*
+.*:[0-9]*: Warning: .*rcx.*rdi.*
+.*:[0-9]*: Warning: .*rcx.*rdi.*
+.*:[0-9]*: Warning: .*rcx.*rdi.*
+.*:[0-9]*: Warning: .*rcx.*rsi.*
+.*:[0-9]*: Warning: .*rcx.*rbx.*
+.*:[0-9]*: Warning: .*rcx.*rsi.*
+.*:[0-9]*: Warning: .*rcx.*rdi.*
+.*:[0-9]*: Warning: .*rcx.*rdi.*
+.*:[0-9]*: Warning: .*rcx.*rsi.*
+.*:[0-9]*: Error: .*rcx.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rcx.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rcx.* 3 .*monitor.*
+.*:[0-9]*: Error: .*rcx.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rcx.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rcx.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rcx.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*ecx.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*rdx.*rsi.*
+.*:[0-9]*: Warning: .*rdx.*rdi.*
+.*:[0-9]*: Warning: .*rdx.*rdi.*
+.*:[0-9]*: Warning: .*rdx.*rdi.*
+.*:[0-9]*: Warning: .*rdx.*rsi.*
+.*:[0-9]*: Warning: .*rdx.*rbx.*
+.*:[0-9]*: Warning: .*rdx.*rsi.*
+.*:[0-9]*: Warning: .*rdx.*rdi.*
+.*:[0-9]*: Warning: .*rdx.*rdi.*
+.*:[0-9]*: Warning: .*rdx.*rsi.*
+.*:[0-9]*: Error: .*rdx.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rdx.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rdx.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rdx.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rdx.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rdx.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rdx.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rdx.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*edx.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*edx.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*rbx.*rsi.*
+.*:[0-9]*: Warning: .*rbx.*rdi.*
+.*:[0-9]*: Warning: .*rbx.*rdi.*
+.*:[0-9]*: Warning: .*rbx.*rdi.*
+.*:[0-9]*: Warning: .*rbx.*rsi.*
+.*:[0-9]*: Warning: .*rbx.*rsi.*
+.*:[0-9]*: Warning: .*rbx.*rdi.*
+.*:[0-9]*: Warning: .*rbx.*rdi.*
+.*:[0-9]*: Warning: .*rbx.*rsi.*
+.*:[0-9]*: Error: .*rbx.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rbx.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rbx.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rbx.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rbx.* 3 .*monitor.*
+.*:[0-9]*: Error: .*rbx.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rbx.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rbx.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rbx.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*ebx.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*ebx.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*rsp.*rsi.*
+.*:[0-9]*: Warning: .*rsp.*rdi.*
+.*:[0-9]*: Warning: .*rsp.*rdi.*
+.*:[0-9]*: Warning: .*rsp.*rdi.*
+.*:[0-9]*: Warning: .*rsp.*rsi.*
+.*:[0-9]*: Warning: .*rsp.*rbx.*
+.*:[0-9]*: Warning: .*rsp.*rsi.*
+.*:[0-9]*: Warning: .*rsp.*rdi.*
+.*:[0-9]*: Warning: .*rsp.*rdi.*
+.*:[0-9]*: Warning: .*rsp.*rsi.*
+.*:[0-9]*: Error: .*rsp.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rsp.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rsp.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rsp.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rsp.* 3 .*monitor.*
+.*:[0-9]*: Error: .*rsp.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rsp.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rsp.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rsp.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*esp.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*esp.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*rbp.*rsi.*
+.*:[0-9]*: Warning: .*rbp.*rdi.*
+.*:[0-9]*: Warning: .*rbp.*rdi.*
+.*:[0-9]*: Warning: .*rbp.*rdi.*
+.*:[0-9]*: Warning: .*rbp.*rsi.*
+.*:[0-9]*: Warning: .*rbp.*rbx.*
+.*:[0-9]*: Warning: .*rbp.*rsi.*
+.*:[0-9]*: Warning: .*rbp.*rdi.*
+.*:[0-9]*: Warning: .*rbp.*rdi.*
+.*:[0-9]*: Warning: .*rbp.*rsi.*
+.*:[0-9]*: Error: .*rbp.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rbp.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rbp.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rbp.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rbp.* 3 .*monitor.*
+.*:[0-9]*: Error: .*rbp.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rbp.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rbp.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rbp.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*ebp.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*ebp.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*rsi.*rdi.*
+.*:[0-9]*: Warning: .*rsi.*rdi.*
+.*:[0-9]*: Warning: .*rsi.*rdi.*
+.*:[0-9]*: Warning: .*rsi.*rbx.*
+.*:[0-9]*: Warning: .*rsi.*rdi.*
+.*:[0-9]*: Warning: .*rsi.*rdi.*
+.*:[0-9]*: Error: .*rsi.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rsi.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rsi.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rsi.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rsi.* 3 .*monitor.*
+.*:[0-9]*: Error: .*rsi.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rsi.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rsi.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rsi.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*esi.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*esi.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*rdi.*rsi.*
+.*:[0-9]*: Warning: .*rdi.*rsi.*
+.*:[0-9]*: Warning: .*rdi.*rbx.*
+.*:[0-9]*: Warning: .*rdi.*rsi.*
+.*:[0-9]*: Warning: .*rdi.*rsi.*
+.*:[0-9]*: Error: .*rdi.* 1 .*mwait.*
+.*:[0-9]*: Error: .*rdi.* 2 .*mwait.*
+.*:[0-9]*: Error: .*rdi.* 1 .*monitor.*
+.*:[0-9]*: Error: .*rdi.* 2 .*monitor.*
+.*:[0-9]*: Error: .*rdi.* 3 .*monitor.*
+.*:[0-9]*: Error: .*rdi.* 1 .*vmload.*
+.*:[0-9]*: Error: .*rdi.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*rdi.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*rdi.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*edi.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*edi.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r8.*rsi.*
+.*:[0-9]*: Warning: .*r8.*rdi.*
+.*:[0-9]*: Warning: .*r8.*rdi.*
+.*:[0-9]*: Warning: .*r8.*rdi.*
+.*:[0-9]*: Warning: .*r8.*rsi.*
+.*:[0-9]*: Warning: .*r8.*rbx.*
+.*:[0-9]*: Warning: .*r8.*rsi.*
+.*:[0-9]*: Warning: .*r8.*rdi.*
+.*:[0-9]*: Warning: .*r8.*rdi.*
+.*:[0-9]*: Warning: .*r8.*rsi.*
+.*:[0-9]*: Error: .*r8.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r8.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r8.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r8.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r8.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r8.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r8.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r8.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r8.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r8.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r8.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r9.*rsi.*
+.*:[0-9]*: Warning: .*r9.*rdi.*
+.*:[0-9]*: Warning: .*r9.*rdi.*
+.*:[0-9]*: Warning: .*r9.*rdi.*
+.*:[0-9]*: Warning: .*r9.*rsi.*
+.*:[0-9]*: Warning: .*r9.*rbx.*
+.*:[0-9]*: Warning: .*r9.*rsi.*
+.*:[0-9]*: Warning: .*r9.*rdi.*
+.*:[0-9]*: Warning: .*r9.*rdi.*
+.*:[0-9]*: Warning: .*r9.*rsi.*
+.*:[0-9]*: Error: .*r9.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r9.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r9.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r9.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r9.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r9.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r9.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r9.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r9.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r9.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r9.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r10.*rsi.*
+.*:[0-9]*: Warning: .*r10.*rdi.*
+.*:[0-9]*: Warning: .*r10.*rdi.*
+.*:[0-9]*: Warning: .*r10.*rdi.*
+.*:[0-9]*: Warning: .*r10.*rsi.*
+.*:[0-9]*: Warning: .*r10.*rbx.*
+.*:[0-9]*: Warning: .*r10.*rsi.*
+.*:[0-9]*: Warning: .*r10.*rdi.*
+.*:[0-9]*: Warning: .*r10.*rdi.*
+.*:[0-9]*: Warning: .*r10.*rsi.*
+.*:[0-9]*: Error: .*r10.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r10.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r10.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r10.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r10.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r10.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r10.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r10.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r10.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r10.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r10.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r11.*rsi.*
+.*:[0-9]*: Warning: .*r11.*rdi.*
+.*:[0-9]*: Warning: .*r11.*rdi.*
+.*:[0-9]*: Warning: .*r11.*rdi.*
+.*:[0-9]*: Warning: .*r11.*rsi.*
+.*:[0-9]*: Warning: .*r11.*rbx.*
+.*:[0-9]*: Warning: .*r11.*rsi.*
+.*:[0-9]*: Warning: .*r11.*rdi.*
+.*:[0-9]*: Warning: .*r11.*rdi.*
+.*:[0-9]*: Warning: .*r11.*rsi.*
+.*:[0-9]*: Error: .*r11.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r11.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r11.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r11.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r11.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r11.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r11.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r11.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r11.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r11.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r11.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r12.*rsi.*
+.*:[0-9]*: Warning: .*r12.*rdi.*
+.*:[0-9]*: Warning: .*r12.*rdi.*
+.*:[0-9]*: Warning: .*r12.*rdi.*
+.*:[0-9]*: Warning: .*r12.*rsi.*
+.*:[0-9]*: Warning: .*r12.*rbx.*
+.*:[0-9]*: Warning: .*r12.*rsi.*
+.*:[0-9]*: Warning: .*r12.*rdi.*
+.*:[0-9]*: Warning: .*r12.*rdi.*
+.*:[0-9]*: Warning: .*r12.*rsi.*
+.*:[0-9]*: Error: .*r12.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r12.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r12.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r12.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r12.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r12.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r12.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r12.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r12.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r12.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r12.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r13.*rsi.*
+.*:[0-9]*: Warning: .*r13.*rdi.*
+.*:[0-9]*: Warning: .*r13.*rdi.*
+.*:[0-9]*: Warning: .*r13.*rdi.*
+.*:[0-9]*: Warning: .*r13.*rsi.*
+.*:[0-9]*: Warning: .*r13.*rbx.*
+.*:[0-9]*: Warning: .*r13.*rsi.*
+.*:[0-9]*: Warning: .*r13.*rdi.*
+.*:[0-9]*: Warning: .*r13.*rdi.*
+.*:[0-9]*: Warning: .*r13.*rsi.*
+.*:[0-9]*: Error: .*r13.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r13.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r13.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r13.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r13.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r13.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r13.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r13.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r13.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r13.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r13.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r14.*rsi.*
+.*:[0-9]*: Warning: .*r14.*rdi.*
+.*:[0-9]*: Warning: .*r14.*rdi.*
+.*:[0-9]*: Warning: .*r14.*rdi.*
+.*:[0-9]*: Warning: .*r14.*rsi.*
+.*:[0-9]*: Warning: .*r14.*rbx.*
+.*:[0-9]*: Warning: .*r14.*rsi.*
+.*:[0-9]*: Warning: .*r14.*rdi.*
+.*:[0-9]*: Warning: .*r14.*rdi.*
+.*:[0-9]*: Warning: .*r14.*rsi.*
+.*:[0-9]*: Error: .*r14.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r14.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r14.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r14.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r14.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r14.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r14.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r14.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r14.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r14.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r14.* 1 .*skinit.*
+.*:[0-9]*: Warning: .*r15.*rsi.*
+.*:[0-9]*: Warning: .*r15.*rdi.*
+.*:[0-9]*: Warning: .*r15.*rdi.*
+.*:[0-9]*: Warning: .*r15.*rdi.*
+.*:[0-9]*: Warning: .*r15.*rsi.*
+.*:[0-9]*: Warning: .*r15.*rbx.*
+.*:[0-9]*: Warning: .*r15.*rsi.*
+.*:[0-9]*: Warning: .*r15.*rdi.*
+.*:[0-9]*: Warning: .*r15.*rdi.*
+.*:[0-9]*: Warning: .*r15.*rsi.*
+.*:[0-9]*: Error: .*r15.* 1 .*mwait.*
+.*:[0-9]*: Error: .*r15.* 2 .*mwait.*
+.*:[0-9]*: Error: .*r15.* 1 .*monitor.*
+.*:[0-9]*: Error: .*r15.* 2 .*monitor.*
+.*:[0-9]*: Error: .*r15.* 3 .*monitor.*
+.*:[0-9]*: Error: .*r15.* 1 .*vmload.*
+.*:[0-9]*: Error: .*r15.* 1 .*vmrun.*
+.*:[0-9]*: Error: .*r15.* 1 .*vmsave.*
+.*:[0-9]*: Error: .*r15.* 1 .*invlpga.*
+.*:[0-9]*: Error: .*r15.* 2 .*invlpga.*
+.*:[0-9]*: Error: .*r15.* 1 .*skinit.*
+# xmm1
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm2
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm3
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm4
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm5
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm6
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm7
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm8
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm9
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm10
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm11
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm12
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm13
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm14
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
+# xmm15
+.*:[0-9]*: Error: .*blendvpd.*xmm0.*
+.*:[0-9]*: Error: .*blendvps.*xmm0.*
+.*:[0-9]*: Error: .*pblendv.*xmm0.*
--- 2012-08-07/gas/testsuite/gas/i386/x86-64-specific-reg.s	1970-01-01 01:00:00.000000000 +0100
+++ 2012-08-07/gas/testsuite/gas/i386/x86-64-specific-reg.s	2012-08-03 15:49:41.000000000 +0200
@@ -0,0 +1,90 @@
+# 64bit insns with special register requirements
+
+	.text
+special:
+.irp reg1, ax, cx, dx, bx, sp, bp, si, di
+	lodsb	%ds:(%r\reg1)
+
+	stosb	%es:(%r\reg1)
+
+	scasb	%es:(%r\reg1)
+
+	insb	%dx, %es:(%r\reg1)
+
+	outsb	%ds:(%r\reg1), %dx
+
+	xlatb	%ds:(%r\reg1)
+
+	movsb	%ds:(%r\reg1), %es:(%rdi)
+	movsb	%ds:(%rsi), %es:(%r\reg1)
+
+	cmpsb	%es:(%r\reg1), %ds:(%rsi)
+	cmpsb	%es:(%rdi), %ds:(%r\reg1)
+
+	mwait	%r\reg1, %rcx
+	mwait	%rax, %r\reg1
+
+	monitor	%r\reg1, %rcx, %rdx
+	monitor	%rax, %r\reg1, %rdx
+	monitor	%rax, %rcx, %r\reg1
+
+# FIXME: Need to ensure only "vmload %[re]ax" is accepted.
+	vmload	%r\reg1
+
+# FIXME: Need to ensure only "vmrun %[re]ax" is accepted.
+	vmrun	%r\reg1
+
+# FIXME: Need to ensure only "vmsave %[re]ax" is accepted.
+	vmsave	%r\reg1
+
+# FIXME: Need to ensure only "invlpga %[re]ax,%ecx" is accepted.
+	invlpga	%r\reg1, %ecx
+	invlpga	%rax, %e\reg1
+
+# FIXME: Need to ensure only "skinit %eax" is accepted.
+	skinit	%e\reg1
+.endr
+
+.irp reg1, 8, 9, 10, 11, 12, 13, 14, 15
+	lodsb	%ds:(%r\reg1)
+
+	stosb	%es:(%r\reg1)
+
+	scasb	%es:(%r\reg1)
+
+	insb	%dx, %es:(%r\reg1)
+
+	outsb	%ds:(%r\reg1), %dx
+
+	xlatb	%ds:(%r\reg1)
+
+	movsb	%ds:(%r\reg1), %es:(%rdi)
+	movsb	%ds:(%rsi), %es:(%r\reg1)
+
+	cmpsb	%es:(%r\reg1), %ds:(%rsi)
+	cmpsb	%es:(%rdi), %ds:(%r\reg1)
+
+	mwait	%r\reg1, %rcx
+	mwait	%rax, %r\reg1
+
+	monitor	%r\reg1, %rcx, %rdx
+	monitor	%rax, %r\reg1, %rdx
+	monitor	%rax, %rcx, %r\reg1
+
+	vmload	%r\reg1
+
+	vmrun	%r\reg1
+
+	vmsave	%r\reg1
+
+	invlpga	%r\reg1, %ecx
+	invlpga	%rax, %r\reg1\(d)
+
+	skinit	%r\reg1\(d)
+.endr
+
+.irp n, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+	blendvpd %xmm\n, %xmm\n, %xmm\n
+	blendvps %xmm\n, %xmm\n, %xmm\n
+	pblendvb %xmm\n, %xmm\n, %xmm\n
+.endr
--- 2012-08-07/opcodes/i386-opc.tbl	2012-07-31 09:37:43.000000000 +0200
+++ 2012-08-07/opcodes/i386-opc.tbl	2012-08-07 11:37:29.000000000 +0200
@@ -3004,21 +3004,16 @@ rdtscp, 0, 0xf01, 0xf9, 2, CpuRdtscp, No
 // AMD Pacifica additions.
 clgi, 0, 0xf01, 0xdd, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
 invlpga, 0, 0xf01, 0xdf, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
-// FIXME: Need to ensure only "invlpga %[re]ax,%ecx" is accepted.
 invlpga, 2, 0xf01, 0xdf, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt|AddrPrefixOp0|NoRex64, { Reg32|Reg64, Reg32 }
 skinit, 0, 0xf01, 0xde, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
-// FIXME: Need to ensure only "skinit %eax" is accepted.
 skinit, 1, 0xf01, 0xde, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { Reg32 }
 stgi, 0, 0xf01, 0xdc, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
 vmload, 0, 0xf01, 0xda, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
-// FIXME: Need to ensure only "vmload %[re]ax" is accepted.
 vmload, 1, 0xf01, 0xda, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt|AddrPrefixOp0|NoRex64, { Reg32|Reg64 }
 vmmcall, 0, 0xf01, 0xd9, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
 vmrun, 0, 0xf01, 0xd8, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
-// FIXME: Need to ensure only "vmrun %[re]ax" is accepted.
 vmrun, 1, 0xf01, 0xd8, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt|AddrPrefixOp0|NoRex64, { Reg32|Reg64 }
 vmsave, 0, 0xf01, 0xdb, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt, { 0 }
-// FIXME: Need to ensure only "vmsave %[re]ax" is accepted.
 vmsave, 1, 0xf01, 0xdb, 2, CpuSVME, No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|ImmExt|AddrPrefixOp0|NoRex64, { Reg32|Reg64 }
 
 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH, v2] gas/x86-64: properly distinguish low and high register ranges
  2012-08-07 10:29               ` [PATCH, v2] " Jan Beulich
@ 2012-08-07 14:02                 ` H.J. Lu
  0 siblings, 0 replies; 9+ messages in thread
From: H.J. Lu @ 2012-08-07 14:02 UTC (permalink / raw)
  To: Jan Beulich; +Cc: binutils

On Tue, Aug 7, 2012 at 3:24 AM, Jan Beulich <JBeulich@suse.com> wrote:
>>>> On 31.07.12 at 20:45, "H.J. Lu" <hjl.tools@gmail.com> wrote:
>> I'd like to see the impact of broken behaviors and verify that
>> the change fixes them.
>
> Here you go.
>
> Jan
>
> There were several cases where the registers in the REX encoded range
> got treated identically to the ones in the base range, due to not
> paying attention to the fact that reg_entry's reg_num field doesn't
> fully specify the register number (reg_flags also needs to be checked
> for RegRex). This patch introduces and uses a new (inline) function to
> obtain the full register number, and uses it to fix all those cases.
>
> It additionally adds the missing operand checks for SVME instructions
> (which match the monitor/mwait ones).
>
> gas/
> 2012-08-07  Jan Beulich <jbeulich@suse.com>
>
>         * config/tc-i386.c (register_number): New function.
>         (build_vex_prefix, process_immext, process_operands,
>         build_modrm_byte, i386_index_check): Use it.
>
> gas/testsuite/
> 2012-08-07  Jan Beulich <jbeulich@suse.com>
>
>         * gas/i386/x86-64-specific-reg.{s,l}: New.
>         * gas/i386/i386.exp: Run new test.
>
> opcodes/
> 2012-08-07  Jan Beulich <jbeulich@suse.com>
>
>         * i386-opc.tbl: Remove "FIXME" comments from SVME instructions.
>
> --- 2012-08-07/gas/config/tc-i386.c     2012-07-31 09:45:03.000000000 +0200
> +++ 2012-08-07/gas/config/tc-i386.c     2012-08-07 11:37:29.000000000 +0200
> @@ -1758,6 +1758,17 @@ operand_type_register_match (i386_operan
>  }
>
>  static INLINE unsigned int
> +register_number (const reg_entry *r)
> +{
> +  unsigned int nr = r->reg_num;
> +
> +  if (r->reg_flags & RegRex)
> +    nr += 8;
> +
> +  return nr;
> +}
> +
> +static INLINE unsigned int
>  mode_from_disp_size (i386_operand_type t)
>  {
>    if (t.bitfield.disp8)
> @@ -2830,12 +2841,7 @@ build_vex_prefix (const insn_template *t
>
>    /* Check register specifier.  */
>    if (i.vex.register_specifier)
> -    {
> -      register_specifier = i.vex.register_specifier->reg_num;
> -      if ((i.vex.register_specifier->reg_flags & RegRex))
> -       register_specifier += 8;
> -      register_specifier = ~register_specifier & 0xf;
> -    }
> +    register_specifier = ~register_number (i.vex.register_specifier) & 0xf;
>    else
>      register_specifier = 0xf;
>
> @@ -2974,16 +2980,15 @@ process_immext (void)
>  {
>    expressionS *exp;
>
> -  if (i.tm.cpu_flags.bitfield.cpusse3 && i.operands > 0)
> +  if ((i.tm.cpu_flags.bitfield.cpusse3 || i.tm.cpu_flags.bitfield.cpusvme)
> +      && i.operands > 0)
>      {
> -      /* SSE3 Instructions have the fixed operands with an opcode
> -        suffix which is coded in the same place as an 8-bit immediate
> -        field would be.  Here we check those operands and remove them
> -        afterwards.  */
> +      /* MONITOR/MWAIT as well as SVME instructions have fixed operands.
> +        Here we check those operands and remove them afterwards.  */
>        unsigned int x;
>

Please keep "with an opcode suffix which is coded in the same place
as an 8-bit immediate field would be."  OK with this change.

Thanks.


-- 
H.J.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2012-08-07 13:56 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-24 14:14 [PATCH] gas/x86-64: properly distinguish low and high register ranges Jan Beulich
     [not found] ` <CAMe9rOrY+ECKpfYM23heJB4Ma1BT9aFd2+-z1oVdhq3EiXwdRQ@mail.gmail.com>
2012-07-25  6:56   ` Jan Beulich
2012-07-30 16:05     ` H.J. Lu
2012-07-31  6:24       ` Jan Beulich
2012-07-31 15:49         ` H.J. Lu
2012-07-31 16:28           ` Jan Beulich
2012-07-31 18:45             ` H.J. Lu
2012-08-07 10:29               ` [PATCH, v2] " Jan Beulich
2012-08-07 14:02                 ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).