diff options
author | Kaz Kojima <kkojima@rr.iij4u.or.jp> | 2007-04-14 14:21:11 +0000 |
---|---|---|
committer | Kaz Kojima <kkojima@rr.iij4u.or.jp> | 2007-04-14 14:21:11 +0000 |
commit | 0cc3409506a056370ab1f7d00c1d1e82f7e67644 (patch) | |
tree | 081a67dd9bc7bd47fa3e9a7a27f2a553fc0ac7c6 /gas | |
parent | 3fcd97f16cb46d4c493e892f85a188969e0a95e7 (diff) | |
download | gdb-0cc3409506a056370ab1f7d00c1d1e82f7e67644.zip gdb-0cc3409506a056370ab1f7d00c1d1e82f7e67644.tar.gz gdb-0cc3409506a056370ab1f7d00c1d1e82f7e67644.tar.bz2 |
* config/tc-sh.c (align_test_frag_offset_fixed_p): New.
(sh_optimize_expr): Likewise.
* config/tc-sh.h (md_optimize_expr): Define.
(sh_optimize_expr): Prototype.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 7 | ||||
-rw-r--r-- | gas/config/tc-sh.c | 83 | ||||
-rw-r--r-- | gas/config/tc-sh.h | 6 |
3 files changed, 96 insertions, 0 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 4c2e52c..d1293f3 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2007-04-14 Kaz Kojima <kkojima@rr.iij4u.or.jp> + + * config/tc-sh.c (align_test_frag_offset_fixed_p): New. + (sh_optimize_expr): Likewise. + * config/tc-sh.h (md_optimize_expr): Define. + (sh_optimize_expr): Prototype. + 2007-04-06 Matt Thomas <matt@netbsd.org> * config/tc-vax.c (vax_cons): Added to support %pcrel{8,16,32}(exp) diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c index 3d1ae79..6cb9c93 100644 --- a/gas/config/tc-sh.c +++ b/gas/config/tc-sh.c @@ -825,8 +825,91 @@ sh_elf_cons (register int nbytes) else demand_empty_rest_of_line (); } + +/* The regular frag_offset_fixed_p doesn't work for rs_align_test + frags. */ + +static bfd_boolean +align_test_frag_offset_fixed_p (const fragS *frag1, const fragS *frag2, + bfd_vma *offset) +{ + const 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_align_test) + { + off += frag->fr_fix; + frag = frag->fr_next; + if (frag == NULL) + break; + if (frag == frag2) + { + *offset = off; + return TRUE; + } + } + + /* Maybe frag1 is after frag2. */ + off = frag1->fr_address - frag2->fr_address; + frag = frag2; + while (frag->fr_type == rs_align_test) + { + off -= frag->fr_fix; + frag = frag->fr_next; + if (frag == NULL) + break; + if (frag == frag1) + { + *offset = off; + return TRUE; + } + } + + return FALSE; +} #endif /* OBJ_ELF */ +/* Optimize a difference of symbols which have rs_align_test frag if + possible. */ + +int +sh_optimize_expr (expressionS *l, operatorT op, expressionS *r) +{ +#ifdef OBJ_ELF + bfd_vma frag_off; + + if (op == O_subtract + && l->X_op == O_symbol + && r->X_op == O_symbol + && S_GET_SEGMENT (l->X_add_symbol) == S_GET_SEGMENT (r->X_add_symbol) + && (SEG_NORMAL (S_GET_SEGMENT (l->X_add_symbol)) + || r->X_add_symbol == l->X_add_symbol) + && align_test_frag_offset_fixed_p (symbol_get_frag (l->X_add_symbol), + symbol_get_frag (r->X_add_symbol), + &frag_off)) + { + l->X_add_number -= r->X_add_number; + l->X_add_number -= frag_off / OCTETS_PER_BYTE; + l->X_add_number += (S_GET_VALUE (l->X_add_symbol) + - S_GET_VALUE (r->X_add_symbol)); + l->X_op = O_constant; + l->X_add_symbol = 0; + return 1; + } +#endif /* OBJ_ELF */ + return 0; +} /* This function is called once, at assembler startup time. This should set up all the tables, etc that the MD part of the assembler needs. */ diff --git a/gas/config/tc-sh.h b/gas/config/tc-sh.h index 0ad914e..b023b48 100644 --- a/gas/config/tc-sh.h +++ b/gas/config/tc-sh.h @@ -44,6 +44,12 @@ extern int sh_small; #define md_cons_align(nbytes) sh_cons_align (nbytes) extern void sh_cons_align (int); +/* We need to optimize expr with taking account of rs_align_test + frags. */ + +#define md_optimize_expr(l,o,r) sh_optimize_expr (l, o, r) +extern int sh_optimize_expr (expressionS *, operatorT, expressionS *); + /* When relaxing, we need to generate relocations for alignment directives. */ #define HANDLE_ALIGN(frag) sh_handle_align (frag) |