* config/tc-sparc.c (tc_gen_reloc): Add a gruesome hack to get

cross section PC relative relocs right for COFF and ELF.
This commit is contained in:
Ian Lance Taylor 1994-03-31 21:54:06 +00:00
parent f8ee1ebba0
commit 7ab2e983d6
2 changed files with 72 additions and 21 deletions

View File

@ -1,3 +1,8 @@
Thu Mar 31 16:51:16 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
* config/tc-sparc.c (tc_gen_reloc): Add a gruesome hack to get
cross section PC relative relocs right for COFF and ELF.
Mon Mar 28 14:38:23 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
* config/obj-coff.h (SEPARATE_STAB_SECTIONS): Always define.

View File

@ -23,6 +23,7 @@
#include <ctype.h>
#include "as.h"
#include "subsegs.h"
/* careful, this file includes data *declarations* */
#include "opcode/sparc.h"
@ -124,6 +125,19 @@ struct sparc_it
struct sparc_it the_insn, set_insn;
static INLINE int
in_signed_range (val, max)
bfd_signed_vma val, max;
{
if (max <= 0)
abort ();
if (val > max)
return 0;
if (val < ~max)
return 0;
return 1;
}
#if 0
static void print_insn PARAMS ((struct sparc_it *insn));
#endif
@ -1377,8 +1391,7 @@ sparc_ip (str)
goto immediate;
case 'i': /* 13 bit immediate */
/* What's the difference between base13 and 13? */
the_insn.reloc = BFD_RELOC_SPARC_BASE13;
the_insn.reloc = BFD_RELOC_SPARC13;
immediate_max = 0x0FFF;
/*FALLTHROUGH */
@ -1464,6 +1477,10 @@ sparc_ip (str)
{
/* start-sanitize-v9 */
#ifndef NO_V9
/* Handle %uhi/%ulo by moving the upper word to the lower
one and pretending it's %hi/%lo. We also need to watch
for %hi/%lo: the top word needs to be zeroed otherwise
fixup_segment will complain the value is too big. */
switch (the_insn.reloc)
{
case BFD_RELOC_SPARC_HH22:
@ -1476,19 +1493,47 @@ sparc_ip (str)
break;
default:
break;
case BFD_RELOC_HI22:
case BFD_RELOC_LO10:
the_insn.exp.X_add_number &= 0xffffffff;
break;
}
#endif
/* end-sanitize-v9 */
/* For pc-relative call instructions, we reject
constants to get better code. */
if (the_insn.pcrel
&& the_insn.reloc == BFD_RELOC_32_PCREL_S2
&& in_signed_range (the_insn.exp.X_add_number, 0x3fff)
)
{
error_message = ": PC-relative operand can't be a constant";
goto error;
}
/* Check for invalid constant values. Don't warn if
constant was inside %hi or %lo, since these
truncate the constant to fit. */
if (immediate_max != 0
&& the_insn.reloc != BFD_RELOC_LO10
&& the_insn.reloc != BFD_RELOC_HI22
&& (the_insn.exp.X_add_number > immediate_max
|| the_insn.exp.X_add_number < ~immediate_max))
as_bad ("constant value must be between %ld and %ld",
~immediate_max, immediate_max);
&& !in_signed_range (the_insn.exp.X_add_number,
immediate_max)
)
{
if (the_insn.pcrel)
/* Who knows? After relocation, we may be within
range. Let the linker figure it out. */
{
the_insn.exp.X_op = O_symbol;
the_insn.exp.X_add_symbol = section_symbol (absolute_section);
}
else
/* Immediate value is non-pcrel, and out of
range. */
as_bad ("constant value %ld out of range (%ld .. %ld)",
the_insn.exp.X_add_number,
~immediate_max, immediate_max);
}
}
/* Reset to prevent extraneous range check. */
@ -1974,15 +2019,6 @@ md_apply_fix (fixP, value)
buf[3] = val & 0xff;
break;
case BFD_RELOC_SPARC13:
if (val & ~0x00001fff)
{
as_bad ("relocation overflow");
} /* on overflow */
buf[2] |= (val >> 8) & 0x1f;
buf[3] = val & 0xff;
break;
/* start-sanitize-v9 */
#ifndef NO_V9
case BFD_RELOC_SPARC_HM10:
@ -2000,12 +2036,11 @@ md_apply_fix (fixP, value)
else
buf[3] = 0;
break;
case BFD_RELOC_SPARC_BASE13:
if (((val > 0) && (val & ~(offsetT)0x00001fff))
|| ((val < 0) && (~(val - 1) & ~(offsetT)0x00001fff)))
{
as_bad ("relocation overflow");
}
case BFD_RELOC_SPARC13:
if (! in_signed_range (val, 0x1fff))
as_bad ("relocation overflow");
buf[2] |= (val >> 8) & 0x1f;
buf[3] = val;
break;
@ -2025,6 +2060,10 @@ md_apply_fix (fixP, value)
break;
}
/* Are we finished with this relocation now? */
if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
fixP->fx_done = 1;
return 1;
}
@ -2051,6 +2090,7 @@ tc_gen_reloc (section, fixp)
case BFD_RELOC_HI22:
case BFD_RELOC_LO10:
case BFD_RELOC_32_PCREL_S2:
case BFD_RELOC_SPARC13:
case BFD_RELOC_SPARC_BASE13:
case BFD_RELOC_SPARC_WDISP22:
/* start-sanitize-v9 */
@ -2076,6 +2116,12 @@ tc_gen_reloc (section, fixp)
/* @@ Why fx_addnumber sometimes and fx_offset other times? */
if (reloc->howto->pc_relative == 0)
reloc->addend = fixp->fx_addnumber;
#if defined (OBJ_ELF) || defined (OBJ_COFF)
else if ((fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
reloc->addend = (section->vma
+ fixp->fx_addnumber
+ md_pcrel_from (fixp));
#endif
else
reloc->addend = fixp->fx_offset - reloc->address;