X-Git-Url: https://oss.titaniummirror.com/gitweb?p=msp430-binutils.git;a=blobdiff_plain;f=gas%2Fexpr.c;fp=gas%2Fexpr.c;h=b9ce5741981d7a0a41f2b91621ed58d77c90a3da;hp=b88328502eebdddbd2250ebdb38c628dcbebb024;hb=d5da4f291af551c0b8b79e1d4a9b173d60e5c10e;hpb=7b5ea4fcdf2819e070665ab5610f8b48e3867c10 diff --git a/gas/expr.c b/gas/expr.c index b883285..b9ce574 100644 --- a/gas/expr.c +++ b/gas/expr.c @@ -1,6 +1,6 @@ /* expr.c -operands, expressions- Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -31,6 +31,13 @@ #include "safe-ctype.h" #include "obstack.h" +#ifdef HAVE_LIMITS_H +#include +#endif +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif + static void floating_constant (expressionS * expressionP); static valueT generic_bignum_to_int32 (void); #ifdef BFD64 @@ -41,7 +48,7 @@ static void mri_char_constant (expressionS *); static void current_location (expressionS *); static void clean_up_expression (expressionS * expressionP); static segT operand (expressionS *, enum expr_mode); -static operatorT operator (int *); +static operatorT operatorf (int *); extern const char EXP_CHARS[], FLT_CHARS[]; @@ -95,7 +102,9 @@ make_expr_symbol (expressionS *expressionP) symbolP = symbol_create (FAKE_LABEL_NAME, (expressionP->X_op == O_constant ? absolute_section - : expr_section), + : expressionP->X_op == O_register + ? reg_section + : expr_section), 0, &zero_address_frag); symbol_set_value_expression (symbolP, expressionP); @@ -402,7 +411,7 @@ integer_constant (int radix, expressionS *expressionP) if (num_little_digits > SIZE_OF_LARGE_NUMBER - 1) num_little_digits = SIZE_OF_LARGE_NUMBER - 1; - assert (num_little_digits >= 4); + gas_assert (num_little_digits >= 4); if (num_little_digits != 8) as_bad (_("a bignum with underscores must have exactly 4 words")); @@ -941,10 +950,15 @@ operand (expressionS *expressionP, enum expr_mode mode) break; - case '(': #ifndef NEED_INDEX_OPERATOR case '[': +# ifdef md_need_index_operator + if (md_need_index_operator()) + goto de_fault; +# endif + /* FALLTHROUGH */ #endif + case '(': /* Didn't begin with digit & not a name. */ if (mode != expr_defer) segment = expression (expressionP); @@ -1002,6 +1016,9 @@ operand (expressionS *expressionP, enum expr_mode mode) case '-': case '+': { +#ifdef md_operator + unary: +#endif operand (expressionP, mode); if (expressionP->X_op == O_constant) { @@ -1198,7 +1215,7 @@ operand (expressionS *expressionP, enum expr_mode mode) #endif default: -#ifdef TC_M68K +#if defined(md_need_index_operator) || defined(TC_M68K) de_fault: #endif if (is_name_beginner (c)) /* Here if did not begin with a digit. */ @@ -1209,6 +1226,43 @@ operand (expressionS *expressionP, enum expr_mode mode) name = --input_line_pointer; c = get_symbol_end (); +#ifdef md_operator + { + operatorT op = md_operator (name, 1, &c); + + switch (op) + { + case O_uminus: + *input_line_pointer = c; + c = '-'; + goto unary; + case O_bit_not: + *input_line_pointer = c; + c = '~'; + goto unary; + case O_logical_not: + *input_line_pointer = c; + c = '!'; + goto unary; + case O_illegal: + as_bad (_("invalid use of operator \"%s\""), name); + break; + default: + break; + } + if (op != O_absent && op != O_illegal) + { + *input_line_pointer = c; + expr (9, expressionP, mode); + expressionP->X_add_symbol = make_expr_symbol (expressionP); + expressionP->X_op_symbol = NULL; + expressionP->X_add_number = 0; + expressionP->X_op = op; + break; + } + } +#endif + #ifdef md_parse_name /* This is a hook for the backend to parse certain names specially in certain contexts. If a name always has a @@ -1432,7 +1486,7 @@ static const operatorT op_encoding[256] = { 7 * / % << >> 8 unary - unary ~ */ -static operator_rankT op_rank[] = { +static operator_rankT op_rank[O_max] = { 0, /* O_illegal */ 0, /* O_absent */ 0, /* O_constant */ @@ -1463,22 +1517,6 @@ static operator_rankT op_rank[] = { 3, /* O_logical_and */ 2, /* O_logical_or */ 1, /* O_index */ - 0, /* O_md1 */ - 0, /* O_md2 */ - 0, /* O_md3 */ - 0, /* O_md4 */ - 0, /* O_md5 */ - 0, /* O_md6 */ - 0, /* O_md7 */ - 0, /* O_md8 */ - 0, /* O_md9 */ - 0, /* O_md10 */ - 0, /* O_md11 */ - 0, /* O_md12 */ - 0, /* O_md13 */ - 0, /* O_md14 */ - 0, /* O_md15 */ - 0, /* O_md16 */ }; /* Unfortunately, in MRI mode for the m68k, multiplication and @@ -1507,6 +1545,13 @@ expr_set_precedence (void) } } +void +expr_set_rank (operatorT op, operator_rankT rank) +{ + gas_assert (op >= O_md1 && op < ARRAY_SIZE (op_rank)); + op_rank[op] = rank; +} + /* Initialize the expression parser. */ void @@ -1518,7 +1563,7 @@ expr_begin (void) { expressionS e; e.X_op = O_max; - assert (e.X_op == O_max); + gas_assert (e.X_op == O_max); } } @@ -1527,7 +1572,7 @@ expr_begin (void) Does not advance INPUT_LINE_POINTER. */ static inline operatorT -operator (int *num_chars) +operatorf (int *num_chars) { int c; operatorT ret; @@ -1538,10 +1583,50 @@ operator (int *num_chars) if (is_end_of_line[c]) return O_illegal; +#ifdef md_operator + if (is_name_beginner (c)) + { + char *name = input_line_pointer; + char c = get_symbol_end (); + + ret = md_operator (name, 2, &c); + switch (ret) + { + case O_absent: + *input_line_pointer = c; + input_line_pointer = name; + break; + case O_uminus: + case O_bit_not: + case O_logical_not: + as_bad (_("invalid use of operator \"%s\""), name); + ret = O_illegal; + /* FALLTHROUGH */ + default: + *input_line_pointer = c; + *num_chars = input_line_pointer - name; + input_line_pointer = name; + return ret; + } + } +#endif + switch (c) { default: - return op_encoding[c]; + ret = op_encoding[c]; +#ifdef md_operator + if (ret == O_illegal) + { + char *start = input_line_pointer; + + ret = md_operator (NULL, 2, NULL); + if (ret != O_illegal) + *num_chars = input_line_pointer - start; + input_line_pointer = start; + } +#endif + return ret; case '+': case '-': @@ -1647,7 +1732,7 @@ expr (int rankarg, /* Larger # is higher rank. */ /* operand () gobbles spaces. */ know (*input_line_pointer != ' '); - op_left = operator (&op_chars); + op_left = operatorf (&op_chars); while (op_left != O_illegal && op_rank[(int) op_left] > rank) { segT rightseg; @@ -1678,12 +1763,16 @@ expr (int rankarg, /* Larger # is higher rank. */ } } - op_right = operator (&op_chars); + op_right = operatorf (&op_chars); - know (op_right == O_illegal + know (op_right == O_illegal || op_left == O_index || op_rank[(int) op_right] <= op_rank[(int) op_left]); - know ((int) op_left >= (int) O_multiply - && (int) op_left <= (int) O_index); + know ((int) op_left >= (int) O_multiply); +#ifndef md_operator + know ((int) op_left <= (int) O_index); +#else + know ((int) op_left < (int) O_max); +#endif /* input_line_pointer->after right-hand quantity. */ /* left-hand quantity in resultP. */ @@ -1722,7 +1811,11 @@ expr (int rankarg, /* Larger # is higher rank. */ } else #endif - if (op_left == O_add && right.X_op == O_constant) +#ifndef md_register_arithmetic +# define md_register_arithmetic 1 +#endif + if (op_left == O_add && right.X_op == O_constant + && (md_register_arithmetic || resultP->X_op != O_register)) { /* X + constant. */ resultP->X_add_number += right.X_add_number; @@ -1732,6 +1825,9 @@ expr (int rankarg, /* Larger # is higher rank. */ && right.X_op == O_symbol && resultP->X_op == O_symbol && retval == rightseg +#ifdef md_allow_local_subtract + && md_allow_local_subtract (resultP, & right, rightseg) +#endif && (SEG_NORMAL (rightseg) || right.X_add_symbol == resultP->X_add_symbol) && frag_offset_fixed_p (symbol_get_frag (resultP->X_add_symbol), @@ -1745,12 +1841,14 @@ expr (int rankarg, /* Larger # is higher rank. */ resultP->X_op = O_constant; resultP->X_add_symbol = 0; } - else if (op_left == O_subtract && right.X_op == O_constant) + else if (op_left == O_subtract && right.X_op == O_constant + && (md_register_arithmetic || resultP->X_op != O_register)) { /* X - constant. */ resultP->X_add_number -= right.X_add_number; } - else if (op_left == O_add && resultP->X_op == O_constant) + else if (op_left == O_add && resultP->X_op == O_constant + && (md_register_arithmetic || right.X_op != O_register)) { /* Constant + X. */ resultP->X_op = right.X_op; @@ -1768,9 +1866,17 @@ expr (int rankarg, /* Larger # is higher rank. */ as_warn (_("division by zero")); v = 1; } + if ((valueT) v >= sizeof(valueT) * CHAR_BIT + && (op_left == O_left_shift || op_left == O_right_shift)) + { + as_warn_value_out_of_range (_("shift count"), v, 0, + sizeof(valueT) * CHAR_BIT - 1, + NULL, 0); + resultP->X_add_number = v = 0; + } switch (op_left) { - default: abort (); + default: goto general; case O_multiply: resultP->X_add_number *= v; break; case O_divide: resultP->X_add_number /= v; break; case O_modulus: resultP->X_add_number %= v; break; @@ -1845,6 +1951,7 @@ expr (int rankarg, /* Larger # is higher rank. */ } else { + general: /* The general case. */ resultP->X_add_symbol = make_expr_symbol (resultP); resultP->X_op_symbol = make_expr_symbol (&right);