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.
This commit is contained in:
parent
bb3af66b41
commit
9963077898
@ -1,3 +1,11 @@
|
||||
2006-04-04 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
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.
|
||||
|
||||
2006-04-03 Sterling Augustine <sterling@tensilica.com>
|
||||
|
||||
* config/tc-xtensa.c (init_op_placement_info_table): Check for formats
|
||||
|
18
gas/expr.c
18
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;
|
||||
|
54
gas/frags.c
54
gas/frags.c
@ -1,6 +1,6 @@
|
||||
/* frags.c - manage frags -
|
||||
Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001, 2003, 2004
|
||||
1999, 2000, 2001, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GAS, the GNU Assembler.
|
||||
@ -383,3 +383,55 @@ frag_append_1_char (int datum)
|
||||
}
|
||||
obstack_1grow (&frchain_now->frch_obstack, datum);
|
||||
}
|
||||
|
||||
/* Return TRUE if FRAG1 and FRAG2 have a fixed relationship between
|
||||
their start addresses. Set OFFSET to the difference in address
|
||||
not already accounted for in the frag FR_ADDRESS. */
|
||||
|
||||
bfd_boolean
|
||||
frag_offset_fixed_p (fragS *frag1, fragS *frag2, bfd_vma *offset)
|
||||
{
|
||||
fragS *frag;
|
||||
bfd_vma off;
|
||||
|
||||
/* Start with offset initialised to difference between the two frags.
|
||||
Prior to assigning frag addresses this will be zero. */
|
||||
off = frag1->fr_address - frag2->fr_address;
|
||||
if (frag1 == frag2)
|
||||
{
|
||||
*offset = off;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Maybe frag2 is after frag1. */
|
||||
frag = frag1;
|
||||
while (frag->fr_type == rs_fill)
|
||||
{
|
||||
off += frag->fr_fix + frag->fr_offset * frag->fr_var;
|
||||
frag = frag->fr_next;
|
||||
if (frag == NULL)
|
||||
break;
|
||||
if (frag == frag2)
|
||||
{
|
||||
*offset = off;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Maybe frag1 is after frag2. */
|
||||
frag = frag2;
|
||||
while (frag->fr_type == rs_fill)
|
||||
{
|
||||
off -= frag->fr_fix + frag->fr_offset * frag->fr_var;
|
||||
frag = frag->fr_next;
|
||||
if (frag == NULL)
|
||||
break;
|
||||
if (frag == frag1)
|
||||
{
|
||||
*offset = off;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* frags.h - Header file for the frag concept.
|
||||
Copyright 1987, 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GAS, the GNU Assembler.
|
||||
|
||||
@ -148,4 +148,6 @@ char *frag_var (relax_stateT type,
|
||||
offsetT offset,
|
||||
char *opcode);
|
||||
|
||||
bfd_boolean frag_offset_fixed_p (fragS *, fragS *, bfd_vma *);
|
||||
|
||||
#endif /* FRAGS_H */
|
||||
|
Loading…
Reference in New Issue
Block a user