diff options
Diffstat (limited to 'gas/expr.c')
-rw-r--r-- | gas/expr.c | 111 |
1 files changed, 104 insertions, 7 deletions
@@ -950,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); @@ -1011,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) { @@ -1207,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. */ @@ -1218,6 +1226,43 @@ operand (expressionS *expressionP, enum expr_mode mode) name = --input_line_pointer; c = get_symbol_end (); +#ifdef md_operator + { + operatorT operator = md_operator (name, 1, &c); + + switch (operator) + { + 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 (operator != O_absent && operator != 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 = operator; + 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 @@ -1516,6 +1561,13 @@ expr_set_precedence (void) } } +void +expr_set_rank (operatorT operator, operator_rankT rank) +{ + assert (operator >= O_md1 && operator < ARRAY_SIZE (op_rank)); + op_rank[operator] = rank; +} + /* Initialize the expression parser. */ void @@ -1547,10 +1599,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 '-': @@ -1689,10 +1781,14 @@ expr (int rankarg, /* Larger # is higher rank. */ op_right = operator (&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. */ @@ -1796,7 +1892,7 @@ expr (int rankarg, /* Larger # is higher rank. */ } 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; @@ -1871,6 +1967,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); |