diff options
author | Nick Clifton <nickc@redhat.com> | 2004-07-27 11:37:12 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2004-07-27 11:37:12 +0000 |
commit | 670ec21de99faddc3a86f9e18fb9ef1a093b3dbf (patch) | |
tree | d809163639cab84dd83ef7b8229321767c541388 /gas | |
parent | 575eebb19f60c85a0e4973dfa9e2f8b1a197005a (diff) | |
download | fsf-binutils-gdb-670ec21de99faddc3a86f9e18fb9ef1a093b3dbf.zip fsf-binutils-gdb-670ec21de99faddc3a86f9e18fb9ef1a093b3dbf.tar.gz fsf-binutils-gdb-670ec21de99faddc3a86f9e18fb9ef1a093b3dbf.tar.bz2 |
Add CRX insns: pushx, popx
Add support to GAS for expressions which are the difference of two symbols
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 8 | ||||
-rw-r--r-- | gas/config/obj-coff.c | 2 | ||||
-rw-r--r-- | gas/config/tc-crx.c | 73 | ||||
-rw-r--r-- | gas/config/tc-crx.h | 8 | ||||
-rw-r--r-- | gas/config/tc-ppc.c | 9 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/all/gas.exp | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/macros/strings.s | 1 |
8 files changed, 89 insertions, 19 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 70bf40c..7fa3398 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,4 +1,10 @@ -2004-07-26 H.J. Lu <hongjiu.lu@intel.com> +2004-07-27 Tomer Levi <Tomer.Levi@nsc.com> + + * config/tc-crx.c: Support evaluating the difference between two + symbols. + * config/tc-crx.h: Likewise. + + 2004-07-26 H.J. Lu <hongjiu.lu@intel.com> * config/tc-ia64.c (start_unwind_section): Set the linked-to section. diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c index ee37b08..1451d9d 100644 --- a/gas/config/obj-coff.c +++ b/gas/config/obj-coff.c @@ -1327,7 +1327,7 @@ coff_frob_symbol (symp, punt) order to call SA_SET_SYM_ENDNDX correctly. */ if (! symbol_used_in_reloc_p (symp) && ((symbol_get_bfdsym (symp)->flags & BSF_SECTION_SYM) != 0 - || (! S_IS_EXTERNAL (symp) + || (! (S_IS_EXTERNAL (symp) || S_IS_WEAK (symp)) && ! symbol_get_tc (symp)->output && S_GET_STORAGE_CLASS (symp) != C_FILE))) *punt = 1; diff --git a/gas/config/tc-crx.c b/gas/config/tc-crx.c index 3b3c49e..3062118 100644 --- a/gas/config/tc-crx.c +++ b/gas/config/tc-crx.c @@ -292,6 +292,34 @@ reset_vars (char *op, ins *crx_ins) strcpy (ins_parse, op); } +/* This macro decides whether a particular reloc is an entry in a + switch table. It is used when relaxing, because the linker needs + to know about all such entries so that it can adjust them if + necessary. */ + +#define SWITCH_TABLE(fix) \ + ( (fix)->fx_addsy != NULL \ + && (fix)->fx_subsy != NULL \ + && S_GET_SEGMENT ((fix)->fx_addsy) == \ + S_GET_SEGMENT ((fix)->fx_subsy) \ + && S_GET_SEGMENT (fix->fx_addsy) != undefined_section \ + && ( (fix)->fx_r_type == BFD_RELOC_CRX_NUM8 \ + || (fix)->fx_r_type == BFD_RELOC_CRX_NUM16 \ + || (fix)->fx_r_type == BFD_RELOC_CRX_NUM32)) + +/* See whether we need to force a relocation into the output file. + This is used to force out switch and PC relative relocations when + relaxing. */ + +int +crx_force_relocation (fixS *fix) +{ + if (generic_force_reloc (fix) || SWITCH_TABLE (fix)) + return 1; + + return 0; +} + /* Generate a relocation entry for a fixup. */ arelent * @@ -306,15 +334,42 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS * fixP) reloc->addend = fixP->fx_offset; if (fixP->fx_subsy != NULL) - /* We don't resolve difference expressions. */ - as_bad_where (fixP->fx_file, fixP->fx_line, - _("can't resolve `%s' {%s section} - `%s' {%s section}"), - fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0", - segment_name (fixP->fx_addsy - ? S_GET_SEGMENT (fixP->fx_addsy) - : absolute_section), - S_GET_NAME (fixP->fx_subsy), - segment_name (S_GET_SEGMENT (fixP->fx_addsy))); + { + if (SWITCH_TABLE (fixP)) + { + /* Keep the current difference in the addend. */ + reloc->addend = (S_GET_VALUE (fixP->fx_addsy) + - S_GET_VALUE (fixP->fx_subsy) + fixP->fx_offset); + + switch (fixP->fx_r_type) + { + case BFD_RELOC_CRX_NUM8: + fixP->fx_r_type = BFD_RELOC_CRX_SWITCH8; + break; + case BFD_RELOC_CRX_NUM16: + fixP->fx_r_type = BFD_RELOC_CRX_SWITCH16; + break; + case BFD_RELOC_CRX_NUM32: + fixP->fx_r_type = BFD_RELOC_CRX_SWITCH32; + break; + default: + abort (); + break; + } + } + else + { + /* We only resolve difference expressions in the same section. */ + as_bad_where (fixP->fx_file, fixP->fx_line, + _("can't resolve `%s' {%s section} - `%s' {%s section}"), + fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0", + segment_name (fixP->fx_addsy + ? S_GET_SEGMENT (fixP->fx_addsy) + : absolute_section), + S_GET_NAME (fixP->fx_subsy), + segment_name (S_GET_SEGMENT (fixP->fx_addsy))); + } + } assert ((int) fixP->fx_r_type > 0); reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type); diff --git a/gas/config/tc-crx.h b/gas/config/tc-crx.h index dc26a70..29e59fe 100644 --- a/gas/config/tc-crx.h +++ b/gas/config/tc-crx.h @@ -48,6 +48,10 @@ extern const struct relax_type md_relax_table[]; linker relaxations easier. */ #define tc_fix_adjustable(fixP) 0 +/* We need to force out some relocations when relaxing. */ +#define TC_FORCE_RELOCATION(FIXP) crx_force_relocation (FIXP) +extern int crx_force_relocation (struct fix *); + /* Fixup debug sections since we will never relax them. */ #define TC_LINKRELAX_FIXUP(seg) (seg->flags & SEC_ALLOC) @@ -58,8 +62,8 @@ extern const struct relax_type md_relax_table[]; /* This is called by emit_expr when creating a reloc for a cons. We could use the definition there, except that we want to handle the CRX reloc type specially, rather than the BFD_RELOC type. */ -#define TC_CONS_FIX_NEW(FRAG,OFF,LEN,EXP) \ - fix_new_exp (FRAG, OFF, (int)LEN, EXP, 0, \ +#define TC_CONS_FIX_NEW(FRAG, OFF, LEN, EXP) \ + fix_new_exp (FRAG, OFF, (int) LEN, EXP, 0, \ LEN == 1 ? BFD_RELOC_CRX_NUM8 \ : LEN == 2 ? BFD_RELOC_CRX_NUM16 \ : LEN == 4 ? BFD_RELOC_CRX_NUM32 \ diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index d4893e7..7bc7011 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -1918,9 +1918,8 @@ ppc_frob_file_before_adjust () free (dotname); if (dotsym != NULL && (symbol_used_p (dotsym) || symbol_used_in_reloc_p (dotsym))) - { - symbol_mark_used (symp); - } + symbol_mark_used (symp); + } /* Don't emit .TOC. symbol. */ @@ -4843,7 +4842,7 @@ ppc_frob_symbol (sym) table. */ if (! symbol_used_in_reloc_p (sym) && ((symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) != 0 - || (! S_IS_EXTERNAL (sym) + || (! (S_IS_EXTERNAL (sym) || S_IS_WEAK (sym)) && ! symbol_get_tc (sym)->output && S_GET_STORAGE_CLASS (sym) != C_FILE))) return 1; @@ -4909,7 +4908,7 @@ ppc_frob_symbol (sym) } } - if (! S_IS_EXTERNAL (sym) + if (! (S_IS_EXTERNAL (sym) || S_IS_WEAK (sym)) && (symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) == 0 && S_GET_STORAGE_CLASS (sym) != C_FILE && S_GET_STORAGE_CLASS (sym) != C_FCN diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 77428e4..13815bb 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-07-27 Tomer Levi <Tomer.Levi@nsc.com> + + * gas/all/gas.exp (do_930509a): Disable test for crx. + 2004-07-22 H.J. Lu <hongjiu.lu@intel.com> * gas/i386/x86-64-inval.l: Remove the leading `+'. diff --git a/gas/testsuite/gas/all/gas.exp b/gas/testsuite/gas/all/gas.exp index 31cfa4e..df8d71d 100644 --- a/gas/testsuite/gas/all/gas.exp +++ b/gas/testsuite/gas/all/gas.exp @@ -85,12 +85,13 @@ proc do_930509a {} { if !$x then { fail $testname } } -# This test is meaningless for the PA; the difference of two symbols +# This test is meaningless for the PA and CRX; the difference of two symbols # must not be resolved by the assembler. # C54x assembler (for compatibility) does not allow differences between # forward references # C30 counts a four byte offset as a difference of one. if { ![istarget hppa*-*-*] && + ![istarget crx*-*-*] && ![istarget *c30*-*-*] && ![istarget *c4x*-*-*] && ![istarget *c54x*-*-*] } then { diff --git a/gas/testsuite/gas/macros/strings.s b/gas/testsuite/gas/macros/strings.s index 291a0dc..9e98c85 100644 --- a/gas/testsuite/gas/macros/strings.s +++ b/gas/testsuite/gas/macros/strings.s @@ -1,3 +1,4 @@ +#NO_APP .macro M arg1 .ascii "\arg1" .endm |