* 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:
parent
f8ee1ebba0
commit
7ab2e983d6
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user