]> Git Repo - binutils.git/blobdiff - gas/expr.c
config.guess: Recognize vax hosts. (Sent to RMS.)
[binutils.git] / gas / expr.c
index a88780bcf6ea8ceaf106a61dd72a3efb267d5fb2..f35f8eee7769695f7bec00afbc0ea6d8005feeea 100644 (file)
@@ -31,6 +31,8 @@
 
 #include "obstack.h"
 
+static void floating_constant PARAMS ((expressionS * expressionP));
+static void integer_constant PARAMS ((int radix, expressionS * expressionP));
 static void clean_up_expression PARAMS ((expressionS * expressionP));
 static symbolS *make_expr_symbol PARAMS ((expressionS * expressionP));
 
@@ -49,11 +51,8 @@ make_expr_symbol (expressionP)
 
   /* FIXME: This should be something which decode_local_label_name
      will handle.  */
-#ifdef DOT_LABEL_PREFIX
-  fake = ".L0\001";
-#else
-  fake = "L0\001";
-#endif
+  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
@@ -81,7 +80,7 @@ LITTLENUM_TYPE generic_bignum[SIZE_OF_LARGE_NUMBER + 6];
 FLONUM_TYPE generic_floating_point_number =
 {
   &generic_bignum[6],          /* low (JF: Was 0) */
-  &generic_bignum[SIZE_OF_LARGE_NUMBER + 6 - 1],       /* high JF: (added +6) */
+  &generic_bignum[SIZE_OF_LARGE_NUMBER + 6 - 1], /* high JF: (added +6) */
   0,                           /* leader */
   0,                           /* exponent */
   0                            /* sign */
@@ -89,7 +88,7 @@ FLONUM_TYPE generic_floating_point_number =
 /* If nonzero, we've been asked to assemble nan, +inf or -inf */
 int generic_floating_point_magic;
 \f
-void
+static void
 floating_constant (expressionP)
      expressionS *expressionP;
 {
@@ -97,9 +96,8 @@ floating_constant (expressionP)
   /* floating-point constant. */
   int error_code;
 
-  error_code = atof_generic
-    (&input_line_pointer, ".", EXP_CHARS,
-     &generic_floating_point_number);
+  error_code = atof_generic (&input_line_pointer, ".", EXP_CHARS,
+                            &generic_floating_point_number);
 
   if (error_code)
     {
@@ -118,12 +116,12 @@ floating_constant (expressionP)
   expressionP->X_add_number = -1;
 }
 
-void
+static void
 integer_constant (radix, expressionP)
      int radix;
      expressionS *expressionP;
 {
-  char *digit_2;       /*->2nd digit of number. */
+  char *start;         /* start of number. */
   char c;
 
   valueT number;       /* offset or (absolute) value */
@@ -150,38 +148,46 @@ integer_constant (radix, expressionP)
      number we are looking for is expected to be positive, but if it
      fits into 32 bits as an unsigned number, we let it be a 32-bit
      number.  The cavalier approach is for speed in ordinary cases. */
+  /* This has been extended for 64 bits.  We blindly assume that if
+     you're compiling in 64-bit mode, the target is a 64-bit machine.
+     This should be cleaned up.  */
+
+#ifdef BFD64
+#define valuesize 64
+#else /* includes non-bfd case, mostly */
+#define valuesize 32
+#endif
 
   switch (radix)
     {
-
     case 2:
       maxdig = 2;
-      too_many_digits = 33;
+      too_many_digits = valuesize + 1;
       break;
     case 8:
       maxdig = radix = 8;
-      too_many_digits = 11;
+      too_many_digits = (valuesize + 2) / 3 + 1;
       break;
     case 16:
-
-
       maxdig = radix = 16;
-      too_many_digits = 9;
+      too_many_digits = (valuesize + 3) / 4 + 1;
       break;
     case 10:
       maxdig = radix = 10;
-      too_many_digits = 11;
+      too_many_digits = (valuesize + 12) / 4; /* very rough */
     }
-  c = *input_line_pointer;
-  input_line_pointer++;
-  digit_2 = input_line_pointer;
-  for (number = 0; (digit = hex_value[c]) < maxdig; c = *input_line_pointer++)
+#undef valuesize
+  start = input_line_pointer;
+  c = *input_line_pointer++;
+  for (number = 0;
+       (digit = hex_value[(unsigned char) c]) < maxdig;
+       c = *input_line_pointer++)
     {
       number = number * radix + digit;
     }
   /* c contains character after number. */
   /* input_line_pointer->char after c. */
-  small = input_line_pointer - digit_2 < too_many_digits;
+  small = (input_line_pointer - start - 1) < too_many_digits;
   if (!small)
     {
       /*
@@ -194,10 +200,11 @@ integer_constant (radix, expressionP)
       leader = generic_bignum;
       generic_bignum[0] = 0;
       generic_bignum[1] = 0;
-      /* we could just use digit_2, but lets be mnemonic. */
-      input_line_pointer = --digit_2;  /*->1st digit. */
+      input_line_pointer = start;      /*->1st digit. */
       c = *input_line_pointer++;
-      for (; (carry = hex_value[c]) < maxdig; c = *input_line_pointer++)
+      for (;
+          (carry = hex_value[(unsigned char) c]) < maxdig;
+          c = *input_line_pointer++)
        {
          for (pointer = generic_bignum;
               pointer <= leader;
@@ -212,18 +219,18 @@ integer_constant (radix, expressionP)
          if (carry)
            {
              if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1)
-               {               /* room to grow a longer bignum. */
+               {
+                 /* room to grow a longer bignum. */
                  *++leader = carry;
                }
            }
        }
       /* again, c is char after number, */
       /* input_line_pointer->after c. */
-      know (sizeof (int) * 8 == 32);
       know (LITTLENUM_NUMBER_OF_BITS == 16);
-      /* hence the constant "2" in the next line. */
       if (leader < generic_bignum + 2)
-       {                       /* will fit into 32 bits. */
+       {
+         /* will fit into 32 bits. */
          number =
            ((generic_bignum[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS)
            | (generic_bignum[0] & LITTLENUM_MASK);
@@ -320,15 +327,15 @@ integer_constant (radix, expressionP)
               then this is a fresh instantiation of that number, so create
               it.  */
 
-           if (dollar_label_defined (number))
+           if (dollar_label_defined ((long) number))
              {
-               name = dollar_label_name (number, 0);
+               name = dollar_label_name ((long) number, 0);
                symbolP = symbol_find (name);
                know (symbolP != NULL);
              }
            else
              {
-               name = dollar_label_name (number, 1);
+               name = dollar_label_name ((long) number, 1);
                symbolP = symbol_find_or_make (name);
              }
 
@@ -351,16 +358,15 @@ integer_constant (radix, expressionP)
 
        }                       /* switch on char following the number */
 
-
     }
   else
     {
       /* not a small number */
       expressionP->X_op = O_big;
-      expressionP->X_add_number = number;
+      expressionP->X_add_number = number;      /* number of littlenums */
       input_line_pointer--;    /*->char following number. */
     }
-}                              /* integer_constant() */
+}
 
 
 /*
@@ -381,7 +387,15 @@ operand (expressionP)
   char c;
   symbolS *symbolP;    /* points to symbol */
   char *name;          /* points to name of symbol */
-  segT retval = absolute_section;
+  segT segment;
+
+  /* All integers are regarded as unsigned unless they are negated.
+     This is because the only thing which cares whether a number is
+     unsigned is the code in emit_expr which extends constants into
+     bignums.  It should only sign extend negative numbers, so that
+     something like ``.quad 0x80000000'' is not sign extended even
+     though it appears negative if valueT is 32 bits.  */
+  expressionP->X_unsigned = 1;
 
   /* digits, assume it is a bignum. */
 
@@ -427,6 +441,7 @@ operand (expressionP)
            {
              input_line_pointer++;
              floating_constant (expressionP);
+             expressionP->X_add_number = -(isupper (c) ? tolower (c) : c);
            }
          else
            {
@@ -445,12 +460,12 @@ operand (expressionP)
 
        case 'b':
 #ifdef LOCAL_LABELS_FB
-         /* FIXME: This seems to be nonsense.  At this point we know
-            for sure that *input_line_pointer is 'b'.  So why are we
-            checking it?  What is this code supposed to do?  */
-         if (!*input_line_pointer
-             || (!strchr ("+-.0123456789", *input_line_pointer)
-                 && !strchr (EXP_CHARS, *input_line_pointer)))
+         if (!input_line_pointer[1]
+             /* Strictly speaking, we should only need to check for
+                "+-01", since that's all you'd normally have in a
+                binary constant.  But some of our code does permit
+                digits greater than the base we're expecting.  */
+             || !strchr ("+-0123456789", input_line_pointer[1]))
            {
              input_line_pointer--;
              integer_constant (10, expressionP);
@@ -478,13 +493,10 @@ operand (expressionP)
          /* if it says '0f' and the line ends or it doesn't look like
             a floating point #, its a local label ref.  dtrt */
          /* likewise for the b's.  xoxorich. */
-         /* FIXME: As in the 'b' case, we know that the
-            *input_line_pointer is 'f'.  What is this code really
-            trying to do?  */
          if (c == 'f'
-             && (!*input_line_pointer ||
-                 (!strchr ("+-.0123456789", *input_line_pointer) &&
-                  !strchr (EXP_CHARS, *input_line_pointer))))
+             && (!input_line_pointer[1]
+                 || (!strchr ("+-.0123456789", input_line_pointer[1])
+                     && !strchr (EXP_CHARS, input_line_pointer[1]))))
            {
              input_line_pointer -= 1;
              integer_constant (10, expressionP);
@@ -517,7 +529,7 @@ operand (expressionP)
 
     case '(':
       /* didn't begin with digit & not a name */
-      retval = expression (expressionP);
+      segment = expression (expressionP);
       /* Expression() will pass trailing whitespace */
       if (*input_line_pointer++ != ')')
        {
@@ -525,7 +537,7 @@ operand (expressionP)
          input_line_pointer--;
        }
       /* here with input_line_pointer->char after "(...)" */
-      return retval;
+      return segment;
 
     case '\'':
       /* Warning: to conform to other people's assemblers NO ESCAPEMENT is
@@ -536,15 +548,12 @@ operand (expressionP)
       break;
 
     case '+':
-      retval = operand (expressionP);
+      (void) operand (expressionP);
       break;
 
     case '~':
     case '-':
       {
-       /* When computing - foo, ignore the segment of foo.  It has
-          nothing to do with the segment of the result, which is
-          ill-defined.  */
        operand (expressionP);
        if (expressionP->X_op == O_constant)
          {
@@ -554,6 +563,7 @@ operand (expressionP)
                expressionP->X_add_number = - expressionP->X_add_number;
                /* Notice: '-' may overflow: no warning is given. This is
                   compatible with other people's assemblers. Sigh.  */
+               expressionP->X_unsigned = 0;
              }
            else
              expressionP->X_add_number = ~ expressionP->X_add_number;
@@ -581,11 +591,7 @@ operand (expressionP)
 
          /* JF: '.' is pseudo symbol with value of current location
             in current segment.  */
-#ifdef DOT_LABEL_PREFIX
-         fake = ".L0\001";
-#else
-         fake = "L0\001";
-#endif
+         fake = FAKE_LABEL_NAME;
          symbolP = symbol_new (fake,
                                now_seg,
                                (valueT) frag_now_fix (),
@@ -594,7 +600,6 @@ operand (expressionP)
          expressionP->X_op = O_symbol;
          expressionP->X_add_symbol = symbolP;
          expressionP->X_add_number = 0;
-         retval = now_seg;
          break;
        }
       else
@@ -612,7 +617,7 @@ operand (expressionP)
       break;
 
     default:
-      if (is_end_of_line[c])
+      if (is_end_of_line[(unsigned char) c])
        goto eol;
       if (is_name_beginner (c))        /* here if did not begin with a digit */
        {
@@ -627,13 +632,13 @@ operand (expressionP)
 
          /* If we have an absolute symbol or a reg, then we know its
             value now.  */
-         retval = S_GET_SEGMENT (symbolP);
-         if (retval == absolute_section)
+         segment = S_GET_SEGMENT (symbolP);
+         if (segment == absolute_section)
            {
              expressionP->X_op = O_constant;
              expressionP->X_add_number = S_GET_VALUE (symbolP);
            }
-         else if (retval == reg_section)
+         else if (segment == reg_section)
            {
              expressionP->X_op = O_register;
              expressionP->X_add_number = S_GET_VALUE (symbolP);
@@ -661,7 +666,20 @@ operand (expressionP)
   clean_up_expression (expressionP);
   SKIP_WHITESPACE ();          /*->1st char after operand. */
   know (*input_line_pointer != ' ');
-  return expressionP->X_op == O_constant ? absolute_section : retval;
+
+  /* The PA port needs this information.  */
+  if (expressionP->X_add_symbol)
+    expressionP->X_add_symbol->sy_used = 1;
+
+  switch (expressionP->X_op)
+    {
+    default:
+      return absolute_section;
+    case O_symbol:
+      return S_GET_SEGMENT (expressionP->X_add_symbol);
+    case O_register:
+      return reg_section;
+    }
 }                              /* operand() */
 \f
 /* Internal. Simplify a struct expression for use by expr() */
@@ -820,7 +838,7 @@ expr (rank, resultP)
   know (*input_line_pointer != ' ');   /* Operand() gobbles spaces. */
 
   c_left = *input_line_pointer;        /* Potential operator character. */
-  op_left = op_encoding[c_left];
+  op_left = op_encoding[(unsigned char) c_left];
   while (op_left != O_illegal && op_rank[(int) op_left] > rank)
     {
       segT rightseg;
@@ -836,20 +854,29 @@ expr (rank, resultP)
          as_warn ("missing operand; zero assumed");
          right.X_op = O_constant;
          right.X_add_number = 0;
-         resultP->X_add_symbol = NULL;
-         resultP->X_op_symbol = NULL;
+         right.X_add_symbol = NULL;
+         right.X_op_symbol = NULL;
        }
 
       know (*input_line_pointer != ' ');
 
-      if (! SEG_NORMAL (retval))
+      if (retval == undefined_section)
+       {
+         if (SEG_NORMAL (rightseg))
+           retval = rightseg;
+       }
+      else if (! SEG_NORMAL (retval))
        retval = rightseg;
       else if (SEG_NORMAL (rightseg)
-              && retval != rightseg)
+              && retval != rightseg
+#ifdef DIFF_EXPR_OK
+              && op_left != O_subtract
+#endif
+              )
        as_bad ("operation combines symbols in different segments");
 
       c_right = *input_line_pointer;
-      op_right = op_encoding[c_right];
+      op_right = op_encoding[(unsigned char) c_right];
       if (*input_line_pointer == c_right && (c_right == '<' || c_right == '>'))
        ++input_line_pointer;
 
@@ -947,11 +974,16 @@ expr (rank, resultP)
          resultP->X_op_symbol = make_expr_symbol (&right);
          resultP->X_op = op_left;
          resultP->X_add_number = 0;
+         resultP->X_unsigned = 1;
        }
-         
+
       op_left = op_right;
     }                          /* While next operator is >= this rank. */
 
+  /* The PA port needs this information.  */
+  if (resultP->X_add_symbol)
+    resultP->X_add_symbol->sy_used = 1;
+
   return resultP->X_op == O_constant ? absolute_section : retval;
 }
 \f
@@ -982,7 +1014,7 @@ get_symbol_end ()
 }
 
 
-unsigned int 
+unsigned int
 get_single_number ()
 {
   expressionS exp;
This page took 0.039584 seconds and 4 git commands to generate.