Fix sh-elf linker relaxation:
gcc: * config/sh/sh.h (EXTRA_SPECS): Add subtarget_asm_relax_spec and subtarget_asm_isa_spec. (SUBTARGET_ASM_RELAX_SPEC, SUBTARGET_ASM_ISA_SPEC): Define. (ASM_SPEC): Define as SH_ASM_SPEC. (SH_ASM_SPEC): New; take the role of ASM_SPEC, but safe from svr4.h. Use subtarget_asm_relax_spec and subtarget_asm_isa_spec. * config/sh/elf.h (ASM_SPEC): Use SH_ASM_SPEC. (SUBTARGET_ASM_ISA_SPEC): Undef / define. gcc/testsuite: gcc.dg/sh-relax.c: New test. include/elf: * sh.h (EF_SH_MERGE_MACH): Make sure SH2E & SH3/SH3E merge to SH3E, and SH2E & SH4 merge to SH4, not SH2E. gas: * config/tc-sh.c (sh_dsp): Replace with preset_target_arch. (md_begin): Use preset_target_arch. (md_longopts): Make isa option unconditional. (md_parse_option): Make OPTION_DSP and OPTION_ISA sh4 / any set preset_target_arch. (md_apply_fix3): If BFD_ASSEMBLER, adjust SWITCH_TABLE fixups by -S_GET_VALUE (fixP->fx_subsy). (tc_gen_reloc): For SWITCH_TABLE fixups, the symbol is fixp->fx_subsy, and the addend is 0. Adjust addend of R_SH_IND12W relocations by fixp->fx_offset - 4. * config/tc-sh.h (TC_FORCE_RELOCATION_SUB_LOCAL): Define. bfd: elf32-sh.c (sh_elf_howto_tab): Make R_SH_IND12W into an ordinary relocation (no special function), and make it non-partial_inplace. (sh_elf_relax_section): When creating a bsr, use a consistent value no matter if the symbol is extern or not; set addend to -4. Don't swap load / non-load instructions for SH4. (sh_elf_relax_delete_bytes): In R_SH_IND12W case, check the offset rather than if the symbol is external to determine if adjusting the offset makes sense. Adjust the addend too if appropriate. (sh_elf_relocate_section): In R_SH_IND12W, don't fiddle with the relocation.
This commit is contained in:
parent
a0ed55327d
commit
bdfaef528f
7 changed files with 91 additions and 19 deletions
|
@ -1,3 +1,16 @@
|
|||
Mon Mar 3 20:48:23 2003 J"orn Rennecke <joern.rennecke@superh.com>
|
||||
|
||||
* elf32-sh.c (sh_elf_howto_tab): Make R_SH_IND12W into an ordinary
|
||||
relocation (no special function), and make it non-partial_inplace.
|
||||
(sh_elf_relax_section): When creating a bsr, use a consistent value
|
||||
no matter if the symbol is extern or not; set addend to -4.
|
||||
Don't swap load / non-load instructions for SH4.
|
||||
(sh_elf_relax_delete_bytes): In R_SH_IND12W case, check the offset
|
||||
rather than if the symbol is external to determine if adjusting the
|
||||
offset makes sense. Adjust the addend too if appropriate.
|
||||
(sh_elf_relocate_section): In R_SH_IND12W, don't fiddle with the
|
||||
relocation.
|
||||
|
||||
2003-03-03 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* po/da.po: Installed latest translation.
|
||||
|
|
|
@ -179,6 +179,8 @@ static reloc_howto_type sh_elf_howto_table[] =
|
|||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* 12 bit PC relative branch divided by 2. */
|
||||
/* This cannot be partial_inplace because relaxation can't know the
|
||||
eventual value of a symbol. */
|
||||
HOWTO (R_SH_IND12W, /* type */
|
||||
1, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
|
@ -186,10 +188,10 @@ static reloc_howto_type sh_elf_howto_table[] =
|
|||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_signed, /* complain_on_overflow */
|
||||
sh_elf_reloc, /* special_function */
|
||||
NULL, /* special_function */
|
||||
"R_SH_IND12W", /* name */
|
||||
TRUE, /* partial_inplace */
|
||||
0xfff, /* src_mask */
|
||||
FALSE, /* partial_inplace */
|
||||
0x0, /* src_mask */
|
||||
0xfff, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
|
@ -2232,6 +2234,12 @@ sh_elf_relax_section (abfd, sec, link_info, again)
|
|||
/* Change the R_SH_USES reloc into an R_SH_IND12W reloc, and
|
||||
replace the jsr with a bsr. */
|
||||
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irelfn->r_info), R_SH_IND12W);
|
||||
/* We used to test (ELF32_R_SYM (irelfn->r_info) < symtab_hdr->sh_info)
|
||||
here, but that only checks if the symbol is an external symbol,
|
||||
not if the symbol is in a different section. Besides, we need
|
||||
a consistent meaning for the relocation, so we just assume here that
|
||||
the value of the symbol is not available. */
|
||||
#if 0
|
||||
if (ELF32_R_SYM (irelfn->r_info) < symtab_hdr->sh_info)
|
||||
{
|
||||
/* If this needs to be changed because of future relaxing,
|
||||
|
@ -2242,12 +2250,14 @@ sh_elf_relax_section (abfd, sec, link_info, again)
|
|||
contents + irel->r_offset);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* We can't fully resolve this yet, because the external
|
||||
symbol value may be changed by future relaxing. We let
|
||||
the final link phase handle it. */
|
||||
bfd_put_16 (abfd, (bfd_vma) 0xb000, contents + irel->r_offset);
|
||||
}
|
||||
irel->r_addend = -4;
|
||||
|
||||
/* See if there is another R_SH_USES reloc referring to the same
|
||||
register load. */
|
||||
|
@ -2316,7 +2326,8 @@ sh_elf_relax_section (abfd, sec, link_info, again)
|
|||
|
||||
/* Look for load and store instructions that we can align on four
|
||||
byte boundaries. */
|
||||
if (have_code)
|
||||
if ((elf_elfheader (abfd)->e_flags & EF_SH_MACH_MASK) != EF_SH4
|
||||
&& have_code)
|
||||
{
|
||||
bfd_boolean swapped;
|
||||
|
||||
|
@ -2542,14 +2553,28 @@ sh_elf_relax_delete_bytes (abfd, sec, addr, count)
|
|||
break;
|
||||
|
||||
case R_SH_IND12W:
|
||||
if (ELF32_R_SYM (irel->r_info) >= symtab_hdr->sh_info)
|
||||
start = stop = addr;
|
||||
off = insn & 0xfff;
|
||||
if (! off)
|
||||
{
|
||||
/* This has been made by previous relaxation. Since the
|
||||
relocation will be against an external symbol, the
|
||||
final relocation will just do the right thing. */
|
||||
start = stop = addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
off = insn & 0xfff;
|
||||
if (off & 0x800)
|
||||
off -= 0x1000;
|
||||
stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
|
||||
|
||||
/* The addend will be against the section symbol, thus
|
||||
for adjusting the addend, the relevant start is the
|
||||
start of the section.
|
||||
N.B. If we want to abandom in-place changes here and
|
||||
test directly using symbol + addend, we have to take into
|
||||
account that the addend has already been adjusted by -4. */
|
||||
if (stop > addr && stop < toaddr)
|
||||
irel->r_addend -= count;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -4811,7 +4836,6 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
break;
|
||||
|
||||
case R_SH_IND12W:
|
||||
relocation -= 4;
|
||||
goto final_link_relocate;
|
||||
|
||||
case R_SH_DIR8WPN:
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
Mon Mar 3 20:36:47 2003 J"orn Rennecke <joern.rennecke@superh.com>
|
||||
|
||||
* config/tc-sh.c (sh_dsp): Replace with preset_target_arch.
|
||||
(md_begin): Use preset_target_arch.
|
||||
(md_longopts): Make isa option unconditional.
|
||||
(md_parse_option): Make OPTION_DSP and OPTION_ISA sh4 / any
|
||||
set preset_target_arch.
|
||||
(md_apply_fix3): If BFD_ASSEMBLER, adjust SWITCH_TABLE fixups
|
||||
by -S_GET_VALUE (fixP->fx_subsy).
|
||||
(tc_gen_reloc): For SWITCH_TABLE fixups, the symbol is fixp->fx_subsy,
|
||||
and the addend is 0.
|
||||
Adjust addend of R_SH_IND12W relocations by fixp->fx_offset - 4.
|
||||
* config/tc-sh.h (TC_FORCE_RELOCATION_SUB_LOCAL): Define.
|
||||
|
||||
2003-03-02 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
|
||||
|
||||
* config/tc-mips.c (append_insn): Add handling of
|
||||
|
|
|
@ -163,9 +163,9 @@ int sh_relax; /* set if -relax seen */
|
|||
|
||||
int sh_small;
|
||||
|
||||
/* Whether -dsp was seen. */
|
||||
/* preset architecture set, if given; zero otherwise. */
|
||||
|
||||
static int sh_dsp;
|
||||
static int preset_target_arch;
|
||||
|
||||
/* The bit mask of architectures that could
|
||||
accomodate the insns seen so far. */
|
||||
|
@ -867,7 +867,8 @@ md_begin ()
|
|||
char *prev_name = "";
|
||||
int target_arch;
|
||||
|
||||
target_arch = arch_sh1_up & ~(sh_dsp ? arch_sh3e_up : arch_sh_dsp_up);
|
||||
target_arch
|
||||
= preset_target_arch ? preset_target_arch : arch_sh1_up & ~arch_sh_dsp_up;
|
||||
valid_arch = target_arch;
|
||||
|
||||
#ifdef HAVE_SH64
|
||||
|
@ -2593,20 +2594,20 @@ struct option md_longopts[] =
|
|||
#define OPTION_LITTLE (OPTION_BIG + 1)
|
||||
#define OPTION_SMALL (OPTION_LITTLE + 1)
|
||||
#define OPTION_DSP (OPTION_SMALL + 1)
|
||||
#define OPTION_ISA (OPTION_DSP + 1)
|
||||
|
||||
{"relax", no_argument, NULL, OPTION_RELAX},
|
||||
{"big", no_argument, NULL, OPTION_BIG},
|
||||
{"little", no_argument, NULL, OPTION_LITTLE},
|
||||
{"small", no_argument, NULL, OPTION_SMALL},
|
||||
{"dsp", no_argument, NULL, OPTION_DSP},
|
||||
{"isa", required_argument, NULL, OPTION_ISA},
|
||||
#ifdef HAVE_SH64
|
||||
#define OPTION_ISA (OPTION_DSP + 1)
|
||||
#define OPTION_ABI (OPTION_ISA + 1)
|
||||
#define OPTION_NO_MIX (OPTION_ABI + 1)
|
||||
#define OPTION_SHCOMPACT_CONST_CRANGE (OPTION_NO_MIX + 1)
|
||||
#define OPTION_NO_EXPAND (OPTION_SHCOMPACT_CONST_CRANGE + 1)
|
||||
#define OPTION_PT32 (OPTION_NO_EXPAND + 1)
|
||||
{"isa", required_argument, NULL, OPTION_ISA},
|
||||
{"abi", required_argument, NULL, OPTION_ABI},
|
||||
{"no-mix", no_argument, NULL, OPTION_NO_MIX},
|
||||
{"shcompact-const-crange", no_argument, NULL, OPTION_SHCOMPACT_CONST_CRANGE},
|
||||
|
@ -2642,12 +2643,16 @@ md_parse_option (c, arg)
|
|||
break;
|
||||
|
||||
case OPTION_DSP:
|
||||
sh_dsp = 1;
|
||||
preset_target_arch = arch_sh1_up & ~arch_sh3e_up;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_SH64
|
||||
case OPTION_ISA:
|
||||
if (strcasecmp (arg, "shmedia") == 0)
|
||||
if (strcasecmp (arg, "sh4") == 0)
|
||||
preset_target_arch = arch_sh4;
|
||||
else if (strcasecmp (arg, "any") == 0)
|
||||
preset_target_arch = arch_sh1_up;
|
||||
#ifdef HAVE_SH64
|
||||
else if (strcasecmp (arg, "shmedia") == 0)
|
||||
{
|
||||
if (sh64_isa_mode == sh64_isa_shcompact)
|
||||
as_bad (_("Invalid combination: --isa=SHcompact with --isa=SHmedia"));
|
||||
|
@ -2661,10 +2666,12 @@ md_parse_option (c, arg)
|
|||
as_bad (_("Invalid combination: --abi=64 with --isa=SHcompact"));
|
||||
sh64_isa_mode = sh64_isa_shcompact;
|
||||
}
|
||||
#endif /* HAVE_SH64 */
|
||||
else
|
||||
as_bad ("Invalid argument to --isa option: %s", arg);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_SH64
|
||||
case OPTION_ABI:
|
||||
if (strcmp (arg, "32") == 0)
|
||||
{
|
||||
|
@ -3381,7 +3388,10 @@ md_apply_fix3 (fixP, valP, seg)
|
|||
val -= S_GET_VALUE (fixP->fx_addsy);
|
||||
#endif
|
||||
|
||||
#ifndef BFD_ASSEMBLER
|
||||
#ifdef BFD_ASSEMBLER
|
||||
if (SWITCH_TABLE (fixP))
|
||||
val -= S_GET_VALUE (fixP->fx_subsy);
|
||||
#else
|
||||
if (fixP->fx_r_type == 0)
|
||||
{
|
||||
if (fixP->fx_size == 2)
|
||||
|
@ -3902,7 +3912,8 @@ tc_gen_reloc (section, fixp)
|
|||
|
||||
if (SWITCH_TABLE (fixp))
|
||||
{
|
||||
rel->addend = rel->address - S_GET_VALUE (fixp->fx_subsy);
|
||||
*rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
|
||||
rel->addend = 0;
|
||||
if (r_type == BFD_RELOC_16)
|
||||
r_type = BFD_RELOC_SH_SWITCH16;
|
||||
else if (r_type == BFD_RELOC_8)
|
||||
|
@ -3941,6 +3952,8 @@ tc_gen_reloc (section, fixp)
|
|||
rel->addend = 0;
|
||||
|
||||
rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
|
||||
if (rel->howto->type == R_SH_IND12W)
|
||||
rel->addend += fixp->fx_offset - 4;
|
||||
if (rel->howto == NULL)
|
||||
{
|
||||
as_bad_where (fixp->fx_file, fixp->fx_line,
|
||||
|
|
|
@ -235,6 +235,8 @@ extern bfd_boolean sh_fix_adjustable PARAMS ((struct fix *));
|
|||
|| (FIX)->fx_r_type == BFD_RELOC_SH_GOTPC \
|
||||
|| TC_FORCE_RELOCATION (FIX))
|
||||
|
||||
#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX) (sh_relax && SWITCH_TABLE (FIX))
|
||||
|
||||
/* This keeps the subtracted symbol around, for use by PLT_PCREL
|
||||
relocs. */
|
||||
#define TC_FORCE_RELOCATION_SUB_ABS(FIX) \
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
Mon Mar 3 20:35:58 2003 J"orn Rennecke <joern.rennecke@superh.com>
|
||||
|
||||
* sh.h (EF_SH_MERGE_MACH): Make sure SH2E & SH3/SH3E merge to SH3E,
|
||||
and SH2E & SH4 merge to SH4, not SH2E.
|
||||
|
||||
2003-02-21 Ian Wienand <ianw@gelato.unsw.edu.au>
|
||||
|
||||
* ia64.h (SHT_IA_64_LOPSREG, SHT_IA_64_HIPSREG,
|
||||
|
|
|
@ -56,7 +56,8 @@
|
|||
: (((mach1) == EF_SH3E && (mach2) == EF_SH_UNKNOWN) \
|
||||
|| ((mach2) == EF_SH3E && (mach1) == EF_SH_UNKNOWN)) \
|
||||
? EF_SH4 \
|
||||
: ((mach1) > (mach2) ? (mach1) : (mach2)))
|
||||
: (((mach1) == EF_SH2E ? 7 : (mach1)) > ((mach2) == EF_SH2E ? 7 : (mach2)) \
|
||||
? (mach1) : (mach2)))
|
||||
|
||||
/* Flags for the st_other symbol field.
|
||||
Keep away from the STV_ visibility flags (bit 0..1). */
|
||||
|
|
Loading…
Reference in a new issue