xref: /openbsd-src/gnu/usr.bin/binutils-2.17/gas/expr.c (revision 20399be96d7986f189235a0b0f960fce1d2d1196)
13d8817e4Smiod /* expr.c -operands, expressions-
23d8817e4Smiod    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
33d8817e4Smiod    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
43d8817e4Smiod    Free Software Foundation, Inc.
53d8817e4Smiod 
63d8817e4Smiod    This file is part of GAS, the GNU Assembler.
73d8817e4Smiod 
83d8817e4Smiod    GAS is free software; you can redistribute it and/or modify
93d8817e4Smiod    it under the terms of the GNU General Public License as published by
103d8817e4Smiod    the Free Software Foundation; either version 2, or (at your option)
113d8817e4Smiod    any later version.
123d8817e4Smiod 
133d8817e4Smiod    GAS is distributed in the hope that it will be useful,
143d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
153d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
163d8817e4Smiod    GNU General Public License for more details.
173d8817e4Smiod 
183d8817e4Smiod    You should have received a copy of the GNU General Public License
193d8817e4Smiod    along with GAS; see the file COPYING.  If not, write to the Free
203d8817e4Smiod    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
213d8817e4Smiod    02110-1301, USA.  */
223d8817e4Smiod 
233d8817e4Smiod /* This is really a branch office of as-read.c. I split it out to clearly
243d8817e4Smiod    distinguish the world of expressions from the world of statements.
253d8817e4Smiod    (It also gives smaller files to re-compile.)
263d8817e4Smiod    Here, "operand"s are of expressions, not instructions.  */
273d8817e4Smiod 
283d8817e4Smiod #include <string.h>
293d8817e4Smiod #define min(a, b)       ((a) < (b) ? (a) : (b))
303d8817e4Smiod 
313d8817e4Smiod #include "as.h"
323d8817e4Smiod #include "safe-ctype.h"
333d8817e4Smiod #include "obstack.h"
343d8817e4Smiod 
353d8817e4Smiod static void floating_constant (expressionS * expressionP);
363d8817e4Smiod static valueT generic_bignum_to_int32 (void);
373d8817e4Smiod #ifdef BFD64
383d8817e4Smiod static valueT generic_bignum_to_int64 (void);
393d8817e4Smiod #endif
403d8817e4Smiod static void integer_constant (int radix, expressionS * expressionP);
413d8817e4Smiod static void mri_char_constant (expressionS *);
423d8817e4Smiod static void current_location (expressionS *);
433d8817e4Smiod static void clean_up_expression (expressionS * expressionP);
443d8817e4Smiod static segT operand (expressionS *, enum expr_mode);
453d8817e4Smiod static operatorT operator (int *);
463d8817e4Smiod 
473d8817e4Smiod extern const char EXP_CHARS[], FLT_CHARS[];
483d8817e4Smiod 
493d8817e4Smiod /* We keep a mapping of expression symbols to file positions, so that
503d8817e4Smiod    we can provide better error messages.  */
513d8817e4Smiod 
523d8817e4Smiod struct expr_symbol_line {
533d8817e4Smiod   struct expr_symbol_line *next;
543d8817e4Smiod   symbolS *sym;
553d8817e4Smiod   char *file;
563d8817e4Smiod   unsigned int line;
573d8817e4Smiod };
583d8817e4Smiod 
593d8817e4Smiod static struct expr_symbol_line *expr_symbol_lines;
603d8817e4Smiod 
613d8817e4Smiod /* Build a dummy symbol to hold a complex expression.  This is how we
623d8817e4Smiod    build expressions up out of other expressions.  The symbol is put
633d8817e4Smiod    into the fake section expr_section.  */
643d8817e4Smiod 
653d8817e4Smiod symbolS *
make_expr_symbol(expressionS * expressionP)663d8817e4Smiod make_expr_symbol (expressionS *expressionP)
673d8817e4Smiod {
683d8817e4Smiod   expressionS zero;
693d8817e4Smiod   symbolS *symbolP;
703d8817e4Smiod   struct expr_symbol_line *n;
713d8817e4Smiod 
723d8817e4Smiod   if (expressionP->X_op == O_symbol
733d8817e4Smiod       && expressionP->X_add_number == 0)
743d8817e4Smiod     return expressionP->X_add_symbol;
753d8817e4Smiod 
763d8817e4Smiod   if (expressionP->X_op == O_big)
773d8817e4Smiod     {
783d8817e4Smiod       /* This won't work, because the actual value is stored in
793d8817e4Smiod 	 generic_floating_point_number or generic_bignum, and we are
803d8817e4Smiod 	 going to lose it if we haven't already.  */
813d8817e4Smiod       if (expressionP->X_add_number > 0)
823d8817e4Smiod 	as_bad (_("bignum invalid"));
833d8817e4Smiod       else
843d8817e4Smiod 	as_bad (_("floating point number invalid"));
853d8817e4Smiod       zero.X_op = O_constant;
863d8817e4Smiod       zero.X_add_number = 0;
873d8817e4Smiod       zero.X_unsigned = 0;
883d8817e4Smiod       clean_up_expression (&zero);
893d8817e4Smiod       expressionP = &zero;
903d8817e4Smiod     }
913d8817e4Smiod 
923d8817e4Smiod   /* Putting constant symbols in absolute_section rather than
933d8817e4Smiod      expr_section is convenient for the old a.out code, for which
943d8817e4Smiod      S_GET_SEGMENT does not always retrieve the value put in by
953d8817e4Smiod      S_SET_SEGMENT.  */
963d8817e4Smiod   symbolP = symbol_create (FAKE_LABEL_NAME,
973d8817e4Smiod 			   (expressionP->X_op == O_constant
983d8817e4Smiod 			    ? absolute_section
993d8817e4Smiod 			    : expr_section),
1003d8817e4Smiod 			   0, &zero_address_frag);
1013d8817e4Smiod   symbol_set_value_expression (symbolP, expressionP);
1023d8817e4Smiod 
1033d8817e4Smiod   if (expressionP->X_op == O_constant)
1043d8817e4Smiod     resolve_symbol_value (symbolP);
1053d8817e4Smiod 
1063d8817e4Smiod   n = (struct expr_symbol_line *) xmalloc (sizeof *n);
1073d8817e4Smiod   n->sym = symbolP;
1083d8817e4Smiod   as_where (&n->file, &n->line);
1093d8817e4Smiod   n->next = expr_symbol_lines;
1103d8817e4Smiod   expr_symbol_lines = n;
1113d8817e4Smiod 
1123d8817e4Smiod   return symbolP;
1133d8817e4Smiod }
1143d8817e4Smiod 
1153d8817e4Smiod /* Return the file and line number for an expr symbol.  Return
1163d8817e4Smiod    non-zero if something was found, 0 if no information is known for
1173d8817e4Smiod    the symbol.  */
1183d8817e4Smiod 
1193d8817e4Smiod int
expr_symbol_where(symbolS * sym,char ** pfile,unsigned int * pline)1203d8817e4Smiod expr_symbol_where (symbolS *sym, char **pfile, unsigned int *pline)
1213d8817e4Smiod {
1223d8817e4Smiod   register struct expr_symbol_line *l;
1233d8817e4Smiod 
1243d8817e4Smiod   for (l = expr_symbol_lines; l != NULL; l = l->next)
1253d8817e4Smiod     {
1263d8817e4Smiod       if (l->sym == sym)
1273d8817e4Smiod 	{
1283d8817e4Smiod 	  *pfile = l->file;
1293d8817e4Smiod 	  *pline = l->line;
1303d8817e4Smiod 	  return 1;
1313d8817e4Smiod 	}
1323d8817e4Smiod     }
1333d8817e4Smiod 
1343d8817e4Smiod   return 0;
1353d8817e4Smiod }
1363d8817e4Smiod 
1373d8817e4Smiod /* Utilities for building expressions.
1383d8817e4Smiod    Since complex expressions are recorded as symbols for use in other
1393d8817e4Smiod    expressions these return a symbolS * and not an expressionS *.
1403d8817e4Smiod    These explicitly do not take an "add_number" argument.  */
1413d8817e4Smiod /* ??? For completeness' sake one might want expr_build_symbol.
1423d8817e4Smiod    It would just return its argument.  */
1433d8817e4Smiod 
1443d8817e4Smiod /* Build an expression for an unsigned constant.
1453d8817e4Smiod    The corresponding one for signed constants is missing because
1463d8817e4Smiod    there's currently no need for it.  One could add an unsigned_p flag
1473d8817e4Smiod    but that seems more clumsy.  */
1483d8817e4Smiod 
1493d8817e4Smiod symbolS *
expr_build_uconstant(offsetT value)1503d8817e4Smiod expr_build_uconstant (offsetT value)
1513d8817e4Smiod {
1523d8817e4Smiod   expressionS e;
1533d8817e4Smiod 
1543d8817e4Smiod   e.X_op = O_constant;
1553d8817e4Smiod   e.X_add_number = value;
1563d8817e4Smiod   e.X_unsigned = 1;
1573d8817e4Smiod   return make_expr_symbol (&e);
1583d8817e4Smiod }
1593d8817e4Smiod 
1603d8817e4Smiod /* Build an expression for the current location ('.').  */
1613d8817e4Smiod 
1623d8817e4Smiod symbolS *
expr_build_dot(void)1633d8817e4Smiod expr_build_dot (void)
1643d8817e4Smiod {
1653d8817e4Smiod   expressionS e;
1663d8817e4Smiod 
1673d8817e4Smiod   current_location (&e);
1683d8817e4Smiod   return make_expr_symbol (&e);
1693d8817e4Smiod }
1703d8817e4Smiod 
1713d8817e4Smiod /* Build any floating-point literal here.
1723d8817e4Smiod    Also build any bignum literal here.  */
1733d8817e4Smiod 
1743d8817e4Smiod /* Seems atof_machine can backscan through generic_bignum and hit whatever
1753d8817e4Smiod    happens to be loaded before it in memory.  And its way too complicated
1763d8817e4Smiod    for me to fix right.  Thus a hack.  JF:  Just make generic_bignum bigger,
1773d8817e4Smiod    and never write into the early words, thus they'll always be zero.
1783d8817e4Smiod    I hate Dean's floating-point code.  Bleh.  */
1793d8817e4Smiod LITTLENUM_TYPE generic_bignum[SIZE_OF_LARGE_NUMBER + 6];
1803d8817e4Smiod 
1813d8817e4Smiod FLONUM_TYPE generic_floating_point_number = {
1823d8817e4Smiod   &generic_bignum[6],		/* low.  (JF: Was 0)  */
1833d8817e4Smiod   &generic_bignum[SIZE_OF_LARGE_NUMBER + 6 - 1], /* high.  JF: (added +6)  */
1843d8817e4Smiod   0,				/* leader.  */
1853d8817e4Smiod   0,				/* exponent.  */
1863d8817e4Smiod   0				/* sign.  */
1873d8817e4Smiod };
1883d8817e4Smiod 
1893d8817e4Smiod 
1903d8817e4Smiod static void
floating_constant(expressionS * expressionP)1913d8817e4Smiod floating_constant (expressionS *expressionP)
1923d8817e4Smiod {
1933d8817e4Smiod   /* input_line_pointer -> floating-point constant.  */
1943d8817e4Smiod   int error_code;
1953d8817e4Smiod 
1963d8817e4Smiod   error_code = atof_generic (&input_line_pointer, ".", EXP_CHARS,
1973d8817e4Smiod 			     &generic_floating_point_number);
1983d8817e4Smiod 
1993d8817e4Smiod   if (error_code)
2003d8817e4Smiod     {
2013d8817e4Smiod       if (error_code == ERROR_EXPONENT_OVERFLOW)
2023d8817e4Smiod 	{
2033d8817e4Smiod 	  as_bad (_("bad floating-point constant: exponent overflow"));
2043d8817e4Smiod 	}
2053d8817e4Smiod       else
2063d8817e4Smiod 	{
2073d8817e4Smiod 	  as_bad (_("bad floating-point constant: unknown error code=%d"),
2083d8817e4Smiod 		  error_code);
2093d8817e4Smiod 	}
2103d8817e4Smiod     }
2113d8817e4Smiod   expressionP->X_op = O_big;
2123d8817e4Smiod   /* input_line_pointer -> just after constant, which may point to
2133d8817e4Smiod      whitespace.  */
2143d8817e4Smiod   expressionP->X_add_number = -1;
2153d8817e4Smiod }
2163d8817e4Smiod 
2173d8817e4Smiod static valueT
generic_bignum_to_int32(void)2183d8817e4Smiod generic_bignum_to_int32 (void)
2193d8817e4Smiod {
2203d8817e4Smiod   valueT number =
2213d8817e4Smiod 	   ((generic_bignum[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS)
2223d8817e4Smiod 	   | (generic_bignum[0] & LITTLENUM_MASK);
2233d8817e4Smiod   number &= 0xffffffff;
2243d8817e4Smiod   return number;
2253d8817e4Smiod }
2263d8817e4Smiod 
2273d8817e4Smiod #ifdef BFD64
2283d8817e4Smiod static valueT
generic_bignum_to_int64(void)2293d8817e4Smiod generic_bignum_to_int64 (void)
2303d8817e4Smiod {
2313d8817e4Smiod   valueT number =
2323d8817e4Smiod     ((((((((valueT) generic_bignum[3] & LITTLENUM_MASK)
2333d8817e4Smiod 	  << LITTLENUM_NUMBER_OF_BITS)
2343d8817e4Smiod 	 | ((valueT) generic_bignum[2] & LITTLENUM_MASK))
2353d8817e4Smiod 	<< LITTLENUM_NUMBER_OF_BITS)
2363d8817e4Smiod        | ((valueT) generic_bignum[1] & LITTLENUM_MASK))
2373d8817e4Smiod       << LITTLENUM_NUMBER_OF_BITS)
2383d8817e4Smiod      | ((valueT) generic_bignum[0] & LITTLENUM_MASK));
2393d8817e4Smiod   return number;
2403d8817e4Smiod }
2413d8817e4Smiod #endif
2423d8817e4Smiod 
2433d8817e4Smiod static void
integer_constant(int radix,expressionS * expressionP)2443d8817e4Smiod integer_constant (int radix, expressionS *expressionP)
2453d8817e4Smiod {
2463d8817e4Smiod   char *start;		/* Start of number.  */
2473d8817e4Smiod   char *suffix = NULL;
2483d8817e4Smiod   char c;
2493d8817e4Smiod   valueT number;	/* Offset or (absolute) value.  */
2503d8817e4Smiod   short int digit;	/* Value of next digit in current radix.  */
2513d8817e4Smiod   short int maxdig = 0;	/* Highest permitted digit value.  */
2523d8817e4Smiod   int too_many_digits = 0;	/* If we see >= this number of.  */
2533d8817e4Smiod   char *name;		/* Points to name of symbol.  */
2543d8817e4Smiod   symbolS *symbolP;	/* Points to symbol.  */
2553d8817e4Smiod 
2563d8817e4Smiod   int small;			/* True if fits in 32 bits.  */
2573d8817e4Smiod 
2583d8817e4Smiod   /* May be bignum, or may fit in 32 bits.  */
2593d8817e4Smiod   /* Most numbers fit into 32 bits, and we want this case to be fast.
2603d8817e4Smiod      so we pretend it will fit into 32 bits.  If, after making up a 32
2613d8817e4Smiod      bit number, we realise that we have scanned more digits than
2623d8817e4Smiod      comfortably fit into 32 bits, we re-scan the digits coding them
2633d8817e4Smiod      into a bignum.  For decimal and octal numbers we are
2643d8817e4Smiod      conservative: Some numbers may be assumed bignums when in fact
2653d8817e4Smiod      they do fit into 32 bits.  Numbers of any radix can have excess
2663d8817e4Smiod      leading zeros: We strive to recognise this and cast them back
2673d8817e4Smiod      into 32 bits.  We must check that the bignum really is more than
2683d8817e4Smiod      32 bits, and change it back to a 32-bit number if it fits.  The
2693d8817e4Smiod      number we are looking for is expected to be positive, but if it
2703d8817e4Smiod      fits into 32 bits as an unsigned number, we let it be a 32-bit
2713d8817e4Smiod      number.  The cavalier approach is for speed in ordinary cases.  */
2723d8817e4Smiod   /* This has been extended for 64 bits.  We blindly assume that if
2733d8817e4Smiod      you're compiling in 64-bit mode, the target is a 64-bit machine.
2743d8817e4Smiod      This should be cleaned up.  */
2753d8817e4Smiod 
2763d8817e4Smiod #ifdef BFD64
2773d8817e4Smiod #define valuesize 64
2783d8817e4Smiod #else /* includes non-bfd case, mostly */
2793d8817e4Smiod #define valuesize 32
2803d8817e4Smiod #endif
2813d8817e4Smiod 
2823d8817e4Smiod   if ((NUMBERS_WITH_SUFFIX || flag_m68k_mri) && radix == 0)
2833d8817e4Smiod     {
2843d8817e4Smiod       int flt = 0;
2853d8817e4Smiod 
2863d8817e4Smiod       /* In MRI mode, the number may have a suffix indicating the
2873d8817e4Smiod 	 radix.  For that matter, it might actually be a floating
2883d8817e4Smiod 	 point constant.  */
2893d8817e4Smiod       for (suffix = input_line_pointer; ISALNUM (*suffix); suffix++)
2903d8817e4Smiod 	{
2913d8817e4Smiod 	  if (*suffix == 'e' || *suffix == 'E')
2923d8817e4Smiod 	    flt = 1;
2933d8817e4Smiod 	}
2943d8817e4Smiod 
2953d8817e4Smiod       if (suffix == input_line_pointer)
2963d8817e4Smiod 	{
2973d8817e4Smiod 	  radix = 10;
2983d8817e4Smiod 	  suffix = NULL;
2993d8817e4Smiod 	}
3003d8817e4Smiod       else
3013d8817e4Smiod 	{
3023d8817e4Smiod 	  c = *--suffix;
3033d8817e4Smiod 	  c = TOUPPER (c);
3043d8817e4Smiod 	  /* If we have both NUMBERS_WITH_SUFFIX and LOCAL_LABELS_FB,
3053d8817e4Smiod 	     we distinguish between 'B' and 'b'.  This is the case for
3063d8817e4Smiod 	     Z80.  */
3073d8817e4Smiod 	  if ((NUMBERS_WITH_SUFFIX && LOCAL_LABELS_FB ? *suffix : c) == 'B')
3083d8817e4Smiod 	    radix = 2;
3093d8817e4Smiod 	  else if (c == 'D')
3103d8817e4Smiod 	    radix = 10;
3113d8817e4Smiod 	  else if (c == 'O' || c == 'Q')
3123d8817e4Smiod 	    radix = 8;
3133d8817e4Smiod 	  else if (c == 'H')
3143d8817e4Smiod 	    radix = 16;
3153d8817e4Smiod 	  else if (suffix[1] == '.' || c == 'E' || flt)
3163d8817e4Smiod 	    {
3173d8817e4Smiod 	      floating_constant (expressionP);
3183d8817e4Smiod 	      return;
3193d8817e4Smiod 	    }
3203d8817e4Smiod 	  else
3213d8817e4Smiod 	    {
3223d8817e4Smiod 	      radix = 10;
3233d8817e4Smiod 	      suffix = NULL;
3243d8817e4Smiod 	    }
3253d8817e4Smiod 	}
3263d8817e4Smiod     }
3273d8817e4Smiod 
3283d8817e4Smiod   switch (radix)
3293d8817e4Smiod     {
3303d8817e4Smiod     case 2:
3313d8817e4Smiod       maxdig = 2;
3323d8817e4Smiod       too_many_digits = valuesize + 1;
3333d8817e4Smiod       break;
3343d8817e4Smiod     case 8:
3353d8817e4Smiod       maxdig = radix = 8;
3363d8817e4Smiod       too_many_digits = (valuesize + 2) / 3 + 1;
3373d8817e4Smiod       break;
3383d8817e4Smiod     case 16:
3393d8817e4Smiod       maxdig = radix = 16;
3403d8817e4Smiod       too_many_digits = (valuesize + 3) / 4 + 1;
3413d8817e4Smiod       break;
3423d8817e4Smiod     case 10:
3433d8817e4Smiod       maxdig = radix = 10;
3443d8817e4Smiod       too_many_digits = (valuesize + 11) / 4; /* Very rough.  */
3453d8817e4Smiod     }
3463d8817e4Smiod #undef valuesize
3473d8817e4Smiod   start = input_line_pointer;
3483d8817e4Smiod   c = *input_line_pointer++;
3493d8817e4Smiod   for (number = 0;
3503d8817e4Smiod        (digit = hex_value (c)) < maxdig;
3513d8817e4Smiod        c = *input_line_pointer++)
3523d8817e4Smiod     {
3533d8817e4Smiod       number = number * radix + digit;
3543d8817e4Smiod     }
3553d8817e4Smiod   /* c contains character after number.  */
3563d8817e4Smiod   /* input_line_pointer->char after c.  */
3573d8817e4Smiod   small = (input_line_pointer - start - 1) < too_many_digits;
3583d8817e4Smiod 
3593d8817e4Smiod   if (radix == 16 && c == '_')
3603d8817e4Smiod     {
3613d8817e4Smiod       /* This is literal of the form 0x333_0_12345678_1.
3623d8817e4Smiod 	 This example is equivalent to 0x00000333000000001234567800000001.  */
3633d8817e4Smiod 
3643d8817e4Smiod       int num_little_digits = 0;
3653d8817e4Smiod       int i;
3663d8817e4Smiod       input_line_pointer = start;	/* -> 1st digit.  */
3673d8817e4Smiod 
3683d8817e4Smiod       know (LITTLENUM_NUMBER_OF_BITS == 16);
3693d8817e4Smiod 
3703d8817e4Smiod       for (c = '_'; c == '_'; num_little_digits += 2)
3713d8817e4Smiod 	{
3723d8817e4Smiod 
3733d8817e4Smiod 	  /* Convert one 64-bit word.  */
3743d8817e4Smiod 	  int ndigit = 0;
3753d8817e4Smiod 	  number = 0;
3763d8817e4Smiod 	  for (c = *input_line_pointer++;
3773d8817e4Smiod 	       (digit = hex_value (c)) < maxdig;
3783d8817e4Smiod 	       c = *(input_line_pointer++))
3793d8817e4Smiod 	    {
3803d8817e4Smiod 	      number = number * radix + digit;
3813d8817e4Smiod 	      ndigit++;
3823d8817e4Smiod 	    }
3833d8817e4Smiod 
3843d8817e4Smiod 	  /* Check for 8 digit per word max.  */
3853d8817e4Smiod 	  if (ndigit > 8)
3863d8817e4Smiod 	    as_bad (_("a bignum with underscores may not have more than 8 hex digits in any word"));
3873d8817e4Smiod 
3883d8817e4Smiod 	  /* Add this chunk to the bignum.
3893d8817e4Smiod 	     Shift things down 2 little digits.  */
3903d8817e4Smiod 	  know (LITTLENUM_NUMBER_OF_BITS == 16);
3913d8817e4Smiod 	  for (i = min (num_little_digits + 1, SIZE_OF_LARGE_NUMBER - 1);
3923d8817e4Smiod 	       i >= 2;
3933d8817e4Smiod 	       i--)
3943d8817e4Smiod 	    generic_bignum[i] = generic_bignum[i - 2];
3953d8817e4Smiod 
3963d8817e4Smiod 	  /* Add the new digits as the least significant new ones.  */
3973d8817e4Smiod 	  generic_bignum[0] = number & 0xffffffff;
3983d8817e4Smiod 	  generic_bignum[1] = number >> 16;
3993d8817e4Smiod 	}
4003d8817e4Smiod 
4013d8817e4Smiod       /* Again, c is char after number, input_line_pointer->after c.  */
4023d8817e4Smiod 
4033d8817e4Smiod       if (num_little_digits > SIZE_OF_LARGE_NUMBER - 1)
4043d8817e4Smiod 	num_little_digits = SIZE_OF_LARGE_NUMBER - 1;
4053d8817e4Smiod 
4063d8817e4Smiod       assert (num_little_digits >= 4);
4073d8817e4Smiod 
4083d8817e4Smiod       if (num_little_digits != 8)
4093d8817e4Smiod 	as_bad (_("a bignum with underscores must have exactly 4 words"));
4103d8817e4Smiod 
4113d8817e4Smiod       /* We might have some leading zeros.  These can be trimmed to give
4123d8817e4Smiod 	 us a change to fit this constant into a small number.  */
4133d8817e4Smiod       while (generic_bignum[num_little_digits - 1] == 0
4143d8817e4Smiod 	     && num_little_digits > 1)
4153d8817e4Smiod 	num_little_digits--;
4163d8817e4Smiod 
4173d8817e4Smiod       if (num_little_digits <= 2)
4183d8817e4Smiod 	{
4193d8817e4Smiod 	  /* will fit into 32 bits.  */
4203d8817e4Smiod 	  number = generic_bignum_to_int32 ();
4213d8817e4Smiod 	  small = 1;
4223d8817e4Smiod 	}
4233d8817e4Smiod #ifdef BFD64
4243d8817e4Smiod       else if (num_little_digits <= 4)
4253d8817e4Smiod 	{
4263d8817e4Smiod 	  /* Will fit into 64 bits.  */
4273d8817e4Smiod 	  number = generic_bignum_to_int64 ();
4283d8817e4Smiod 	  small = 1;
4293d8817e4Smiod 	}
4303d8817e4Smiod #endif
4313d8817e4Smiod       else
4323d8817e4Smiod 	{
4333d8817e4Smiod 	  small = 0;
4343d8817e4Smiod 
4353d8817e4Smiod 	  /* Number of littlenums in the bignum.  */
4363d8817e4Smiod 	  number = num_little_digits;
4373d8817e4Smiod 	}
4383d8817e4Smiod     }
4393d8817e4Smiod   else if (!small)
4403d8817e4Smiod     {
4413d8817e4Smiod       /* We saw a lot of digits. manufacture a bignum the hard way.  */
4423d8817e4Smiod       LITTLENUM_TYPE *leader;	/* -> high order littlenum of the bignum.  */
4433d8817e4Smiod       LITTLENUM_TYPE *pointer;	/* -> littlenum we are frobbing now.  */
4443d8817e4Smiod       long carry;
4453d8817e4Smiod 
4463d8817e4Smiod       leader = generic_bignum;
4473d8817e4Smiod       generic_bignum[0] = 0;
4483d8817e4Smiod       generic_bignum[1] = 0;
4493d8817e4Smiod       generic_bignum[2] = 0;
4503d8817e4Smiod       generic_bignum[3] = 0;
4513d8817e4Smiod       input_line_pointer = start;	/* -> 1st digit.  */
4523d8817e4Smiod       c = *input_line_pointer++;
4533d8817e4Smiod       for (; (carry = hex_value (c)) < maxdig; c = *input_line_pointer++)
4543d8817e4Smiod 	{
4553d8817e4Smiod 	  for (pointer = generic_bignum; pointer <= leader; pointer++)
4563d8817e4Smiod 	    {
4573d8817e4Smiod 	      long work;
4583d8817e4Smiod 
4593d8817e4Smiod 	      work = carry + radix * *pointer;
4603d8817e4Smiod 	      *pointer = work & LITTLENUM_MASK;
4613d8817e4Smiod 	      carry = work >> LITTLENUM_NUMBER_OF_BITS;
4623d8817e4Smiod 	    }
4633d8817e4Smiod 	  if (carry)
4643d8817e4Smiod 	    {
4653d8817e4Smiod 	      if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1)
4663d8817e4Smiod 		{
4673d8817e4Smiod 		  /* Room to grow a longer bignum.  */
4683d8817e4Smiod 		  *++leader = carry;
4693d8817e4Smiod 		}
4703d8817e4Smiod 	    }
4713d8817e4Smiod 	}
4723d8817e4Smiod       /* Again, c is char after number.  */
4733d8817e4Smiod       /* input_line_pointer -> after c.  */
4743d8817e4Smiod       know (LITTLENUM_NUMBER_OF_BITS == 16);
4753d8817e4Smiod       if (leader < generic_bignum + 2)
4763d8817e4Smiod 	{
4773d8817e4Smiod 	  /* Will fit into 32 bits.  */
4783d8817e4Smiod 	  number = generic_bignum_to_int32 ();
4793d8817e4Smiod 	  small = 1;
4803d8817e4Smiod 	}
4813d8817e4Smiod #ifdef BFD64
4823d8817e4Smiod       else if (leader < generic_bignum + 4)
4833d8817e4Smiod 	{
4843d8817e4Smiod 	  /* Will fit into 64 bits.  */
4853d8817e4Smiod 	  number = generic_bignum_to_int64 ();
4863d8817e4Smiod 	  small = 1;
4873d8817e4Smiod 	}
4883d8817e4Smiod #endif
4893d8817e4Smiod       else
4903d8817e4Smiod 	{
4913d8817e4Smiod 	  /* Number of littlenums in the bignum.  */
4923d8817e4Smiod 	  number = leader - generic_bignum + 1;
4933d8817e4Smiod 	}
4943d8817e4Smiod     }
4953d8817e4Smiod 
4963d8817e4Smiod   if ((NUMBERS_WITH_SUFFIX || flag_m68k_mri)
4973d8817e4Smiod       && suffix != NULL
4983d8817e4Smiod       && input_line_pointer - 1 == suffix)
4993d8817e4Smiod     c = *input_line_pointer++;
5003d8817e4Smiod 
5013d8817e4Smiod   if (small)
5023d8817e4Smiod     {
5033d8817e4Smiod       /* Here with number, in correct radix. c is the next char.
5043d8817e4Smiod 	 Note that unlike un*x, we allow "011f" "0x9f" to both mean
5053d8817e4Smiod 	 the same as the (conventional) "9f".
5063d8817e4Smiod 	 This is simply easier than checking for strict canonical
5073d8817e4Smiod 	 form.  Syntax sux!  */
5083d8817e4Smiod 
5093d8817e4Smiod       if (LOCAL_LABELS_FB && c == 'b')
5103d8817e4Smiod 	{
5113d8817e4Smiod 	  /* Backward ref to local label.
5123d8817e4Smiod 	     Because it is backward, expect it to be defined.  */
5133d8817e4Smiod 	  /* Construct a local label.  */
5143d8817e4Smiod 	  name = fb_label_name ((int) number, 0);
5153d8817e4Smiod 
5163d8817e4Smiod 	  /* Seen before, or symbol is defined: OK.  */
5173d8817e4Smiod 	  symbolP = symbol_find (name);
5183d8817e4Smiod 	  if ((symbolP != NULL) && (S_IS_DEFINED (symbolP)))
5193d8817e4Smiod 	    {
5203d8817e4Smiod 	      /* Local labels are never absolute.  Don't waste time
5213d8817e4Smiod 		 checking absoluteness.  */
5223d8817e4Smiod 	      know (SEG_NORMAL (S_GET_SEGMENT (symbolP)));
5233d8817e4Smiod 
5243d8817e4Smiod 	      expressionP->X_op = O_symbol;
5253d8817e4Smiod 	      expressionP->X_add_symbol = symbolP;
5263d8817e4Smiod 	    }
5273d8817e4Smiod 	  else
5283d8817e4Smiod 	    {
5293d8817e4Smiod 	      /* Either not seen or not defined.  */
5303d8817e4Smiod 	      /* @@ Should print out the original string instead of
5313d8817e4Smiod 		 the parsed number.  */
5323d8817e4Smiod 	      as_bad (_("backward ref to unknown label \"%d:\""),
5333d8817e4Smiod 		      (int) number);
5343d8817e4Smiod 	      expressionP->X_op = O_constant;
5353d8817e4Smiod 	    }
5363d8817e4Smiod 
5373d8817e4Smiod 	  expressionP->X_add_number = 0;
5383d8817e4Smiod 	}			/* case 'b' */
5393d8817e4Smiod       else if (LOCAL_LABELS_FB && c == 'f')
5403d8817e4Smiod 	{
5413d8817e4Smiod 	  /* Forward reference.  Expect symbol to be undefined or
5423d8817e4Smiod 	     unknown.  undefined: seen it before.  unknown: never seen
5433d8817e4Smiod 	     it before.
5443d8817e4Smiod 
5453d8817e4Smiod 	     Construct a local label name, then an undefined symbol.
5463d8817e4Smiod 	     Don't create a xseg frag for it: caller may do that.
5473d8817e4Smiod 	     Just return it as never seen before.  */
5483d8817e4Smiod 	  name = fb_label_name ((int) number, 1);
5493d8817e4Smiod 	  symbolP = symbol_find_or_make (name);
5503d8817e4Smiod 	  /* We have no need to check symbol properties.  */
5513d8817e4Smiod #ifndef many_segments
5523d8817e4Smiod 	  /* Since "know" puts its arg into a "string", we
5533d8817e4Smiod 	     can't have newlines in the argument.  */
5543d8817e4Smiod 	  know (S_GET_SEGMENT (symbolP) == undefined_section || S_GET_SEGMENT (symbolP) == text_section || S_GET_SEGMENT (symbolP) == data_section);
5553d8817e4Smiod #endif
5563d8817e4Smiod 	  expressionP->X_op = O_symbol;
5573d8817e4Smiod 	  expressionP->X_add_symbol = symbolP;
5583d8817e4Smiod 	  expressionP->X_add_number = 0;
5593d8817e4Smiod 	}			/* case 'f' */
5603d8817e4Smiod       else if (LOCAL_LABELS_DOLLAR && c == '$')
5613d8817e4Smiod 	{
5623d8817e4Smiod 	  /* If the dollar label is *currently* defined, then this is just
5633d8817e4Smiod 	     another reference to it.  If it is not *currently* defined,
5643d8817e4Smiod 	     then this is a fresh instantiation of that number, so create
5653d8817e4Smiod 	     it.  */
5663d8817e4Smiod 
5673d8817e4Smiod 	  if (dollar_label_defined ((long) number))
5683d8817e4Smiod 	    {
5693d8817e4Smiod 	      name = dollar_label_name ((long) number, 0);
5703d8817e4Smiod 	      symbolP = symbol_find (name);
5713d8817e4Smiod 	      know (symbolP != NULL);
5723d8817e4Smiod 	    }
5733d8817e4Smiod 	  else
5743d8817e4Smiod 	    {
5753d8817e4Smiod 	      name = dollar_label_name ((long) number, 1);
5763d8817e4Smiod 	      symbolP = symbol_find_or_make (name);
5773d8817e4Smiod 	    }
5783d8817e4Smiod 
5793d8817e4Smiod 	  expressionP->X_op = O_symbol;
5803d8817e4Smiod 	  expressionP->X_add_symbol = symbolP;
5813d8817e4Smiod 	  expressionP->X_add_number = 0;
5823d8817e4Smiod 	}			/* case '$' */
5833d8817e4Smiod       else
5843d8817e4Smiod 	{
5853d8817e4Smiod 	  expressionP->X_op = O_constant;
5863d8817e4Smiod 	  expressionP->X_add_number = number;
5873d8817e4Smiod 	  input_line_pointer--;	/* Restore following character.  */
5883d8817e4Smiod 	}			/* Really just a number.  */
5893d8817e4Smiod     }
5903d8817e4Smiod   else
5913d8817e4Smiod     {
5923d8817e4Smiod       /* Not a small number.  */
5933d8817e4Smiod       expressionP->X_op = O_big;
5943d8817e4Smiod       expressionP->X_add_number = number;	/* Number of littlenums.  */
5953d8817e4Smiod       input_line_pointer--;	/* -> char following number.  */
5963d8817e4Smiod     }
5973d8817e4Smiod }
5983d8817e4Smiod 
5993d8817e4Smiod /* Parse an MRI multi character constant.  */
6003d8817e4Smiod 
6013d8817e4Smiod static void
mri_char_constant(expressionS * expressionP)6023d8817e4Smiod mri_char_constant (expressionS *expressionP)
6033d8817e4Smiod {
6043d8817e4Smiod   int i;
6053d8817e4Smiod 
6063d8817e4Smiod   if (*input_line_pointer == '\''
6073d8817e4Smiod       && input_line_pointer[1] != '\'')
6083d8817e4Smiod     {
6093d8817e4Smiod       expressionP->X_op = O_constant;
6103d8817e4Smiod       expressionP->X_add_number = 0;
6113d8817e4Smiod       return;
6123d8817e4Smiod     }
6133d8817e4Smiod 
6143d8817e4Smiod   /* In order to get the correct byte ordering, we must build the
6153d8817e4Smiod      number in reverse.  */
6163d8817e4Smiod   for (i = SIZE_OF_LARGE_NUMBER - 1; i >= 0; i--)
6173d8817e4Smiod     {
6183d8817e4Smiod       int j;
6193d8817e4Smiod 
6203d8817e4Smiod       generic_bignum[i] = 0;
6213d8817e4Smiod       for (j = 0; j < CHARS_PER_LITTLENUM; j++)
6223d8817e4Smiod 	{
6233d8817e4Smiod 	  if (*input_line_pointer == '\'')
6243d8817e4Smiod 	    {
6253d8817e4Smiod 	      if (input_line_pointer[1] != '\'')
6263d8817e4Smiod 		break;
6273d8817e4Smiod 	      ++input_line_pointer;
6283d8817e4Smiod 	    }
6293d8817e4Smiod 	  generic_bignum[i] <<= 8;
6303d8817e4Smiod 	  generic_bignum[i] += *input_line_pointer;
6313d8817e4Smiod 	  ++input_line_pointer;
6323d8817e4Smiod 	}
6333d8817e4Smiod 
6343d8817e4Smiod       if (i < SIZE_OF_LARGE_NUMBER - 1)
6353d8817e4Smiod 	{
6363d8817e4Smiod 	  /* If there is more than one littlenum, left justify the
6373d8817e4Smiod 	     last one to make it match the earlier ones.  If there is
6383d8817e4Smiod 	     only one, we can just use the value directly.  */
6393d8817e4Smiod 	  for (; j < CHARS_PER_LITTLENUM; j++)
6403d8817e4Smiod 	    generic_bignum[i] <<= 8;
6413d8817e4Smiod 	}
6423d8817e4Smiod 
6433d8817e4Smiod       if (*input_line_pointer == '\''
6443d8817e4Smiod 	  && input_line_pointer[1] != '\'')
6453d8817e4Smiod 	break;
6463d8817e4Smiod     }
6473d8817e4Smiod 
6483d8817e4Smiod   if (i < 0)
6493d8817e4Smiod     {
6503d8817e4Smiod       as_bad (_("character constant too large"));
6513d8817e4Smiod       i = 0;
6523d8817e4Smiod     }
6533d8817e4Smiod 
6543d8817e4Smiod   if (i > 0)
6553d8817e4Smiod     {
6563d8817e4Smiod       int c;
6573d8817e4Smiod       int j;
6583d8817e4Smiod 
6593d8817e4Smiod       c = SIZE_OF_LARGE_NUMBER - i;
6603d8817e4Smiod       for (j = 0; j < c; j++)
6613d8817e4Smiod 	generic_bignum[j] = generic_bignum[i + j];
6623d8817e4Smiod       i = c;
6633d8817e4Smiod     }
6643d8817e4Smiod 
6653d8817e4Smiod   know (LITTLENUM_NUMBER_OF_BITS == 16);
6663d8817e4Smiod   if (i > 2)
6673d8817e4Smiod     {
6683d8817e4Smiod       expressionP->X_op = O_big;
6693d8817e4Smiod       expressionP->X_add_number = i;
6703d8817e4Smiod     }
6713d8817e4Smiod   else
6723d8817e4Smiod     {
6733d8817e4Smiod       expressionP->X_op = O_constant;
6743d8817e4Smiod       if (i < 2)
6753d8817e4Smiod 	expressionP->X_add_number = generic_bignum[0] & LITTLENUM_MASK;
6763d8817e4Smiod       else
6773d8817e4Smiod 	expressionP->X_add_number =
6783d8817e4Smiod 	  (((generic_bignum[1] & LITTLENUM_MASK)
6793d8817e4Smiod 	    << LITTLENUM_NUMBER_OF_BITS)
6803d8817e4Smiod 	   | (generic_bignum[0] & LITTLENUM_MASK));
6813d8817e4Smiod     }
6823d8817e4Smiod 
6833d8817e4Smiod   /* Skip the final closing quote.  */
6843d8817e4Smiod   ++input_line_pointer;
6853d8817e4Smiod }
6863d8817e4Smiod 
6873d8817e4Smiod /* Return an expression representing the current location.  This
6883d8817e4Smiod    handles the magic symbol `.'.  */
6893d8817e4Smiod 
6903d8817e4Smiod static void
current_location(expressionS * expressionp)6913d8817e4Smiod current_location (expressionS *expressionp)
6923d8817e4Smiod {
6933d8817e4Smiod   if (now_seg == absolute_section)
6943d8817e4Smiod     {
6953d8817e4Smiod       expressionp->X_op = O_constant;
6963d8817e4Smiod       expressionp->X_add_number = abs_section_offset;
6973d8817e4Smiod     }
6983d8817e4Smiod   else
6993d8817e4Smiod     {
7003d8817e4Smiod       expressionp->X_op = O_symbol;
7013d8817e4Smiod       expressionp->X_add_symbol = symbol_temp_new_now ();
7023d8817e4Smiod       expressionp->X_add_number = 0;
7033d8817e4Smiod     }
7043d8817e4Smiod }
7053d8817e4Smiod 
7063d8817e4Smiod /* In:	Input_line_pointer points to 1st char of operand, which may
7073d8817e4Smiod 	be a space.
7083d8817e4Smiod 
7093d8817e4Smiod    Out:	An expressionS.
7103d8817e4Smiod 	The operand may have been empty: in this case X_op == O_absent.
7113d8817e4Smiod 	Input_line_pointer->(next non-blank) char after operand.  */
7123d8817e4Smiod 
7133d8817e4Smiod static segT
operand(expressionS * expressionP,enum expr_mode mode)7143d8817e4Smiod operand (expressionS *expressionP, enum expr_mode mode)
7153d8817e4Smiod {
7163d8817e4Smiod   char c;
7173d8817e4Smiod   symbolS *symbolP;	/* Points to symbol.  */
7183d8817e4Smiod   char *name;		/* Points to name of symbol.  */
7193d8817e4Smiod   segT segment;
7203d8817e4Smiod 
7213d8817e4Smiod   /* All integers are regarded as unsigned unless they are negated.
7223d8817e4Smiod      This is because the only thing which cares whether a number is
7233d8817e4Smiod      unsigned is the code in emit_expr which extends constants into
7243d8817e4Smiod      bignums.  It should only sign extend negative numbers, so that
7253d8817e4Smiod      something like ``.quad 0x80000000'' is not sign extended even
7263d8817e4Smiod      though it appears negative if valueT is 32 bits.  */
7273d8817e4Smiod   expressionP->X_unsigned = 1;
7283d8817e4Smiod 
7293d8817e4Smiod   /* Digits, assume it is a bignum.  */
7303d8817e4Smiod 
7313d8817e4Smiod   SKIP_WHITESPACE ();		/* Leading whitespace is part of operand.  */
7323d8817e4Smiod   c = *input_line_pointer++;	/* input_line_pointer -> past char in c.  */
7333d8817e4Smiod 
7343d8817e4Smiod   if (is_end_of_line[(unsigned char) c])
7353d8817e4Smiod     goto eol;
7363d8817e4Smiod 
7373d8817e4Smiod   switch (c)
7383d8817e4Smiod     {
7393d8817e4Smiod     case '1':
7403d8817e4Smiod     case '2':
7413d8817e4Smiod     case '3':
7423d8817e4Smiod     case '4':
7433d8817e4Smiod     case '5':
7443d8817e4Smiod     case '6':
7453d8817e4Smiod     case '7':
7463d8817e4Smiod     case '8':
7473d8817e4Smiod     case '9':
7483d8817e4Smiod       input_line_pointer--;
7493d8817e4Smiod 
7503d8817e4Smiod       integer_constant ((NUMBERS_WITH_SUFFIX || flag_m68k_mri)
7513d8817e4Smiod 			? 0 : 10,
7523d8817e4Smiod 			expressionP);
7533d8817e4Smiod       break;
7543d8817e4Smiod 
7553d8817e4Smiod #ifdef LITERAL_PREFIXDOLLAR_HEX
7563d8817e4Smiod     case '$':
7573d8817e4Smiod       /* $L is the start of a local label, not a hex constant.  */
7583d8817e4Smiod       if (* input_line_pointer == 'L')
7593d8817e4Smiod       goto isname;
7603d8817e4Smiod       integer_constant (16, expressionP);
7613d8817e4Smiod       break;
7623d8817e4Smiod #endif
7633d8817e4Smiod 
7643d8817e4Smiod #ifdef LITERAL_PREFIXPERCENT_BIN
7653d8817e4Smiod     case '%':
7663d8817e4Smiod       integer_constant (2, expressionP);
7673d8817e4Smiod       break;
7683d8817e4Smiod #endif
7693d8817e4Smiod 
7703d8817e4Smiod     case '0':
7713d8817e4Smiod       /* Non-decimal radix.  */
7723d8817e4Smiod 
7733d8817e4Smiod       if (NUMBERS_WITH_SUFFIX || flag_m68k_mri)
7743d8817e4Smiod 	{
7753d8817e4Smiod 	  char *s;
7763d8817e4Smiod 
7773d8817e4Smiod 	  /* Check for a hex or float constant.  */
7783d8817e4Smiod 	  for (s = input_line_pointer; hex_p (*s); s++)
7793d8817e4Smiod 	    ;
7803d8817e4Smiod 	  if (*s == 'h' || *s == 'H' || *input_line_pointer == '.')
7813d8817e4Smiod 	    {
7823d8817e4Smiod 	      --input_line_pointer;
7833d8817e4Smiod 	      integer_constant (0, expressionP);
7843d8817e4Smiod 	      break;
7853d8817e4Smiod 	    }
7863d8817e4Smiod 	}
7873d8817e4Smiod       c = *input_line_pointer;
7883d8817e4Smiod       switch (c)
7893d8817e4Smiod 	{
7903d8817e4Smiod 	case 'o':
7913d8817e4Smiod 	case 'O':
7923d8817e4Smiod 	case 'q':
7933d8817e4Smiod 	case 'Q':
7943d8817e4Smiod 	case '8':
7953d8817e4Smiod 	case '9':
7963d8817e4Smiod 	  if (NUMBERS_WITH_SUFFIX || flag_m68k_mri)
7973d8817e4Smiod 	    {
7983d8817e4Smiod 	      integer_constant (0, expressionP);
7993d8817e4Smiod 	      break;
8003d8817e4Smiod 	    }
8013d8817e4Smiod 	  /* Fall through.  */
8023d8817e4Smiod 	default:
8033d8817e4Smiod 	default_case:
8043d8817e4Smiod 	  if (c && strchr (FLT_CHARS, c))
8053d8817e4Smiod 	    {
8063d8817e4Smiod 	      input_line_pointer++;
8073d8817e4Smiod 	      floating_constant (expressionP);
8083d8817e4Smiod 	      expressionP->X_add_number = - TOLOWER (c);
8093d8817e4Smiod 	    }
8103d8817e4Smiod 	  else
8113d8817e4Smiod 	    {
8123d8817e4Smiod 	      /* The string was only zero.  */
8133d8817e4Smiod 	      expressionP->X_op = O_constant;
8143d8817e4Smiod 	      expressionP->X_add_number = 0;
8153d8817e4Smiod 	    }
8163d8817e4Smiod 
8173d8817e4Smiod 	  break;
8183d8817e4Smiod 
8193d8817e4Smiod 	case 'x':
8203d8817e4Smiod 	case 'X':
8213d8817e4Smiod 	  if (flag_m68k_mri)
8223d8817e4Smiod 	    goto default_case;
8233d8817e4Smiod 	  input_line_pointer++;
8243d8817e4Smiod 	  integer_constant (16, expressionP);
8253d8817e4Smiod 	  break;
8263d8817e4Smiod 
8273d8817e4Smiod 	case 'b':
8283d8817e4Smiod 	  if (LOCAL_LABELS_FB && ! (flag_m68k_mri || NUMBERS_WITH_SUFFIX))
8293d8817e4Smiod 	    {
8303d8817e4Smiod 	      /* This code used to check for '+' and '-' here, and, in
8313d8817e4Smiod 		 some conditions, fall through to call
8323d8817e4Smiod 		 integer_constant.  However, that didn't make sense,
8333d8817e4Smiod 		 as integer_constant only accepts digits.  */
8343d8817e4Smiod 	      /* Some of our code elsewhere does permit digits greater
8353d8817e4Smiod 		 than the expected base; for consistency, do the same
8363d8817e4Smiod 		 here.  */
8373d8817e4Smiod 	      if (input_line_pointer[1] < '0'
8383d8817e4Smiod 		  || input_line_pointer[1] > '9')
8393d8817e4Smiod 		{
8403d8817e4Smiod 		  /* Parse this as a back reference to label 0.  */
8413d8817e4Smiod 		  input_line_pointer--;
8423d8817e4Smiod 		  integer_constant (10, expressionP);
8433d8817e4Smiod 		  break;
8443d8817e4Smiod 		}
8453d8817e4Smiod 	      /* Otherwise, parse this as a binary number.  */
8463d8817e4Smiod 	    }
8473d8817e4Smiod 	  /* Fall through.  */
8483d8817e4Smiod 	case 'B':
8493d8817e4Smiod 	  input_line_pointer++;
8503d8817e4Smiod 	  if (flag_m68k_mri || NUMBERS_WITH_SUFFIX)
8513d8817e4Smiod 	    goto default_case;
8523d8817e4Smiod 	  integer_constant (2, expressionP);
8533d8817e4Smiod 	  break;
8543d8817e4Smiod 
8553d8817e4Smiod 	case '0':
8563d8817e4Smiod 	case '1':
8573d8817e4Smiod 	case '2':
8583d8817e4Smiod 	case '3':
8593d8817e4Smiod 	case '4':
8603d8817e4Smiod 	case '5':
8613d8817e4Smiod 	case '6':
8623d8817e4Smiod 	case '7':
8633d8817e4Smiod 	  integer_constant ((flag_m68k_mri || NUMBERS_WITH_SUFFIX)
8643d8817e4Smiod 			    ? 0 : 8,
8653d8817e4Smiod 			    expressionP);
8663d8817e4Smiod 	  break;
8673d8817e4Smiod 
8683d8817e4Smiod 	case 'f':
8693d8817e4Smiod 	  if (LOCAL_LABELS_FB)
8703d8817e4Smiod 	    {
8713d8817e4Smiod 	      /* If it says "0f" and it could possibly be a floating point
8723d8817e4Smiod 		 number, make it one.  Otherwise, make it a local label,
8733d8817e4Smiod 		 and try to deal with parsing the rest later.  */
8743d8817e4Smiod 	      if (!input_line_pointer[1]
8753d8817e4Smiod 		  || (is_end_of_line[0xff & input_line_pointer[1]])
8763d8817e4Smiod 		  || strchr (FLT_CHARS, 'f') == NULL)
8773d8817e4Smiod 		goto is_0f_label;
8783d8817e4Smiod 	      {
8793d8817e4Smiod 		char *cp = input_line_pointer + 1;
8803d8817e4Smiod 		int r = atof_generic (&cp, ".", EXP_CHARS,
8813d8817e4Smiod 				      &generic_floating_point_number);
8823d8817e4Smiod 		switch (r)
8833d8817e4Smiod 		  {
8843d8817e4Smiod 		  case 0:
8853d8817e4Smiod 		  case ERROR_EXPONENT_OVERFLOW:
8863d8817e4Smiod 		    if (*cp == 'f' || *cp == 'b')
8873d8817e4Smiod 		      /* Looks like a difference expression.  */
8883d8817e4Smiod 		      goto is_0f_label;
8893d8817e4Smiod 		    else if (cp == input_line_pointer + 1)
8903d8817e4Smiod 		      /* No characters has been accepted -- looks like
8913d8817e4Smiod 			 end of operand.  */
8923d8817e4Smiod 		      goto is_0f_label;
8933d8817e4Smiod 		    else
8943d8817e4Smiod 		      goto is_0f_float;
8953d8817e4Smiod 		  default:
8963d8817e4Smiod 		    as_fatal (_("expr.c(operand): bad atof_generic return val %d"),
8973d8817e4Smiod 			      r);
8983d8817e4Smiod 		  }
8993d8817e4Smiod 	      }
9003d8817e4Smiod 
9013d8817e4Smiod 	      /* Okay, now we've sorted it out.  We resume at one of these
9023d8817e4Smiod 		 two labels, depending on what we've decided we're probably
9033d8817e4Smiod 		 looking at.  */
9043d8817e4Smiod 	    is_0f_label:
9053d8817e4Smiod 	      input_line_pointer--;
9063d8817e4Smiod 	      integer_constant (10, expressionP);
9073d8817e4Smiod 	      break;
9083d8817e4Smiod 
9093d8817e4Smiod 	    is_0f_float:
9103d8817e4Smiod 	      /* Fall through.  */
9113d8817e4Smiod 	      ;
9123d8817e4Smiod 	    }
9133d8817e4Smiod 
9143d8817e4Smiod 	case 'd':
9153d8817e4Smiod 	case 'D':
9163d8817e4Smiod 	  if (flag_m68k_mri || NUMBERS_WITH_SUFFIX)
9173d8817e4Smiod 	    {
9183d8817e4Smiod 	      integer_constant (0, expressionP);
9193d8817e4Smiod 	      break;
9203d8817e4Smiod 	    }
9213d8817e4Smiod 	  /* Fall through.  */
9223d8817e4Smiod 	case 'F':
9233d8817e4Smiod 	case 'r':
9243d8817e4Smiod 	case 'e':
9253d8817e4Smiod 	case 'E':
9263d8817e4Smiod 	case 'g':
9273d8817e4Smiod 	case 'G':
9283d8817e4Smiod 	  input_line_pointer++;
9293d8817e4Smiod 	  floating_constant (expressionP);
9303d8817e4Smiod 	  expressionP->X_add_number = - TOLOWER (c);
9313d8817e4Smiod 	  break;
9323d8817e4Smiod 
9333d8817e4Smiod 	case '$':
9343d8817e4Smiod 	  if (LOCAL_LABELS_DOLLAR)
9353d8817e4Smiod 	    {
9363d8817e4Smiod 	      integer_constant (10, expressionP);
9373d8817e4Smiod 	      break;
9383d8817e4Smiod 	    }
9393d8817e4Smiod 	  else
9403d8817e4Smiod 	    goto default_case;
9413d8817e4Smiod 	}
9423d8817e4Smiod 
9433d8817e4Smiod       break;
9443d8817e4Smiod 
9453d8817e4Smiod     case '(':
9463d8817e4Smiod #ifndef NEED_INDEX_OPERATOR
9473d8817e4Smiod     case '[':
9483d8817e4Smiod #endif
9493d8817e4Smiod       /* Didn't begin with digit & not a name.  */
9503d8817e4Smiod       if (mode != expr_defer)
9513d8817e4Smiod 	segment = expression (expressionP);
9523d8817e4Smiod       else
9533d8817e4Smiod 	segment = deferred_expression (expressionP);
9543d8817e4Smiod       /* expression () will pass trailing whitespace.  */
9553d8817e4Smiod       if ((c == '(' && *input_line_pointer != ')')
9563d8817e4Smiod 	  || (c == '[' && *input_line_pointer != ']'))
9573d8817e4Smiod 	as_bad (_("missing '%c'"), c == '(' ? ')' : ']');
9583d8817e4Smiod       else
9593d8817e4Smiod 	input_line_pointer++;
9603d8817e4Smiod       SKIP_WHITESPACE ();
9613d8817e4Smiod       /* Here with input_line_pointer -> char after "(...)".  */
9623d8817e4Smiod       return segment;
9633d8817e4Smiod 
9643d8817e4Smiod #ifdef TC_M68K
9653d8817e4Smiod     case 'E':
9663d8817e4Smiod       if (! flag_m68k_mri || *input_line_pointer != '\'')
9673d8817e4Smiod 	goto de_fault;
9683d8817e4Smiod       as_bad (_("EBCDIC constants are not supported"));
9693d8817e4Smiod       /* Fall through.  */
9703d8817e4Smiod     case 'A':
9713d8817e4Smiod       if (! flag_m68k_mri || *input_line_pointer != '\'')
9723d8817e4Smiod 	goto de_fault;
9733d8817e4Smiod       ++input_line_pointer;
9743d8817e4Smiod       /* Fall through.  */
9753d8817e4Smiod #endif
9763d8817e4Smiod     case '\'':
9773d8817e4Smiod       if (! flag_m68k_mri)
9783d8817e4Smiod 	{
9793d8817e4Smiod 	  /* Warning: to conform to other people's assemblers NO
9803d8817e4Smiod 	     ESCAPEMENT is permitted for a single quote.  The next
9813d8817e4Smiod 	     character, parity errors and all, is taken as the value
9823d8817e4Smiod 	     of the operand.  VERY KINKY.  */
9833d8817e4Smiod 	  expressionP->X_op = O_constant;
9843d8817e4Smiod 	  expressionP->X_add_number = *input_line_pointer++;
9853d8817e4Smiod 	  break;
9863d8817e4Smiod 	}
9873d8817e4Smiod 
9883d8817e4Smiod       mri_char_constant (expressionP);
9893d8817e4Smiod       break;
9903d8817e4Smiod 
9913d8817e4Smiod #ifdef TC_M68K
9923d8817e4Smiod     case '"':
9933d8817e4Smiod       /* Double quote is the bitwise not operator in MRI mode.  */
9943d8817e4Smiod       if (! flag_m68k_mri)
9953d8817e4Smiod 	goto de_fault;
9963d8817e4Smiod       /* Fall through.  */
9973d8817e4Smiod #endif
9983d8817e4Smiod     case '~':
9993d8817e4Smiod       /* '~' is permitted to start a label on the Delta.  */
10003d8817e4Smiod       if (is_name_beginner (c))
10013d8817e4Smiod 	goto isname;
10023d8817e4Smiod     case '!':
10033d8817e4Smiod     case '-':
10043d8817e4Smiod     case '+':
10053d8817e4Smiod       {
10063d8817e4Smiod 	/* Do not accept ++e or --e as +(+e) or -(-e)
10073d8817e4Smiod 	   Disabled, since the preprocessor removes whitespace.  */
10083d8817e4Smiod 	if (0 && (c == '-' || c == '+') && *input_line_pointer == c)
10093d8817e4Smiod 	  goto target_op;
10103d8817e4Smiod 
10113d8817e4Smiod 	operand (expressionP, mode);
10123d8817e4Smiod 	if (expressionP->X_op == O_constant)
10133d8817e4Smiod 	  {
10143d8817e4Smiod 	    /* input_line_pointer -> char after operand.  */
10153d8817e4Smiod 	    if (c == '-')
10163d8817e4Smiod 	      {
10173d8817e4Smiod 		expressionP->X_add_number = - expressionP->X_add_number;
10183d8817e4Smiod 		/* Notice: '-' may overflow: no warning is given.
10193d8817e4Smiod 		   This is compatible with other people's
10203d8817e4Smiod 		   assemblers.  Sigh.  */
10213d8817e4Smiod 		expressionP->X_unsigned = 0;
10223d8817e4Smiod 	      }
10233d8817e4Smiod 	    else if (c == '~' || c == '"')
10243d8817e4Smiod 	      expressionP->X_add_number = ~ expressionP->X_add_number;
10253d8817e4Smiod 	    else if (c == '!')
10263d8817e4Smiod 	      expressionP->X_add_number = ! expressionP->X_add_number;
10273d8817e4Smiod 	  }
10283d8817e4Smiod 	else if (expressionP->X_op == O_big
10293d8817e4Smiod 		 && expressionP->X_add_number <= 0
10303d8817e4Smiod 		 && c == '-'
10313d8817e4Smiod 		 && (generic_floating_point_number.sign == '+'
10323d8817e4Smiod 		     || generic_floating_point_number.sign == 'P'))
10333d8817e4Smiod 	  {
10343d8817e4Smiod 	    /* Negative flonum (eg, -1.000e0).  */
10353d8817e4Smiod 	    if (generic_floating_point_number.sign == '+')
10363d8817e4Smiod 	      generic_floating_point_number.sign = '-';
10373d8817e4Smiod 	    else
10383d8817e4Smiod 	      generic_floating_point_number.sign = 'N';
10393d8817e4Smiod 	  }
10403d8817e4Smiod 	else if (expressionP->X_op == O_big
10413d8817e4Smiod 		 && expressionP->X_add_number > 0)
10423d8817e4Smiod 	  {
10433d8817e4Smiod 	    int i;
10443d8817e4Smiod 
10453d8817e4Smiod 	    if (c == '~' || c == '-')
10463d8817e4Smiod 	      {
10473d8817e4Smiod 		for (i = 0; i < expressionP->X_add_number; ++i)
10483d8817e4Smiod 		  generic_bignum[i] = ~generic_bignum[i];
1049*20399be9Sdaniel 
1050*20399be9Sdaniel 		/* Extend the bignum to at least the size of .octa.  */
1051*20399be9Sdaniel 		if (expressionP->X_add_number < SIZE_OF_LARGE_NUMBER)
1052*20399be9Sdaniel 		  {
1053*20399be9Sdaniel 		    expressionP->X_add_number = SIZE_OF_LARGE_NUMBER;
1054*20399be9Sdaniel 		    for (; i < expressionP->X_add_number; ++i)
1055*20399be9Sdaniel 		      generic_bignum[i] = ~(LITTLENUM_TYPE) 0;
1056*20399be9Sdaniel 		  }
1057*20399be9Sdaniel 
10583d8817e4Smiod 		if (c == '-')
10593d8817e4Smiod 		  for (i = 0; i < expressionP->X_add_number; ++i)
10603d8817e4Smiod 		    {
10613d8817e4Smiod 		      generic_bignum[i] += 1;
10623d8817e4Smiod 		      if (generic_bignum[i])
10633d8817e4Smiod 			break;
10643d8817e4Smiod 		    }
10653d8817e4Smiod 	      }
10663d8817e4Smiod 	    else if (c == '!')
10673d8817e4Smiod 	      {
10683d8817e4Smiod 		for (i = 0; i < expressionP->X_add_number; ++i)
1069*20399be9Sdaniel 		  if (generic_bignum[i] != 0)
1070*20399be9Sdaniel 		    break;
1071*20399be9Sdaniel 		expressionP->X_add_number = i >= expressionP->X_add_number;
1072*20399be9Sdaniel 		expressionP->X_op = O_constant;
1073*20399be9Sdaniel 		expressionP->X_unsigned = 1;
10743d8817e4Smiod 	      }
10753d8817e4Smiod 	  }
10763d8817e4Smiod 	else if (expressionP->X_op != O_illegal
10773d8817e4Smiod 		 && expressionP->X_op != O_absent)
10783d8817e4Smiod 	  {
10793d8817e4Smiod 	    if (c != '+')
10803d8817e4Smiod 	      {
10813d8817e4Smiod 		expressionP->X_add_symbol = make_expr_symbol (expressionP);
10823d8817e4Smiod 		if (c == '-')
10833d8817e4Smiod 		  expressionP->X_op = O_uminus;
10843d8817e4Smiod 		else if (c == '~' || c == '"')
10853d8817e4Smiod 		  expressionP->X_op = O_bit_not;
10863d8817e4Smiod 		else
10873d8817e4Smiod 		  expressionP->X_op = O_logical_not;
10883d8817e4Smiod 		expressionP->X_add_number = 0;
10893d8817e4Smiod 	      }
10903d8817e4Smiod 	  }
10913d8817e4Smiod 	else
10923d8817e4Smiod 	  as_warn (_("Unary operator %c ignored because bad operand follows"),
10933d8817e4Smiod 		   c);
10943d8817e4Smiod       }
10953d8817e4Smiod       break;
10963d8817e4Smiod 
10973d8817e4Smiod #if defined (DOLLAR_DOT) || defined (TC_M68K)
10983d8817e4Smiod     case '$':
10993d8817e4Smiod       /* '$' is the program counter when in MRI mode, or when
11003d8817e4Smiod 	 DOLLAR_DOT is defined.  */
11013d8817e4Smiod #ifndef DOLLAR_DOT
11023d8817e4Smiod       if (! flag_m68k_mri)
11033d8817e4Smiod 	goto de_fault;
11043d8817e4Smiod #endif
11053d8817e4Smiod       if (DOLLAR_AMBIGU && hex_p (*input_line_pointer))
11063d8817e4Smiod 	{
11073d8817e4Smiod 	  /* In MRI mode and on Z80, '$' is also used as the prefix
11083d8817e4Smiod 	     for a hexadecimal constant.  */
11093d8817e4Smiod 	  integer_constant (16, expressionP);
11103d8817e4Smiod 	  break;
11113d8817e4Smiod 	}
11123d8817e4Smiod 
11133d8817e4Smiod       if (is_part_of_name (*input_line_pointer))
11143d8817e4Smiod 	goto isname;
11153d8817e4Smiod 
11163d8817e4Smiod       current_location (expressionP);
11173d8817e4Smiod       break;
11183d8817e4Smiod #endif
11193d8817e4Smiod 
11203d8817e4Smiod     case '.':
11213d8817e4Smiod       if (!is_part_of_name (*input_line_pointer))
11223d8817e4Smiod 	{
11233d8817e4Smiod 	  current_location (expressionP);
11243d8817e4Smiod 	  break;
11253d8817e4Smiod 	}
11263d8817e4Smiod       else if ((strncasecmp (input_line_pointer, "startof.", 8) == 0
11273d8817e4Smiod 		&& ! is_part_of_name (input_line_pointer[8]))
11283d8817e4Smiod 	       || (strncasecmp (input_line_pointer, "sizeof.", 7) == 0
11293d8817e4Smiod 		   && ! is_part_of_name (input_line_pointer[7])))
11303d8817e4Smiod 	{
11313d8817e4Smiod 	  int start;
11323d8817e4Smiod 
11333d8817e4Smiod 	  start = (input_line_pointer[1] == 't'
11343d8817e4Smiod 		   || input_line_pointer[1] == 'T');
11353d8817e4Smiod 	  input_line_pointer += start ? 8 : 7;
11363d8817e4Smiod 	  SKIP_WHITESPACE ();
11373d8817e4Smiod 	  if (*input_line_pointer != '(')
11383d8817e4Smiod 	    as_bad (_("syntax error in .startof. or .sizeof."));
11393d8817e4Smiod 	  else
11403d8817e4Smiod 	    {
11413d8817e4Smiod 	      char *buf;
11423d8817e4Smiod 
11433d8817e4Smiod 	      ++input_line_pointer;
11443d8817e4Smiod 	      SKIP_WHITESPACE ();
11453d8817e4Smiod 	      name = input_line_pointer;
11463d8817e4Smiod 	      c = get_symbol_end ();
11473d8817e4Smiod 
11483d8817e4Smiod 	      buf = (char *) xmalloc (strlen (name) + 10);
11493d8817e4Smiod 	      if (start)
11503d8817e4Smiod 		sprintf (buf, ".startof.%s", name);
11513d8817e4Smiod 	      else
11523d8817e4Smiod 		sprintf (buf, ".sizeof.%s", name);
11533d8817e4Smiod 	      symbolP = symbol_make (buf);
11543d8817e4Smiod 	      free (buf);
11553d8817e4Smiod 
11563d8817e4Smiod 	      expressionP->X_op = O_symbol;
11573d8817e4Smiod 	      expressionP->X_add_symbol = symbolP;
11583d8817e4Smiod 	      expressionP->X_add_number = 0;
11593d8817e4Smiod 
11603d8817e4Smiod 	      *input_line_pointer = c;
11613d8817e4Smiod 	      SKIP_WHITESPACE ();
11623d8817e4Smiod 	      if (*input_line_pointer != ')')
11633d8817e4Smiod 		as_bad (_("syntax error in .startof. or .sizeof."));
11643d8817e4Smiod 	      else
11653d8817e4Smiod 		++input_line_pointer;
11663d8817e4Smiod 	    }
11673d8817e4Smiod 	  break;
11683d8817e4Smiod 	}
11693d8817e4Smiod       else
11703d8817e4Smiod 	{
11713d8817e4Smiod 	  goto isname;
11723d8817e4Smiod 	}
11733d8817e4Smiod 
11743d8817e4Smiod     case ',':
11753d8817e4Smiod     eol:
11763d8817e4Smiod       /* Can't imagine any other kind of operand.  */
11773d8817e4Smiod       expressionP->X_op = O_absent;
11783d8817e4Smiod       input_line_pointer--;
11793d8817e4Smiod       break;
11803d8817e4Smiod 
11813d8817e4Smiod #ifdef TC_M68K
11823d8817e4Smiod     case '%':
11833d8817e4Smiod       if (! flag_m68k_mri)
11843d8817e4Smiod 	goto de_fault;
11853d8817e4Smiod       integer_constant (2, expressionP);
11863d8817e4Smiod       break;
11873d8817e4Smiod 
11883d8817e4Smiod     case '@':
11893d8817e4Smiod       if (! flag_m68k_mri)
11903d8817e4Smiod 	goto de_fault;
11913d8817e4Smiod       integer_constant (8, expressionP);
11923d8817e4Smiod       break;
11933d8817e4Smiod 
11943d8817e4Smiod     case ':':
11953d8817e4Smiod       if (! flag_m68k_mri)
11963d8817e4Smiod 	goto de_fault;
11973d8817e4Smiod 
11983d8817e4Smiod       /* In MRI mode, this is a floating point constant represented
11993d8817e4Smiod 	 using hexadecimal digits.  */
12003d8817e4Smiod 
12013d8817e4Smiod       ++input_line_pointer;
12023d8817e4Smiod       integer_constant (16, expressionP);
12033d8817e4Smiod       break;
12043d8817e4Smiod 
12053d8817e4Smiod     case '*':
12063d8817e4Smiod       if (! flag_m68k_mri || is_part_of_name (*input_line_pointer))
12073d8817e4Smiod 	goto de_fault;
12083d8817e4Smiod 
12093d8817e4Smiod       current_location (expressionP);
12103d8817e4Smiod       break;
12113d8817e4Smiod #endif
12123d8817e4Smiod 
12133d8817e4Smiod     default:
12143d8817e4Smiod #ifdef TC_M68K
12153d8817e4Smiod     de_fault:
12163d8817e4Smiod #endif
12173d8817e4Smiod       if (is_name_beginner (c))	/* Here if did not begin with a digit.  */
12183d8817e4Smiod 	{
12193d8817e4Smiod 	  /* Identifier begins here.
12203d8817e4Smiod 	     This is kludged for speed, so code is repeated.  */
12213d8817e4Smiod 	isname:
12223d8817e4Smiod 	  name = --input_line_pointer;
12233d8817e4Smiod 	  c = get_symbol_end ();
12243d8817e4Smiod 
12253d8817e4Smiod #ifdef md_parse_name
12263d8817e4Smiod 	  /* This is a hook for the backend to parse certain names
12273d8817e4Smiod 	     specially in certain contexts.  If a name always has a
12283d8817e4Smiod 	     specific value, it can often be handled by simply
12293d8817e4Smiod 	     entering it in the symbol table.  */
12303d8817e4Smiod 	  if (md_parse_name (name, expressionP, mode, &c))
12313d8817e4Smiod 	    {
12323d8817e4Smiod 	      *input_line_pointer = c;
12333d8817e4Smiod 	      break;
12343d8817e4Smiod 	    }
12353d8817e4Smiod #endif
12363d8817e4Smiod 
12373d8817e4Smiod #ifdef TC_I960
12383d8817e4Smiod 	  /* The MRI i960 assembler permits
12393d8817e4Smiod 	         lda sizeof code,g13
12403d8817e4Smiod 	     FIXME: This should use md_parse_name.  */
12413d8817e4Smiod 	  if (flag_mri
12423d8817e4Smiod 	      && (strcasecmp (name, "sizeof") == 0
12433d8817e4Smiod 		  || strcasecmp (name, "startof") == 0))
12443d8817e4Smiod 	    {
12453d8817e4Smiod 	      int start;
12463d8817e4Smiod 	      char *buf;
12473d8817e4Smiod 
12483d8817e4Smiod 	      start = (name[1] == 't'
12493d8817e4Smiod 		       || name[1] == 'T');
12503d8817e4Smiod 
12513d8817e4Smiod 	      *input_line_pointer = c;
12523d8817e4Smiod 	      SKIP_WHITESPACE ();
12533d8817e4Smiod 
12543d8817e4Smiod 	      name = input_line_pointer;
12553d8817e4Smiod 	      c = get_symbol_end ();
12563d8817e4Smiod 
12573d8817e4Smiod 	      buf = (char *) xmalloc (strlen (name) + 10);
12583d8817e4Smiod 	      if (start)
12593d8817e4Smiod 		sprintf (buf, ".startof.%s", name);
12603d8817e4Smiod 	      else
12613d8817e4Smiod 		sprintf (buf, ".sizeof.%s", name);
12623d8817e4Smiod 	      symbolP = symbol_make (buf);
12633d8817e4Smiod 	      free (buf);
12643d8817e4Smiod 
12653d8817e4Smiod 	      expressionP->X_op = O_symbol;
12663d8817e4Smiod 	      expressionP->X_add_symbol = symbolP;
12673d8817e4Smiod 	      expressionP->X_add_number = 0;
12683d8817e4Smiod 
12693d8817e4Smiod 	      *input_line_pointer = c;
12703d8817e4Smiod 	      SKIP_WHITESPACE ();
12713d8817e4Smiod 
12723d8817e4Smiod 	      break;
12733d8817e4Smiod 	    }
12743d8817e4Smiod #endif
12753d8817e4Smiod 
12763d8817e4Smiod 	  symbolP = symbol_find_or_make (name);
12773d8817e4Smiod 
12783d8817e4Smiod 	  /* If we have an absolute symbol or a reg, then we know its
12793d8817e4Smiod 	     value now.  */
12803d8817e4Smiod 	  segment = S_GET_SEGMENT (symbolP);
12813d8817e4Smiod 	  if (mode != expr_defer && segment == absolute_section)
12823d8817e4Smiod 	    {
12833d8817e4Smiod 	      expressionP->X_op = O_constant;
12843d8817e4Smiod 	      expressionP->X_add_number = S_GET_VALUE (symbolP);
12853d8817e4Smiod 	    }
12863d8817e4Smiod 	  else if (mode != expr_defer && segment == reg_section)
12873d8817e4Smiod 	    {
12883d8817e4Smiod 	      expressionP->X_op = O_register;
12893d8817e4Smiod 	      expressionP->X_add_number = S_GET_VALUE (symbolP);
12903d8817e4Smiod 	    }
12913d8817e4Smiod 	  else
12923d8817e4Smiod 	    {
12933d8817e4Smiod 	      expressionP->X_op = O_symbol;
12943d8817e4Smiod 	      expressionP->X_add_symbol = symbolP;
12953d8817e4Smiod 	      expressionP->X_add_number = 0;
12963d8817e4Smiod 	    }
12973d8817e4Smiod 	  *input_line_pointer = c;
12983d8817e4Smiod 	}
12993d8817e4Smiod       else
13003d8817e4Smiod 	{
13013d8817e4Smiod 	target_op:
13023d8817e4Smiod 	  /* Let the target try to parse it.  Success is indicated by changing
13033d8817e4Smiod 	     the X_op field to something other than O_absent and pointing
13043d8817e4Smiod 	     input_line_pointer past the expression.  If it can't parse the
13053d8817e4Smiod 	     expression, X_op and input_line_pointer should be unchanged.  */
13063d8817e4Smiod 	  expressionP->X_op = O_absent;
13073d8817e4Smiod 	  --input_line_pointer;
13083d8817e4Smiod 	  md_operand (expressionP);
13093d8817e4Smiod 	  if (expressionP->X_op == O_absent)
13103d8817e4Smiod 	    {
13113d8817e4Smiod 	      ++input_line_pointer;
13123d8817e4Smiod 	      as_bad (_("bad expression"));
13133d8817e4Smiod 	      expressionP->X_op = O_constant;
13143d8817e4Smiod 	      expressionP->X_add_number = 0;
13153d8817e4Smiod 	    }
13163d8817e4Smiod 	}
13173d8817e4Smiod       break;
13183d8817e4Smiod     }
13193d8817e4Smiod 
13203d8817e4Smiod   /* It is more 'efficient' to clean up the expressionS when they are
13213d8817e4Smiod      created.  Doing it here saves lines of code.  */
13223d8817e4Smiod   clean_up_expression (expressionP);
13233d8817e4Smiod   SKIP_WHITESPACE ();		/* -> 1st char after operand.  */
13243d8817e4Smiod   know (*input_line_pointer != ' ');
13253d8817e4Smiod 
13263d8817e4Smiod   /* The PA port needs this information.  */
13273d8817e4Smiod   if (expressionP->X_add_symbol)
13283d8817e4Smiod     symbol_mark_used (expressionP->X_add_symbol);
13293d8817e4Smiod 
13303d8817e4Smiod   expressionP->X_add_symbol = symbol_clone_if_forward_ref (expressionP->X_add_symbol);
13313d8817e4Smiod   expressionP->X_op_symbol = symbol_clone_if_forward_ref (expressionP->X_op_symbol);
13323d8817e4Smiod 
13333d8817e4Smiod   switch (expressionP->X_op)
13343d8817e4Smiod     {
13353d8817e4Smiod     default:
13363d8817e4Smiod       return absolute_section;
13373d8817e4Smiod     case O_symbol:
13383d8817e4Smiod       return S_GET_SEGMENT (expressionP->X_add_symbol);
13393d8817e4Smiod     case O_register:
13403d8817e4Smiod       return reg_section;
13413d8817e4Smiod     }
13423d8817e4Smiod }
13433d8817e4Smiod 
13443d8817e4Smiod /* Internal.  Simplify a struct expression for use by expr ().  */
13453d8817e4Smiod 
13463d8817e4Smiod /* In:	address of an expressionS.
13473d8817e4Smiod 	The X_op field of the expressionS may only take certain values.
13483d8817e4Smiod 	Elsewise we waste time special-case testing. Sigh. Ditto SEG_ABSENT.
13493d8817e4Smiod 
13503d8817e4Smiod    Out:	expressionS may have been modified:
13513d8817e4Smiod 	Unused fields zeroed to help expr ().  */
13523d8817e4Smiod 
13533d8817e4Smiod static void
clean_up_expression(expressionS * expressionP)13543d8817e4Smiod clean_up_expression (expressionS *expressionP)
13553d8817e4Smiod {
13563d8817e4Smiod   switch (expressionP->X_op)
13573d8817e4Smiod     {
13583d8817e4Smiod     case O_illegal:
13593d8817e4Smiod     case O_absent:
13603d8817e4Smiod       expressionP->X_add_number = 0;
13613d8817e4Smiod       /* Fall through.  */
13623d8817e4Smiod     case O_big:
13633d8817e4Smiod     case O_constant:
13643d8817e4Smiod     case O_register:
13653d8817e4Smiod       expressionP->X_add_symbol = NULL;
13663d8817e4Smiod       /* Fall through.  */
13673d8817e4Smiod     case O_symbol:
13683d8817e4Smiod     case O_uminus:
13693d8817e4Smiod     case O_bit_not:
13703d8817e4Smiod       expressionP->X_op_symbol = NULL;
13713d8817e4Smiod       break;
13723d8817e4Smiod     default:
13733d8817e4Smiod       break;
13743d8817e4Smiod     }
13753d8817e4Smiod }
13763d8817e4Smiod 
13773d8817e4Smiod /* Expression parser.  */
13783d8817e4Smiod 
13793d8817e4Smiod /* We allow an empty expression, and just assume (absolute,0) silently.
13803d8817e4Smiod    Unary operators and parenthetical expressions are treated as operands.
13813d8817e4Smiod    As usual, Q==quantity==operand, O==operator, X==expression mnemonics.
13823d8817e4Smiod 
13833d8817e4Smiod    We used to do an aho/ullman shift-reduce parser, but the logic got so
13843d8817e4Smiod    warped that I flushed it and wrote a recursive-descent parser instead.
13853d8817e4Smiod    Now things are stable, would anybody like to write a fast parser?
13863d8817e4Smiod    Most expressions are either register (which does not even reach here)
13873d8817e4Smiod    or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common.
13883d8817e4Smiod    So I guess it doesn't really matter how inefficient more complex expressions
13893d8817e4Smiod    are parsed.
13903d8817e4Smiod 
13913d8817e4Smiod    After expr(RANK,resultP) input_line_pointer->operator of rank <= RANK.
13923d8817e4Smiod    Also, we have consumed any leading or trailing spaces (operand does that)
13933d8817e4Smiod    and done all intervening operators.
13943d8817e4Smiod 
13953d8817e4Smiod    This returns the segment of the result, which will be
13963d8817e4Smiod    absolute_section or the segment of a symbol.  */
13973d8817e4Smiod 
13983d8817e4Smiod #undef __
13993d8817e4Smiod #define __ O_illegal
14003d8817e4Smiod #ifndef O_SINGLE_EQ
14013d8817e4Smiod #define O_SINGLE_EQ O_illegal
14023d8817e4Smiod #endif
14033d8817e4Smiod 
14043d8817e4Smiod /* Maps ASCII -> operators.  */
14053d8817e4Smiod static const operatorT op_encoding[256] = {
14063d8817e4Smiod   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
14073d8817e4Smiod   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
14083d8817e4Smiod 
14093d8817e4Smiod   __, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __,
14103d8817e4Smiod   __, __, O_multiply, O_add, __, O_subtract, __, O_divide,
14113d8817e4Smiod   __, __, __, __, __, __, __, __,
14123d8817e4Smiod   __, __, __, __, O_lt, O_SINGLE_EQ, O_gt, __,
14133d8817e4Smiod   __, __, __, __, __, __, __, __,
14143d8817e4Smiod   __, __, __, __, __, __, __, __,
14153d8817e4Smiod   __, __, __, __, __, __, __, __,
14163d8817e4Smiod   __, __, __,
14173d8817e4Smiod #ifdef NEED_INDEX_OPERATOR
14183d8817e4Smiod   O_index,
14193d8817e4Smiod #else
14203d8817e4Smiod   __,
14213d8817e4Smiod #endif
14223d8817e4Smiod   __, __, O_bit_exclusive_or, __,
14233d8817e4Smiod   __, __, __, __, __, __, __, __,
14243d8817e4Smiod   __, __, __, __, __, __, __, __,
14253d8817e4Smiod   __, __, __, __, __, __, __, __,
14263d8817e4Smiod   __, __, __, __, O_bit_inclusive_or, __, __, __,
14273d8817e4Smiod 
14283d8817e4Smiod   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
14293d8817e4Smiod   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
14303d8817e4Smiod   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
14313d8817e4Smiod   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
14323d8817e4Smiod   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
14333d8817e4Smiod   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
14343d8817e4Smiod   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
14353d8817e4Smiod   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
14363d8817e4Smiod };
14373d8817e4Smiod 
14383d8817e4Smiod /* Rank	Examples
14393d8817e4Smiod    0	operand, (expression)
14403d8817e4Smiod    1	||
14413d8817e4Smiod    2	&&
14423d8817e4Smiod    3	== <> < <= >= >
14433d8817e4Smiod    4	+ -
14443d8817e4Smiod    5	used for * / % in MRI mode
14453d8817e4Smiod    6	& ^ ! |
14463d8817e4Smiod    7	* / % << >>
14473d8817e4Smiod    8	unary - unary ~
14483d8817e4Smiod */
14493d8817e4Smiod static operator_rankT op_rank[] = {
14503d8817e4Smiod   0,	/* O_illegal */
14513d8817e4Smiod   0,	/* O_absent */
14523d8817e4Smiod   0,	/* O_constant */
14533d8817e4Smiod   0,	/* O_symbol */
14543d8817e4Smiod   0,	/* O_symbol_rva */
14553d8817e4Smiod   0,	/* O_register */
14563d8817e4Smiod   0,	/* O_big */
14573d8817e4Smiod   9,	/* O_uminus */
14583d8817e4Smiod   9,	/* O_bit_not */
14593d8817e4Smiod   9,	/* O_logical_not */
14603d8817e4Smiod   8,	/* O_multiply */
14613d8817e4Smiod   8,	/* O_divide */
14623d8817e4Smiod   8,	/* O_modulus */
14633d8817e4Smiod   8,	/* O_left_shift */
14643d8817e4Smiod   8,	/* O_right_shift */
14653d8817e4Smiod   7,	/* O_bit_inclusive_or */
14663d8817e4Smiod   7,	/* O_bit_or_not */
14673d8817e4Smiod   7,	/* O_bit_exclusive_or */
14683d8817e4Smiod   7,	/* O_bit_and */
14693d8817e4Smiod   5,	/* O_add */
14703d8817e4Smiod   5,	/* O_subtract */
14713d8817e4Smiod   4,	/* O_eq */
14723d8817e4Smiod   4,	/* O_ne */
14733d8817e4Smiod   4,	/* O_lt */
14743d8817e4Smiod   4,	/* O_le */
14753d8817e4Smiod   4,	/* O_ge */
14763d8817e4Smiod   4,	/* O_gt */
14773d8817e4Smiod   3,	/* O_logical_and */
14783d8817e4Smiod   2,	/* O_logical_or */
14793d8817e4Smiod   1,	/* O_index */
14803d8817e4Smiod   0,	/* O_md1 */
14813d8817e4Smiod   0,	/* O_md2 */
14823d8817e4Smiod   0,	/* O_md3 */
14833d8817e4Smiod   0,	/* O_md4 */
14843d8817e4Smiod   0,	/* O_md5 */
14853d8817e4Smiod   0,	/* O_md6 */
14863d8817e4Smiod   0,	/* O_md7 */
14873d8817e4Smiod   0,	/* O_md8 */
14883d8817e4Smiod   0,	/* O_md9 */
14893d8817e4Smiod   0,	/* O_md10 */
14903d8817e4Smiod   0,	/* O_md11 */
14913d8817e4Smiod   0,	/* O_md12 */
14923d8817e4Smiod   0,	/* O_md13 */
14933d8817e4Smiod   0,	/* O_md14 */
14943d8817e4Smiod   0,	/* O_md15 */
14953d8817e4Smiod   0,	/* O_md16 */
14963d8817e4Smiod };
14973d8817e4Smiod 
14983d8817e4Smiod /* Unfortunately, in MRI mode for the m68k, multiplication and
14993d8817e4Smiod    division have lower precedence than the bit wise operators.  This
15003d8817e4Smiod    function sets the operator precedences correctly for the current
15013d8817e4Smiod    mode.  Also, MRI uses a different bit_not operator, and this fixes
15023d8817e4Smiod    that as well.  */
15033d8817e4Smiod 
15043d8817e4Smiod #define STANDARD_MUL_PRECEDENCE 8
15053d8817e4Smiod #define MRI_MUL_PRECEDENCE 6
15063d8817e4Smiod 
15073d8817e4Smiod void
expr_set_precedence(void)15083d8817e4Smiod expr_set_precedence (void)
15093d8817e4Smiod {
15103d8817e4Smiod   if (flag_m68k_mri)
15113d8817e4Smiod     {
15123d8817e4Smiod       op_rank[O_multiply] = MRI_MUL_PRECEDENCE;
15133d8817e4Smiod       op_rank[O_divide] = MRI_MUL_PRECEDENCE;
15143d8817e4Smiod       op_rank[O_modulus] = MRI_MUL_PRECEDENCE;
15153d8817e4Smiod     }
15163d8817e4Smiod   else
15173d8817e4Smiod     {
15183d8817e4Smiod       op_rank[O_multiply] = STANDARD_MUL_PRECEDENCE;
15193d8817e4Smiod       op_rank[O_divide] = STANDARD_MUL_PRECEDENCE;
15203d8817e4Smiod       op_rank[O_modulus] = STANDARD_MUL_PRECEDENCE;
15213d8817e4Smiod     }
15223d8817e4Smiod }
15233d8817e4Smiod 
15243d8817e4Smiod /* Initialize the expression parser.  */
15253d8817e4Smiod 
15263d8817e4Smiod void
expr_begin(void)15273d8817e4Smiod expr_begin (void)
15283d8817e4Smiod {
15293d8817e4Smiod   expr_set_precedence ();
15303d8817e4Smiod 
15313d8817e4Smiod   /* Verify that X_op field is wide enough.  */
15323d8817e4Smiod   {
15333d8817e4Smiod     expressionS e;
15343d8817e4Smiod     e.X_op = O_max;
15353d8817e4Smiod     assert (e.X_op == O_max);
15363d8817e4Smiod   }
15373d8817e4Smiod }
15383d8817e4Smiod 
15393d8817e4Smiod /* Return the encoding for the operator at INPUT_LINE_POINTER, and
15403d8817e4Smiod    sets NUM_CHARS to the number of characters in the operator.
15413d8817e4Smiod    Does not advance INPUT_LINE_POINTER.  */
15423d8817e4Smiod 
15433d8817e4Smiod static inline operatorT
operator(int * num_chars)15443d8817e4Smiod operator (int *num_chars)
15453d8817e4Smiod {
15463d8817e4Smiod   int c;
15473d8817e4Smiod   operatorT ret;
15483d8817e4Smiod 
15493d8817e4Smiod   c = *input_line_pointer & 0xff;
15503d8817e4Smiod   *num_chars = 1;
15513d8817e4Smiod 
15523d8817e4Smiod   if (is_end_of_line[c])
15533d8817e4Smiod     return O_illegal;
15543d8817e4Smiod 
15553d8817e4Smiod   switch (c)
15563d8817e4Smiod     {
15573d8817e4Smiod     default:
15583d8817e4Smiod       return op_encoding[c];
15593d8817e4Smiod 
15603d8817e4Smiod     case '+':
15613d8817e4Smiod     case '-':
15623d8817e4Smiod       /* Do not allow a++b and a--b to be a + (+b) and a - (-b)
15633d8817e4Smiod 	 Disabled, since the preprocessor removes whitespace.  */
15643d8817e4Smiod       if (1 || input_line_pointer[1] != c)
15653d8817e4Smiod 	return op_encoding[c];
15663d8817e4Smiod       return O_illegal;
15673d8817e4Smiod 
15683d8817e4Smiod     case '<':
15693d8817e4Smiod       switch (input_line_pointer[1])
15703d8817e4Smiod 	{
15713d8817e4Smiod 	default:
15723d8817e4Smiod 	  return op_encoding[c];
15733d8817e4Smiod 	case '<':
15743d8817e4Smiod 	  ret = O_left_shift;
15753d8817e4Smiod 	  break;
15763d8817e4Smiod 	case '>':
15773d8817e4Smiod 	  ret = O_ne;
15783d8817e4Smiod 	  break;
15793d8817e4Smiod 	case '=':
15803d8817e4Smiod 	  ret = O_le;
15813d8817e4Smiod 	  break;
15823d8817e4Smiod 	}
15833d8817e4Smiod       *num_chars = 2;
15843d8817e4Smiod       return ret;
15853d8817e4Smiod 
15863d8817e4Smiod     case '=':
15873d8817e4Smiod       if (input_line_pointer[1] != '=')
15883d8817e4Smiod 	return op_encoding[c];
15893d8817e4Smiod 
15903d8817e4Smiod       *num_chars = 2;
15913d8817e4Smiod       return O_eq;
15923d8817e4Smiod 
15933d8817e4Smiod     case '>':
15943d8817e4Smiod       switch (input_line_pointer[1])
15953d8817e4Smiod 	{
15963d8817e4Smiod 	default:
15973d8817e4Smiod 	  return op_encoding[c];
15983d8817e4Smiod 	case '>':
15993d8817e4Smiod 	  ret = O_right_shift;
16003d8817e4Smiod 	  break;
16013d8817e4Smiod 	case '=':
16023d8817e4Smiod 	  ret = O_ge;
16033d8817e4Smiod 	  break;
16043d8817e4Smiod 	}
16053d8817e4Smiod       *num_chars = 2;
16063d8817e4Smiod       return ret;
16073d8817e4Smiod 
16083d8817e4Smiod     case '!':
16093d8817e4Smiod       switch (input_line_pointer[1])
16103d8817e4Smiod 	{
16113d8817e4Smiod 	case '!':
16123d8817e4Smiod 	  /* We accept !! as equivalent to ^ for MRI compatibility. */
16133d8817e4Smiod 	  *num_chars = 2;
16143d8817e4Smiod 	  return O_bit_exclusive_or;
16153d8817e4Smiod 	case '=':
16163d8817e4Smiod 	  /* We accept != as equivalent to <>.  */
16173d8817e4Smiod 	  *num_chars = 2;
16183d8817e4Smiod 	  return O_ne;
16193d8817e4Smiod 	default:
16203d8817e4Smiod 	  if (flag_m68k_mri)
16213d8817e4Smiod 	    return O_bit_inclusive_or;
16223d8817e4Smiod 	  return op_encoding[c];
16233d8817e4Smiod 	}
16243d8817e4Smiod 
16253d8817e4Smiod     case '|':
16263d8817e4Smiod       if (input_line_pointer[1] != '|')
16273d8817e4Smiod 	return op_encoding[c];
16283d8817e4Smiod 
16293d8817e4Smiod       *num_chars = 2;
16303d8817e4Smiod       return O_logical_or;
16313d8817e4Smiod 
16323d8817e4Smiod     case '&':
16333d8817e4Smiod       if (input_line_pointer[1] != '&')
16343d8817e4Smiod 	return op_encoding[c];
16353d8817e4Smiod 
16363d8817e4Smiod       *num_chars = 2;
16373d8817e4Smiod       return O_logical_and;
16383d8817e4Smiod     }
16393d8817e4Smiod 
16403d8817e4Smiod   /* NOTREACHED  */
16413d8817e4Smiod }
16423d8817e4Smiod 
16433d8817e4Smiod /* Parse an expression.  */
16443d8817e4Smiod 
16453d8817e4Smiod segT
expr(int rankarg,expressionS * resultP,enum expr_mode mode)16463d8817e4Smiod expr (int rankarg,		/* Larger # is higher rank.  */
16473d8817e4Smiod       expressionS *resultP,	/* Deliver result here.  */
16483d8817e4Smiod       enum expr_mode mode	/* Controls behavior.  */)
16493d8817e4Smiod {
16503d8817e4Smiod   operator_rankT rank = (operator_rankT) rankarg;
16513d8817e4Smiod   segT retval;
16523d8817e4Smiod   expressionS right;
16533d8817e4Smiod   operatorT op_left;
16543d8817e4Smiod   operatorT op_right;
16553d8817e4Smiod   int op_chars;
16563d8817e4Smiod 
16573d8817e4Smiod   know (rank >= 0);
16583d8817e4Smiod 
16593d8817e4Smiod   /* Save the value of dot for the fixup code.  */
16603d8817e4Smiod   if (rank == 0)
16613d8817e4Smiod     dot_value = frag_now_fix ();
16623d8817e4Smiod 
16633d8817e4Smiod   retval = operand (resultP, mode);
16643d8817e4Smiod 
16653d8817e4Smiod   /* operand () gobbles spaces.  */
16663d8817e4Smiod   know (*input_line_pointer != ' ');
16673d8817e4Smiod 
16683d8817e4Smiod   op_left = operator (&op_chars);
16693d8817e4Smiod   while (op_left != O_illegal && op_rank[(int) op_left] > rank)
16703d8817e4Smiod     {
16713d8817e4Smiod       segT rightseg;
16723d8817e4Smiod       bfd_vma frag_off;
16733d8817e4Smiod 
16743d8817e4Smiod       input_line_pointer += op_chars;	/* -> after operator.  */
16753d8817e4Smiod 
16763d8817e4Smiod       rightseg = expr (op_rank[(int) op_left], &right, mode);
16773d8817e4Smiod       if (right.X_op == O_absent)
16783d8817e4Smiod 	{
16793d8817e4Smiod 	  as_warn (_("missing operand; zero assumed"));
16803d8817e4Smiod 	  right.X_op = O_constant;
16813d8817e4Smiod 	  right.X_add_number = 0;
16823d8817e4Smiod 	  right.X_add_symbol = NULL;
16833d8817e4Smiod 	  right.X_op_symbol = NULL;
16843d8817e4Smiod 	}
16853d8817e4Smiod 
16863d8817e4Smiod       know (*input_line_pointer != ' ');
16873d8817e4Smiod 
16883d8817e4Smiod       if (op_left == O_index)
16893d8817e4Smiod 	{
16903d8817e4Smiod 	  if (*input_line_pointer != ']')
16913d8817e4Smiod 	    as_bad ("missing right bracket");
16923d8817e4Smiod 	  else
16933d8817e4Smiod 	    {
16943d8817e4Smiod 	      ++input_line_pointer;
16953d8817e4Smiod 	      SKIP_WHITESPACE ();
16963d8817e4Smiod 	    }
16973d8817e4Smiod 	}
16983d8817e4Smiod 
16993d8817e4Smiod       op_right = operator (&op_chars);
17003d8817e4Smiod 
17013d8817e4Smiod       know (op_right == O_illegal
17023d8817e4Smiod 	    || op_rank[(int) op_right] <= op_rank[(int) op_left]);
17033d8817e4Smiod       know ((int) op_left >= (int) O_multiply
17043d8817e4Smiod 	    && (int) op_left <= (int) O_index);
17053d8817e4Smiod 
17063d8817e4Smiod       /* input_line_pointer->after right-hand quantity.  */
17073d8817e4Smiod       /* left-hand quantity in resultP.  */
17083d8817e4Smiod       /* right-hand quantity in right.  */
17093d8817e4Smiod       /* operator in op_left.  */
17103d8817e4Smiod 
17113d8817e4Smiod       if (resultP->X_op == O_big)
17123d8817e4Smiod 	{
17133d8817e4Smiod 	  if (resultP->X_add_number > 0)
17143d8817e4Smiod 	    as_warn (_("left operand is a bignum; integer 0 assumed"));
17153d8817e4Smiod 	  else
17163d8817e4Smiod 	    as_warn (_("left operand is a float; integer 0 assumed"));
17173d8817e4Smiod 	  resultP->X_op = O_constant;
17183d8817e4Smiod 	  resultP->X_add_number = 0;
17193d8817e4Smiod 	  resultP->X_add_symbol = NULL;
17203d8817e4Smiod 	  resultP->X_op_symbol = NULL;
17213d8817e4Smiod 	}
17223d8817e4Smiod       if (right.X_op == O_big)
17233d8817e4Smiod 	{
17243d8817e4Smiod 	  if (right.X_add_number > 0)
17253d8817e4Smiod 	    as_warn (_("right operand is a bignum; integer 0 assumed"));
17263d8817e4Smiod 	  else
17273d8817e4Smiod 	    as_warn (_("right operand is a float; integer 0 assumed"));
17283d8817e4Smiod 	  right.X_op = O_constant;
17293d8817e4Smiod 	  right.X_add_number = 0;
17303d8817e4Smiod 	  right.X_add_symbol = NULL;
17313d8817e4Smiod 	  right.X_op_symbol = NULL;
17323d8817e4Smiod 	}
17333d8817e4Smiod 
17343d8817e4Smiod       /* Optimize common cases.  */
17353d8817e4Smiod #ifdef md_optimize_expr
17363d8817e4Smiod       if (md_optimize_expr (resultP, op_left, &right))
17373d8817e4Smiod 	{
17383d8817e4Smiod 	  /* Skip.  */
17393d8817e4Smiod 	  ;
17403d8817e4Smiod 	}
17413d8817e4Smiod       else
17423d8817e4Smiod #endif
17433d8817e4Smiod       if (op_left == O_add && right.X_op == O_constant)
17443d8817e4Smiod 	{
17453d8817e4Smiod 	  /* X + constant.  */
17463d8817e4Smiod 	  resultP->X_add_number += right.X_add_number;
17473d8817e4Smiod 	}
17483d8817e4Smiod       /* This case comes up in PIC code.  */
17493d8817e4Smiod       else if (op_left == O_subtract
17503d8817e4Smiod 	       && right.X_op == O_symbol
17513d8817e4Smiod 	       && resultP->X_op == O_symbol
17523d8817e4Smiod 	       && retval == rightseg
17533d8817e4Smiod 	       && (SEG_NORMAL (rightseg)
17543d8817e4Smiod 		   || right.X_add_symbol == resultP->X_add_symbol)
17553d8817e4Smiod 	       && frag_offset_fixed_p (symbol_get_frag (resultP->X_add_symbol),
17563d8817e4Smiod 				       symbol_get_frag (right.X_add_symbol),
17573d8817e4Smiod 				       &frag_off))
17583d8817e4Smiod 	{
17593d8817e4Smiod 	  resultP->X_add_number -= right.X_add_number;
17603d8817e4Smiod 	  resultP->X_add_number -= frag_off / OCTETS_PER_BYTE;
17613d8817e4Smiod 	  resultP->X_add_number += (S_GET_VALUE (resultP->X_add_symbol)
17623d8817e4Smiod 				    - S_GET_VALUE (right.X_add_symbol));
17633d8817e4Smiod 	  resultP->X_op = O_constant;
17643d8817e4Smiod 	  resultP->X_add_symbol = 0;
17653d8817e4Smiod 	}
17663d8817e4Smiod       else if (op_left == O_subtract && right.X_op == O_constant)
17673d8817e4Smiod 	{
17683d8817e4Smiod 	  /* X - constant.  */
17693d8817e4Smiod 	  resultP->X_add_number -= right.X_add_number;
17703d8817e4Smiod 	}
17713d8817e4Smiod       else if (op_left == O_add && resultP->X_op == O_constant)
17723d8817e4Smiod 	{
17733d8817e4Smiod 	  /* Constant + X.  */
17743d8817e4Smiod 	  resultP->X_op = right.X_op;
17753d8817e4Smiod 	  resultP->X_add_symbol = right.X_add_symbol;
17763d8817e4Smiod 	  resultP->X_op_symbol = right.X_op_symbol;
17773d8817e4Smiod 	  resultP->X_add_number += right.X_add_number;
17783d8817e4Smiod 	  retval = rightseg;
17793d8817e4Smiod 	}
17803d8817e4Smiod       else if (resultP->X_op == O_constant && right.X_op == O_constant)
17813d8817e4Smiod 	{
17823d8817e4Smiod 	  /* Constant OP constant.  */
17833d8817e4Smiod 	  offsetT v = right.X_add_number;
17843d8817e4Smiod 	  if (v == 0 && (op_left == O_divide || op_left == O_modulus))
17853d8817e4Smiod 	    {
17863d8817e4Smiod 	      as_warn (_("division by zero"));
17873d8817e4Smiod 	      v = 1;
17883d8817e4Smiod 	    }
17893d8817e4Smiod 	  switch (op_left)
17903d8817e4Smiod 	    {
17913d8817e4Smiod 	    default:			abort ();
17923d8817e4Smiod 	    case O_multiply:		resultP->X_add_number *= v; break;
17933d8817e4Smiod 	    case O_divide:		resultP->X_add_number /= v; break;
17943d8817e4Smiod 	    case O_modulus:		resultP->X_add_number %= v; break;
17953d8817e4Smiod 	    case O_left_shift:		resultP->X_add_number <<= v; break;
17963d8817e4Smiod 	    case O_right_shift:
17973d8817e4Smiod 	      /* We always use unsigned shifts, to avoid relying on
17983d8817e4Smiod 		 characteristics of the compiler used to compile gas.  */
17993d8817e4Smiod 	      resultP->X_add_number =
18003d8817e4Smiod 		(offsetT) ((valueT) resultP->X_add_number >> (valueT) v);
18013d8817e4Smiod 	      break;
18023d8817e4Smiod 	    case O_bit_inclusive_or:	resultP->X_add_number |= v; break;
18033d8817e4Smiod 	    case O_bit_or_not:		resultP->X_add_number |= ~v; break;
18043d8817e4Smiod 	    case O_bit_exclusive_or:	resultP->X_add_number ^= v; break;
18053d8817e4Smiod 	    case O_bit_and:		resultP->X_add_number &= v; break;
18063d8817e4Smiod 	    case O_add:			resultP->X_add_number += v; break;
18073d8817e4Smiod 	    case O_subtract:		resultP->X_add_number -= v; break;
18083d8817e4Smiod 	    case O_eq:
18093d8817e4Smiod 	      resultP->X_add_number =
18103d8817e4Smiod 		resultP->X_add_number == v ? ~ (offsetT) 0 : 0;
18113d8817e4Smiod 	      break;
18123d8817e4Smiod 	    case O_ne:
18133d8817e4Smiod 	      resultP->X_add_number =
18143d8817e4Smiod 		resultP->X_add_number != v ? ~ (offsetT) 0 : 0;
18153d8817e4Smiod 	      break;
18163d8817e4Smiod 	    case O_lt:
18173d8817e4Smiod 	      resultP->X_add_number =
18183d8817e4Smiod 		resultP->X_add_number <  v ? ~ (offsetT) 0 : 0;
18193d8817e4Smiod 	      break;
18203d8817e4Smiod 	    case O_le:
18213d8817e4Smiod 	      resultP->X_add_number =
18223d8817e4Smiod 		resultP->X_add_number <= v ? ~ (offsetT) 0 : 0;
18233d8817e4Smiod 	      break;
18243d8817e4Smiod 	    case O_ge:
18253d8817e4Smiod 	      resultP->X_add_number =
18263d8817e4Smiod 		resultP->X_add_number >= v ? ~ (offsetT) 0 : 0;
18273d8817e4Smiod 	      break;
18283d8817e4Smiod 	    case O_gt:
18293d8817e4Smiod 	      resultP->X_add_number =
18303d8817e4Smiod 		resultP->X_add_number >  v ? ~ (offsetT) 0 : 0;
18313d8817e4Smiod 	      break;
18323d8817e4Smiod 	    case O_logical_and:
18333d8817e4Smiod 	      resultP->X_add_number = resultP->X_add_number && v;
18343d8817e4Smiod 	      break;
18353d8817e4Smiod 	    case O_logical_or:
18363d8817e4Smiod 	      resultP->X_add_number = resultP->X_add_number || v;
18373d8817e4Smiod 	      break;
18383d8817e4Smiod 	    }
18393d8817e4Smiod 	}
18403d8817e4Smiod       else if (resultP->X_op == O_symbol
18413d8817e4Smiod 	       && right.X_op == O_symbol
18423d8817e4Smiod 	       && (op_left == O_add
18433d8817e4Smiod 		   || op_left == O_subtract
18443d8817e4Smiod 		   || (resultP->X_add_number == 0
18453d8817e4Smiod 		       && right.X_add_number == 0)))
18463d8817e4Smiod 	{
18473d8817e4Smiod 	  /* Symbol OP symbol.  */
18483d8817e4Smiod 	  resultP->X_op = op_left;
18493d8817e4Smiod 	  resultP->X_op_symbol = right.X_add_symbol;
18503d8817e4Smiod 	  if (op_left == O_add)
18513d8817e4Smiod 	    resultP->X_add_number += right.X_add_number;
18523d8817e4Smiod 	  else if (op_left == O_subtract)
18533d8817e4Smiod 	    {
18543d8817e4Smiod 	      resultP->X_add_number -= right.X_add_number;
18553d8817e4Smiod 	      if (retval == rightseg && SEG_NORMAL (retval))
18563d8817e4Smiod 		{
18573d8817e4Smiod 		  retval = absolute_section;
18583d8817e4Smiod 		  rightseg = absolute_section;
18593d8817e4Smiod 		}
18603d8817e4Smiod 	    }
18613d8817e4Smiod 	}
18623d8817e4Smiod       else
18633d8817e4Smiod 	{
18643d8817e4Smiod 	  /* The general case.  */
18653d8817e4Smiod 	  resultP->X_add_symbol = make_expr_symbol (resultP);
18663d8817e4Smiod 	  resultP->X_op_symbol = make_expr_symbol (&right);
18673d8817e4Smiod 	  resultP->X_op = op_left;
18683d8817e4Smiod 	  resultP->X_add_number = 0;
18693d8817e4Smiod 	  resultP->X_unsigned = 1;
18703d8817e4Smiod 	}
18713d8817e4Smiod 
18723d8817e4Smiod       if (retval != rightseg)
18733d8817e4Smiod 	{
18743d8817e4Smiod 	  if (! SEG_NORMAL (retval))
18753d8817e4Smiod 	    {
18763d8817e4Smiod 	      if (retval != undefined_section || SEG_NORMAL (rightseg))
18773d8817e4Smiod 		retval = rightseg;
18783d8817e4Smiod 	    }
18793d8817e4Smiod 	  else if (SEG_NORMAL (rightseg)
18803d8817e4Smiod #ifdef DIFF_EXPR_OK
18813d8817e4Smiod 		   && op_left != O_subtract
18823d8817e4Smiod #endif
18833d8817e4Smiod 		   )
18843d8817e4Smiod 	    as_bad (_("operation combines symbols in different segments"));
18853d8817e4Smiod 	}
18863d8817e4Smiod 
18873d8817e4Smiod       op_left = op_right;
18883d8817e4Smiod     }				/* While next operator is >= this rank.  */
18893d8817e4Smiod 
18903d8817e4Smiod   /* The PA port needs this information.  */
18913d8817e4Smiod   if (resultP->X_add_symbol)
18923d8817e4Smiod     symbol_mark_used (resultP->X_add_symbol);
18933d8817e4Smiod 
18943d8817e4Smiod   if (rank == 0 && mode == expr_evaluate)
18953d8817e4Smiod     resolve_expression (resultP);
18963d8817e4Smiod 
18973d8817e4Smiod   return resultP->X_op == O_constant ? absolute_section : retval;
18983d8817e4Smiod }
18993d8817e4Smiod 
19003d8817e4Smiod /* Resolve an expression without changing any symbols/sub-expressions
19013d8817e4Smiod    used.  */
19023d8817e4Smiod 
19033d8817e4Smiod int
resolve_expression(expressionS * expressionP)19043d8817e4Smiod resolve_expression (expressionS *expressionP)
19053d8817e4Smiod {
19063d8817e4Smiod   /* Help out with CSE.  */
19073d8817e4Smiod   valueT final_val = expressionP->X_add_number;
19083d8817e4Smiod   symbolS *add_symbol = expressionP->X_add_symbol;
19093d8817e4Smiod   symbolS *op_symbol = expressionP->X_op_symbol;
19103d8817e4Smiod   operatorT op = expressionP->X_op;
19113d8817e4Smiod   valueT left, right;
19123d8817e4Smiod   segT seg_left, seg_right;
19133d8817e4Smiod   fragS *frag_left, *frag_right;
19143d8817e4Smiod   bfd_vma frag_off;
19153d8817e4Smiod 
19163d8817e4Smiod   switch (op)
19173d8817e4Smiod     {
19183d8817e4Smiod     default:
19193d8817e4Smiod       return 0;
19203d8817e4Smiod 
19213d8817e4Smiod     case O_constant:
19223d8817e4Smiod     case O_register:
19233d8817e4Smiod       left = 0;
19243d8817e4Smiod       break;
19253d8817e4Smiod 
19263d8817e4Smiod     case O_symbol:
19273d8817e4Smiod     case O_symbol_rva:
19283d8817e4Smiod       if (!snapshot_symbol (&add_symbol, &left, &seg_left, &frag_left))
19293d8817e4Smiod 	return 0;
19303d8817e4Smiod 
19313d8817e4Smiod       break;
19323d8817e4Smiod 
19333d8817e4Smiod     case O_uminus:
19343d8817e4Smiod     case O_bit_not:
19353d8817e4Smiod     case O_logical_not:
19363d8817e4Smiod       if (!snapshot_symbol (&add_symbol, &left, &seg_left, &frag_left))
19373d8817e4Smiod 	return 0;
19383d8817e4Smiod 
19393d8817e4Smiod       if (seg_left != absolute_section)
19403d8817e4Smiod 	return 0;
19413d8817e4Smiod 
19423d8817e4Smiod       if (op == O_logical_not)
19433d8817e4Smiod 	left = !left;
19443d8817e4Smiod       else if (op == O_uminus)
19453d8817e4Smiod 	left = -left;
19463d8817e4Smiod       else
19473d8817e4Smiod 	left = ~left;
19483d8817e4Smiod       op = O_constant;
19493d8817e4Smiod       break;
19503d8817e4Smiod 
19513d8817e4Smiod     case O_multiply:
19523d8817e4Smiod     case O_divide:
19533d8817e4Smiod     case O_modulus:
19543d8817e4Smiod     case O_left_shift:
19553d8817e4Smiod     case O_right_shift:
19563d8817e4Smiod     case O_bit_inclusive_or:
19573d8817e4Smiod     case O_bit_or_not:
19583d8817e4Smiod     case O_bit_exclusive_or:
19593d8817e4Smiod     case O_bit_and:
19603d8817e4Smiod     case O_add:
19613d8817e4Smiod     case O_subtract:
19623d8817e4Smiod     case O_eq:
19633d8817e4Smiod     case O_ne:
19643d8817e4Smiod     case O_lt:
19653d8817e4Smiod     case O_le:
19663d8817e4Smiod     case O_ge:
19673d8817e4Smiod     case O_gt:
19683d8817e4Smiod     case O_logical_and:
19693d8817e4Smiod     case O_logical_or:
19703d8817e4Smiod       if (!snapshot_symbol (&add_symbol, &left, &seg_left, &frag_left)
19713d8817e4Smiod 	  || !snapshot_symbol (&op_symbol, &right, &seg_right, &frag_right))
19723d8817e4Smiod 	return 0;
19733d8817e4Smiod 
19743d8817e4Smiod       /* Simplify addition or subtraction of a constant by folding the
19753d8817e4Smiod 	 constant into X_add_number.  */
19763d8817e4Smiod       if (op == O_add)
19773d8817e4Smiod 	{
19783d8817e4Smiod 	  if (seg_right == absolute_section)
19793d8817e4Smiod 	    {
19803d8817e4Smiod 	      final_val += right;
19813d8817e4Smiod 	      op = O_symbol;
19823d8817e4Smiod 	      break;
19833d8817e4Smiod 	    }
19843d8817e4Smiod 	  else if (seg_left == absolute_section)
19853d8817e4Smiod 	    {
19863d8817e4Smiod 	      final_val += left;
19873d8817e4Smiod 	      left = right;
19883d8817e4Smiod 	      seg_left = seg_right;
19893d8817e4Smiod 	      add_symbol = op_symbol;
19903d8817e4Smiod 	      op = O_symbol;
19913d8817e4Smiod 	      break;
19923d8817e4Smiod 	    }
19933d8817e4Smiod 	}
19943d8817e4Smiod       else if (op == O_subtract)
19953d8817e4Smiod 	{
19963d8817e4Smiod 	  if (seg_right == absolute_section)
19973d8817e4Smiod 	    {
19983d8817e4Smiod 	      final_val -= right;
19993d8817e4Smiod 	      op = O_symbol;
20003d8817e4Smiod 	      break;
20013d8817e4Smiod 	    }
20023d8817e4Smiod 	}
20033d8817e4Smiod 
20043d8817e4Smiod       /* Equality and non-equality tests are permitted on anything.
20053d8817e4Smiod 	 Subtraction, and other comparison operators are permitted if
20063d8817e4Smiod 	 both operands are in the same section.
20073d8817e4Smiod 	 Shifts by constant zero are permitted on anything.
20083d8817e4Smiod 	 Multiplies, bit-ors, and bit-ands with constant zero are
20093d8817e4Smiod 	 permitted on anything.
20103d8817e4Smiod 	 Multiplies and divides by constant one are permitted on
20113d8817e4Smiod 	 anything.
20123d8817e4Smiod 	 Binary operations with both operands being the same register
20133d8817e4Smiod 	 or undefined symbol are permitted if the result doesn't depend
20143d8817e4Smiod 	 on the input value.
20153d8817e4Smiod 	 Otherwise, both operands must be absolute.  We already handled
20163d8817e4Smiod 	 the case of addition or subtraction of a constant above.  */
20173d8817e4Smiod       frag_off = 0;
20183d8817e4Smiod       if (!(seg_left == absolute_section
20193d8817e4Smiod 	       && seg_right == absolute_section)
20203d8817e4Smiod 	  && !(op == O_eq || op == O_ne)
20213d8817e4Smiod 	  && !((op == O_subtract
20223d8817e4Smiod 		|| op == O_lt || op == O_le || op == O_ge || op == O_gt)
20233d8817e4Smiod 	       && seg_left == seg_right
20243d8817e4Smiod 	       && (finalize_syms
20253d8817e4Smiod 		   || frag_offset_fixed_p (frag_left, frag_right, &frag_off))
20263d8817e4Smiod 	       && (seg_left != reg_section || left == right)
20273d8817e4Smiod 	       && (seg_left != undefined_section || add_symbol == op_symbol)))
20283d8817e4Smiod 	{
20293d8817e4Smiod 	  if ((seg_left == absolute_section && left == 0)
20303d8817e4Smiod 	      || (seg_right == absolute_section && right == 0))
20313d8817e4Smiod 	    {
20323d8817e4Smiod 	      if (op == O_bit_exclusive_or || op == O_bit_inclusive_or)
20333d8817e4Smiod 		{
20343d8817e4Smiod 		  if (seg_right != absolute_section || right != 0)
20353d8817e4Smiod 		    {
20363d8817e4Smiod 		      seg_left = seg_right;
20373d8817e4Smiod 		      left = right;
20383d8817e4Smiod 		      add_symbol = op_symbol;
20393d8817e4Smiod 		    }
20403d8817e4Smiod 		  op = O_symbol;
20413d8817e4Smiod 		  break;
20423d8817e4Smiod 		}
20433d8817e4Smiod 	      else if (op == O_left_shift || op == O_right_shift)
20443d8817e4Smiod 		{
20453d8817e4Smiod 		  if (seg_left != absolute_section || left != 0)
20463d8817e4Smiod 		    {
20473d8817e4Smiod 		      op = O_symbol;
20483d8817e4Smiod 		      break;
20493d8817e4Smiod 		    }
20503d8817e4Smiod 		}
20513d8817e4Smiod 	      else if (op != O_multiply
20523d8817e4Smiod 		       && op != O_bit_or_not && op != O_bit_and)
20533d8817e4Smiod 	        return 0;
20543d8817e4Smiod 	    }
20553d8817e4Smiod 	  else if (op == O_multiply
20563d8817e4Smiod 		   && seg_left == absolute_section && left == 1)
20573d8817e4Smiod 	    {
20583d8817e4Smiod 	      seg_left = seg_right;
20593d8817e4Smiod 	      left = right;
20603d8817e4Smiod 	      add_symbol = op_symbol;
20613d8817e4Smiod 	      op = O_symbol;
20623d8817e4Smiod 	      break;
20633d8817e4Smiod 	    }
20643d8817e4Smiod 	  else if ((op == O_multiply || op == O_divide)
20653d8817e4Smiod 		   && seg_right == absolute_section && right == 1)
20663d8817e4Smiod 	    {
20673d8817e4Smiod 	      op = O_symbol;
20683d8817e4Smiod 	      break;
20693d8817e4Smiod 	    }
20703d8817e4Smiod 	  else if (left != right
20713d8817e4Smiod 		   || ((seg_left != reg_section || seg_right != reg_section)
20723d8817e4Smiod 		       && (seg_left != undefined_section
20733d8817e4Smiod 			   || seg_right != undefined_section
20743d8817e4Smiod 			   || add_symbol != op_symbol)))
20753d8817e4Smiod 	    return 0;
20763d8817e4Smiod 	  else if (op == O_bit_and || op == O_bit_inclusive_or)
20773d8817e4Smiod 	    {
20783d8817e4Smiod 	      op = O_symbol;
20793d8817e4Smiod 	      break;
20803d8817e4Smiod 	    }
20813d8817e4Smiod 	  else if (op != O_bit_exclusive_or && op != O_bit_or_not)
20823d8817e4Smiod 	    return 0;
20833d8817e4Smiod 	}
20843d8817e4Smiod 
20853d8817e4Smiod       right += frag_off / OCTETS_PER_BYTE;
20863d8817e4Smiod       switch (op)
20873d8817e4Smiod 	{
20883d8817e4Smiod 	case O_add:			left += right; break;
20893d8817e4Smiod 	case O_subtract:		left -= right; break;
20903d8817e4Smiod 	case O_multiply:		left *= right; break;
20913d8817e4Smiod 	case O_divide:
20923d8817e4Smiod 	  if (right == 0)
20933d8817e4Smiod 	    return 0;
20943d8817e4Smiod 	  left = (offsetT) left / (offsetT) right;
20953d8817e4Smiod 	  break;
20963d8817e4Smiod 	case O_modulus:
20973d8817e4Smiod 	  if (right == 0)
20983d8817e4Smiod 	    return 0;
20993d8817e4Smiod 	  left = (offsetT) left % (offsetT) right;
21003d8817e4Smiod 	  break;
21013d8817e4Smiod 	case O_left_shift:		left <<= right; break;
21023d8817e4Smiod 	case O_right_shift:		left >>= right; break;
21033d8817e4Smiod 	case O_bit_inclusive_or:	left |= right; break;
21043d8817e4Smiod 	case O_bit_or_not:		left |= ~right; break;
21053d8817e4Smiod 	case O_bit_exclusive_or:	left ^= right; break;
21063d8817e4Smiod 	case O_bit_and:			left &= right; break;
21073d8817e4Smiod 	case O_eq:
21083d8817e4Smiod 	case O_ne:
21093d8817e4Smiod 	  left = (left == right
21103d8817e4Smiod 		  && seg_left == seg_right
21113d8817e4Smiod 		  && (finalize_syms || frag_left == frag_right)
21123d8817e4Smiod 		  && (seg_left != undefined_section
21133d8817e4Smiod 		      || add_symbol == op_symbol)
21143d8817e4Smiod 		  ? ~ (valueT) 0 : 0);
21153d8817e4Smiod 	  if (op == O_ne)
21163d8817e4Smiod 	    left = ~left;
21173d8817e4Smiod 	  break;
21183d8817e4Smiod 	case O_lt:
21193d8817e4Smiod 	  left = (offsetT) left <  (offsetT) right ? ~ (valueT) 0 : 0;
21203d8817e4Smiod 	  break;
21213d8817e4Smiod 	case O_le:
21223d8817e4Smiod 	  left = (offsetT) left <= (offsetT) right ? ~ (valueT) 0 : 0;
21233d8817e4Smiod 	  break;
21243d8817e4Smiod 	case O_ge:
21253d8817e4Smiod 	  left = (offsetT) left >= (offsetT) right ? ~ (valueT) 0 : 0;
21263d8817e4Smiod 	  break;
21273d8817e4Smiod 	case O_gt:
21283d8817e4Smiod 	  left = (offsetT) left >  (offsetT) right ? ~ (valueT) 0 : 0;
21293d8817e4Smiod 	  break;
21303d8817e4Smiod 	case O_logical_and:	left = left && right; break;
21313d8817e4Smiod 	case O_logical_or:	left = left || right; break;
21323d8817e4Smiod 	default:		abort ();
21333d8817e4Smiod 	}
21343d8817e4Smiod 
21353d8817e4Smiod       op = O_constant;
21363d8817e4Smiod       break;
21373d8817e4Smiod     }
21383d8817e4Smiod 
21393d8817e4Smiod   if (op == O_symbol)
21403d8817e4Smiod     {
21413d8817e4Smiod       if (seg_left == absolute_section)
21423d8817e4Smiod 	op = O_constant;
21433d8817e4Smiod       else if (seg_left == reg_section && final_val == 0)
21443d8817e4Smiod 	op = O_register;
21453d8817e4Smiod       else if (add_symbol != expressionP->X_add_symbol)
21463d8817e4Smiod 	final_val += left;
21473d8817e4Smiod       expressionP->X_add_symbol = add_symbol;
21483d8817e4Smiod     }
21493d8817e4Smiod   expressionP->X_op = op;
21503d8817e4Smiod 
21513d8817e4Smiod   if (op == O_constant || op == O_register)
21523d8817e4Smiod     final_val += left;
21533d8817e4Smiod   expressionP->X_add_number = final_val;
21543d8817e4Smiod 
21553d8817e4Smiod   return 1;
21563d8817e4Smiod }
21573d8817e4Smiod 
21583d8817e4Smiod /* This lives here because it belongs equally in expr.c & read.c.
21593d8817e4Smiod    expr.c is just a branch office read.c anyway, and putting it
21603d8817e4Smiod    here lessens the crowd at read.c.
21613d8817e4Smiod 
21623d8817e4Smiod    Assume input_line_pointer is at start of symbol name.
21633d8817e4Smiod    Advance input_line_pointer past symbol name.
21643d8817e4Smiod    Turn that character into a '\0', returning its former value.
21653d8817e4Smiod    This allows a string compare (RMS wants symbol names to be strings)
21663d8817e4Smiod    of the symbol name.
21673d8817e4Smiod    There will always be a char following symbol name, because all good
21683d8817e4Smiod    lines end in end-of-line.  */
21693d8817e4Smiod 
21703d8817e4Smiod char
get_symbol_end(void)21713d8817e4Smiod get_symbol_end (void)
21723d8817e4Smiod {
21733d8817e4Smiod   char c;
21743d8817e4Smiod 
21753d8817e4Smiod   /* We accept \001 in a name in case this is being called with a
21763d8817e4Smiod      constructed string.  */
21773d8817e4Smiod   if (is_name_beginner (c = *input_line_pointer++) || c == '\001')
21783d8817e4Smiod     {
21793d8817e4Smiod       while (is_part_of_name (c = *input_line_pointer++)
21803d8817e4Smiod 	     || c == '\001')
21813d8817e4Smiod 	;
21823d8817e4Smiod       if (is_name_ender (c))
21833d8817e4Smiod 	c = *input_line_pointer++;
21843d8817e4Smiod     }
21853d8817e4Smiod   *--input_line_pointer = 0;
21863d8817e4Smiod   return (c);
21873d8817e4Smiod }
21883d8817e4Smiod 
21893d8817e4Smiod unsigned int
get_single_number(void)21903d8817e4Smiod get_single_number (void)
21913d8817e4Smiod {
21923d8817e4Smiod   expressionS exp;
21933d8817e4Smiod   operand (&exp, expr_normal);
21943d8817e4Smiod   return exp.X_add_number;
21953d8817e4Smiod }
2196