aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-sh.c
diff options
context:
space:
mode:
authorJoern Rennecke <joern.rennecke@embecosm.com>2003-03-03 21:04:01 +0000
committerJoern Rennecke <joern.rennecke@embecosm.com>2003-03-03 21:04:01 +0000
commitbdfaef528f42e9c07279aab2f37e3b888a08fc22 (patch)
tree7d39668f5661d2f58be6c5a8aa5d7e9cb93dc85b /gas/config/tc-sh.c
parenta0ed55327d141094e07c8cdb3ac6f877109d917c (diff)
downloadgdb-bdfaef528f42e9c07279aab2f37e3b888a08fc22.zip
gdb-bdfaef528f42e9c07279aab2f37e3b888a08fc22.tar.gz
gdb-bdfaef528f42e9c07279aab2f37e3b888a08fc22.tar.bz2
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.
Diffstat (limited to 'gas/config/tc-sh.c')
-rw-r--r--gas/config/tc-sh.c33
1 files changed, 23 insertions, 10 deletions
diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c
index d3a6ac3..c73b81f 100644
--- a/gas/config/tc-sh.c
+++ b/gas/config/tc-sh.c
@@ -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,