This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: PR gas/11509: Strange evaluation of symbol containing register


Hi,

I checked in this patch to handle ".equ symbol, reg + NUM" in x86 Intel
syntax.  The problem is "reg + NUM" is evaluated and fully resolved at
the first use. This patch stores the register information in X_md
and handles it in i386_intel_simplify_register. However, my patch
doesn't fix

[hjl@gnu-6 pr11509]$ cat 1.s
.intel_syntax noprefix

.eqv param, ebp-4
[hjl@gnu-6 pr11509]$ ./as --32 -o 1.o 1.s
1.s: Assembler messages:
1.s:3: Error: can't make global register symbol `param'
[hjl@gnu-6 pr11509]$ 

I have no plan to fix it.

Thanks.


H.J.
---
Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/gas/ChangeLog,v
retrieving revision 1.4136
diff -u -p -r1.4136 ChangeLog
--- ChangeLog	21 Apr 2010 17:10:42 -0000	1.4136
+++ ChangeLog	21 Apr 2010 18:08:18 -0000
@@ -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: config/tc-i386-intel.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386-intel.c,v
retrieving revision 1.9
diff -u -p -r1.9 tc-i386-intel.c
--- config/tc-i386-intel.c	11 Dec 2009 13:42:10 -0000	1.9
+++ config/tc-i386-intel.c	21 Apr 2010 18:08:19 -0000
@@ -233,6 +233,49 @@ static INLINE void i386_intel_fold (expr
     }
 }
 
+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 (expressi
 	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 (expressi
       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 (expressi
       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 (expressi
 
 	  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
 		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: config/tc-i386.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386.c,v
retrieving revision 1.431
diff -u -p -r1.431 tc-i386.c
--- config/tc-i386.c	22 Mar 2010 13:49:50 -0000	1.431
+++ config/tc-i386.c	21 Apr 2010 18:08:19 -0000
@@ -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 *
 	{
 	  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 *
   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: testsuite/ChangeLog
===================================================================
RCS file: /cvs/src/src/gas/testsuite/ChangeLog,v
retrieving revision 1.1657
diff -u -p -r1.1657 ChangeLog
--- testsuite/ChangeLog	20 Apr 2010 15:54:48 -0000	1.1657
+++ testsuite/ChangeLog	21 Apr 2010 18:08:19 -0000
@@ -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: testsuite/gas/i386/equ.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/i386/equ.d,v
retrieving revision 1.3
diff -u -p -r1.3 equ.d
--- testsuite/gas/i386/equ.d	20 Apr 2009 06:31:50 -0000	1.3
+++ testsuite/gas/i386/equ.d	21 Apr 2010 18:08:19 -0000
@@ -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: testsuite/gas/i386/equ.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/i386/equ.s,v
retrieving revision 1.4
diff -u -p -r1.4 equ.s
--- testsuite/gas/i386/equ.s	20 Apr 2009 06:31:50 -0000	1.4
+++ testsuite/gas/i386/equ.s	21 Apr 2010 18:08:19 -0000
@@ -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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]