133965Sjdp/* expr.c -operands, expressions- 278828Sobrien Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3218822Sdim 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 433965Sjdp Free Software Foundation, Inc. 533965Sjdp 633965Sjdp This file is part of GAS, the GNU Assembler. 733965Sjdp 833965Sjdp GAS is free software; you can redistribute it and/or modify 933965Sjdp it under the terms of the GNU General Public License as published by 1033965Sjdp the Free Software Foundation; either version 2, or (at your option) 1133965Sjdp any later version. 1233965Sjdp 1333965Sjdp GAS is distributed in the hope that it will be useful, 1433965Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1533965Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965Sjdp GNU General Public License for more details. 1733965Sjdp 1833965Sjdp You should have received a copy of the GNU General Public License 1933965Sjdp along with GAS; see the file COPYING. If not, write to the Free 20218822Sdim Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 21218822Sdim 02110-1301, USA. */ 2233965Sjdp 2377298Sobrien/* This is really a branch office of as-read.c. I split it out to clearly 2477298Sobrien distinguish the world of expressions from the world of statements. 2577298Sobrien (It also gives smaller files to re-compile.) 2677298Sobrien Here, "operand"s are of expressions, not instructions. */ 2733965Sjdp 2838889Sjdp#define min(a, b) ((a) < (b) ? (a) : (b)) 2933965Sjdp 3033965Sjdp#include "as.h" 3189857Sobrien#include "safe-ctype.h" 3233965Sjdp#include "obstack.h" 3333965Sjdp 34130561Sobrienstatic void floating_constant (expressionS * expressionP); 35130561Sobrienstatic valueT generic_bignum_to_int32 (void); 3660484Sobrien#ifdef BFD64 37130561Sobrienstatic valueT generic_bignum_to_int64 (void); 3860484Sobrien#endif 39130561Sobrienstatic void integer_constant (int radix, expressionS * expressionP); 40130561Sobrienstatic void mri_char_constant (expressionS *); 41130561Sobrienstatic void current_location (expressionS *); 42130561Sobrienstatic void clean_up_expression (expressionS * expressionP); 43218822Sdimstatic segT operand (expressionS *, enum expr_mode); 44130561Sobrienstatic operatorT operator (int *); 4533965Sjdp 4633965Sjdpextern const char EXP_CHARS[], FLT_CHARS[]; 4733965Sjdp 4833965Sjdp/* We keep a mapping of expression symbols to file positions, so that 4933965Sjdp we can provide better error messages. */ 5033965Sjdp 5177298Sobrienstruct expr_symbol_line { 5233965Sjdp struct expr_symbol_line *next; 5333965Sjdp symbolS *sym; 5433965Sjdp char *file; 5533965Sjdp unsigned int line; 5633965Sjdp}; 5733965Sjdp 5833965Sjdpstatic struct expr_symbol_line *expr_symbol_lines; 5933965Sjdp 6033965Sjdp/* Build a dummy symbol to hold a complex expression. This is how we 6133965Sjdp build expressions up out of other expressions. The symbol is put 6233965Sjdp into the fake section expr_section. */ 6333965Sjdp 6433965SjdpsymbolS * 65130561Sobrienmake_expr_symbol (expressionS *expressionP) 6633965Sjdp{ 6760484Sobrien expressionS zero; 6833965Sjdp symbolS *symbolP; 6933965Sjdp struct expr_symbol_line *n; 7033965Sjdp 7133965Sjdp if (expressionP->X_op == O_symbol 7233965Sjdp && expressionP->X_add_number == 0) 7333965Sjdp return expressionP->X_add_symbol; 7433965Sjdp 7560484Sobrien if (expressionP->X_op == O_big) 7660484Sobrien { 7760484Sobrien /* This won't work, because the actual value is stored in 78130561Sobrien generic_floating_point_number or generic_bignum, and we are 79130561Sobrien going to lose it if we haven't already. */ 8060484Sobrien if (expressionP->X_add_number > 0) 8189857Sobrien as_bad (_("bignum invalid")); 8260484Sobrien else 8389857Sobrien as_bad (_("floating point number invalid")); 8460484Sobrien zero.X_op = O_constant; 8560484Sobrien zero.X_add_number = 0; 8660484Sobrien zero.X_unsigned = 0; 8760484Sobrien clean_up_expression (&zero); 8860484Sobrien expressionP = &zero; 8960484Sobrien } 9060484Sobrien 9133965Sjdp /* Putting constant symbols in absolute_section rather than 9233965Sjdp expr_section is convenient for the old a.out code, for which 9333965Sjdp S_GET_SEGMENT does not always retrieve the value put in by 9433965Sjdp S_SET_SEGMENT. */ 95130561Sobrien symbolP = symbol_create (FAKE_LABEL_NAME, 9633965Sjdp (expressionP->X_op == O_constant 9733965Sjdp ? absolute_section 9833965Sjdp : expr_section), 9933965Sjdp 0, &zero_address_frag); 10060484Sobrien symbol_set_value_expression (symbolP, expressionP); 10133965Sjdp 10233965Sjdp if (expressionP->X_op == O_constant) 10389857Sobrien resolve_symbol_value (symbolP); 10433965Sjdp 10533965Sjdp n = (struct expr_symbol_line *) xmalloc (sizeof *n); 10633965Sjdp n->sym = symbolP; 10733965Sjdp as_where (&n->file, &n->line); 10833965Sjdp n->next = expr_symbol_lines; 10933965Sjdp expr_symbol_lines = n; 11033965Sjdp 11133965Sjdp return symbolP; 11233965Sjdp} 11333965Sjdp 11433965Sjdp/* Return the file and line number for an expr symbol. Return 11533965Sjdp non-zero if something was found, 0 if no information is known for 11633965Sjdp the symbol. */ 11733965Sjdp 11833965Sjdpint 119130561Sobrienexpr_symbol_where (symbolS *sym, char **pfile, unsigned int *pline) 12033965Sjdp{ 12133965Sjdp register struct expr_symbol_line *l; 12233965Sjdp 12333965Sjdp for (l = expr_symbol_lines; l != NULL; l = l->next) 12433965Sjdp { 12533965Sjdp if (l->sym == sym) 12633965Sjdp { 12733965Sjdp *pfile = l->file; 12833965Sjdp *pline = l->line; 12933965Sjdp return 1; 13033965Sjdp } 13133965Sjdp } 13233965Sjdp 13333965Sjdp return 0; 13433965Sjdp} 13533965Sjdp 13638889Sjdp/* Utilities for building expressions. 13738889Sjdp Since complex expressions are recorded as symbols for use in other 13838889Sjdp expressions these return a symbolS * and not an expressionS *. 13938889Sjdp These explicitly do not take an "add_number" argument. */ 14038889Sjdp/* ??? For completeness' sake one might want expr_build_symbol. 14138889Sjdp It would just return its argument. */ 14238889Sjdp 14338889Sjdp/* Build an expression for an unsigned constant. 14438889Sjdp The corresponding one for signed constants is missing because 14538889Sjdp there's currently no need for it. One could add an unsigned_p flag 14638889Sjdp but that seems more clumsy. */ 14738889Sjdp 14838889SjdpsymbolS * 149130561Sobrienexpr_build_uconstant (offsetT value) 15038889Sjdp{ 15138889Sjdp expressionS e; 15238889Sjdp 15338889Sjdp e.X_op = O_constant; 15438889Sjdp e.X_add_number = value; 15538889Sjdp e.X_unsigned = 1; 15638889Sjdp return make_expr_symbol (&e); 15738889Sjdp} 15838889Sjdp 15960484Sobrien/* Build an expression for the current location ('.'). */ 16060484Sobrien 16160484SobriensymbolS * 162130561Sobrienexpr_build_dot (void) 16360484Sobrien{ 16460484Sobrien expressionS e; 16560484Sobrien 16660484Sobrien current_location (&e); 16760484Sobrien return make_expr_symbol (&e); 16860484Sobrien} 16938889Sjdp 17077298Sobrien/* Build any floating-point literal here. 17177298Sobrien Also build any bignum literal here. */ 17233965Sjdp 17333965Sjdp/* Seems atof_machine can backscan through generic_bignum and hit whatever 17433965Sjdp happens to be loaded before it in memory. And its way too complicated 17533965Sjdp for me to fix right. Thus a hack. JF: Just make generic_bignum bigger, 17633965Sjdp and never write into the early words, thus they'll always be zero. 17733965Sjdp I hate Dean's floating-point code. Bleh. */ 17833965SjdpLITTLENUM_TYPE generic_bignum[SIZE_OF_LARGE_NUMBER + 6]; 17977298Sobrien 18077298SobrienFLONUM_TYPE generic_floating_point_number = { 18177298Sobrien &generic_bignum[6], /* low. (JF: Was 0) */ 18277298Sobrien &generic_bignum[SIZE_OF_LARGE_NUMBER + 6 - 1], /* high. JF: (added +6) */ 18377298Sobrien 0, /* leader. */ 18477298Sobrien 0, /* exponent. */ 18577298Sobrien 0 /* sign. */ 18633965Sjdp}; 18777298Sobrien 18833965Sjdp 18933965Sjdpstatic void 190130561Sobrienfloating_constant (expressionS *expressionP) 19133965Sjdp{ 19277298Sobrien /* input_line_pointer -> floating-point constant. */ 19333965Sjdp int error_code; 19433965Sjdp 19533965Sjdp error_code = atof_generic (&input_line_pointer, ".", EXP_CHARS, 19633965Sjdp &generic_floating_point_number); 19733965Sjdp 19833965Sjdp if (error_code) 19933965Sjdp { 20033965Sjdp if (error_code == ERROR_EXPONENT_OVERFLOW) 20133965Sjdp { 20289857Sobrien as_bad (_("bad floating-point constant: exponent overflow")); 20333965Sjdp } 20433965Sjdp else 20533965Sjdp { 20689857Sobrien as_bad (_("bad floating-point constant: unknown error code=%d"), 20789857Sobrien error_code); 20833965Sjdp } 20933965Sjdp } 21033965Sjdp expressionP->X_op = O_big; 21177298Sobrien /* input_line_pointer -> just after constant, which may point to 21277298Sobrien whitespace. */ 21333965Sjdp expressionP->X_add_number = -1; 21433965Sjdp} 21533965Sjdp 21677298Sobrienstatic valueT 217130561Sobriengeneric_bignum_to_int32 (void) 21838889Sjdp{ 21938889Sjdp valueT number = 22038889Sjdp ((generic_bignum[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS) 22138889Sjdp | (generic_bignum[0] & LITTLENUM_MASK); 22238889Sjdp number &= 0xffffffff; 22338889Sjdp return number; 22438889Sjdp} 22538889Sjdp 22638889Sjdp#ifdef BFD64 22777298Sobrienstatic valueT 228130561Sobriengeneric_bignum_to_int64 (void) 22938889Sjdp{ 23077298Sobrien valueT number = 23177298Sobrien ((((((((valueT) generic_bignum[3] & LITTLENUM_MASK) 23277298Sobrien << LITTLENUM_NUMBER_OF_BITS) 23377298Sobrien | ((valueT) generic_bignum[2] & LITTLENUM_MASK)) 23477298Sobrien << LITTLENUM_NUMBER_OF_BITS) 23577298Sobrien | ((valueT) generic_bignum[1] & LITTLENUM_MASK)) 23677298Sobrien << LITTLENUM_NUMBER_OF_BITS) 23777298Sobrien | ((valueT) generic_bignum[0] & LITTLENUM_MASK)); 23838889Sjdp return number; 23938889Sjdp} 24038889Sjdp#endif 24138889Sjdp 24233965Sjdpstatic void 243130561Sobrieninteger_constant (int radix, expressionS *expressionP) 24433965Sjdp{ 24577298Sobrien char *start; /* Start of number. */ 24633965Sjdp char *suffix = NULL; 24733965Sjdp char c; 24877298Sobrien valueT number; /* Offset or (absolute) value. */ 24977298Sobrien short int digit; /* Value of next digit in current radix. */ 25077298Sobrien short int maxdig = 0; /* Highest permitted digit value. */ 25177298Sobrien int too_many_digits = 0; /* If we see >= this number of. */ 25277298Sobrien char *name; /* Points to name of symbol. */ 25377298Sobrien symbolS *symbolP; /* Points to symbol. */ 25433965Sjdp 25577298Sobrien int small; /* True if fits in 32 bits. */ 25633965Sjdp 25777298Sobrien /* May be bignum, or may fit in 32 bits. */ 25833965Sjdp /* Most numbers fit into 32 bits, and we want this case to be fast. 25933965Sjdp so we pretend it will fit into 32 bits. If, after making up a 32 26033965Sjdp bit number, we realise that we have scanned more digits than 26133965Sjdp comfortably fit into 32 bits, we re-scan the digits coding them 26233965Sjdp into a bignum. For decimal and octal numbers we are 26333965Sjdp conservative: Some numbers may be assumed bignums when in fact 26433965Sjdp they do fit into 32 bits. Numbers of any radix can have excess 26533965Sjdp leading zeros: We strive to recognise this and cast them back 26633965Sjdp into 32 bits. We must check that the bignum really is more than 26733965Sjdp 32 bits, and change it back to a 32-bit number if it fits. The 26833965Sjdp number we are looking for is expected to be positive, but if it 26933965Sjdp fits into 32 bits as an unsigned number, we let it be a 32-bit 27077298Sobrien number. The cavalier approach is for speed in ordinary cases. */ 27133965Sjdp /* This has been extended for 64 bits. We blindly assume that if 27233965Sjdp you're compiling in 64-bit mode, the target is a 64-bit machine. 27333965Sjdp This should be cleaned up. */ 27433965Sjdp 27533965Sjdp#ifdef BFD64 27633965Sjdp#define valuesize 64 27733965Sjdp#else /* includes non-bfd case, mostly */ 27833965Sjdp#define valuesize 32 27933965Sjdp#endif 28033965Sjdp 28160484Sobrien if ((NUMBERS_WITH_SUFFIX || flag_m68k_mri) && radix == 0) 28233965Sjdp { 28333965Sjdp int flt = 0; 28433965Sjdp 28533965Sjdp /* In MRI mode, the number may have a suffix indicating the 286130561Sobrien radix. For that matter, it might actually be a floating 287130561Sobrien point constant. */ 28889857Sobrien for (suffix = input_line_pointer; ISALNUM (*suffix); suffix++) 28933965Sjdp { 29033965Sjdp if (*suffix == 'e' || *suffix == 'E') 29133965Sjdp flt = 1; 29233965Sjdp } 29333965Sjdp 29433965Sjdp if (suffix == input_line_pointer) 29533965Sjdp { 29633965Sjdp radix = 10; 29733965Sjdp suffix = NULL; 29833965Sjdp } 29933965Sjdp else 30033965Sjdp { 30133965Sjdp c = *--suffix; 30289857Sobrien c = TOUPPER (c); 303218822Sdim /* If we have both NUMBERS_WITH_SUFFIX and LOCAL_LABELS_FB, 304218822Sdim we distinguish between 'B' and 'b'. This is the case for 305218822Sdim Z80. */ 306218822Sdim if ((NUMBERS_WITH_SUFFIX && LOCAL_LABELS_FB ? *suffix : c) == 'B') 30733965Sjdp radix = 2; 30833965Sjdp else if (c == 'D') 30933965Sjdp radix = 10; 31033965Sjdp else if (c == 'O' || c == 'Q') 31133965Sjdp radix = 8; 31233965Sjdp else if (c == 'H') 31333965Sjdp radix = 16; 31433965Sjdp else if (suffix[1] == '.' || c == 'E' || flt) 31533965Sjdp { 31633965Sjdp floating_constant (expressionP); 31733965Sjdp return; 31833965Sjdp } 31933965Sjdp else 32033965Sjdp { 32133965Sjdp radix = 10; 32233965Sjdp suffix = NULL; 32333965Sjdp } 32433965Sjdp } 32533965Sjdp } 32633965Sjdp 32733965Sjdp switch (radix) 32833965Sjdp { 32933965Sjdp case 2: 33033965Sjdp maxdig = 2; 33133965Sjdp too_many_digits = valuesize + 1; 33233965Sjdp break; 33333965Sjdp case 8: 33433965Sjdp maxdig = radix = 8; 33533965Sjdp too_many_digits = (valuesize + 2) / 3 + 1; 33633965Sjdp break; 33733965Sjdp case 16: 33833965Sjdp maxdig = radix = 16; 33933965Sjdp too_many_digits = (valuesize + 3) / 4 + 1; 34033965Sjdp break; 34133965Sjdp case 10: 34233965Sjdp maxdig = radix = 10; 34377298Sobrien too_many_digits = (valuesize + 11) / 4; /* Very rough. */ 34433965Sjdp } 34533965Sjdp#undef valuesize 34633965Sjdp start = input_line_pointer; 34733965Sjdp c = *input_line_pointer++; 34833965Sjdp for (number = 0; 34933965Sjdp (digit = hex_value (c)) < maxdig; 35033965Sjdp c = *input_line_pointer++) 35133965Sjdp { 35233965Sjdp number = number * radix + digit; 35333965Sjdp } 35477298Sobrien /* c contains character after number. */ 35577298Sobrien /* input_line_pointer->char after c. */ 35633965Sjdp small = (input_line_pointer - start - 1) < too_many_digits; 35738889Sjdp 35877298Sobrien if (radix == 16 && c == '_') 35933965Sjdp { 36038889Sjdp /* This is literal of the form 0x333_0_12345678_1. 361130561Sobrien This example is equivalent to 0x00000333000000001234567800000001. */ 36238889Sjdp 36338889Sjdp int num_little_digits = 0; 36438889Sjdp int i; 36577298Sobrien input_line_pointer = start; /* -> 1st digit. */ 36638889Sjdp 36738889Sjdp know (LITTLENUM_NUMBER_OF_BITS == 16); 36838889Sjdp 36977298Sobrien for (c = '_'; c == '_'; num_little_digits += 2) 37038889Sjdp { 37138889Sjdp 37277298Sobrien /* Convert one 64-bit word. */ 37377298Sobrien int ndigit = 0; 37438889Sjdp number = 0; 37538889Sjdp for (c = *input_line_pointer++; 37638889Sjdp (digit = hex_value (c)) < maxdig; 37738889Sjdp c = *(input_line_pointer++)) 37838889Sjdp { 37938889Sjdp number = number * radix + digit; 38038889Sjdp ndigit++; 38138889Sjdp } 38238889Sjdp 38338889Sjdp /* Check for 8 digit per word max. */ 38477298Sobrien if (ndigit > 8) 38589857Sobrien as_bad (_("a bignum with underscores may not have more than 8 hex digits in any word")); 38638889Sjdp 38777298Sobrien /* Add this chunk to the bignum. 38877298Sobrien Shift things down 2 little digits. */ 38938889Sjdp know (LITTLENUM_NUMBER_OF_BITS == 16); 39077298Sobrien for (i = min (num_little_digits + 1, SIZE_OF_LARGE_NUMBER - 1); 39177298Sobrien i >= 2; 39277298Sobrien i--) 39377298Sobrien generic_bignum[i] = generic_bignum[i - 2]; 39438889Sjdp 39577298Sobrien /* Add the new digits as the least significant new ones. */ 39638889Sjdp generic_bignum[0] = number & 0xffffffff; 39738889Sjdp generic_bignum[1] = number >> 16; 39838889Sjdp } 39938889Sjdp 40077298Sobrien /* Again, c is char after number, input_line_pointer->after c. */ 40138889Sjdp 40238889Sjdp if (num_little_digits > SIZE_OF_LARGE_NUMBER - 1) 40338889Sjdp num_little_digits = SIZE_OF_LARGE_NUMBER - 1; 40438889Sjdp 40538889Sjdp assert (num_little_digits >= 4); 40638889Sjdp 40738889Sjdp if (num_little_digits != 8) 40889857Sobrien as_bad (_("a bignum with underscores must have exactly 4 words")); 40938889Sjdp 41038889Sjdp /* We might have some leading zeros. These can be trimmed to give 41177298Sobrien us a change to fit this constant into a small number. */ 41277298Sobrien while (generic_bignum[num_little_digits - 1] == 0 41377298Sobrien && num_little_digits > 1) 41438889Sjdp num_little_digits--; 41577298Sobrien 41638889Sjdp if (num_little_digits <= 2) 41738889Sjdp { 41877298Sobrien /* will fit into 32 bits. */ 41938889Sjdp number = generic_bignum_to_int32 (); 42038889Sjdp small = 1; 42138889Sjdp } 42238889Sjdp#ifdef BFD64 42338889Sjdp else if (num_little_digits <= 4) 42438889Sjdp { 42538889Sjdp /* Will fit into 64 bits. */ 42638889Sjdp number = generic_bignum_to_int64 (); 42738889Sjdp small = 1; 42838889Sjdp } 42938889Sjdp#endif 43038889Sjdp else 43138889Sjdp { 43238889Sjdp small = 0; 43377298Sobrien 43477298Sobrien /* Number of littlenums in the bignum. */ 43577298Sobrien number = num_little_digits; 43638889Sjdp } 43738889Sjdp } 43838889Sjdp else if (!small) 43938889Sjdp { 44077298Sobrien /* We saw a lot of digits. manufacture a bignum the hard way. */ 44177298Sobrien LITTLENUM_TYPE *leader; /* -> high order littlenum of the bignum. */ 44277298Sobrien LITTLENUM_TYPE *pointer; /* -> littlenum we are frobbing now. */ 44333965Sjdp long carry; 44433965Sjdp 44533965Sjdp leader = generic_bignum; 44633965Sjdp generic_bignum[0] = 0; 44733965Sjdp generic_bignum[1] = 0; 44838889Sjdp generic_bignum[2] = 0; 44938889Sjdp generic_bignum[3] = 0; 45077298Sobrien input_line_pointer = start; /* -> 1st digit. */ 45133965Sjdp c = *input_line_pointer++; 45277298Sobrien for (; (carry = hex_value (c)) < maxdig; c = *input_line_pointer++) 45333965Sjdp { 45477298Sobrien for (pointer = generic_bignum; pointer <= leader; pointer++) 45533965Sjdp { 45633965Sjdp long work; 45733965Sjdp 45833965Sjdp work = carry + radix * *pointer; 45933965Sjdp *pointer = work & LITTLENUM_MASK; 46033965Sjdp carry = work >> LITTLENUM_NUMBER_OF_BITS; 46133965Sjdp } 46233965Sjdp if (carry) 46333965Sjdp { 46433965Sjdp if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1) 46533965Sjdp { 46677298Sobrien /* Room to grow a longer bignum. */ 46733965Sjdp *++leader = carry; 46833965Sjdp } 46933965Sjdp } 47033965Sjdp } 47177298Sobrien /* Again, c is char after number. */ 47277298Sobrien /* input_line_pointer -> after c. */ 47333965Sjdp know (LITTLENUM_NUMBER_OF_BITS == 16); 47433965Sjdp if (leader < generic_bignum + 2) 47533965Sjdp { 47677298Sobrien /* Will fit into 32 bits. */ 47738889Sjdp number = generic_bignum_to_int32 (); 47833965Sjdp small = 1; 47933965Sjdp } 48038889Sjdp#ifdef BFD64 48138889Sjdp else if (leader < generic_bignum + 4) 48238889Sjdp { 48338889Sjdp /* Will fit into 64 bits. */ 48438889Sjdp number = generic_bignum_to_int64 (); 48538889Sjdp small = 1; 48638889Sjdp } 48738889Sjdp#endif 48833965Sjdp else 48933965Sjdp { 49077298Sobrien /* Number of littlenums in the bignum. */ 49177298Sobrien number = leader - generic_bignum + 1; 49233965Sjdp } 49333965Sjdp } 49433965Sjdp 49577298Sobrien if ((NUMBERS_WITH_SUFFIX || flag_m68k_mri) 49677298Sobrien && suffix != NULL 49760484Sobrien && input_line_pointer - 1 == suffix) 49833965Sjdp c = *input_line_pointer++; 49933965Sjdp 50033965Sjdp if (small) 50133965Sjdp { 50277298Sobrien /* Here with number, in correct radix. c is the next char. 50377298Sobrien Note that unlike un*x, we allow "011f" "0x9f" to both mean 50477298Sobrien the same as the (conventional) "9f". 50577298Sobrien This is simply easier than checking for strict canonical 50677298Sobrien form. Syntax sux! */ 50733965Sjdp 50833965Sjdp if (LOCAL_LABELS_FB && c == 'b') 50933965Sjdp { 51077298Sobrien /* Backward ref to local label. 51177298Sobrien Because it is backward, expect it to be defined. */ 51233965Sjdp /* Construct a local label. */ 51333965Sjdp name = fb_label_name ((int) number, 0); 51433965Sjdp 51577298Sobrien /* Seen before, or symbol is defined: OK. */ 51633965Sjdp symbolP = symbol_find (name); 51733965Sjdp if ((symbolP != NULL) && (S_IS_DEFINED (symbolP))) 51833965Sjdp { 51977298Sobrien /* Local labels are never absolute. Don't waste time 52077298Sobrien checking absoluteness. */ 52133965Sjdp know (SEG_NORMAL (S_GET_SEGMENT (symbolP))); 52233965Sjdp 52333965Sjdp expressionP->X_op = O_symbol; 52433965Sjdp expressionP->X_add_symbol = symbolP; 52533965Sjdp } 52633965Sjdp else 52733965Sjdp { 52877298Sobrien /* Either not seen or not defined. */ 52933965Sjdp /* @@ Should print out the original string instead of 53033965Sjdp the parsed number. */ 53189857Sobrien as_bad (_("backward ref to unknown label \"%d:\""), 53233965Sjdp (int) number); 53333965Sjdp expressionP->X_op = O_constant; 53433965Sjdp } 53533965Sjdp 53633965Sjdp expressionP->X_add_number = 0; 53733965Sjdp } /* case 'b' */ 53833965Sjdp else if (LOCAL_LABELS_FB && c == 'f') 53933965Sjdp { 54077298Sobrien /* Forward reference. Expect symbol to be undefined or 54177298Sobrien unknown. undefined: seen it before. unknown: never seen 54277298Sobrien it before. 54377298Sobrien 54477298Sobrien Construct a local label name, then an undefined symbol. 54577298Sobrien Don't create a xseg frag for it: caller may do that. 54677298Sobrien Just return it as never seen before. */ 54733965Sjdp name = fb_label_name ((int) number, 1); 54833965Sjdp symbolP = symbol_find_or_make (name); 54977298Sobrien /* We have no need to check symbol properties. */ 55033965Sjdp#ifndef many_segments 55177298Sobrien /* Since "know" puts its arg into a "string", we 55233965Sjdp can't have newlines in the argument. */ 55333965Sjdp know (S_GET_SEGMENT (symbolP) == undefined_section || S_GET_SEGMENT (symbolP) == text_section || S_GET_SEGMENT (symbolP) == data_section); 55433965Sjdp#endif 55533965Sjdp expressionP->X_op = O_symbol; 55633965Sjdp expressionP->X_add_symbol = symbolP; 55733965Sjdp expressionP->X_add_number = 0; 55833965Sjdp } /* case 'f' */ 55933965Sjdp else if (LOCAL_LABELS_DOLLAR && c == '$') 56033965Sjdp { 56133965Sjdp /* If the dollar label is *currently* defined, then this is just 56233965Sjdp another reference to it. If it is not *currently* defined, 56333965Sjdp then this is a fresh instantiation of that number, so create 56433965Sjdp it. */ 56533965Sjdp 56633965Sjdp if (dollar_label_defined ((long) number)) 56733965Sjdp { 56833965Sjdp name = dollar_label_name ((long) number, 0); 56933965Sjdp symbolP = symbol_find (name); 57033965Sjdp know (symbolP != NULL); 57133965Sjdp } 57233965Sjdp else 57333965Sjdp { 57433965Sjdp name = dollar_label_name ((long) number, 1); 57533965Sjdp symbolP = symbol_find_or_make (name); 57633965Sjdp } 57733965Sjdp 57833965Sjdp expressionP->X_op = O_symbol; 57933965Sjdp expressionP->X_add_symbol = symbolP; 58033965Sjdp expressionP->X_add_number = 0; 58133965Sjdp } /* case '$' */ 58233965Sjdp else 58333965Sjdp { 58433965Sjdp expressionP->X_op = O_constant; 58533965Sjdp expressionP->X_add_number = number; 58677298Sobrien input_line_pointer--; /* Restore following character. */ 58777298Sobrien } /* Really just a number. */ 58833965Sjdp } 58933965Sjdp else 59033965Sjdp { 59177298Sobrien /* Not a small number. */ 59233965Sjdp expressionP->X_op = O_big; 59377298Sobrien expressionP->X_add_number = number; /* Number of littlenums. */ 59477298Sobrien input_line_pointer--; /* -> char following number. */ 59533965Sjdp } 59633965Sjdp} 59733965Sjdp 59833965Sjdp/* Parse an MRI multi character constant. */ 59933965Sjdp 60033965Sjdpstatic void 601130561Sobrienmri_char_constant (expressionS *expressionP) 60233965Sjdp{ 60333965Sjdp int i; 60433965Sjdp 60533965Sjdp if (*input_line_pointer == '\'' 60633965Sjdp && input_line_pointer[1] != '\'') 60733965Sjdp { 60833965Sjdp expressionP->X_op = O_constant; 60933965Sjdp expressionP->X_add_number = 0; 61033965Sjdp return; 61133965Sjdp } 61233965Sjdp 61333965Sjdp /* In order to get the correct byte ordering, we must build the 61433965Sjdp number in reverse. */ 61533965Sjdp for (i = SIZE_OF_LARGE_NUMBER - 1; i >= 0; i--) 61633965Sjdp { 61733965Sjdp int j; 61833965Sjdp 61933965Sjdp generic_bignum[i] = 0; 62033965Sjdp for (j = 0; j < CHARS_PER_LITTLENUM; j++) 62133965Sjdp { 62233965Sjdp if (*input_line_pointer == '\'') 62333965Sjdp { 62433965Sjdp if (input_line_pointer[1] != '\'') 62533965Sjdp break; 62633965Sjdp ++input_line_pointer; 62733965Sjdp } 62833965Sjdp generic_bignum[i] <<= 8; 62933965Sjdp generic_bignum[i] += *input_line_pointer; 63033965Sjdp ++input_line_pointer; 63133965Sjdp } 63233965Sjdp 63333965Sjdp if (i < SIZE_OF_LARGE_NUMBER - 1) 63433965Sjdp { 63533965Sjdp /* If there is more than one littlenum, left justify the 636130561Sobrien last one to make it match the earlier ones. If there is 637130561Sobrien only one, we can just use the value directly. */ 63833965Sjdp for (; j < CHARS_PER_LITTLENUM; j++) 63933965Sjdp generic_bignum[i] <<= 8; 64033965Sjdp } 64133965Sjdp 64233965Sjdp if (*input_line_pointer == '\'' 64333965Sjdp && input_line_pointer[1] != '\'') 64433965Sjdp break; 64533965Sjdp } 64633965Sjdp 64733965Sjdp if (i < 0) 64833965Sjdp { 64989857Sobrien as_bad (_("character constant too large")); 65033965Sjdp i = 0; 65133965Sjdp } 65233965Sjdp 65333965Sjdp if (i > 0) 65433965Sjdp { 65533965Sjdp int c; 65633965Sjdp int j; 65733965Sjdp 65833965Sjdp c = SIZE_OF_LARGE_NUMBER - i; 65933965Sjdp for (j = 0; j < c; j++) 66033965Sjdp generic_bignum[j] = generic_bignum[i + j]; 66133965Sjdp i = c; 66233965Sjdp } 66333965Sjdp 66433965Sjdp know (LITTLENUM_NUMBER_OF_BITS == 16); 66533965Sjdp if (i > 2) 66633965Sjdp { 66733965Sjdp expressionP->X_op = O_big; 66833965Sjdp expressionP->X_add_number = i; 66933965Sjdp } 67033965Sjdp else 67133965Sjdp { 67233965Sjdp expressionP->X_op = O_constant; 67333965Sjdp if (i < 2) 67433965Sjdp expressionP->X_add_number = generic_bignum[0] & LITTLENUM_MASK; 67533965Sjdp else 67633965Sjdp expressionP->X_add_number = 67733965Sjdp (((generic_bignum[1] & LITTLENUM_MASK) 67833965Sjdp << LITTLENUM_NUMBER_OF_BITS) 67933965Sjdp | (generic_bignum[0] & LITTLENUM_MASK)); 68033965Sjdp } 68133965Sjdp 68233965Sjdp /* Skip the final closing quote. */ 68333965Sjdp ++input_line_pointer; 68433965Sjdp} 68533965Sjdp 68633965Sjdp/* Return an expression representing the current location. This 68733965Sjdp handles the magic symbol `.'. */ 68833965Sjdp 68933965Sjdpstatic void 690130561Sobriencurrent_location (expressionS *expressionp) 69133965Sjdp{ 69233965Sjdp if (now_seg == absolute_section) 69333965Sjdp { 69433965Sjdp expressionp->X_op = O_constant; 69533965Sjdp expressionp->X_add_number = abs_section_offset; 69633965Sjdp } 69733965Sjdp else 69833965Sjdp { 69933965Sjdp expressionp->X_op = O_symbol; 700130561Sobrien expressionp->X_add_symbol = symbol_temp_new_now (); 70133965Sjdp expressionp->X_add_number = 0; 70233965Sjdp } 70333965Sjdp} 70433965Sjdp 70577298Sobrien/* In: Input_line_pointer points to 1st char of operand, which may 70677298Sobrien be a space. 70733965Sjdp 70889857Sobrien Out: An expressionS. 70977298Sobrien The operand may have been empty: in this case X_op == O_absent. 71077298Sobrien Input_line_pointer->(next non-blank) char after operand. */ 71177298Sobrien 71233965Sjdpstatic segT 713218822Sdimoperand (expressionS *expressionP, enum expr_mode mode) 71433965Sjdp{ 71533965Sjdp char c; 71677298Sobrien symbolS *symbolP; /* Points to symbol. */ 71777298Sobrien char *name; /* Points to name of symbol. */ 71833965Sjdp segT segment; 71933965Sjdp 72033965Sjdp /* All integers are regarded as unsigned unless they are negated. 72133965Sjdp This is because the only thing which cares whether a number is 72233965Sjdp unsigned is the code in emit_expr which extends constants into 72333965Sjdp bignums. It should only sign extend negative numbers, so that 72433965Sjdp something like ``.quad 0x80000000'' is not sign extended even 72533965Sjdp though it appears negative if valueT is 32 bits. */ 72633965Sjdp expressionP->X_unsigned = 1; 72733965Sjdp 72877298Sobrien /* Digits, assume it is a bignum. */ 72933965Sjdp 73077298Sobrien SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */ 73177298Sobrien c = *input_line_pointer++; /* input_line_pointer -> past char in c. */ 73233965Sjdp 73377298Sobrien if (is_end_of_line[(unsigned char) c]) 73477298Sobrien goto eol; 73577298Sobrien 73633965Sjdp switch (c) 73733965Sjdp { 73833965Sjdp case '1': 73933965Sjdp case '2': 74033965Sjdp case '3': 74133965Sjdp case '4': 74233965Sjdp case '5': 74333965Sjdp case '6': 74433965Sjdp case '7': 74533965Sjdp case '8': 74633965Sjdp case '9': 74733965Sjdp input_line_pointer--; 74833965Sjdp 74977298Sobrien integer_constant ((NUMBERS_WITH_SUFFIX || flag_m68k_mri) 75077298Sobrien ? 0 : 10, 751104834Sobrien expressionP); 75233965Sjdp break; 75333965Sjdp 75477298Sobrien#ifdef LITERAL_PREFIXDOLLAR_HEX 75577298Sobrien case '$': 75689857Sobrien /* $L is the start of a local label, not a hex constant. */ 75789857Sobrien if (* input_line_pointer == 'L') 75889857Sobrien goto isname; 75977298Sobrien integer_constant (16, expressionP); 76077298Sobrien break; 76177298Sobrien#endif 76277298Sobrien 76377298Sobrien#ifdef LITERAL_PREFIXPERCENT_BIN 76477298Sobrien case '%': 76577298Sobrien integer_constant (2, expressionP); 76677298Sobrien break; 76777298Sobrien#endif 76877298Sobrien 76933965Sjdp case '0': 77077298Sobrien /* Non-decimal radix. */ 77133965Sjdp 77260484Sobrien if (NUMBERS_WITH_SUFFIX || flag_m68k_mri) 77333965Sjdp { 77433965Sjdp char *s; 77533965Sjdp 776130561Sobrien /* Check for a hex or float constant. */ 77733965Sjdp for (s = input_line_pointer; hex_p (*s); s++) 77833965Sjdp ; 779130561Sobrien if (*s == 'h' || *s == 'H' || *input_line_pointer == '.') 78033965Sjdp { 78133965Sjdp --input_line_pointer; 78233965Sjdp integer_constant (0, expressionP); 78333965Sjdp break; 78433965Sjdp } 78577298Sobrien } 78633965Sjdp c = *input_line_pointer; 78733965Sjdp switch (c) 78833965Sjdp { 78933965Sjdp case 'o': 79033965Sjdp case 'O': 79133965Sjdp case 'q': 79233965Sjdp case 'Q': 79333965Sjdp case '8': 79433965Sjdp case '9': 79560484Sobrien if (NUMBERS_WITH_SUFFIX || flag_m68k_mri) 79633965Sjdp { 79733965Sjdp integer_constant (0, expressionP); 79833965Sjdp break; 79933965Sjdp } 80033965Sjdp /* Fall through. */ 80133965Sjdp default: 80233965Sjdp default_case: 80333965Sjdp if (c && strchr (FLT_CHARS, c)) 80433965Sjdp { 80533965Sjdp input_line_pointer++; 80633965Sjdp floating_constant (expressionP); 80789857Sobrien expressionP->X_add_number = - TOLOWER (c); 80833965Sjdp } 80933965Sjdp else 81033965Sjdp { 81177298Sobrien /* The string was only zero. */ 81233965Sjdp expressionP->X_op = O_constant; 81333965Sjdp expressionP->X_add_number = 0; 81433965Sjdp } 81533965Sjdp 81633965Sjdp break; 81733965Sjdp 81833965Sjdp case 'x': 81933965Sjdp case 'X': 82033965Sjdp if (flag_m68k_mri) 82133965Sjdp goto default_case; 82233965Sjdp input_line_pointer++; 82333965Sjdp integer_constant (16, expressionP); 82433965Sjdp break; 82533965Sjdp 82633965Sjdp case 'b': 82760484Sobrien if (LOCAL_LABELS_FB && ! (flag_m68k_mri || NUMBERS_WITH_SUFFIX)) 82833965Sjdp { 82933965Sjdp /* This code used to check for '+' and '-' here, and, in 83033965Sjdp some conditions, fall through to call 83133965Sjdp integer_constant. However, that didn't make sense, 83233965Sjdp as integer_constant only accepts digits. */ 83333965Sjdp /* Some of our code elsewhere does permit digits greater 83433965Sjdp than the expected base; for consistency, do the same 83533965Sjdp here. */ 83633965Sjdp if (input_line_pointer[1] < '0' 83733965Sjdp || input_line_pointer[1] > '9') 83833965Sjdp { 83933965Sjdp /* Parse this as a back reference to label 0. */ 84033965Sjdp input_line_pointer--; 84133965Sjdp integer_constant (10, expressionP); 84233965Sjdp break; 84333965Sjdp } 84433965Sjdp /* Otherwise, parse this as a binary number. */ 84533965Sjdp } 84633965Sjdp /* Fall through. */ 84733965Sjdp case 'B': 84833965Sjdp input_line_pointer++; 84960484Sobrien if (flag_m68k_mri || NUMBERS_WITH_SUFFIX) 85033965Sjdp goto default_case; 85133965Sjdp integer_constant (2, expressionP); 85233965Sjdp break; 85333965Sjdp 85433965Sjdp case '0': 85533965Sjdp case '1': 85633965Sjdp case '2': 85733965Sjdp case '3': 85833965Sjdp case '4': 85933965Sjdp case '5': 86033965Sjdp case '6': 86133965Sjdp case '7': 86260484Sobrien integer_constant ((flag_m68k_mri || NUMBERS_WITH_SUFFIX) 86377298Sobrien ? 0 : 8, 86477298Sobrien expressionP); 86533965Sjdp break; 86633965Sjdp 86733965Sjdp case 'f': 86833965Sjdp if (LOCAL_LABELS_FB) 86933965Sjdp { 87033965Sjdp /* If it says "0f" and it could possibly be a floating point 87133965Sjdp number, make it one. Otherwise, make it a local label, 87233965Sjdp and try to deal with parsing the rest later. */ 87333965Sjdp if (!input_line_pointer[1] 87460484Sobrien || (is_end_of_line[0xff & input_line_pointer[1]]) 87560484Sobrien || strchr (FLT_CHARS, 'f') == NULL) 87633965Sjdp goto is_0f_label; 87733965Sjdp { 87833965Sjdp char *cp = input_line_pointer + 1; 87933965Sjdp int r = atof_generic (&cp, ".", EXP_CHARS, 88033965Sjdp &generic_floating_point_number); 88133965Sjdp switch (r) 88233965Sjdp { 88333965Sjdp case 0: 88433965Sjdp case ERROR_EXPONENT_OVERFLOW: 88533965Sjdp if (*cp == 'f' || *cp == 'b') 88677298Sobrien /* Looks like a difference expression. */ 88733965Sjdp goto is_0f_label; 88860484Sobrien else if (cp == input_line_pointer + 1) 88960484Sobrien /* No characters has been accepted -- looks like 89077298Sobrien end of operand. */ 89160484Sobrien goto is_0f_label; 89233965Sjdp else 89333965Sjdp goto is_0f_float; 89433965Sjdp default: 89560484Sobrien as_fatal (_("expr.c(operand): bad atof_generic return val %d"), 89633965Sjdp r); 89733965Sjdp } 89833965Sjdp } 89933965Sjdp 90033965Sjdp /* Okay, now we've sorted it out. We resume at one of these 90133965Sjdp two labels, depending on what we've decided we're probably 90233965Sjdp looking at. */ 90333965Sjdp is_0f_label: 90433965Sjdp input_line_pointer--; 90533965Sjdp integer_constant (10, expressionP); 90633965Sjdp break; 90733965Sjdp 90833965Sjdp is_0f_float: 90977298Sobrien /* Fall through. */ 91033965Sjdp ; 91133965Sjdp } 91233965Sjdp 91333965Sjdp case 'd': 91433965Sjdp case 'D': 91560484Sobrien if (flag_m68k_mri || NUMBERS_WITH_SUFFIX) 91633965Sjdp { 91733965Sjdp integer_constant (0, expressionP); 91833965Sjdp break; 91933965Sjdp } 92033965Sjdp /* Fall through. */ 92133965Sjdp case 'F': 92233965Sjdp case 'r': 92333965Sjdp case 'e': 92433965Sjdp case 'E': 92533965Sjdp case 'g': 92633965Sjdp case 'G': 92733965Sjdp input_line_pointer++; 92833965Sjdp floating_constant (expressionP); 92989857Sobrien expressionP->X_add_number = - TOLOWER (c); 93033965Sjdp break; 93133965Sjdp 93233965Sjdp case '$': 93333965Sjdp if (LOCAL_LABELS_DOLLAR) 93433965Sjdp { 93533965Sjdp integer_constant (10, expressionP); 93633965Sjdp break; 93733965Sjdp } 93833965Sjdp else 93933965Sjdp goto default_case; 94033965Sjdp } 94133965Sjdp 94233965Sjdp break; 94333965Sjdp 94433965Sjdp case '(': 94560484Sobrien#ifndef NEED_INDEX_OPERATOR 94633965Sjdp case '[': 94760484Sobrien#endif 94877298Sobrien /* Didn't begin with digit & not a name. */ 949218822Sdim if (mode != expr_defer) 950218822Sdim segment = expression (expressionP); 951218822Sdim else 952218822Sdim segment = deferred_expression (expressionP); 95377298Sobrien /* expression () will pass trailing whitespace. */ 95477298Sobrien if ((c == '(' && *input_line_pointer != ')') 95577298Sobrien || (c == '[' && *input_line_pointer != ']')) 956218822Sdim as_bad (_("missing '%c'"), c == '(' ? ')' : ']'); 95777298Sobrien else 95877298Sobrien input_line_pointer++; 95933965Sjdp SKIP_WHITESPACE (); 96077298Sobrien /* Here with input_line_pointer -> char after "(...)". */ 96133965Sjdp return segment; 96233965Sjdp 96360484Sobrien#ifdef TC_M68K 96433965Sjdp case 'E': 96533965Sjdp if (! flag_m68k_mri || *input_line_pointer != '\'') 96633965Sjdp goto de_fault; 96760484Sobrien as_bad (_("EBCDIC constants are not supported")); 96833965Sjdp /* Fall through. */ 96933965Sjdp case 'A': 97033965Sjdp if (! flag_m68k_mri || *input_line_pointer != '\'') 97133965Sjdp goto de_fault; 97233965Sjdp ++input_line_pointer; 97333965Sjdp /* Fall through. */ 97460484Sobrien#endif 97533965Sjdp case '\'': 97633965Sjdp if (! flag_m68k_mri) 97733965Sjdp { 97833965Sjdp /* Warning: to conform to other people's assemblers NO 97977298Sobrien ESCAPEMENT is permitted for a single quote. The next 98033965Sjdp character, parity errors and all, is taken as the value 98177298Sobrien of the operand. VERY KINKY. */ 98233965Sjdp expressionP->X_op = O_constant; 98333965Sjdp expressionP->X_add_number = *input_line_pointer++; 98433965Sjdp break; 98533965Sjdp } 98633965Sjdp 98733965Sjdp mri_char_constant (expressionP); 98833965Sjdp break; 98933965Sjdp 99060484Sobrien#ifdef TC_M68K 99133965Sjdp case '"': 99233965Sjdp /* Double quote is the bitwise not operator in MRI mode. */ 99333965Sjdp if (! flag_m68k_mri) 99433965Sjdp goto de_fault; 99533965Sjdp /* Fall through. */ 99660484Sobrien#endif 99733965Sjdp case '~': 99877298Sobrien /* '~' is permitted to start a label on the Delta. */ 99933965Sjdp if (is_name_beginner (c)) 100033965Sjdp goto isname; 100133965Sjdp case '!': 100233965Sjdp case '-': 1003218822Sdim case '+': 100433965Sjdp { 1005218822Sdim operand (expressionP, mode); 100633965Sjdp if (expressionP->X_op == O_constant) 100733965Sjdp { 100877298Sobrien /* input_line_pointer -> char after operand. */ 100933965Sjdp if (c == '-') 101033965Sjdp { 101133965Sjdp expressionP->X_add_number = - expressionP->X_add_number; 101277298Sobrien /* Notice: '-' may overflow: no warning is given. 101377298Sobrien This is compatible with other people's 101477298Sobrien assemblers. Sigh. */ 101533965Sjdp expressionP->X_unsigned = 0; 101633965Sjdp } 101733965Sjdp else if (c == '~' || c == '"') 101833965Sjdp expressionP->X_add_number = ~ expressionP->X_add_number; 1019218822Sdim else if (c == '!') 102033965Sjdp expressionP->X_add_number = ! expressionP->X_add_number; 102133965Sjdp } 1022130561Sobrien else if (expressionP->X_op == O_big 1023130561Sobrien && expressionP->X_add_number <= 0 1024130561Sobrien && c == '-' 1025130561Sobrien && (generic_floating_point_number.sign == '+' 1026130561Sobrien || generic_floating_point_number.sign == 'P')) 1027130561Sobrien { 1028130561Sobrien /* Negative flonum (eg, -1.000e0). */ 1029130561Sobrien if (generic_floating_point_number.sign == '+') 1030130561Sobrien generic_floating_point_number.sign = '-'; 1031130561Sobrien else 1032130561Sobrien generic_floating_point_number.sign = 'N'; 1033130561Sobrien } 1034218822Sdim else if (expressionP->X_op == O_big 1035218822Sdim && expressionP->X_add_number > 0) 1036218822Sdim { 1037218822Sdim int i; 1038218822Sdim 1039218822Sdim if (c == '~' || c == '-') 1040218822Sdim { 1041218822Sdim for (i = 0; i < expressionP->X_add_number; ++i) 1042218822Sdim generic_bignum[i] = ~generic_bignum[i]; 1043276229Spfg 1044276229Spfg /* Extend the bignum to at least the size of .octa. */ 1045276229Spfg if (expressionP->X_add_number < SIZE_OF_LARGE_NUMBER) 1046276229Spfg { 1047276229Spfg expressionP->X_add_number = SIZE_OF_LARGE_NUMBER; 1048276229Spfg for (; i < expressionP->X_add_number; ++i) 1049276229Spfg generic_bignum[i] = ~(LITTLENUM_TYPE) 0; 1050276229Spfg } 1051276229Spfg 1052218822Sdim if (c == '-') 1053218822Sdim for (i = 0; i < expressionP->X_add_number; ++i) 1054218822Sdim { 1055218822Sdim generic_bignum[i] += 1; 1056218822Sdim if (generic_bignum[i]) 1057218822Sdim break; 1058218822Sdim } 1059218822Sdim } 1060218822Sdim else if (c == '!') 1061218822Sdim { 1062218822Sdim for (i = 0; i < expressionP->X_add_number; ++i) 1063276229Spfg if (generic_bignum[i] != 0) 1064276229Spfg break; 1065276229Spfg expressionP->X_add_number = i >= expressionP->X_add_number; 1066276229Spfg expressionP->X_op = O_constant; 1067276229Spfg expressionP->X_unsigned = 1; 1068218822Sdim } 1069218822Sdim } 107033965Sjdp else if (expressionP->X_op != O_illegal 107133965Sjdp && expressionP->X_op != O_absent) 107233965Sjdp { 1073218822Sdim if (c != '+') 1074218822Sdim { 1075218822Sdim expressionP->X_add_symbol = make_expr_symbol (expressionP); 1076218822Sdim if (c == '-') 1077218822Sdim expressionP->X_op = O_uminus; 1078218822Sdim else if (c == '~' || c == '"') 1079218822Sdim expressionP->X_op = O_bit_not; 1080218822Sdim else 1081218822Sdim expressionP->X_op = O_logical_not; 1082218822Sdim expressionP->X_add_number = 0; 1083218822Sdim } 108433965Sjdp } 108533965Sjdp else 108660484Sobrien as_warn (_("Unary operator %c ignored because bad operand follows"), 108733965Sjdp c); 108833965Sjdp } 108933965Sjdp break; 109033965Sjdp 109160484Sobrien#if defined (DOLLAR_DOT) || defined (TC_M68K) 109233965Sjdp case '$': 109377298Sobrien /* '$' is the program counter when in MRI mode, or when 1094130561Sobrien DOLLAR_DOT is defined. */ 109533965Sjdp#ifndef DOLLAR_DOT 109633965Sjdp if (! flag_m68k_mri) 109733965Sjdp goto de_fault; 109833965Sjdp#endif 1099218822Sdim if (DOLLAR_AMBIGU && hex_p (*input_line_pointer)) 110033965Sjdp { 1101218822Sdim /* In MRI mode and on Z80, '$' is also used as the prefix 1102218822Sdim for a hexadecimal constant. */ 110333965Sjdp integer_constant (16, expressionP); 110433965Sjdp break; 110533965Sjdp } 110633965Sjdp 110733965Sjdp if (is_part_of_name (*input_line_pointer)) 110833965Sjdp goto isname; 110933965Sjdp 111033965Sjdp current_location (expressionP); 111133965Sjdp break; 111260484Sobrien#endif 111333965Sjdp 111433965Sjdp case '.': 111533965Sjdp if (!is_part_of_name (*input_line_pointer)) 111633965Sjdp { 111733965Sjdp current_location (expressionP); 111833965Sjdp break; 111933965Sjdp } 112033965Sjdp else if ((strncasecmp (input_line_pointer, "startof.", 8) == 0 112133965Sjdp && ! is_part_of_name (input_line_pointer[8])) 112233965Sjdp || (strncasecmp (input_line_pointer, "sizeof.", 7) == 0 112333965Sjdp && ! is_part_of_name (input_line_pointer[7]))) 112433965Sjdp { 112533965Sjdp int start; 112633965Sjdp 112733965Sjdp start = (input_line_pointer[1] == 't' 112833965Sjdp || input_line_pointer[1] == 'T'); 112933965Sjdp input_line_pointer += start ? 8 : 7; 113033965Sjdp SKIP_WHITESPACE (); 113133965Sjdp if (*input_line_pointer != '(') 113260484Sobrien as_bad (_("syntax error in .startof. or .sizeof.")); 113333965Sjdp else 113433965Sjdp { 113533965Sjdp char *buf; 113633965Sjdp 113733965Sjdp ++input_line_pointer; 113833965Sjdp SKIP_WHITESPACE (); 113933965Sjdp name = input_line_pointer; 114033965Sjdp c = get_symbol_end (); 114133965Sjdp 114233965Sjdp buf = (char *) xmalloc (strlen (name) + 10); 114333965Sjdp if (start) 114433965Sjdp sprintf (buf, ".startof.%s", name); 114533965Sjdp else 114633965Sjdp sprintf (buf, ".sizeof.%s", name); 114733965Sjdp symbolP = symbol_make (buf); 114833965Sjdp free (buf); 114933965Sjdp 115033965Sjdp expressionP->X_op = O_symbol; 115133965Sjdp expressionP->X_add_symbol = symbolP; 115233965Sjdp expressionP->X_add_number = 0; 115333965Sjdp 115433965Sjdp *input_line_pointer = c; 115533965Sjdp SKIP_WHITESPACE (); 115633965Sjdp if (*input_line_pointer != ')') 115760484Sobrien as_bad (_("syntax error in .startof. or .sizeof.")); 115833965Sjdp else 115933965Sjdp ++input_line_pointer; 116033965Sjdp } 116133965Sjdp break; 116233965Sjdp } 116333965Sjdp else 116433965Sjdp { 116533965Sjdp goto isname; 116633965Sjdp } 116777298Sobrien 116833965Sjdp case ',': 116933965Sjdp eol: 117077298Sobrien /* Can't imagine any other kind of operand. */ 117133965Sjdp expressionP->X_op = O_absent; 117233965Sjdp input_line_pointer--; 117333965Sjdp break; 117433965Sjdp 117560484Sobrien#ifdef TC_M68K 117633965Sjdp case '%': 117733965Sjdp if (! flag_m68k_mri) 117833965Sjdp goto de_fault; 117933965Sjdp integer_constant (2, expressionP); 118033965Sjdp break; 118133965Sjdp 118233965Sjdp case '@': 118333965Sjdp if (! flag_m68k_mri) 118433965Sjdp goto de_fault; 118533965Sjdp integer_constant (8, expressionP); 118633965Sjdp break; 118733965Sjdp 118833965Sjdp case ':': 118933965Sjdp if (! flag_m68k_mri) 119033965Sjdp goto de_fault; 119133965Sjdp 119233965Sjdp /* In MRI mode, this is a floating point constant represented 1193130561Sobrien using hexadecimal digits. */ 119433965Sjdp 119533965Sjdp ++input_line_pointer; 119633965Sjdp integer_constant (16, expressionP); 119733965Sjdp break; 119833965Sjdp 119933965Sjdp case '*': 120033965Sjdp if (! flag_m68k_mri || is_part_of_name (*input_line_pointer)) 120133965Sjdp goto de_fault; 120233965Sjdp 120333965Sjdp current_location (expressionP); 120433965Sjdp break; 120560484Sobrien#endif 120633965Sjdp 120733965Sjdp default: 120860484Sobrien#ifdef TC_M68K 120933965Sjdp de_fault: 121060484Sobrien#endif 121177298Sobrien if (is_name_beginner (c)) /* Here if did not begin with a digit. */ 121233965Sjdp { 121377298Sobrien /* Identifier begins here. 121477298Sobrien This is kludged for speed, so code is repeated. */ 121533965Sjdp isname: 121633965Sjdp name = --input_line_pointer; 121733965Sjdp c = get_symbol_end (); 121833965Sjdp 121933965Sjdp#ifdef md_parse_name 122033965Sjdp /* This is a hook for the backend to parse certain names 1221130561Sobrien specially in certain contexts. If a name always has a 1222130561Sobrien specific value, it can often be handled by simply 1223130561Sobrien entering it in the symbol table. */ 1224218822Sdim if (md_parse_name (name, expressionP, mode, &c)) 122533965Sjdp { 122633965Sjdp *input_line_pointer = c; 122733965Sjdp break; 122833965Sjdp } 122933965Sjdp#endif 123033965Sjdp 123133965Sjdp#ifdef TC_I960 123233965Sjdp /* The MRI i960 assembler permits 123333965Sjdp lda sizeof code,g13 123433965Sjdp FIXME: This should use md_parse_name. */ 123533965Sjdp if (flag_mri 123633965Sjdp && (strcasecmp (name, "sizeof") == 0 123733965Sjdp || strcasecmp (name, "startof") == 0)) 123833965Sjdp { 123933965Sjdp int start; 124033965Sjdp char *buf; 124133965Sjdp 124233965Sjdp start = (name[1] == 't' 124333965Sjdp || name[1] == 'T'); 124433965Sjdp 124533965Sjdp *input_line_pointer = c; 124633965Sjdp SKIP_WHITESPACE (); 124733965Sjdp 124833965Sjdp name = input_line_pointer; 124933965Sjdp c = get_symbol_end (); 125033965Sjdp 125133965Sjdp buf = (char *) xmalloc (strlen (name) + 10); 125233965Sjdp if (start) 125333965Sjdp sprintf (buf, ".startof.%s", name); 125433965Sjdp else 125533965Sjdp sprintf (buf, ".sizeof.%s", name); 125633965Sjdp symbolP = symbol_make (buf); 125733965Sjdp free (buf); 125833965Sjdp 125933965Sjdp expressionP->X_op = O_symbol; 126033965Sjdp expressionP->X_add_symbol = symbolP; 126133965Sjdp expressionP->X_add_number = 0; 126233965Sjdp 126333965Sjdp *input_line_pointer = c; 126433965Sjdp SKIP_WHITESPACE (); 126533965Sjdp 126633965Sjdp break; 126777298Sobrien } 126833965Sjdp#endif 126933965Sjdp 127033965Sjdp symbolP = symbol_find_or_make (name); 127133965Sjdp 127233965Sjdp /* If we have an absolute symbol or a reg, then we know its 127333965Sjdp value now. */ 127433965Sjdp segment = S_GET_SEGMENT (symbolP); 1275218822Sdim if (mode != expr_defer && segment == absolute_section) 127633965Sjdp { 127733965Sjdp expressionP->X_op = O_constant; 127833965Sjdp expressionP->X_add_number = S_GET_VALUE (symbolP); 127933965Sjdp } 1280218822Sdim else if (mode != expr_defer && segment == reg_section) 128133965Sjdp { 128233965Sjdp expressionP->X_op = O_register; 128333965Sjdp expressionP->X_add_number = S_GET_VALUE (symbolP); 128433965Sjdp } 128533965Sjdp else 128633965Sjdp { 128733965Sjdp expressionP->X_op = O_symbol; 128833965Sjdp expressionP->X_add_symbol = symbolP; 128933965Sjdp expressionP->X_add_number = 0; 129033965Sjdp } 129133965Sjdp *input_line_pointer = c; 129233965Sjdp } 129333965Sjdp else 129433965Sjdp { 129533965Sjdp /* Let the target try to parse it. Success is indicated by changing 129633965Sjdp the X_op field to something other than O_absent and pointing 129777298Sobrien input_line_pointer past the expression. If it can't parse the 129833965Sjdp expression, X_op and input_line_pointer should be unchanged. */ 129933965Sjdp expressionP->X_op = O_absent; 130033965Sjdp --input_line_pointer; 130133965Sjdp md_operand (expressionP); 130233965Sjdp if (expressionP->X_op == O_absent) 130333965Sjdp { 130433965Sjdp ++input_line_pointer; 130589857Sobrien as_bad (_("bad expression")); 130633965Sjdp expressionP->X_op = O_constant; 130733965Sjdp expressionP->X_add_number = 0; 130833965Sjdp } 130933965Sjdp } 131033965Sjdp break; 131133965Sjdp } 131233965Sjdp 131377298Sobrien /* It is more 'efficient' to clean up the expressionS when they are 131477298Sobrien created. Doing it here saves lines of code. */ 131533965Sjdp clean_up_expression (expressionP); 131677298Sobrien SKIP_WHITESPACE (); /* -> 1st char after operand. */ 131733965Sjdp know (*input_line_pointer != ' '); 131833965Sjdp 131933965Sjdp /* The PA port needs this information. */ 132033965Sjdp if (expressionP->X_add_symbol) 132160484Sobrien symbol_mark_used (expressionP->X_add_symbol); 132233965Sjdp 1323218822Sdim expressionP->X_add_symbol = symbol_clone_if_forward_ref (expressionP->X_add_symbol); 1324218822Sdim expressionP->X_op_symbol = symbol_clone_if_forward_ref (expressionP->X_op_symbol); 1325218822Sdim 132633965Sjdp switch (expressionP->X_op) 132733965Sjdp { 132833965Sjdp default: 132933965Sjdp return absolute_section; 133033965Sjdp case O_symbol: 133133965Sjdp return S_GET_SEGMENT (expressionP->X_add_symbol); 133233965Sjdp case O_register: 133333965Sjdp return reg_section; 133433965Sjdp } 133577298Sobrien} 133633965Sjdp 133777298Sobrien/* Internal. Simplify a struct expression for use by expr (). */ 133833965Sjdp 133989857Sobrien/* In: address of an expressionS. 134077298Sobrien The X_op field of the expressionS may only take certain values. 134177298Sobrien Elsewise we waste time special-case testing. Sigh. Ditto SEG_ABSENT. 134233965Sjdp 134377298Sobrien Out: expressionS may have been modified: 134477298Sobrien Unused fields zeroed to help expr (). */ 134577298Sobrien 134633965Sjdpstatic void 1347130561Sobrienclean_up_expression (expressionS *expressionP) 134833965Sjdp{ 134933965Sjdp switch (expressionP->X_op) 135033965Sjdp { 135133965Sjdp case O_illegal: 135233965Sjdp case O_absent: 135333965Sjdp expressionP->X_add_number = 0; 135433965Sjdp /* Fall through. */ 135533965Sjdp case O_big: 135633965Sjdp case O_constant: 135733965Sjdp case O_register: 135833965Sjdp expressionP->X_add_symbol = NULL; 135933965Sjdp /* Fall through. */ 136033965Sjdp case O_symbol: 136133965Sjdp case O_uminus: 136233965Sjdp case O_bit_not: 136333965Sjdp expressionP->X_op_symbol = NULL; 136433965Sjdp break; 136533965Sjdp default: 136633965Sjdp break; 136733965Sjdp } 136833965Sjdp} 136933965Sjdp 137077298Sobrien/* Expression parser. */ 137133965Sjdp 137277298Sobrien/* We allow an empty expression, and just assume (absolute,0) silently. 137377298Sobrien Unary operators and parenthetical expressions are treated as operands. 137477298Sobrien As usual, Q==quantity==operand, O==operator, X==expression mnemonics. 137533965Sjdp 137689857Sobrien We used to do an aho/ullman shift-reduce parser, but the logic got so 137777298Sobrien warped that I flushed it and wrote a recursive-descent parser instead. 137877298Sobrien Now things are stable, would anybody like to write a fast parser? 137977298Sobrien Most expressions are either register (which does not even reach here) 138077298Sobrien or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common. 138177298Sobrien So I guess it doesn't really matter how inefficient more complex expressions 138277298Sobrien are parsed. 138377298Sobrien 138477298Sobrien After expr(RANK,resultP) input_line_pointer->operator of rank <= RANK. 138577298Sobrien Also, we have consumed any leading or trailing spaces (operand does that) 138677298Sobrien and done all intervening operators. 138777298Sobrien 138877298Sobrien This returns the segment of the result, which will be 138977298Sobrien absolute_section or the segment of a symbol. */ 139077298Sobrien 139133965Sjdp#undef __ 139233965Sjdp#define __ O_illegal 1393218822Sdim#ifndef O_SINGLE_EQ 1394218822Sdim#define O_SINGLE_EQ O_illegal 1395218822Sdim#endif 139633965Sjdp 139777298Sobrien/* Maps ASCII -> operators. */ 139877298Sobrienstatic const operatorT op_encoding[256] = { 139933965Sjdp __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, 140033965Sjdp __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, 140133965Sjdp 140233965Sjdp __, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __, 140333965Sjdp __, __, O_multiply, O_add, __, O_subtract, __, O_divide, 140433965Sjdp __, __, __, __, __, __, __, __, 1405218822Sdim __, __, __, __, O_lt, O_SINGLE_EQ, O_gt, __, 140633965Sjdp __, __, __, __, __, __, __, __, 140733965Sjdp __, __, __, __, __, __, __, __, 140833965Sjdp __, __, __, __, __, __, __, __, 140960484Sobrien __, __, __, 141060484Sobrien#ifdef NEED_INDEX_OPERATOR 141160484Sobrien O_index, 141260484Sobrien#else 141360484Sobrien __, 141460484Sobrien#endif 141560484Sobrien __, __, O_bit_exclusive_or, __, 141633965Sjdp __, __, __, __, __, __, __, __, 141733965Sjdp __, __, __, __, __, __, __, __, 141833965Sjdp __, __, __, __, __, __, __, __, 141933965Sjdp __, __, __, __, O_bit_inclusive_or, __, __, __, 142033965Sjdp 142133965Sjdp __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, 142233965Sjdp __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, 142333965Sjdp __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, 142433965Sjdp __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, 142533965Sjdp __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, 142633965Sjdp __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, 142733965Sjdp __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, 142833965Sjdp __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __ 142933965Sjdp}; 143033965Sjdp 143177298Sobrien/* Rank Examples 143277298Sobrien 0 operand, (expression) 143377298Sobrien 1 || 143477298Sobrien 2 && 143589857Sobrien 3 == <> < <= >= > 143677298Sobrien 4 + - 143777298Sobrien 5 used for * / % in MRI mode 143877298Sobrien 6 & ^ ! | 143977298Sobrien 7 * / % << >> 144077298Sobrien 8 unary - unary ~ 144177298Sobrien*/ 144277298Sobrienstatic operator_rankT op_rank[] = { 144333965Sjdp 0, /* O_illegal */ 144433965Sjdp 0, /* O_absent */ 144533965Sjdp 0, /* O_constant */ 144633965Sjdp 0, /* O_symbol */ 144733965Sjdp 0, /* O_symbol_rva */ 144833965Sjdp 0, /* O_register */ 144977298Sobrien 0, /* O_big */ 145060484Sobrien 9, /* O_uminus */ 145160484Sobrien 9, /* O_bit_not */ 145260484Sobrien 9, /* O_logical_not */ 145360484Sobrien 8, /* O_multiply */ 145460484Sobrien 8, /* O_divide */ 145560484Sobrien 8, /* O_modulus */ 145660484Sobrien 8, /* O_left_shift */ 145760484Sobrien 8, /* O_right_shift */ 145860484Sobrien 7, /* O_bit_inclusive_or */ 145960484Sobrien 7, /* O_bit_or_not */ 146060484Sobrien 7, /* O_bit_exclusive_or */ 146160484Sobrien 7, /* O_bit_and */ 146260484Sobrien 5, /* O_add */ 146360484Sobrien 5, /* O_subtract */ 146460484Sobrien 4, /* O_eq */ 146560484Sobrien 4, /* O_ne */ 146660484Sobrien 4, /* O_lt */ 146760484Sobrien 4, /* O_le */ 146860484Sobrien 4, /* O_ge */ 146960484Sobrien 4, /* O_gt */ 147060484Sobrien 3, /* O_logical_and */ 147160484Sobrien 2, /* O_logical_or */ 147260484Sobrien 1, /* O_index */ 147360484Sobrien 0, /* O_md1 */ 147460484Sobrien 0, /* O_md2 */ 147560484Sobrien 0, /* O_md3 */ 147660484Sobrien 0, /* O_md4 */ 147760484Sobrien 0, /* O_md5 */ 147860484Sobrien 0, /* O_md6 */ 147960484Sobrien 0, /* O_md7 */ 148060484Sobrien 0, /* O_md8 */ 148160484Sobrien 0, /* O_md9 */ 148260484Sobrien 0, /* O_md10 */ 148360484Sobrien 0, /* O_md11 */ 148460484Sobrien 0, /* O_md12 */ 148560484Sobrien 0, /* O_md13 */ 148660484Sobrien 0, /* O_md14 */ 148760484Sobrien 0, /* O_md15 */ 148860484Sobrien 0, /* O_md16 */ 148933965Sjdp}; 149033965Sjdp 149160484Sobrien/* Unfortunately, in MRI mode for the m68k, multiplication and 149260484Sobrien division have lower precedence than the bit wise operators. This 149360484Sobrien function sets the operator precedences correctly for the current 149460484Sobrien mode. Also, MRI uses a different bit_not operator, and this fixes 149560484Sobrien that as well. */ 149633965Sjdp 149777298Sobrien#define STANDARD_MUL_PRECEDENCE 8 149877298Sobrien#define MRI_MUL_PRECEDENCE 6 149960484Sobrien 150033965Sjdpvoid 1501130561Sobrienexpr_set_precedence (void) 150233965Sjdp{ 150333965Sjdp if (flag_m68k_mri) 150433965Sjdp { 150560484Sobrien op_rank[O_multiply] = MRI_MUL_PRECEDENCE; 150660484Sobrien op_rank[O_divide] = MRI_MUL_PRECEDENCE; 150760484Sobrien op_rank[O_modulus] = MRI_MUL_PRECEDENCE; 150833965Sjdp } 150960484Sobrien else 151060484Sobrien { 151160484Sobrien op_rank[O_multiply] = STANDARD_MUL_PRECEDENCE; 151260484Sobrien op_rank[O_divide] = STANDARD_MUL_PRECEDENCE; 151360484Sobrien op_rank[O_modulus] = STANDARD_MUL_PRECEDENCE; 151460484Sobrien } 151560484Sobrien} 151633965Sjdp 151760484Sobrien/* Initialize the expression parser. */ 151860484Sobrien 151960484Sobrienvoid 1520130561Sobrienexpr_begin (void) 152160484Sobrien{ 152260484Sobrien expr_set_precedence (); 152360484Sobrien 152433965Sjdp /* Verify that X_op field is wide enough. */ 152533965Sjdp { 152633965Sjdp expressionS e; 152733965Sjdp e.X_op = O_max; 152833965Sjdp assert (e.X_op == O_max); 152933965Sjdp } 153033965Sjdp} 153133965Sjdp 153277298Sobrien/* Return the encoding for the operator at INPUT_LINE_POINTER, and 153377298Sobrien sets NUM_CHARS to the number of characters in the operator. 153477298Sobrien Does not advance INPUT_LINE_POINTER. */ 153533965Sjdp 153633965Sjdpstatic inline operatorT 1537130561Sobrienoperator (int *num_chars) 153833965Sjdp{ 153933965Sjdp int c; 154033965Sjdp operatorT ret; 154133965Sjdp 154260484Sobrien c = *input_line_pointer & 0xff; 154377298Sobrien *num_chars = 1; 154433965Sjdp 154577298Sobrien if (is_end_of_line[c]) 154677298Sobrien return O_illegal; 154777298Sobrien 154833965Sjdp switch (c) 154933965Sjdp { 155033965Sjdp default: 155133965Sjdp return op_encoding[c]; 155233965Sjdp 1553130561Sobrien case '+': 1554130561Sobrien case '-': 1555218822Sdim return op_encoding[c]; 1556130561Sobrien 155733965Sjdp case '<': 155833965Sjdp switch (input_line_pointer[1]) 155933965Sjdp { 156033965Sjdp default: 156133965Sjdp return op_encoding[c]; 156233965Sjdp case '<': 156333965Sjdp ret = O_left_shift; 156433965Sjdp break; 156533965Sjdp case '>': 156633965Sjdp ret = O_ne; 156733965Sjdp break; 156833965Sjdp case '=': 156933965Sjdp ret = O_le; 157033965Sjdp break; 157133965Sjdp } 157277298Sobrien *num_chars = 2; 157333965Sjdp return ret; 157433965Sjdp 157538889Sjdp case '=': 157638889Sjdp if (input_line_pointer[1] != '=') 157738889Sjdp return op_encoding[c]; 157838889Sjdp 157977298Sobrien *num_chars = 2; 158038889Sjdp return O_eq; 158138889Sjdp 158233965Sjdp case '>': 158333965Sjdp switch (input_line_pointer[1]) 158433965Sjdp { 158533965Sjdp default: 158633965Sjdp return op_encoding[c]; 158733965Sjdp case '>': 158833965Sjdp ret = O_right_shift; 158933965Sjdp break; 159033965Sjdp case '=': 159133965Sjdp ret = O_ge; 159233965Sjdp break; 159333965Sjdp } 159477298Sobrien *num_chars = 2; 159533965Sjdp return ret; 159633965Sjdp 159733965Sjdp case '!': 1598218822Sdim switch (input_line_pointer[1]) 159933965Sjdp { 1600218822Sdim case '!': 1601218822Sdim /* We accept !! as equivalent to ^ for MRI compatibility. */ 1602218822Sdim *num_chars = 2; 1603218822Sdim return O_bit_exclusive_or; 1604218822Sdim case '=': 1605218822Sdim /* We accept != as equivalent to <>. */ 1606218822Sdim *num_chars = 2; 1607218822Sdim return O_ne; 1608218822Sdim default: 160933965Sjdp if (flag_m68k_mri) 161033965Sjdp return O_bit_inclusive_or; 161133965Sjdp return op_encoding[c]; 161233965Sjdp } 161333965Sjdp 161433965Sjdp case '|': 161533965Sjdp if (input_line_pointer[1] != '|') 161633965Sjdp return op_encoding[c]; 161733965Sjdp 161877298Sobrien *num_chars = 2; 161933965Sjdp return O_logical_or; 162033965Sjdp 162133965Sjdp case '&': 162233965Sjdp if (input_line_pointer[1] != '&') 162333965Sjdp return op_encoding[c]; 162433965Sjdp 162577298Sobrien *num_chars = 2; 162633965Sjdp return O_logical_and; 162733965Sjdp } 162833965Sjdp 162977298Sobrien /* NOTREACHED */ 163038889Sjdp} 163133965Sjdp 163233965Sjdp/* Parse an expression. */ 163333965Sjdp 163433965SjdpsegT 1635130561Sobrienexpr (int rankarg, /* Larger # is higher rank. */ 1636218822Sdim expressionS *resultP, /* Deliver result here. */ 1637218822Sdim enum expr_mode mode /* Controls behavior. */) 163833965Sjdp{ 163960484Sobrien operator_rankT rank = (operator_rankT) rankarg; 164033965Sjdp segT retval; 164133965Sjdp expressionS right; 164233965Sjdp operatorT op_left; 164333965Sjdp operatorT op_right; 164477298Sobrien int op_chars; 164533965Sjdp 1646218822Sdim know (rankarg >= 0); 164733965Sjdp 1648130561Sobrien /* Save the value of dot for the fixup code. */ 1649130561Sobrien if (rank == 0) 1650130561Sobrien dot_value = frag_now_fix (); 1651130561Sobrien 1652218822Sdim retval = operand (resultP, mode); 165333965Sjdp 165477298Sobrien /* operand () gobbles spaces. */ 165577298Sobrien know (*input_line_pointer != ' '); 165633965Sjdp 165777298Sobrien op_left = operator (&op_chars); 165833965Sjdp while (op_left != O_illegal && op_rank[(int) op_left] > rank) 165933965Sjdp { 166033965Sjdp segT rightseg; 1661218822Sdim bfd_vma frag_off; 166233965Sjdp 166377298Sobrien input_line_pointer += op_chars; /* -> after operator. */ 166433965Sjdp 1665218822Sdim rightseg = expr (op_rank[(int) op_left], &right, mode); 166633965Sjdp if (right.X_op == O_absent) 166733965Sjdp { 166860484Sobrien as_warn (_("missing operand; zero assumed")); 166933965Sjdp right.X_op = O_constant; 167033965Sjdp right.X_add_number = 0; 167133965Sjdp right.X_add_symbol = NULL; 167233965Sjdp right.X_op_symbol = NULL; 167333965Sjdp } 167433965Sjdp 167533965Sjdp know (*input_line_pointer != ' '); 167633965Sjdp 167760484Sobrien if (op_left == O_index) 167860484Sobrien { 167960484Sobrien if (*input_line_pointer != ']') 168060484Sobrien as_bad ("missing right bracket"); 168160484Sobrien else 168260484Sobrien { 168360484Sobrien ++input_line_pointer; 168460484Sobrien SKIP_WHITESPACE (); 168560484Sobrien } 168660484Sobrien } 168760484Sobrien 168877298Sobrien op_right = operator (&op_chars); 168933965Sjdp 169077298Sobrien know (op_right == O_illegal 169177298Sobrien || op_rank[(int) op_right] <= op_rank[(int) op_left]); 169233965Sjdp know ((int) op_left >= (int) O_multiply 1693218822Sdim && (int) op_left <= (int) O_index); 169433965Sjdp 169577298Sobrien /* input_line_pointer->after right-hand quantity. */ 169677298Sobrien /* left-hand quantity in resultP. */ 169777298Sobrien /* right-hand quantity in right. */ 169877298Sobrien /* operator in op_left. */ 169933965Sjdp 170033965Sjdp if (resultP->X_op == O_big) 170133965Sjdp { 170260484Sobrien if (resultP->X_add_number > 0) 170360484Sobrien as_warn (_("left operand is a bignum; integer 0 assumed")); 170460484Sobrien else 170560484Sobrien as_warn (_("left operand is a float; integer 0 assumed")); 170633965Sjdp resultP->X_op = O_constant; 170733965Sjdp resultP->X_add_number = 0; 170833965Sjdp resultP->X_add_symbol = NULL; 170933965Sjdp resultP->X_op_symbol = NULL; 171033965Sjdp } 171133965Sjdp if (right.X_op == O_big) 171233965Sjdp { 171360484Sobrien if (right.X_add_number > 0) 171460484Sobrien as_warn (_("right operand is a bignum; integer 0 assumed")); 171560484Sobrien else 171660484Sobrien as_warn (_("right operand is a float; integer 0 assumed")); 171733965Sjdp right.X_op = O_constant; 171833965Sjdp right.X_add_number = 0; 171933965Sjdp right.X_add_symbol = NULL; 172033965Sjdp right.X_op_symbol = NULL; 172133965Sjdp } 172233965Sjdp 172333965Sjdp /* Optimize common cases. */ 172477298Sobrien#ifdef md_optimize_expr 172577298Sobrien if (md_optimize_expr (resultP, op_left, &right)) 172677298Sobrien { 172777298Sobrien /* Skip. */ 172877298Sobrien ; 172977298Sobrien } 173077298Sobrien else 173177298Sobrien#endif 173233965Sjdp if (op_left == O_add && right.X_op == O_constant) 173333965Sjdp { 173433965Sjdp /* X + constant. */ 173533965Sjdp resultP->X_add_number += right.X_add_number; 173633965Sjdp } 173733965Sjdp /* This case comes up in PIC code. */ 173833965Sjdp else if (op_left == O_subtract 173933965Sjdp && right.X_op == O_symbol 174033965Sjdp && resultP->X_op == O_symbol 1741218822Sdim && retval == rightseg 1742130561Sobrien && (SEG_NORMAL (rightseg) 1743218822Sdim || right.X_add_symbol == resultP->X_add_symbol) 1744218822Sdim && frag_offset_fixed_p (symbol_get_frag (resultP->X_add_symbol), 1745218822Sdim symbol_get_frag (right.X_add_symbol), 1746218822Sdim &frag_off)) 174733965Sjdp { 174833965Sjdp resultP->X_add_number -= right.X_add_number; 1749218822Sdim resultP->X_add_number -= frag_off / OCTETS_PER_BYTE; 175033965Sjdp resultP->X_add_number += (S_GET_VALUE (resultP->X_add_symbol) 175133965Sjdp - S_GET_VALUE (right.X_add_symbol)); 175233965Sjdp resultP->X_op = O_constant; 175333965Sjdp resultP->X_add_symbol = 0; 175433965Sjdp } 175533965Sjdp else if (op_left == O_subtract && right.X_op == O_constant) 175633965Sjdp { 175733965Sjdp /* X - constant. */ 175833965Sjdp resultP->X_add_number -= right.X_add_number; 175933965Sjdp } 176033965Sjdp else if (op_left == O_add && resultP->X_op == O_constant) 176133965Sjdp { 176233965Sjdp /* Constant + X. */ 176333965Sjdp resultP->X_op = right.X_op; 176433965Sjdp resultP->X_add_symbol = right.X_add_symbol; 176533965Sjdp resultP->X_op_symbol = right.X_op_symbol; 176633965Sjdp resultP->X_add_number += right.X_add_number; 176733965Sjdp retval = rightseg; 176833965Sjdp } 176933965Sjdp else if (resultP->X_op == O_constant && right.X_op == O_constant) 177033965Sjdp { 177133965Sjdp /* Constant OP constant. */ 177233965Sjdp offsetT v = right.X_add_number; 177333965Sjdp if (v == 0 && (op_left == O_divide || op_left == O_modulus)) 177433965Sjdp { 177560484Sobrien as_warn (_("division by zero")); 177633965Sjdp v = 1; 177733965Sjdp } 177833965Sjdp switch (op_left) 177933965Sjdp { 178033965Sjdp default: abort (); 178133965Sjdp case O_multiply: resultP->X_add_number *= v; break; 178233965Sjdp case O_divide: resultP->X_add_number /= v; break; 178333965Sjdp case O_modulus: resultP->X_add_number %= v; break; 178433965Sjdp case O_left_shift: resultP->X_add_number <<= v; break; 178533965Sjdp case O_right_shift: 178633965Sjdp /* We always use unsigned shifts, to avoid relying on 1787130561Sobrien characteristics of the compiler used to compile gas. */ 178833965Sjdp resultP->X_add_number = 178933965Sjdp (offsetT) ((valueT) resultP->X_add_number >> (valueT) v); 179033965Sjdp break; 179133965Sjdp case O_bit_inclusive_or: resultP->X_add_number |= v; break; 179233965Sjdp case O_bit_or_not: resultP->X_add_number |= ~v; break; 179333965Sjdp case O_bit_exclusive_or: resultP->X_add_number ^= v; break; 179433965Sjdp case O_bit_and: resultP->X_add_number &= v; break; 1795218822Sdim /* Constant + constant (O_add) is handled by the 1796218822Sdim previous if statement for constant + X, so is omitted 1797218822Sdim here. */ 179833965Sjdp case O_subtract: resultP->X_add_number -= v; break; 179933965Sjdp case O_eq: 180033965Sjdp resultP->X_add_number = 180133965Sjdp resultP->X_add_number == v ? ~ (offsetT) 0 : 0; 180233965Sjdp break; 180333965Sjdp case O_ne: 180433965Sjdp resultP->X_add_number = 180533965Sjdp resultP->X_add_number != v ? ~ (offsetT) 0 : 0; 180633965Sjdp break; 180733965Sjdp case O_lt: 180833965Sjdp resultP->X_add_number = 180933965Sjdp resultP->X_add_number < v ? ~ (offsetT) 0 : 0; 181033965Sjdp break; 181133965Sjdp case O_le: 181233965Sjdp resultP->X_add_number = 181333965Sjdp resultP->X_add_number <= v ? ~ (offsetT) 0 : 0; 181433965Sjdp break; 181533965Sjdp case O_ge: 181633965Sjdp resultP->X_add_number = 181733965Sjdp resultP->X_add_number >= v ? ~ (offsetT) 0 : 0; 181833965Sjdp break; 181933965Sjdp case O_gt: 182033965Sjdp resultP->X_add_number = 182133965Sjdp resultP->X_add_number > v ? ~ (offsetT) 0 : 0; 182233965Sjdp break; 182333965Sjdp case O_logical_and: 182433965Sjdp resultP->X_add_number = resultP->X_add_number && v; 182533965Sjdp break; 182633965Sjdp case O_logical_or: 182733965Sjdp resultP->X_add_number = resultP->X_add_number || v; 182833965Sjdp break; 182933965Sjdp } 183033965Sjdp } 183133965Sjdp else if (resultP->X_op == O_symbol 183233965Sjdp && right.X_op == O_symbol 183333965Sjdp && (op_left == O_add 183433965Sjdp || op_left == O_subtract 183533965Sjdp || (resultP->X_add_number == 0 183633965Sjdp && right.X_add_number == 0))) 183733965Sjdp { 183833965Sjdp /* Symbol OP symbol. */ 183933965Sjdp resultP->X_op = op_left; 184033965Sjdp resultP->X_op_symbol = right.X_add_symbol; 184133965Sjdp if (op_left == O_add) 184233965Sjdp resultP->X_add_number += right.X_add_number; 184333965Sjdp else if (op_left == O_subtract) 184489857Sobrien { 184589857Sobrien resultP->X_add_number -= right.X_add_number; 184689857Sobrien if (retval == rightseg && SEG_NORMAL (retval)) 184789857Sobrien { 184889857Sobrien retval = absolute_section; 184989857Sobrien rightseg = absolute_section; 185089857Sobrien } 185189857Sobrien } 185233965Sjdp } 185333965Sjdp else 185433965Sjdp { 185533965Sjdp /* The general case. */ 185633965Sjdp resultP->X_add_symbol = make_expr_symbol (resultP); 185733965Sjdp resultP->X_op_symbol = make_expr_symbol (&right); 185833965Sjdp resultP->X_op = op_left; 185933965Sjdp resultP->X_add_number = 0; 186033965Sjdp resultP->X_unsigned = 1; 186133965Sjdp } 186233965Sjdp 186389857Sobrien if (retval != rightseg) 186489857Sobrien { 186589857Sobrien if (! SEG_NORMAL (retval)) 186689857Sobrien { 186789857Sobrien if (retval != undefined_section || SEG_NORMAL (rightseg)) 186889857Sobrien retval = rightseg; 186989857Sobrien } 187089857Sobrien else if (SEG_NORMAL (rightseg) 187189857Sobrien#ifdef DIFF_EXPR_OK 187289857Sobrien && op_left != O_subtract 187389857Sobrien#endif 187489857Sobrien ) 187589857Sobrien as_bad (_("operation combines symbols in different segments")); 187689857Sobrien } 187789857Sobrien 187833965Sjdp op_left = op_right; 187977298Sobrien } /* While next operator is >= this rank. */ 188033965Sjdp 188133965Sjdp /* The PA port needs this information. */ 188233965Sjdp if (resultP->X_add_symbol) 188360484Sobrien symbol_mark_used (resultP->X_add_symbol); 188433965Sjdp 1885218822Sdim if (rank == 0 && mode == expr_evaluate) 1886218822Sdim resolve_expression (resultP); 1887218822Sdim 188833965Sjdp return resultP->X_op == O_constant ? absolute_section : retval; 188933965Sjdp} 1890218822Sdim 1891218822Sdim/* Resolve an expression without changing any symbols/sub-expressions 1892218822Sdim used. */ 1893218822Sdim 1894218822Sdimint 1895218822Sdimresolve_expression (expressionS *expressionP) 1896218822Sdim{ 1897218822Sdim /* Help out with CSE. */ 1898218822Sdim valueT final_val = expressionP->X_add_number; 1899218822Sdim symbolS *add_symbol = expressionP->X_add_symbol; 1900218822Sdim symbolS *op_symbol = expressionP->X_op_symbol; 1901218822Sdim operatorT op = expressionP->X_op; 1902218822Sdim valueT left, right; 1903218822Sdim segT seg_left, seg_right; 1904218822Sdim fragS *frag_left, *frag_right; 1905218822Sdim bfd_vma frag_off; 1906218822Sdim 1907218822Sdim switch (op) 1908218822Sdim { 1909218822Sdim default: 1910218822Sdim return 0; 1911218822Sdim 1912218822Sdim case O_constant: 1913218822Sdim case O_register: 1914218822Sdim left = 0; 1915218822Sdim break; 1916218822Sdim 1917218822Sdim case O_symbol: 1918218822Sdim case O_symbol_rva: 1919218822Sdim if (!snapshot_symbol (&add_symbol, &left, &seg_left, &frag_left)) 1920218822Sdim return 0; 1921218822Sdim 1922218822Sdim break; 1923218822Sdim 1924218822Sdim case O_uminus: 1925218822Sdim case O_bit_not: 1926218822Sdim case O_logical_not: 1927218822Sdim if (!snapshot_symbol (&add_symbol, &left, &seg_left, &frag_left)) 1928218822Sdim return 0; 1929218822Sdim 1930218822Sdim if (seg_left != absolute_section) 1931218822Sdim return 0; 1932218822Sdim 1933218822Sdim if (op == O_logical_not) 1934218822Sdim left = !left; 1935218822Sdim else if (op == O_uminus) 1936218822Sdim left = -left; 1937218822Sdim else 1938218822Sdim left = ~left; 1939218822Sdim op = O_constant; 1940218822Sdim break; 1941218822Sdim 1942218822Sdim case O_multiply: 1943218822Sdim case O_divide: 1944218822Sdim case O_modulus: 1945218822Sdim case O_left_shift: 1946218822Sdim case O_right_shift: 1947218822Sdim case O_bit_inclusive_or: 1948218822Sdim case O_bit_or_not: 1949218822Sdim case O_bit_exclusive_or: 1950218822Sdim case O_bit_and: 1951218822Sdim case O_add: 1952218822Sdim case O_subtract: 1953218822Sdim case O_eq: 1954218822Sdim case O_ne: 1955218822Sdim case O_lt: 1956218822Sdim case O_le: 1957218822Sdim case O_ge: 1958218822Sdim case O_gt: 1959218822Sdim case O_logical_and: 1960218822Sdim case O_logical_or: 1961218822Sdim if (!snapshot_symbol (&add_symbol, &left, &seg_left, &frag_left) 1962218822Sdim || !snapshot_symbol (&op_symbol, &right, &seg_right, &frag_right)) 1963218822Sdim return 0; 1964218822Sdim 1965218822Sdim /* Simplify addition or subtraction of a constant by folding the 1966218822Sdim constant into X_add_number. */ 1967218822Sdim if (op == O_add) 1968218822Sdim { 1969218822Sdim if (seg_right == absolute_section) 1970218822Sdim { 1971218822Sdim final_val += right; 1972218822Sdim op = O_symbol; 1973218822Sdim break; 1974218822Sdim } 1975218822Sdim else if (seg_left == absolute_section) 1976218822Sdim { 1977218822Sdim final_val += left; 1978218822Sdim left = right; 1979218822Sdim seg_left = seg_right; 1980218822Sdim add_symbol = op_symbol; 1981218822Sdim op = O_symbol; 1982218822Sdim break; 1983218822Sdim } 1984218822Sdim } 1985218822Sdim else if (op == O_subtract) 1986218822Sdim { 1987218822Sdim if (seg_right == absolute_section) 1988218822Sdim { 1989218822Sdim final_val -= right; 1990218822Sdim op = O_symbol; 1991218822Sdim break; 1992218822Sdim } 1993218822Sdim } 1994218822Sdim 1995218822Sdim /* Equality and non-equality tests are permitted on anything. 1996218822Sdim Subtraction, and other comparison operators are permitted if 1997218822Sdim both operands are in the same section. 1998218822Sdim Shifts by constant zero are permitted on anything. 1999218822Sdim Multiplies, bit-ors, and bit-ands with constant zero are 2000218822Sdim permitted on anything. 2001218822Sdim Multiplies and divides by constant one are permitted on 2002218822Sdim anything. 2003218822Sdim Binary operations with both operands being the same register 2004218822Sdim or undefined symbol are permitted if the result doesn't depend 2005218822Sdim on the input value. 2006218822Sdim Otherwise, both operands must be absolute. We already handled 2007218822Sdim the case of addition or subtraction of a constant above. */ 2008218822Sdim frag_off = 0; 2009218822Sdim if (!(seg_left == absolute_section 2010218822Sdim && seg_right == absolute_section) 2011218822Sdim && !(op == O_eq || op == O_ne) 2012218822Sdim && !((op == O_subtract 2013218822Sdim || op == O_lt || op == O_le || op == O_ge || op == O_gt) 2014218822Sdim && seg_left == seg_right 2015218822Sdim && (finalize_syms 2016218822Sdim || frag_offset_fixed_p (frag_left, frag_right, &frag_off)) 2017218822Sdim && (seg_left != reg_section || left == right) 2018218822Sdim && (seg_left != undefined_section || add_symbol == op_symbol))) 2019218822Sdim { 2020218822Sdim if ((seg_left == absolute_section && left == 0) 2021218822Sdim || (seg_right == absolute_section && right == 0)) 2022218822Sdim { 2023218822Sdim if (op == O_bit_exclusive_or || op == O_bit_inclusive_or) 2024218822Sdim { 2025218822Sdim if (seg_right != absolute_section || right != 0) 2026218822Sdim { 2027218822Sdim seg_left = seg_right; 2028218822Sdim left = right; 2029218822Sdim add_symbol = op_symbol; 2030218822Sdim } 2031218822Sdim op = O_symbol; 2032218822Sdim break; 2033218822Sdim } 2034218822Sdim else if (op == O_left_shift || op == O_right_shift) 2035218822Sdim { 2036218822Sdim if (seg_left != absolute_section || left != 0) 2037218822Sdim { 2038218822Sdim op = O_symbol; 2039218822Sdim break; 2040218822Sdim } 2041218822Sdim } 2042218822Sdim else if (op != O_multiply 2043218822Sdim && op != O_bit_or_not && op != O_bit_and) 2044218822Sdim return 0; 2045218822Sdim } 2046218822Sdim else if (op == O_multiply 2047218822Sdim && seg_left == absolute_section && left == 1) 2048218822Sdim { 2049218822Sdim seg_left = seg_right; 2050218822Sdim left = right; 2051218822Sdim add_symbol = op_symbol; 2052218822Sdim op = O_symbol; 2053218822Sdim break; 2054218822Sdim } 2055218822Sdim else if ((op == O_multiply || op == O_divide) 2056218822Sdim && seg_right == absolute_section && right == 1) 2057218822Sdim { 2058218822Sdim op = O_symbol; 2059218822Sdim break; 2060218822Sdim } 2061218822Sdim else if (left != right 2062218822Sdim || ((seg_left != reg_section || seg_right != reg_section) 2063218822Sdim && (seg_left != undefined_section 2064218822Sdim || seg_right != undefined_section 2065218822Sdim || add_symbol != op_symbol))) 2066218822Sdim return 0; 2067218822Sdim else if (op == O_bit_and || op == O_bit_inclusive_or) 2068218822Sdim { 2069218822Sdim op = O_symbol; 2070218822Sdim break; 2071218822Sdim } 2072218822Sdim else if (op != O_bit_exclusive_or && op != O_bit_or_not) 2073218822Sdim return 0; 2074218822Sdim } 2075218822Sdim 2076218822Sdim right += frag_off / OCTETS_PER_BYTE; 2077218822Sdim switch (op) 2078218822Sdim { 2079218822Sdim case O_add: left += right; break; 2080218822Sdim case O_subtract: left -= right; break; 2081218822Sdim case O_multiply: left *= right; break; 2082218822Sdim case O_divide: 2083218822Sdim if (right == 0) 2084218822Sdim return 0; 2085218822Sdim left = (offsetT) left / (offsetT) right; 2086218822Sdim break; 2087218822Sdim case O_modulus: 2088218822Sdim if (right == 0) 2089218822Sdim return 0; 2090218822Sdim left = (offsetT) left % (offsetT) right; 2091218822Sdim break; 2092218822Sdim case O_left_shift: left <<= right; break; 2093218822Sdim case O_right_shift: left >>= right; break; 2094218822Sdim case O_bit_inclusive_or: left |= right; break; 2095218822Sdim case O_bit_or_not: left |= ~right; break; 2096218822Sdim case O_bit_exclusive_or: left ^= right; break; 2097218822Sdim case O_bit_and: left &= right; break; 2098218822Sdim case O_eq: 2099218822Sdim case O_ne: 2100218822Sdim left = (left == right 2101218822Sdim && seg_left == seg_right 2102218822Sdim && (finalize_syms || frag_left == frag_right) 2103218822Sdim && (seg_left != undefined_section 2104218822Sdim || add_symbol == op_symbol) 2105218822Sdim ? ~ (valueT) 0 : 0); 2106218822Sdim if (op == O_ne) 2107218822Sdim left = ~left; 2108218822Sdim break; 2109218822Sdim case O_lt: 2110218822Sdim left = (offsetT) left < (offsetT) right ? ~ (valueT) 0 : 0; 2111218822Sdim break; 2112218822Sdim case O_le: 2113218822Sdim left = (offsetT) left <= (offsetT) right ? ~ (valueT) 0 : 0; 2114218822Sdim break; 2115218822Sdim case O_ge: 2116218822Sdim left = (offsetT) left >= (offsetT) right ? ~ (valueT) 0 : 0; 2117218822Sdim break; 2118218822Sdim case O_gt: 2119218822Sdim left = (offsetT) left > (offsetT) right ? ~ (valueT) 0 : 0; 2120218822Sdim break; 2121218822Sdim case O_logical_and: left = left && right; break; 2122218822Sdim case O_logical_or: left = left || right; break; 2123218822Sdim default: abort (); 2124218822Sdim } 2125218822Sdim 2126218822Sdim op = O_constant; 2127218822Sdim break; 2128218822Sdim } 2129218822Sdim 2130218822Sdim if (op == O_symbol) 2131218822Sdim { 2132218822Sdim if (seg_left == absolute_section) 2133218822Sdim op = O_constant; 2134218822Sdim else if (seg_left == reg_section && final_val == 0) 2135218822Sdim op = O_register; 2136218822Sdim else if (add_symbol != expressionP->X_add_symbol) 2137218822Sdim final_val += left; 2138218822Sdim expressionP->X_add_symbol = add_symbol; 2139218822Sdim } 2140218822Sdim expressionP->X_op = op; 2141218822Sdim 2142218822Sdim if (op == O_constant || op == O_register) 2143218822Sdim final_val += left; 2144218822Sdim expressionP->X_add_number = final_val; 2145218822Sdim 2146218822Sdim return 1; 2147218822Sdim} 214833965Sjdp 214977298Sobrien/* This lives here because it belongs equally in expr.c & read.c. 215077298Sobrien expr.c is just a branch office read.c anyway, and putting it 215177298Sobrien here lessens the crowd at read.c. 215277298Sobrien 215377298Sobrien Assume input_line_pointer is at start of symbol name. 215477298Sobrien Advance input_line_pointer past symbol name. 215577298Sobrien Turn that character into a '\0', returning its former value. 215677298Sobrien This allows a string compare (RMS wants symbol names to be strings) 215777298Sobrien of the symbol name. 215877298Sobrien There will always be a char following symbol name, because all good 215977298Sobrien lines end in end-of-line. */ 216077298Sobrien 216133965Sjdpchar 2162130561Sobrienget_symbol_end (void) 216333965Sjdp{ 216433965Sjdp char c; 216533965Sjdp 216633965Sjdp /* We accept \001 in a name in case this is being called with a 216733965Sjdp constructed string. */ 216833965Sjdp if (is_name_beginner (c = *input_line_pointer++) || c == '\001') 216960484Sobrien { 217060484Sobrien while (is_part_of_name (c = *input_line_pointer++) 217160484Sobrien || c == '\001') 217260484Sobrien ; 217360484Sobrien if (is_name_ender (c)) 217460484Sobrien c = *input_line_pointer++; 217560484Sobrien } 217633965Sjdp *--input_line_pointer = 0; 217733965Sjdp return (c); 217833965Sjdp} 217933965Sjdp 218033965Sjdpunsigned int 2181130561Sobrienget_single_number (void) 218233965Sjdp{ 218333965Sjdp expressionS exp; 2184218822Sdim operand (&exp, expr_normal); 218533965Sjdp return exp.X_add_number; 218633965Sjdp} 2187