@ -1,5 +1,6 @@
/* ehopt.c--optimize gcc exception frame information.
Copyright 1998 , 2000 , 2001 , 2003 , 2005 , 2007 Free Software Foundation , Inc .
Copyright 1998 , 2000 , 2001 , 2003 , 2005 , 2007 , 2008
Free Software Foundation , Inc .
Written by Ian Lance Taylor < ian @ cygnus . com > .
This file is part of GAS , the GNU Assembler .
@ -21,6 +22,7 @@
# include "as.h"
# include "subsegs.h"
# include "struc-symbol.h"
/* We include this ELF file, even though we may not be assembling for
ELF , since the exception frame information is always in a format
@ -398,13 +400,10 @@ check_eh_frame (expressionS *exp, unsigned int *pnbytes)
subtracted were in the same frag and the expression was
reduced to a constant . We can do the optimization entirely
in this function . */
if ( d - > cie_info . code_alignment > 0
& & exp - > X_add_number % d - > cie_info . code_alignment = = 0
& & exp - > X_add_number / d - > cie_info . code_alignment < 0x40 )
if ( exp - > X_add_number < 0x40 )
{
d - > loc4_frag - > fr_literal [ d - > loc4_fix ]
= DW_CFA_advance_loc
| ( exp - > X_add_number / d - > cie_info . code_alignment ) ;
= DW_CFA_advance_loc | exp - > X_add_number ;
/* No more bytes needed. */
return 1 ;
}
@ -419,23 +418,39 @@ check_eh_frame (expressionS *exp, unsigned int *pnbytes)
* pnbytes = 2 ;
}
}
else if ( exp - > X_op = = O_subtract )
else if ( exp - > X_op = = O_subtract & & d - > cie_info . code_alignment = = 1 )
{
/* This is a case we can optimize. The expression was not
reduced , so we can not finish the optimization until the end
of the assembly . We set up a variant frag which we handle
later . */
int fr_subtype ;
if ( d - > cie_info . code_alignment > 0 )
fr_subtype = d - > cie_info . code_alignment < < 3 ;
else
fr_subtype = 0 ;
frag_var ( rs_cfa , 4 , 0 , fr_subtype , make_expr_symbol ( exp ) ,
frag_var ( rs_cfa , 4 , 0 , 1 < < 3 , make_expr_symbol ( exp ) ,
d - > loc4_fix , ( char * ) d - > loc4_frag ) ;
return 1 ;
}
else if ( ( exp - > X_op = = O_divide
| | exp - > X_op = = O_right_shift )
& & d - > cie_info . code_alignment > 1 )
{
if ( exp - > X_add_symbol - > bsym
& & exp - > X_op_symbol - > bsym
& & exp - > X_add_symbol - > sy_value . X_op = = O_subtract
& & exp - > X_op_symbol - > sy_value . X_op = = O_constant
& & ( ( exp - > X_op = = O_divide
? exp - > X_op_symbol - > sy_value . X_add_number
: ( offsetT ) 1 < < exp - > X_op_symbol - > sy_value . X_add_number )
= = ( offsetT ) d - > cie_info . code_alignment ) )
{
/* This is a case we can optimize as well. The expression was
not reduced , so we can not finish the optimization until the
end of the assembly . We set up a variant frag which we
handle later . */
frag_var ( rs_cfa , 4 , 0 , d - > cie_info . code_alignment < < 3 ,
make_expr_symbol ( & exp - > X_add_symbol - > sy_value ) ,
d - > loc4_fix , ( char * ) d - > loc4_frag ) ;
return 1 ;
}
}
break ;
case state_error :
@ -459,7 +474,9 @@ eh_frame_estimate_size_before_relax (fragS *frag)
diff = resolve_symbol_value ( frag - > fr_symbol ) ;
if ( ca > 0 & & diff % ca = = 0 & & diff / ca < 0x40 )
assert ( ca > 0 ) ;
diff / = ca ;
if ( diff < 0x40 )
ret = 0 ;
else if ( diff < 0x100 )
ret = 1 ;
@ -496,21 +513,21 @@ eh_frame_convert_frag (fragS *frag)
{
offsetT diff ;
fragS * loc4_frag ;
int loc4_fix ;
int loc4_fix , ca ;
loc4_frag = ( fragS * ) frag - > fr_opcode ;
loc4_fix = ( int ) frag - > fr_offset ;
diff = resolve_symbol_value ( frag - > fr_symbol ) ;
ca = frag - > fr_subtype > > 3 ;
assert ( ca > 0 ) ;
diff / = ca ;
switch ( frag - > fr_subtype & 7 )
{
case 0 :
{
int ca = frag - > fr_subtype > > 3 ;
assert ( ca > 0 & & diff % ca = = 0 & & diff / ca < 0x40 ) ;
loc4_frag - > fr_literal [ loc4_fix ] = DW_CFA_advance_loc | ( diff / ca ) ;
}
assert ( diff < 0x40 ) ;
loc4_frag - > fr_literal [ loc4_fix ] = DW_CFA_advance_loc | diff ;
break ;
case 1 :