summaryrefslogtreecommitdiff
path: root/gas/expr.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2005-12-22 17:05:40 +0000
committerJan Beulich <jbeulich@novell.com>2005-12-22 17:05:40 +0000
commit2bcc67f24e4f08ffc01231508622001fcc09fa9d (patch)
treeaf08cd2021653700ed8ee35861c49940b19915ad /gas/expr.c
parenta2ceceaedb8cffaacb49c3d4dd6de52eb9575831 (diff)
downloadbinutils-redhat-2bcc67f24e4f08ffc01231508622001fcc09fa9d.tar.gz
gas/
2005-12-22 Jan Beulich <jbeulich@novell.com> * symbols.h (snapshot_symbol): First parameter is now pointer to pointer to symbolS. * symbols.c (snapshot_symbol): Likewise. Store resulting symbol there. Use symbol_equated_p. * expr.c (resolve_expression): Change first argument to snapshot_symbol. Track possibly changed add_symbol consistently across function. Resolve more special cases with known result. Also update final_val when replacing add_symbol. gas/testsuite/ 2005-12-22 Jan Beulich <jbeulich@novell.com> * gas/all/cond.s: Also check .if works on equates to undefined when the expression value can be known without knowing the value of the symbol. * gas/all/cond.l: Adjust. * gas/i386/equ.s: Also check .if works on (equates to) registers when the expression value can be known without knowing the value of the register. * gas/i386/equ.e: Adjust.
Diffstat (limited to 'gas/expr.c')
-rw-r--r--gas/expr.c92
1 files changed, 78 insertions, 14 deletions
diff --git a/gas/expr.c b/gas/expr.c
index c601b0af69..3ae1bcc581 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -1913,7 +1913,7 @@ resolve_expression (expressionS *expressionP)
case O_symbol:
case O_symbol_rva:
- if (!snapshot_symbol (add_symbol, &left, &seg_left, &frag_left))
+ if (!snapshot_symbol (&add_symbol, &left, &seg_left, &frag_left))
return 0;
break;
@@ -1921,7 +1921,7 @@ resolve_expression (expressionS *expressionP)
case O_uminus:
case O_bit_not:
case O_logical_not:
- if (!snapshot_symbol (add_symbol, &left, &seg_left, &frag_left))
+ if (!snapshot_symbol (&add_symbol, &left, &seg_left, &frag_left))
return 0;
if (seg_left != absolute_section)
@@ -1955,8 +1955,8 @@ resolve_expression (expressionS *expressionP)
case O_gt:
case O_logical_and:
case O_logical_or:
- if (!snapshot_symbol (add_symbol, &left, &seg_left, &frag_left)
- || !snapshot_symbol (op_symbol, &right, &seg_right, &frag_right))
+ if (!snapshot_symbol (&add_symbol, &left, &seg_left, &frag_left)
+ || !snapshot_symbol (&op_symbol, &right, &seg_right, &frag_right))
return 0;
/* Simplify addition or subtraction of a constant by folding the
@@ -1974,7 +1974,7 @@ resolve_expression (expressionS *expressionP)
final_val += left;
left = right;
seg_left = seg_right;
- expressionP->X_add_symbol = expressionP->X_op_symbol;
+ add_symbol = op_symbol;
op = O_symbol;
break;
}
@@ -1991,9 +1991,17 @@ resolve_expression (expressionS *expressionP)
/* Equality and non-equality tests are permitted on anything.
Subtraction, and other comparison operators are permitted if
- both operands are in the same section. Otherwise, both
- operands must be absolute. We already handled the case of
- addition or subtraction of a constant above. */
+ both operands are in the same section.
+ Shifts by constant zero are permitted on anything.
+ Multiplies, bit-ors, and bit-ands with constant zero are
+ permitted on anything.
+ Multiplies and divides by constant one are permitted on
+ anything.
+ Binary operations with both operands being the same register
+ or undefined symbol are permitted if the result doesn't depend
+ on the input value.
+ Otherwise, both operands must be absolute. We already handled
+ the case of addition or subtraction of a constant above. */
if (!(seg_left == absolute_section
&& seg_right == absolute_section)
&& !(op == O_eq || op == O_ne)
@@ -2001,10 +2009,64 @@ resolve_expression (expressionS *expressionP)
|| op == O_lt || op == O_le || op == O_ge || op == O_gt)
&& seg_left == seg_right
&& (finalize_syms || frag_left == frag_right)
- && ((seg_left != undefined_section
- && seg_left != reg_section)
- || add_symbol == op_symbol)))
- return 0;
+ && (seg_left != reg_section || left == right)
+ && (seg_left != undefined_section || add_symbol == op_symbol)))
+ {
+ if ((seg_left == absolute_section && left == 0)
+ || (seg_right == absolute_section && right == 0))
+ {
+ if (op == O_bit_exclusive_or || op == O_bit_inclusive_or)
+ {
+ if (seg_right != absolute_section || right != 0)
+ {
+ seg_left = seg_right;
+ left = right;
+ add_symbol = op_symbol;
+ }
+ op = O_symbol;
+ break;
+ }
+ else if (op == O_left_shift || op == O_right_shift)
+ {
+ if (seg_left != absolute_section || left != 0)
+ {
+ op = O_symbol;
+ break;
+ }
+ }
+ else if (op != O_multiply
+ && op != O_bit_or_not && op != O_bit_and)
+ return 0;
+ }
+ else if (op == O_multiply
+ && seg_left == absolute_section && left == 1)
+ {
+ seg_left = seg_right;
+ left = right;
+ add_symbol = op_symbol;
+ op = O_symbol;
+ break;
+ }
+ else if ((op == O_multiply || op == O_divide)
+ && seg_right == absolute_section && right == 1)
+ {
+ op = O_symbol;
+ break;
+ }
+ else if (left != right
+ || ((seg_left != reg_section || seg_right != reg_section)
+ && (seg_left != undefined_section
+ || seg_right != undefined_section
+ || add_symbol != op_symbol)))
+ return 0;
+ else if (op == O_bit_and || op == O_bit_inclusive_or)
+ {
+ op = O_symbol;
+ break;
+ }
+ else if (op != O_bit_exclusive_or && op != O_bit_or_not)
+ return 0;
+ }
switch (op)
{
@@ -2032,8 +2094,7 @@ resolve_expression (expressionS *expressionP)
left = (left == right
&& seg_left == seg_right
&& (finalize_syms || frag_left == frag_right)
- && ((seg_left != undefined_section
- && seg_left != reg_section)
+ && (seg_left != undefined_section
|| add_symbol == op_symbol)
? ~ (valueT) 0 : 0);
if (op == O_ne)
@@ -2066,6 +2127,9 @@ resolve_expression (expressionS *expressionP)
op = O_constant;
else if (seg_left == reg_section && final_val == 0)
op = O_register;
+ else if (add_symbol != expressionP->X_add_symbol)
+ final_val += left;
+ expressionP->X_add_symbol = add_symbol;
}
expressionP->X_op = op;