* 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)
|
Mon Mar 28 14:38:23 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
|
||||||
|
|
||||||
* config/obj-coff.h (SEPARATE_STAB_SECTIONS): Always define.
|
* config/obj-coff.h (SEPARATE_STAB_SECTIONS): Always define.
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "as.h"
|
#include "as.h"
|
||||||
|
#include "subsegs.h"
|
||||||
|
|
||||||
/* careful, this file includes data *declarations* */
|
/* careful, this file includes data *declarations* */
|
||||||
#include "opcode/sparc.h"
|
#include "opcode/sparc.h"
|
||||||
@ -124,6 +125,19 @@ struct sparc_it
|
|||||||
|
|
||||||
struct sparc_it the_insn, set_insn;
|
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
|
#if 0
|
||||||
static void print_insn PARAMS ((struct sparc_it *insn));
|
static void print_insn PARAMS ((struct sparc_it *insn));
|
||||||
#endif
|
#endif
|
||||||
@ -1377,8 +1391,7 @@ sparc_ip (str)
|
|||||||
goto immediate;
|
goto immediate;
|
||||||
|
|
||||||
case 'i': /* 13 bit immediate */
|
case 'i': /* 13 bit immediate */
|
||||||
/* What's the difference between base13 and 13? */
|
the_insn.reloc = BFD_RELOC_SPARC13;
|
||||||
the_insn.reloc = BFD_RELOC_SPARC_BASE13;
|
|
||||||
immediate_max = 0x0FFF;
|
immediate_max = 0x0FFF;
|
||||||
|
|
||||||
/*FALLTHROUGH */
|
/*FALLTHROUGH */
|
||||||
@ -1464,6 +1477,10 @@ sparc_ip (str)
|
|||||||
{
|
{
|
||||||
/* start-sanitize-v9 */
|
/* start-sanitize-v9 */
|
||||||
#ifndef NO_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)
|
switch (the_insn.reloc)
|
||||||
{
|
{
|
||||||
case BFD_RELOC_SPARC_HH22:
|
case BFD_RELOC_SPARC_HH22:
|
||||||
@ -1476,19 +1493,47 @@ sparc_ip (str)
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
case BFD_RELOC_HI22:
|
||||||
|
case BFD_RELOC_LO10:
|
||||||
|
the_insn.exp.X_add_number &= 0xffffffff;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* end-sanitize-v9 */
|
/* 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
|
/* Check for invalid constant values. Don't warn if
|
||||||
constant was inside %hi or %lo, since these
|
constant was inside %hi or %lo, since these
|
||||||
truncate the constant to fit. */
|
truncate the constant to fit. */
|
||||||
if (immediate_max != 0
|
if (immediate_max != 0
|
||||||
&& the_insn.reloc != BFD_RELOC_LO10
|
&& the_insn.reloc != BFD_RELOC_LO10
|
||||||
&& the_insn.reloc != BFD_RELOC_HI22
|
&& the_insn.reloc != BFD_RELOC_HI22
|
||||||
&& (the_insn.exp.X_add_number > immediate_max
|
&& !in_signed_range (the_insn.exp.X_add_number,
|
||||||
|| the_insn.exp.X_add_number < ~immediate_max))
|
immediate_max)
|
||||||
as_bad ("constant value must be between %ld and %ld",
|
)
|
||||||
~immediate_max, 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. */
|
/* Reset to prevent extraneous range check. */
|
||||||
@ -1974,15 +2019,6 @@ md_apply_fix (fixP, value)
|
|||||||
buf[3] = val & 0xff;
|
buf[3] = val & 0xff;
|
||||||
break;
|
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 */
|
/* start-sanitize-v9 */
|
||||||
#ifndef NO_V9
|
#ifndef NO_V9
|
||||||
case BFD_RELOC_SPARC_HM10:
|
case BFD_RELOC_SPARC_HM10:
|
||||||
@ -2000,12 +2036,11 @@ md_apply_fix (fixP, value)
|
|||||||
else
|
else
|
||||||
buf[3] = 0;
|
buf[3] = 0;
|
||||||
break;
|
break;
|
||||||
case BFD_RELOC_SPARC_BASE13:
|
|
||||||
if (((val > 0) && (val & ~(offsetT)0x00001fff))
|
case BFD_RELOC_SPARC13:
|
||||||
|| ((val < 0) && (~(val - 1) & ~(offsetT)0x00001fff)))
|
if (! in_signed_range (val, 0x1fff))
|
||||||
{
|
as_bad ("relocation overflow");
|
||||||
as_bad ("relocation overflow");
|
|
||||||
}
|
|
||||||
buf[2] |= (val >> 8) & 0x1f;
|
buf[2] |= (val >> 8) & 0x1f;
|
||||||
buf[3] = val;
|
buf[3] = val;
|
||||||
break;
|
break;
|
||||||
@ -2025,6 +2060,10 @@ md_apply_fix (fixP, value)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Are we finished with this relocation now? */
|
||||||
|
if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
|
||||||
|
fixP->fx_done = 1;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2051,6 +2090,7 @@ tc_gen_reloc (section, fixp)
|
|||||||
case BFD_RELOC_HI22:
|
case BFD_RELOC_HI22:
|
||||||
case BFD_RELOC_LO10:
|
case BFD_RELOC_LO10:
|
||||||
case BFD_RELOC_32_PCREL_S2:
|
case BFD_RELOC_32_PCREL_S2:
|
||||||
|
case BFD_RELOC_SPARC13:
|
||||||
case BFD_RELOC_SPARC_BASE13:
|
case BFD_RELOC_SPARC_BASE13:
|
||||||
case BFD_RELOC_SPARC_WDISP22:
|
case BFD_RELOC_SPARC_WDISP22:
|
||||||
/* start-sanitize-v9 */
|
/* start-sanitize-v9 */
|
||||||
@ -2076,6 +2116,12 @@ tc_gen_reloc (section, fixp)
|
|||||||
/* @@ Why fx_addnumber sometimes and fx_offset other times? */
|
/* @@ Why fx_addnumber sometimes and fx_offset other times? */
|
||||||
if (reloc->howto->pc_relative == 0)
|
if (reloc->howto->pc_relative == 0)
|
||||||
reloc->addend = fixp->fx_addnumber;
|
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
|
else
|
||||||
reloc->addend = fixp->fx_offset - reloc->address;
|
reloc->addend = fixp->fx_offset - reloc->address;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user