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