diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 17 | ||||
-rw-r--r-- | gas/Makefile.am | 3 | ||||
-rw-r--r-- | gas/Makefile.in | 3 | ||||
-rw-r--r-- | gas/dw2gencfi.c | 12 | ||||
-rw-r--r-- | gas/ehopt.c | 61 |
5 files changed, 66 insertions, 30 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index a3b9384..8874fe6 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,20 @@ +2008-11-28 Jakub Jelinek <jakub@redhat.com> + + * Makefile.am (ehopt.o): Add struc-symbol.h. + * Makefile.in: Regenerated. + * ehopt.c: Include struc-symbol.h. + (check_eh_frame): For very small O_constant DW_CFA_advance_loc4 + create correct DW_CFA_advance_loc. Handle O_subtract only + for code alignment factor 1, otherwise handle O_divide or + O_right_shift of O_subtract and O_constant. + (eh_frame_estimate_size_before_relax): Always divide by ca. + (eh_frame_convert_frag): Likewise. + +2008-11-28 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> + + * dw2gencfi.c (output_cfi_insn): Scale DW_CFA_advance_loc1, + DW_CFA_advance_loc2 and DW_CFA_advance_loc4 outputs. + 2008-11-28 Joshua Kinard <kumba@gentoo.org> * config/tc-mips.c (hilo_interlocks): Handle CPU_R14000, CPU_R16000. diff --git a/gas/Makefile.am b/gas/Makefile.am index 38fe255..260c211 100644 --- a/gas/Makefile.am +++ b/gas/Makefile.am @@ -2159,7 +2159,8 @@ dwarf2dbg.o: dwarf2dbg.c $(INCDIR)/safe-ctype.h dwarf2dbg.h \ dw2gencfi.o: dw2gencfi.c dw2gencfi.h $(INCDIR)/elf/dwarf2.h \ subsegs.h $(INCDIR)/obstack.h ecoff.o: ecoff.c ecoff.h -ehopt.o: ehopt.c subsegs.h $(INCDIR)/obstack.h $(INCDIR)/elf/dwarf2.h +ehopt.o: ehopt.c subsegs.h $(INCDIR)/obstack.h $(INCDIR)/elf/dwarf2.h \ + struc-symbol.h expr.o: expr.c $(INCDIR)/safe-ctype.h $(INCDIR)/obstack.h flonum-copy.o: flonum-copy.c flonum-konst.o: flonum-konst.c diff --git a/gas/Makefile.in b/gas/Makefile.in index 5735a0a..c0f932a 100644 --- a/gas/Makefile.in +++ b/gas/Makefile.in @@ -3015,7 +3015,8 @@ dwarf2dbg.o: dwarf2dbg.c $(INCDIR)/safe-ctype.h dwarf2dbg.h \ dw2gencfi.o: dw2gencfi.c dw2gencfi.h $(INCDIR)/elf/dwarf2.h \ subsegs.h $(INCDIR)/obstack.h ecoff.o: ecoff.c ecoff.h -ehopt.o: ehopt.c subsegs.h $(INCDIR)/obstack.h $(INCDIR)/elf/dwarf2.h +ehopt.o: ehopt.c subsegs.h $(INCDIR)/obstack.h $(INCDIR)/elf/dwarf2.h \ + struc-symbol.h expr.o: expr.c $(INCDIR)/safe-ctype.h $(INCDIR)/obstack.h flonum-copy.o: flonum-copy.c flonum-konst.o: flonum-konst.c diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c index 4adfeab..a9b58d4 100644 --- a/gas/dw2gencfi.c +++ b/gas/dw2gencfi.c @@ -1,5 +1,5 @@ /* dw2gencfi.c - Support for generating Dwarf2 CFI information. - Copyright 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. Contributed by Michal Ludvig <mludvig@suse.cz> This file is part of GAS, the GNU Assembler. @@ -972,20 +972,20 @@ output_cfi_insn (struct cfi_insn_data *insn) if (scaled <= 0x3F) out_one (DW_CFA_advance_loc + scaled); - else if (delta <= 0xFF) + else if (scaled <= 0xFF) { out_one (DW_CFA_advance_loc1); - out_one (delta); + out_one (scaled); } - else if (delta <= 0xFFFF) + else if (scaled <= 0xFFFF) { out_one (DW_CFA_advance_loc2); - out_two (delta); + out_two (scaled); } else { out_one (DW_CFA_advance_loc4); - out_four (delta); + out_four (scaled); } } else diff --git a/gas/ehopt.c b/gas/ehopt.c index 048bc57..323e27e 100644 --- a/gas/ehopt.c +++ b/gas/ehopt.c @@ -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: |