summaryrefslogtreecommitdiff
path: root/gas/expr.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2006-04-04 08:04:57 +0000
committerAlan Modra <amodra@bigpond.net.au>2006-04-04 08:04:57 +0000
commit462cd0c4859dd0cce72fc61bff61ca6a4d8996e5 (patch)
treea05cc247361b309d6e77be564f5a2afd73632a10 /gas/expr.c
parent11ff6654d91a8ecee1517d690612dd41a04debc6 (diff)
downloadbinutils-redhat-462cd0c4859dd0cce72fc61bff61ca6a4d8996e5.tar.gz
PR 997
* frags.c (frag_offset_fixed_p): New function. * frags.h (frag_offset_fixed_p): Declare. * expr.c (expr): Use frag_offset_fixed_p when simplifying subtraction. (resolve_expression): Likewise.
Diffstat (limited to 'gas/expr.c')
-rw-r--r--gas/expr.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/gas/expr.c b/gas/expr.c
index 3ae1bcc581..69f0aaccdb 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
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -1662,6 +1662,7 @@ expr (int rankarg, /* Larger # is higher rank. */
while (op_left != O_illegal && op_rank[(int) op_left] > rank)
{
segT rightseg;
+ bfd_vma frag_off;
input_line_pointer += op_chars; /* -> after operator. */
@@ -1741,12 +1742,15 @@ expr (int rankarg, /* Larger # is higher rank. */
else if (op_left == O_subtract
&& right.X_op == O_symbol
&& resultP->X_op == O_symbol
- && (symbol_get_frag (right.X_add_symbol)
- == symbol_get_frag (resultP->X_add_symbol))
+ && retval == rightseg
&& (SEG_NORMAL (rightseg)
- || right.X_add_symbol == resultP->X_add_symbol))
+ || right.X_add_symbol == resultP->X_add_symbol)
+ && frag_offset_fixed_p (symbol_get_frag (resultP->X_add_symbol),
+ symbol_get_frag (right.X_add_symbol),
+ &frag_off))
{
resultP->X_add_number -= right.X_add_number;
+ resultP->X_add_number -= frag_off / OCTETS_PER_BYTE;
resultP->X_add_number += (S_GET_VALUE (resultP->X_add_symbol)
- S_GET_VALUE (right.X_add_symbol));
resultP->X_op = O_constant;
@@ -1900,6 +1904,7 @@ resolve_expression (expressionS *expressionP)
valueT left, right;
segT seg_left, seg_right;
fragS *frag_left, *frag_right;
+ bfd_vma frag_off;
switch (op)
{
@@ -2002,13 +2007,15 @@ resolve_expression (expressionS *expressionP)
on the input value.
Otherwise, both operands must be absolute. We already handled
the case of addition or subtraction of a constant above. */
+ frag_off = 0;
if (!(seg_left == absolute_section
&& seg_right == absolute_section)
&& !(op == O_eq || op == O_ne)
&& !((op == O_subtract
|| op == O_lt || op == O_le || op == O_ge || op == O_gt)
&& seg_left == seg_right
- && (finalize_syms || frag_left == frag_right)
+ && (finalize_syms
+ || frag_offset_fixed_p (frag_left, frag_right, &frag_off))
&& (seg_left != reg_section || left == right)
&& (seg_left != undefined_section || add_symbol == op_symbol)))
{
@@ -2068,6 +2075,7 @@ resolve_expression (expressionS *expressionP)
return 0;
}
+ right += frag_off / OCTETS_PER_BYTE;
switch (op)
{
case O_add: left += right; break;