+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.
 
         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) */
         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 */
 
       /* 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,
                      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.  */
 
   /* 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;
 
          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;
 
          break;
 
        case R_SH_IND12W:
-         relocation -= 4;
          goto final_link_relocate;
 
        case R_SH_DIR8WPN:
 
+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
 
 
 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.  */
   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
 #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},
       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"));
            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)
        {
     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)
 
   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)
     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,
 
    || (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)               \
 
+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,
 
    : (((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).  */