From 99630778988bcd5195fc056fbd013d32d1362d5a Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 4 Apr 2006 08:04:57 +0000 Subject: 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. --- gas/expr.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'gas/expr.c') diff --git a/gas/expr.c b/gas/expr.c index 3ae1bcc..69f0aac 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; -- cgit v1.1