2003-09-09 Dave Brolley <brolley@redhat.com>
[deliverable/binutils-gdb.git] / gas / expr.c
index 74c49d9c7bf721aec4ea2ba9f690f9b38eb3196d..58db726191ebeb08ab5e987ed18ce4f07396130c 100644 (file)
@@ -1,6 +1,6 @@
 /* expr.c -operands, expressions-
    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001
+   1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -67,7 +67,6 @@ make_expr_symbol (expressionP)
      expressionS *expressionP;
 {
   expressionS zero;
-  const char *fake;
   symbolS *symbolP;
   struct expr_symbol_line *n;
 
@@ -78,8 +77,8 @@ make_expr_symbol (expressionP)
   if (expressionP->X_op == O_big)
     {
       /* This won't work, because the actual value is stored in
-         generic_floating_point_number or generic_bignum, and we are
-         going to lose it if we haven't already.  */
+        generic_floating_point_number or generic_bignum, and we are
+        going to lose it if we haven't already.  */
       if (expressionP->X_add_number > 0)
        as_bad (_("bignum invalid"));
       else
@@ -91,13 +90,11 @@ make_expr_symbol (expressionP)
       expressionP = &zero;
     }
 
-  fake = FAKE_LABEL_NAME;
-
   /* Putting constant symbols in absolute_section rather than
      expr_section is convenient for the old a.out code, for which
      S_GET_SEGMENT does not always retrieve the value put in by
      S_SET_SEGMENT.  */
-  symbolP = symbol_create (fake,
+  symbolP = symbol_create (FAKE_LABEL_NAME,
                           (expressionP->X_op == O_constant
                            ? absolute_section
                            : expr_section),
@@ -329,8 +326,8 @@ integer_constant (radix, expressionP)
       int flt = 0;
 
       /* In MRI mode, the number may have a suffix indicating the
-         radix.  For that matter, it might actually be a floating
-         point constant.  */
+        radix.  For that matter, it might actually be a floating
+        point constant.  */
       for (suffix = input_line_pointer; ISALNUM (*suffix); suffix++)
        {
          if (*suffix == 'e' || *suffix == 'E')
@@ -401,7 +398,7 @@ integer_constant (radix, expressionP)
   if (radix == 16 && c == '_')
     {
       /* This is literal of the form 0x333_0_12345678_1.
-         This example is equivalent to 0x00000333000000001234567800000001.  */
+        This example is equivalent to 0x00000333000000001234567800000001.  */
 
       int num_little_digits = 0;
       int i;
@@ -681,8 +678,8 @@ mri_char_constant (expressionP)
       if (i < SIZE_OF_LARGE_NUMBER - 1)
        {
          /* If there is more than one littlenum, left justify the
-             last one to make it match the earlier ones.  If there is
-             only one, we can just use the value directly.  */
+            last one to make it match the earlier ones.  If there is
+            only one, we can just use the value directly.  */
          for (; j < CHARS_PER_LITTLENUM; j++)
            generic_bignum[i] <<= 8;
        }
@@ -745,13 +742,8 @@ current_location (expressionp)
     }
   else
     {
-      symbolS *symbolp;
-
-      symbolp = symbol_new (FAKE_LABEL_NAME, now_seg,
-                           (valueT) frag_now_fix (),
-                           frag_now);
       expressionp->X_op = O_symbol;
-      expressionp->X_add_symbol = symbolp;
+      expressionp->X_add_symbol = symbol_temp_new_now ();
       expressionp->X_add_number = 0;
     }
 }
@@ -803,7 +795,7 @@ operand (expressionP)
 
       integer_constant ((NUMBERS_WITH_SUFFIX || flag_m68k_mri)
                        ? 0 : 10,
-                        expressionP);
+                       expressionP);
       break;
 
 #ifdef LITERAL_PREFIXDOLLAR_HEX
@@ -828,10 +820,10 @@ operand (expressionP)
        {
          char *s;
 
-         /* Check for a hex constant.  */
+         /* Check for a hex or float constant.  */
          for (s = input_line_pointer; hex_p (*s); s++)
            ;
-         if (*s == 'h' || *s == 'H')
+         if (*s == 'h' || *s == 'H' || *input_line_pointer == '.')
            {
              --input_line_pointer;
              integer_constant (0, expressionP);
@@ -1079,6 +1071,18 @@ operand (expressionP)
            else
              expressionP->X_add_number = ! expressionP->X_add_number;
          }
+       else if (expressionP->X_op == O_big
+                && expressionP->X_add_number <= 0
+                && c == '-'
+                && (generic_floating_point_number.sign == '+'
+                    || generic_floating_point_number.sign == 'P'))
+         {
+           /* Negative flonum (eg, -1.000e0).  */
+           if (generic_floating_point_number.sign == '+')
+             generic_floating_point_number.sign = '-';
+           else
+             generic_floating_point_number.sign = 'N';
+         }
        else if (expressionP->X_op != O_illegal
                 && expressionP->X_op != O_absent)
          {
@@ -1100,7 +1104,7 @@ operand (expressionP)
 #if defined (DOLLAR_DOT) || defined (TC_M68K)
     case '$':
       /* '$' is the program counter when in MRI mode, or when
-         DOLLAR_DOT is defined.  */
+        DOLLAR_DOT is defined.  */
 #ifndef DOLLAR_DOT
       if (! flag_m68k_mri)
        goto de_fault;
@@ -1108,7 +1112,7 @@ operand (expressionP)
       if (flag_m68k_mri && hex_p (*input_line_pointer))
        {
          /* In MRI mode, '$' is also used as the prefix for a
-             hexadecimal constant.  */
+            hexadecimal constant.  */
          integer_constant (16, expressionP);
          break;
        }
@@ -1199,7 +1203,7 @@ operand (expressionP)
        goto de_fault;
 
       /* In MRI mode, this is a floating point constant represented
-         using hexadecimal digits.  */
+        using hexadecimal digits.  */
 
       ++input_line_pointer;
       integer_constant (16, expressionP);
@@ -1227,9 +1231,9 @@ operand (expressionP)
 
 #ifdef md_parse_name
          /* This is a hook for the backend to parse certain names
-             specially in certain contexts.  If a name always has a
-             specific value, it can often be handled by simply
-             entering it in the symbol table.  */
+            specially in certain contexts.  If a name always has a
+            specific value, it can often be handled by simply
+            entering it in the symbol table.  */
          if (md_parse_name (name, expressionP, &c))
            {
              *input_line_pointer = c;
@@ -1347,8 +1351,6 @@ operand (expressionP)
        Elsewise we waste time special-case testing. Sigh. Ditto SEG_ABSENT.
 
    Out:        expressionS may have been modified:
-       'foo-foo' symbol references cancelled to 0, which changes X_op
-       from O_subtract to O_constant.
        Unused fields zeroed to help expr ().  */
 
 static void
@@ -1371,23 +1373,6 @@ clean_up_expression (expressionP)
     case O_bit_not:
       expressionP->X_op_symbol = NULL;
       break;
-    case O_subtract:
-      if (expressionP->X_op_symbol == expressionP->X_add_symbol
-         || ((symbol_get_frag (expressionP->X_op_symbol)
-              == symbol_get_frag (expressionP->X_add_symbol))
-             && SEG_NORMAL (S_GET_SEGMENT (expressionP->X_add_symbol))
-             && (S_GET_VALUE (expressionP->X_op_symbol)
-                 == S_GET_VALUE (expressionP->X_add_symbol))))
-       {
-         addressT diff = (S_GET_VALUE (expressionP->X_add_symbol)
-                          - S_GET_VALUE (expressionP->X_op_symbol));
-
-         expressionP->X_op = O_constant;
-         expressionP->X_add_symbol = NULL;
-         expressionP->X_op_symbol = NULL;
-         expressionP->X_add_number += diff;
-       }
-      break;
     default:
       break;
     }
@@ -1659,6 +1644,10 @@ expr (rankarg, resultP)
 
   know (rank >= 0);
 
+  /* Save the value of dot for the fixup code.  */
+  if (rank == 0)
+    dot_value = frag_now_fix ();
+
   retval = operand (resultP);
 
   /* operand () gobbles spaces.  */
@@ -1749,7 +1738,8 @@ expr (rankarg, resultP)
               && resultP->X_op == O_symbol
               && (symbol_get_frag (right.X_add_symbol)
                   == symbol_get_frag (resultP->X_add_symbol))
-              && SEG_NORMAL (rightseg))
+              && (SEG_NORMAL (rightseg)
+                  || right.X_add_symbol == resultP->X_add_symbol))
        {
          resultP->X_add_number -= right.X_add_number;
          resultP->X_add_number += (S_GET_VALUE (resultP->X_add_symbol)
@@ -1789,7 +1779,7 @@ expr (rankarg, resultP)
            case O_left_shift:          resultP->X_add_number <<= v; break;
            case O_right_shift:
              /* We always use unsigned shifts, to avoid relying on
-                 characteristics of the compiler used to compile gas.  */
+                characteristics of the compiler used to compile gas.  */
              resultP->X_add_number =
                (offsetT) ((valueT) resultP->X_add_number >> (valueT) v);
              break;
This page took 0.026494 seconds and 4 git commands to generate.