Properly handle ".equ symbol, reg + NUM" in x86 Intel syntax.
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 21 Apr 2010 18:09:52 +0000 (18:09 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 21 Apr 2010 18:09:52 +0000 (18:09 +0000)
gas/

2010-04-21  H.J. Lu  <hongjiu.lu@intel.com>

PR gas/11509
* config/tc-i386-intel.c (i386_intel_simplify_register): New.
(i386_intel_simplify): Use i386_is_register and
i386_intel_simplify_register. Set X_md for O_register and
check X_md for O_constant.
(i386_intel_operand): Use i386_is_register.

* config/tc-i386.c (i386_is_register): New.
(x86_cons): Initialize the X_md field.  Use i386_is_register.
(parse_register): Use i386_is_register.
(tc_x86_parse_to_dw2regnum): Likewise.

gas/testsuite/

2010-04-21  H.J. Lu  <hongjiu.lu@intel.com>

PR gas/11509
* gas/i386/equ.s: Add tests for ".equ symbol, reg + NUM".
* gas/i386/equ.d: Updated.

gas/ChangeLog
gas/config/tc-i386-intel.c
gas/config/tc-i386.c
gas/read.c
gas/testsuite/ChangeLog
gas/testsuite/gas/i386/equ.d
gas/testsuite/gas/i386/equ.s

index 8dcc359..2514b28 100644 (file)
@@ -1,5 +1,19 @@
 2010-04-21  H.J. Lu  <hongjiu.lu@intel.com>
 
+       PR gas/11509
+       * config/tc-i386-intel.c (i386_intel_simplify_register): New.
+       (i386_intel_simplify): Use i386_is_register and
+       i386_intel_simplify_register. Set X_md for O_register and
+       check X_md for O_constant.
+       (i386_intel_operand): Use i386_is_register.
+
+       * config/tc-i386.c (i386_is_register): New.
+       (x86_cons): Initialize the X_md field.  Use i386_is_register.
+       (parse_register): Use i386_is_register.
+       (tc_x86_parse_to_dw2regnum): Likewise.
+
+2010-04-21  H.J. Lu  <hongjiu.lu@intel.com>
+
        * expr.c (expr): Initialize the X_md field.
 
 2010-04-20  Joseph Myers  <joseph@codesourcery.com>
index b3cdcd3..cb99518 100644 (file)
@@ -233,6 +233,49 @@ static INLINE void i386_intel_fold (expressionS *e, symbolS *sym)
     }
 }
 
+static int
+i386_intel_simplify_register (expressionS *e)
+{
+  int reg_num;
+
+  if (this_operand < 0 || intel_state.in_offset)
+    {
+      as_bad (_("invalid use of register"));
+      return 0;
+    }
+
+  if (e->X_op == O_register)
+    reg_num = e->X_add_number;
+  else
+    reg_num = e->X_md - 1;
+
+  if (!intel_state.in_bracket)
+    {
+      if (i.op[this_operand].regs)
+       {
+         as_bad (_("invalid use of register"));
+         return 0;
+       }
+      if (i386_regtab[reg_num].reg_type.bitfield.sreg3
+         && i386_regtab[reg_num].reg_num == RegFlat)
+       {
+         as_bad (_("invalid use of pseudo-register"));
+         return 0;
+       }
+      i.op[this_operand].regs = i386_regtab + reg_num;
+    }
+  else if (!intel_state.base && !intel_state.in_scale)
+    intel_state.base = i386_regtab + reg_num;
+  else if (!intel_state.index)
+    intel_state.index = i386_regtab + reg_num;
+  else
+    {
+      /* esp is invalid as index */
+      intel_state.index = i386_regtab + REGNAM_EAX + 4;
+    }
+  return 2;
+}
+
 static int i386_intel_simplify (expressionS *);
 
 static INLINE int i386_intel_simplify_symbol(symbolS *sym)
@@ -304,7 +347,8 @@ static int i386_intel_simplify (expressionS *e)
        intel_state.op_modifier = e->X_op;
       /* FALLTHROUGH */
     case O_short:
-      if (symbol_get_value_expression (e->X_add_symbol)->X_op == O_register)
+      if (i386_is_register (symbol_get_value_expression (e->X_add_symbol),
+                           1))
        {
          as_bad (_("invalid use of register"));
          return 0;
@@ -315,7 +359,8 @@ static int i386_intel_simplify (expressionS *e)
       break;
 
     case O_full_ptr:
-      if (symbol_get_value_expression (e->X_op_symbol)->X_op == O_register)
+      if (i386_is_register (symbol_get_value_expression (e->X_op_symbol),
+                           1))
        {
          as_bad (_("invalid use of register"));
          return 0;
@@ -328,40 +373,6 @@ static int i386_intel_simplify (expressionS *e)
       i386_intel_fold (e, e->X_op_symbol);
       break;
 
-    case O_register:
-      if (this_operand < 0 || intel_state.in_offset)
-       {
-         as_bad (_("invalid use of register"));
-         return 0;
-       }
-      if (!intel_state.in_bracket)
-       {
-         if (i.op[this_operand].regs)
-           {
-             as_bad (_("invalid use of register"));
-             return 0;
-           }
-         if (i386_regtab[e->X_add_number].reg_type.bitfield.sreg3
-             && i386_regtab[e->X_add_number].reg_num == RegFlat)
-           {
-             as_bad (_("invalid use of pseudo-register"));
-             return 0;
-           }
-         i.op[this_operand].regs = i386_regtab + e->X_add_number;
-       }
-      else if (!intel_state.base && !intel_state.in_scale)
-       intel_state.base = i386_regtab + e->X_add_number;
-      else if (!intel_state.index)
-       intel_state.index = i386_regtab + e->X_add_number;
-      else
-       {
-         /* esp is invalid as index */
-         intel_state.index = i386_regtab + REGNAM_EAX + 4;
-       }
-      e->X_op = O_constant;
-      e->X_add_number = 0;
-      return 2;
-
     case O_multiply:
       if (this_operand >= 0 && intel_state.in_bracket)
        {
@@ -418,6 +429,22 @@ static int i386_intel_simplify (expressionS *e)
 
          break;
        }
+
+    case O_register:
+      ret = i386_intel_simplify_register (e);
+      if (ret == 2)
+       {
+         gas_assert (e->X_add_number < (unsigned short) -1);
+         e->X_md = (unsigned short) e->X_add_number + 1;
+         e->X_op = O_constant;
+         e->X_add_number = 0;
+       }
+      return ret;
+
+    case O_constant:
+      if (e->X_md)
+       return i386_intel_simplify_register (e);
+
       /* FALLTHROUGH */
     default:
       if (e->X_add_symbol && !i386_intel_simplify_symbol (e->X_add_symbol))
@@ -832,7 +859,7 @@ i386_intel_operand (char *operand_string, int got_a_float)
                break;
              intel_state.seg = expP->X_add_symbol;
            }
-         if (expP->X_op != O_register)
+         if (!i386_is_register (expP, 1))
            {
              as_bad (_("segment register name expected"));
              return 0;
index db50c62..1728e60 100644 (file)
@@ -3534,6 +3534,15 @@ swap_operands (void)
     }
 }
 
+static int
+i386_is_register (const expressionS *e, int is_intel_syntax)
+{
+  return (e->X_op == O_register
+         || (is_intel_syntax
+             && e->X_op == O_constant
+             && e->X_md));
+}
+
 /* Try to ensure constant immediates are represented in the smallest
    opcode possible.  */
 static void
@@ -6451,6 +6460,7 @@ x86_cons (expressionS *exp, int size)
 {
   intel_syntax = -intel_syntax;
 
+  exp->X_md = 0;
   if (size == 4 || (object_64bit && size == 8))
     {
       /* Handle @GOTOFF and the like in an expression.  */
@@ -6477,7 +6487,7 @@ x86_cons (expressionS *exp, int size)
          if (exp->X_op == O_constant
              || exp->X_op == O_absent
              || exp->X_op == O_illegal
-             || exp->X_op == O_register
+             || i386_is_register (exp, intel_syntax)
              || exp->X_op == O_big)
            {
              char c = *input_line_pointer;
@@ -7956,7 +7966,7 @@ parse_register (char *reg_string, char **end_op)
        {
          const expressionS *e = symbol_get_value_expression (symbolP);
 
-         know (e->X_op == O_register);
+         know (i386_is_register (e, intel_syntax));
          know (e->X_add_number >= 0
                && (valueT) e->X_add_number < i386_regtab_size);
          r = i386_regtab + e->X_add_number;
@@ -8863,7 +8873,7 @@ tc_x86_parse_to_dw2regnum (expressionS *exp)
   register_chars['.'] = saved_register_dot;
   allow_naked_reg = saved_naked_reg;
 
-  if (exp->X_op == O_register && exp->X_add_number >= 0)
+  if (i386_is_register (exp, intel_syntax) && exp->X_add_number >= 0)
     {
       if ((addressT) exp->X_add_number < i386_regtab_size)
        {
index 4afb190..ae0dbb8 100644 (file)
@@ -471,6 +471,7 @@ get_absolute_expression (void)
 {
   expressionS exp;
 
+  exp.X_md = 0;
   return get_absolute_expr (&exp);
 }
 
index f5522ad..9b36f2a 100644 (file)
@@ -1,3 +1,9 @@
+2010-04-21  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR gas/11509
+       * gas/i386/equ.s: Add tests for ".equ symbol, reg + NUM".
+       * gas/i386/equ.d: Updated.
+
 2010-04-20  Nick Clifton  <nickc@redhat.com>
 
        PR gas/11507
index c23616f..0f270a6 100644 (file)
@@ -22,4 +22,6 @@ Disassembly of section .text:
 [ 0-9a-f]+:[   0-9a-f]+mov[    ]+%gs:\(%edx,%edx,8\),%edx
 [ 0-9a-f]+:[   0-9a-f]+fadd[   ]+%st\(1\),%st
 [ 0-9a-f]+:[   0-9a-f]+fadd[   ]+%st\(7\),%st
+[ 0-9a-f]+:[   0-9a-f]+mov[    ]+0x4\(%edx\),%eax
+[ 0-9a-f]+:[   0-9a-f]+mov[    ]+0x4\(%edx\),%eax
 #pass
index 94ec81d..e15148a 100644 (file)
@@ -39,6 +39,9 @@ _start:
        fadd    x
  .equ x, st(7)
        fadd    x
+ .equ r, edx + 4
+       mov     eax, [r]
+       mov     eax, [r]
 
  .if s <> gs
  .err