aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/config/tc-hppa.c1
-rw-r--r--gas/config/tc-ppc.c6
-rw-r--r--gas/doc/internals.texi8
-rw-r--r--gas/expr.c47
4 files changed, 40 insertions, 22 deletions
diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c
index c91b2b5..2e5de07 100644
--- a/gas/config/tc-hppa.c
+++ b/gas/config/tc-hppa.c
@@ -6354,6 +6354,7 @@ hppa_force_reg_syms_absolute (expressionS *resultP,
expressionS *rightP)
{
if (fudge_reg_expressions
+ && resultP
&& rightP->X_op == O_register
&& resultP->X_op == O_register)
{
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index 8b1d995..a8b034c 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -945,9 +945,9 @@ ppc_optimize_expr (expressionS *left, operatorT op, expressionS *right)
}
/* Accept the above plus <cr bit>, and <cr bit> plus the above. */
- if (right->X_op == O_register
+ if (op == O_add
&& left->X_op == O_register
- && op == O_add
+ && right->X_op == O_register
&& ((right->X_md == PPC_OPERAND_CR_BIT
&& left->X_md == (PPC_OPERAND_CR_REG | PPC_OPERAND_CR_BIT))
|| (right->X_md == (PPC_OPERAND_CR_REG | PPC_OPERAND_CR_BIT)
@@ -959,7 +959,7 @@ ppc_optimize_expr (expressionS *left, operatorT op, expressionS *right)
}
/* Accept reg +/- constant. */
- if (left->X_op == O_register
+ if (left && left->X_op == O_register
&& !((op == O_add || op == O_subtract) && right->X_op == O_constant))
as_warn (_("invalid register expression"));
diff --git a/gas/doc/internals.texi b/gas/doc/internals.texi
index 56f10fd..3eea25b 100644
--- a/gas/doc/internals.texi
+++ b/gas/doc/internals.texi
@@ -1047,6 +1047,14 @@ pointer, for any expression that can not be recognized. When the function
is called, @code{input_line_pointer} will point to the start of the
expression.
+@item md_optimize_expr
+@cindex md_optimize_expr
+GAS will call this function before trying to carry out certain operations,
+like the adding of two constants. The function is passed the left-hand
+operand, an @code{expressionS} pointer, the operator, an @code{operatorT}
+value, and the right-hand operand, again an @code{expressionS} pointer. For
+unary expressions NULL is passed as first argument.
+
@item md_register_arithmetic
@cindex md_register_arithmetic
If this macro is defined and evaluates to zero then GAS will not fold
diff --git a/gas/expr.c b/gas/expr.c
index b83296c..204cfeb 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -764,6 +764,7 @@ operand (expressionS *expressionP, enum expr_mode mode)
symbolS *symbolP; /* Points to symbol. */
char *name; /* Points to name of symbol. */
segT segment;
+ operatorT op = O_absent; /* For unary operators. */
/* All integers are regarded as unsigned unless they are negated.
This is because the only thing which cares whether a number is
@@ -1029,19 +1030,33 @@ operand (expressionS *expressionP, enum expr_mode mode)
/* '~' is permitted to start a label on the Delta. */
if (is_name_beginner (c))
goto isname;
- /* Fall through. */
+ op = O_bit_not;
+ goto unary;
+
case '!':
+ op = O_logical_not;
+ goto unary;
+
case '-':
+ op = O_uminus;
+ /* Fall through. */
case '+':
{
-#ifdef md_operator
unary:
-#endif
operand (expressionP, mode);
+
+#ifdef md_optimize_expr
+ if (md_optimize_expr (NULL, op, expressionP))
+ {
+ /* Skip. */
+ ;
+ }
+ else
+#endif
if (expressionP->X_op == O_constant)
{
/* input_line_pointer -> char after operand. */
- if (c == '-')
+ if (op == O_uminus)
{
expressionP->X_add_number
= - (addressT) expressionP->X_add_number;
@@ -1052,13 +1067,13 @@ operand (expressionS *expressionP, enum expr_mode mode)
if (expressionP->X_add_number)
expressionP->X_extrabit ^= 1;
}
- else if (c == '~' || c == '"')
+ else if (op == O_bit_not)
{
expressionP->X_add_number = ~ expressionP->X_add_number;
expressionP->X_extrabit ^= 1;
expressionP->X_unsigned = 0;
}
- else if (c == '!')
+ else if (op == O_logical_not)
{
expressionP->X_add_number = ! expressionP->X_add_number;
expressionP->X_unsigned = 1;
@@ -1067,7 +1082,7 @@ operand (expressionS *expressionP, enum expr_mode mode)
}
else if (expressionP->X_op == O_big
&& expressionP->X_add_number <= 0
- && c == '-'
+ && op == O_uminus
&& (generic_floating_point_number.sign == '+'
|| generic_floating_point_number.sign == 'P'))
{
@@ -1082,7 +1097,7 @@ operand (expressionS *expressionP, enum expr_mode mode)
{
int i;
- if (c == '~' || c == '-')
+ if (op == O_uminus || op == O_bit_not)
{
for (i = 0; i < expressionP->X_add_number; ++i)
generic_bignum[i] = ~generic_bignum[i];
@@ -1095,7 +1110,7 @@ operand (expressionS *expressionP, enum expr_mode mode)
generic_bignum[i] = ~(LITTLENUM_TYPE) 0;
}
- if (c == '-')
+ if (op == O_uminus)
for (i = 0; i < expressionP->X_add_number; ++i)
{
generic_bignum[i] += 1;
@@ -1103,7 +1118,7 @@ operand (expressionS *expressionP, enum expr_mode mode)
break;
}
}
- else if (c == '!')
+ else if (op == O_logical_not)
{
for (i = 0; i < expressionP->X_add_number; ++i)
if (generic_bignum[i] != 0)
@@ -1117,15 +1132,10 @@ operand (expressionS *expressionP, enum expr_mode mode)
else if (expressionP->X_op != O_illegal
&& expressionP->X_op != O_absent)
{
- if (c != '+')
+ if (op != O_absent)
{
expressionP->X_add_symbol = make_expr_symbol (expressionP);
- if (c == '-')
- expressionP->X_op = O_uminus;
- else if (c == '~' || c == '"')
- expressionP->X_op = O_bit_not;
- else
- expressionP->X_op = O_logical_not;
+ expressionP->X_op = op;
expressionP->X_add_number = 0;
}
else if (!md_register_arithmetic && expressionP->X_op == O_register)
@@ -1288,8 +1298,7 @@ operand (expressionS *expressionP, enum expr_mode mode)
#ifdef md_operator
{
- operatorT op = md_operator (name, 1, &c);
-
+ op = md_operator (name, 1, &c);
switch (op)
{
case O_uminus: