aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-mn10300.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2007-10-30 15:18:29 +0000
committerNick Clifton <nickc@redhat.com>2007-10-30 15:18:29 +0000
commit569006e5824adcb39d114e815712b7aa3f5e136c (patch)
tree327248411133c3dd62a95c7ff69c33935c168e0f /gas/config/tc-mn10300.c
parent4e188d170a4a1c89ab9969c638a0bf5490d27984 (diff)
downloadgdb-569006e5824adcb39d114e815712b7aa3f5e136c.zip
gdb-569006e5824adcb39d114e815712b7aa3f5e136c.tar.gz
gdb-569006e5824adcb39d114e815712b7aa3f5e136c.tar.bz2
* mn10300.h (R_MN10300_ALIGN): Define.
* reloc.c (BFD_RELOC_MN10300_ALIGN): Add. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. * elf-m10300.h: Handle R_MN10300_ALIGN relocs. * mn10300_elf_relax_delete_bytes): Honour R_MN10300_ALIGN relocs. Re-fix off by one error in comparisons. * config/tc-mn10300.c (tc_gen_reloc): Fix test that decides when sym_diff relocs should be generated. (md_apply_fix): Skip R_MN10300_ALIGN relocs. (mn10300_fix_adjustable): Do not adjust R_MN10300_ALIGN relocs. (mn10300_handle_align): New function. Generate R_MN10300_ALIGN relocs to record alignment requests. * config/tc-mn10300.h (TC_FORCE_RELOCATION_SUB_SAME): Also force R_MN10300_ALIGN relocs. (HANDLE_ALIGN): Define. Call mn10300_handle_align. * gas/all/gas.exp: Do not run diff1.s test for mn10300. * ld-mn10300/mn10300.exp: Run new tests. Skip i126256 test if a compiler is not available. * ld-mn10300/i112045-3.s: New test. * ld-mn10300/i112045-3.d: Expected disassembly. * ld-mn10300/i135409.s: Rename to i135409-1.s. * ld-mn10300/i135409.d: Rename to i135409-1.d * ld-mn10300/i135409-2.s: New test. * ld-mn10300/i135409-2.d: Expected symbol table. * ld-mn10300/i36434.d: Adjust expected disassembly.
Diffstat (limited to 'gas/config/tc-mn10300.c')
-rw-r--r--gas/config/tc-mn10300.c58
1 files changed, 43 insertions, 15 deletions
diff --git a/gas/config/tc-mn10300.c b/gas/config/tc-mn10300.c
index 5ec58bb..e16a764 100644
--- a/gas/config/tc-mn10300.c
+++ b/gas/config/tc-mn10300.c
@@ -2181,13 +2181,18 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
if (fixp->fx_addsy && fixp->fx_subsy)
{
+ asection *asec, *ssec;
+
+ asec = S_GET_SEGMENT (fixp->fx_addsy);
+ ssec = S_GET_SEGMENT (fixp->fx_subsy);
+
reloc->sym_ptr_ptr = NULL;
/* If we have a difference between two (non-absolute) symbols we must
generate two relocs (one for each symbol) and allow the linker to
resolve them - relaxation may change the distances between symbols,
- even local symbols defined in the same segment. */
- if (S_GET_SEGMENT (fixp->fx_subsy) == seg)
+ even local symbols defined in the same section. */
+ if (ssec != absolute_section || asec != absolute_section)
{
arelent * reloc2 = xmalloc (sizeof * reloc);
@@ -2201,7 +2206,7 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
*reloc2->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
reloc->addend = fixp->fx_offset;
- if (S_GET_SEGMENT (fixp->fx_addsy) == absolute_section)
+ if (asec == absolute_section)
reloc->addend += S_GET_VALUE (fixp->fx_addsy);
reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
@@ -2211,13 +2216,6 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
fixp->fx_done = 1;
return relocs;
}
-
- if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy))
- || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section)
- {
- as_bad_where (fixp->fx_file, fixp->fx_line,
- "Difference of symbols in different sections is not supported");
- }
else
{
char *fixpos = fixp->fx_where + fixp->fx_frag->fr_literal;
@@ -2248,12 +2246,12 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
= (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
return relocs;
}
- }
- if (reloc->sym_ptr_ptr)
- free (reloc->sym_ptr_ptr);
- free (reloc);
- return & no_relocs;
+ if (reloc->sym_ptr_ptr)
+ free (reloc->sym_ptr_ptr);
+ free (reloc);
+ return & no_relocs;
+ }
}
else
{
@@ -2357,6 +2355,10 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg)
fixP->fx_done = 0;
return;
+ case BFD_RELOC_MN10300_ALIGN:
+ fixP->fx_done = 1;
+ return;
+
case BFD_RELOC_NONE:
default:
as_bad_where (fixP->fx_file, fixP->fx_line,
@@ -2562,3 +2564,29 @@ mn10300_allow_local_subtract (expressionS * left, expressionS * right, segT sect
return result;
}
+
+/* When relaxing, we need to output a reloc for any .align directive
+ that requests alignment to a two byte boundary or larger. */
+
+void
+mn10300_handle_align (fragS *frag)
+{
+ if (! linkrelax)
+ return;
+
+ if ((frag->fr_type == rs_align
+ || frag->fr_type == rs_align_code)
+ && frag->fr_address + frag->fr_fix > 0
+ && frag->fr_offset > 1
+ && now_seg != bss_section
+ /* Do not create relocs for the merging sections - such
+ relocs will prevent the contents from being merged. */
+ && (bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE) == 0)
+ /* Create a new fixup to record the alignment request. The symbol is
+ irrelevent but must be present so we use the absolute section symbol.
+ The offset from the symbol is used to record the power-of-two alignment
+ value. The size is set to 0 because the frag may already be aligned,
+ thus causing cvt_frag_to_fill to reduce the size of the frag to zero. */
+ fix_new (frag, frag->fr_fix, 0, & abs_symbol, frag->fr_offset, FALSE,
+ BFD_RELOC_MN10300_ALIGN);
+}