This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH/RFA] SH TLS support


Hi,

This patch adds TLS support for 32-bit SH elf targets. There is no
new regressions on sh-unknown-linux-gnu and sh64-any-elf targets.
It's almost same with the slightly older version of Jakub Jelinek's
TLS patch for i386 elf targets except a few changes for type I vs.
type II deference of TLS models. Patch includes new tests corresponding
to i386 TLS tests.
TLS support in elf32-sh.c is added only if the macro USE_SH_TLS32
is defined, so the current patch enables it for 32-bit linux target
only.

The SH ELF TLS relocation numbers (144-155) are allocated as a GNU
extension, though I'm not sure whether these numbers are used for
another purpose on non-GNU system or not. I think it isn't a problem
because GNU linker will not likely support them, at least for linux.
Thoughts?

	kaz
--
	2002-10-01  Kaz Kojima  <kkojima@rr.iij4u.or.jp>

[bfd/ChangeLog]
	* elf32-sh-lin.c (USE_SH_TLS32): Define.
	* elf32-sh.c (sh_elf_tls_transition, sh_elf_mkobject,
	sh_elf_object_p, dtpoff_base): New functions.
	(sh_elf_howto_table): Add TLS relocs.
	(sh_reloc_map): Likewise.
	(sh_elf_info_to_howto): Support TLS relocs.
	(elf_sh_link_hash_entry): Add tls_type and tls_tpoff32.
	(sh_elf_hash_entry, sh_elf_tdata, sh_elf_local_got_tls_type):
	New macros.
	(sh_elf_obj_tdata): New.
	(elf_sh_link_hash_table): Add tls_ldm_got.
	(sh_elf_link_hash_table_create): Clear refcount of tls_ldm_got.
	(allocate_dynrelocs): Support TLS relocs.
	(sh_elf_size_dynamic_sections): Likewise.
	(sh_elf_relocate_section): Likewise.
	(sh_elf_gc_sweep_hook): Likewise.
	(sh_elf_check_relocs): Likewise.
	(sh_elf_finish_dynamic_symbol): Likewise.
	(bfd_elf32_mkobject, elf_backend_object_p): Define for TLS case.
	* reloc.c: Add SH TSL relocs.

[gas/ChangeLog]
	* config/tc-sh.c (sh_frob_tls_section): New function.
	(sh_frob_file): Map sh_frob_tls_section over sections.	
	(md_apply_fix3): Add TLS relocs.
	(sh_parse_name): Support @TLSGD, @TLSLDM, @GOTTPOFF, @TPOFF and
	@DTPOFF.

[include/ChangeLog]
	* elf/sh.h: Add SH TLS relocs.

[gas/testsuite/ChangeLog]
	* gas/sh/tlsd.s, gas/sh/tlsd.d: New.
	* gas/sh/tlsnopic.s, gas/sh/tlsnopic.d: New.
	* gas/sh/tlspic.s, gas/sh/tlspic.d: New.
	* gas/sh/basic.exp: Add new tests.

[ld/testsuite/ChangeLog]
	* ld-sh/sh-tls.exp: New.
	* ld-sh/tlsbin.s, ld-sh/tlsbinpic.s, ld-sh/tlslib.s: New.
	* ld-sh/tlsbin.dd: New.
	* ld-sh/tlsbin.rd: New.
	* ld-sh/tlsbin.sd: New.
	* ld-sh/tlsbin.td: New.
	* ld-sh/tlspic1.s, ld-sh/tlspic2.s: New.
	* ld-sh/tlspic.dd: New.
	* ld-sh/tlspic.rd: New.
	* ld-sh/tlspic.sd: New.
	* ld-sh/tlspic.td: New.

diff -urN ORIG/src/bfd/elf32-sh-lin.c LOCAL/src/bfd/elf32-sh-lin.c
--- ORIG/src/bfd/elf32-sh-lin.c	Sun Feb 17 07:20:24 2002
+++ LOCAL/src/bfd/elf32-sh-lin.c	Tue Oct  1 12:13:01 2002
@@ -105,6 +105,6 @@
 #define elf_backend_grok_prstatus	elf32_shlin_grok_prstatus
 #define elf_backend_grok_psinfo		elf32_shlin_grok_psinfo
 
-
+#define USE_SH_TLS32
 
 #include "elf32-sh.c"
diff -urN ORIG/src/bfd/elf32-sh.c LOCAL/src/bfd/elf32-sh.c
--- ORIG/src/bfd/elf32-sh.c	Sat Aug 24 10:29:30 2002
+++ LOCAL/src/bfd/elf32-sh.c	Tue Oct  1 22:09:03 2002
@@ -59,6 +59,14 @@
 static void sh_elf_copy_indirect_symbol
   PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *,
 	   struct elf_link_hash_entry *));
+#ifdef USE_SH_TLS32
+static int sh_elf_tls_transition
+  PARAMS ((struct bfd_link_info *, int, int));
+static boolean sh_elf_mkobject
+  PARAMS((bfd *));
+static boolean sh_elf_object_p
+  PARAMS((bfd *));
+#endif
 static boolean sh_elf_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
 	   const Elf_Internal_Rela *));
@@ -82,6 +90,10 @@
   PARAMS((bfd *, struct bfd_link_info *));
 static boolean sh_elf_create_dynamic_sections
   PARAMS ((bfd *, struct bfd_link_info *));
+#ifdef USE_SH_TLS32
+static bfd_vma dtpoff_base
+  PARAMS ((struct bfd_link_info *));
+#endif
 static asection * sh_elf_gc_mark_hook
   PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 	   struct elf_link_hash_entry *, Elf_Internal_Sym *));
@@ -713,6 +725,176 @@
   EMPTY_HOWTO (141),
   EMPTY_HOWTO (142),
   EMPTY_HOWTO (143),
+
+#ifdef USE_SH_TLS32
+  HOWTO (R_SH_TLS_GD_32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* */
+	 "R_SH_TLS_GD_32",	/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_SH_TLS_LD_32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* */
+	 "R_SH_TLS_LD_32",	/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_SH_TLS_LDO_32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* */
+	 "R_SH_TLS_LDO_32",	/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_SH_TLS_IE_32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* */
+	 "R_SH_TLS_IE_32",	/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_SH_TLS_LE_32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* */
+	 "R_SH_TLS_LE_32",	/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_SH_TLS_DTPMOD32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* */
+	 "R_SH_TLS_DTPMOD32",	/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_SH_TLS_DTPOFF32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* */
+	 "R_SH_TLS_DTPOFF32",	/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_SH_TLS_TPOFF32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* */
+	 "R_SH_TLS_TPOFF32",	/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_SH_TLS_GD_MOV,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 sh_elf_ignore_reloc,	/* */
+	 "R_SH_TLS_GD_MOV",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_SH_TLS_LDM_MOV,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 sh_elf_ignore_reloc,	/* */
+	 "R_SH_TLS_LDM_MOV",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_SH_TLS_LDO_MOV,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 sh_elf_ignore_reloc,	/* */
+	 "R_SH_TLS_LDO_MOV",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_SH_TLS_IE_MOV,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 sh_elf_ignore_reloc,	/* */
+	 "R_SH_TLS_IE_MOV",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 true),			/* pcrel_offset */
+#else
   EMPTY_HOWTO (144),
   EMPTY_HOWTO (145),
   EMPTY_HOWTO (146),
@@ -725,6 +907,8 @@
   EMPTY_HOWTO (153),
   EMPTY_HOWTO (154),
   EMPTY_HOWTO (155),
+#endif
+
   EMPTY_HOWTO (156),
   EMPTY_HOWTO (157),
   EMPTY_HOWTO (158),
@@ -1776,6 +1960,20 @@
   { BFD_RELOC_VTABLE_ENTRY, R_SH_GNU_VTENTRY },
   { BFD_RELOC_SH_LOOP_START, R_SH_LOOP_START },
   { BFD_RELOC_SH_LOOP_END, R_SH_LOOP_END },
+#ifdef USE_SH_TLS32
+  { BFD_RELOC_SH_TLS_GD_32, R_SH_TLS_GD_32 },
+  { BFD_RELOC_SH_TLS_LD_32, R_SH_TLS_LD_32 },
+  { BFD_RELOC_SH_TLS_LDO_32, R_SH_TLS_LDO_32 },
+  { BFD_RELOC_SH_TLS_IE_32, R_SH_TLS_IE_32 },
+  { BFD_RELOC_SH_TLS_LE_32, R_SH_TLS_LE_32 },
+  { BFD_RELOC_SH_TLS_DTPMOD32, R_SH_TLS_DTPMOD32 },
+  { BFD_RELOC_SH_TLS_DTPOFF32, R_SH_TLS_DTPOFF32 },
+  { BFD_RELOC_SH_TLS_TPOFF32, R_SH_TLS_TPOFF32 },
+  { BFD_RELOC_SH_TLS_GD_MOV, R_SH_TLS_GD_MOV },
+  { BFD_RELOC_SH_TLS_LDM_MOV, R_SH_TLS_LDM_MOV },
+  { BFD_RELOC_SH_TLS_LDO_MOV, R_SH_TLS_LDO_MOV },
+  { BFD_RELOC_SH_TLS_IE_MOV, R_SH_TLS_IE_MOV },
+#endif
   { BFD_RELOC_32_GOT_PCREL, R_SH_GOT32 },
   { BFD_RELOC_32_PLT_PCREL, R_SH_PLT32 },
   { BFD_RELOC_SH_COPY, R_SH_COPY },
@@ -1873,7 +2071,10 @@
   BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC || r > R_SH_LAST_INVALID_RELOC);
   BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_2 || r > R_SH_LAST_INVALID_RELOC_2);
   BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_3 || r > R_SH_LAST_INVALID_RELOC_3);
+#ifdef USE_SH_TLS32
   BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_4 || r > R_SH_LAST_INVALID_RELOC_4);
+#endif
+  BFD_ASSERT (r < R_SH_FIRST_INVALID_RELOC_5 || r > R_SH_LAST_INVALID_RELOC_5);
 
   cache_ptr->howto = &sh_elf_howto_table[r];
 }
@@ -3388,8 +3589,46 @@
 
   /* Track dynamic relocs copied for this symbol.  */
   struct elf_sh_dyn_relocs *dyn_relocs;
+
+#ifdef USE_SH_TLS32
+  enum {
+    GOT_UNKNOWN = 0, GOT_NORMAL, GOT_TLS_GD, GOT_TLS_IE
+  } tls_type;
+
+  /* If true, R_SH_TLS_TPOFF32 relocation is generated.  */
+  boolean tls_tpoff32;
+#endif
+};
+
+#ifdef USE_SH_TLS32
+#define sh_elf_hash_entry(ent) ((struct elf_sh_link_hash_entry *)(ent))
+
+struct sh_elf_obj_tdata
+{
+  struct elf_obj_tdata root;
+
+  /* tls_type for each local got entry.  */
+  char *local_got_tls_type;
 };
 
+#define sh_elf_tdata(abfd) \
+  ((struct sh_elf_obj_tdata *) (abfd)->tdata.any)
+
+#define sh_elf_local_got_tls_type(abfd) \
+  (sh_elf_tdata (abfd)->local_got_tls_type)
+
+static boolean
+sh_elf_mkobject (abfd)
+     bfd *abfd;
+{
+  bfd_size_type amt = sizeof (struct sh_elf_obj_tdata);
+  abfd->tdata.any = bfd_zalloc (abfd, amt);
+  if (abfd->tdata.any == NULL)
+    return false;
+  return true;
+}
+#endif
+                 
 /* sh ELF linker hash table.  */
 
 struct elf_sh_link_hash_table
@@ -3407,6 +3646,15 @@
 
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
+
+#ifdef USE_SH_TLS32
+  /* A counter or offset to track a TLS got entry.  */
+  union
+    {
+      bfd_signed_vma refcount;
+      bfd_vma offset;
+    } tls_ldm_got;
+#endif
 };
 
 /* Traverse an sh ELF linker hash table.  */
@@ -3455,6 +3703,10 @@
 #ifdef INCLUDE_SHMEDIA
       ret->datalabel_got_offset = (bfd_vma) -1;
 #endif
+#ifdef USE_SH_TLS32
+      ret->tls_type = GOT_UNKNOWN;
+      ret->tls_tpoff32 = false;
+#endif
     }
 
   return (struct bfd_hash_entry *) ret;
@@ -3488,6 +3740,9 @@
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->sym_sec.abfd = NULL;
+#ifdef USE_SH_TLS32
+  ret->tls_ldm_got.refcount = 0;
+#endif
 
   return &ret->root.root;
 }
@@ -3928,6 +4183,9 @@
     {
       asection *s;
       boolean dyn;
+#ifdef USE_SH_TLS32
+      int tls_type = sh_elf_hash_entry(h)->tls_type;
+#endif
 
       /* Make sure this symbol is output as a dynamic symbol.
 	 Undefined weak syms won't yet be marked as dynamic.  */
@@ -3954,9 +4212,26 @@
       h->got.offset = s->_raw_size;
 #endif
       s->_raw_size += 4;
+#ifdef USE_SH_TLS32
+      /* R_SH_TLS_GD needs 2 consecutive GOT slots.  */
+      if (tls_type == GOT_TLS_GD)
+	s->_raw_size += 4;
+#endif
       dyn = htab->root.dynamic_sections_created;
+#ifdef USE_SH_TLS32
+      /* R_SH_TLS_IE_32 needs one dynamic relocation,
+	 R_SH_TLS_GD needs one if local symbol and two if global.  */
+      if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
+	  || tls_type == GOT_TLS_IE)
+	htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
+      else if (tls_type == GOT_TLS_GD)
+	htab->srelgot->_raw_size += 2 * sizeof (Elf32_External_Rela);
+      else if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
+	htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
+#else
       if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
 	htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
+#endif
     }
   else
     h->got.offset = (bfd_vma) -1;
@@ -3992,6 +4267,11 @@
     }
   else
     {
+#ifdef USE_SH_TLS32
+      if (sh_elf_hash_entry(h)->tls_tpoff32)
+	goto keep;
+#endif
+
       /* For the non-shared case, discard space for relocs against
 	 symbols which turn out to need copy relocs or are not
 	 dynamic.  */
@@ -4099,6 +4379,9 @@
     {
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
+#ifdef USE_SH_TLS32
+      char *local_tls_type;
+#endif
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
@@ -4144,6 +4427,9 @@
       locsymcount *= 2;
 #endif
       end_local_got = local_got + locsymcount;
+#ifdef USE_SH_TLS32
+      local_tls_type = sh_elf_local_got_tls_type (ibfd);
+#endif
       s = htab->sgot;
       srel = htab->srelgot;
       for (; local_got < end_local_got; ++local_got)
@@ -4152,14 +4438,34 @@
 	    {
 	      *local_got = s->_raw_size;
 	      s->_raw_size += 4;
+#ifdef USE_SH_TLS32
+	      if (*local_tls_type == GOT_TLS_GD)
+		s->_raw_size += 4;
+#endif
 	      if (info->shared)
 		srel->_raw_size += sizeof (Elf32_External_Rela);
 	    }
 	  else
 	    *local_got = (bfd_vma) -1;
+#ifdef USE_SH_TLS32
+	  ++local_tls_type;
+#endif
 	}
     }
 
+#ifdef USE_SH_TLS32
+  if (htab->tls_ldm_got.refcount > 0)
+    {
+      /* Allocate 2 got entries and 1 dynamic reloc for R_SH_TLS_LD_32
+	 relocs.  */
+      htab->tls_ldm_got.offset = htab->sgot->_raw_size;
+      htab->sgot->_raw_size += 8;
+      htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
+    }
+  else
+    htab->tls_ldm_got.offset = -1;
+#endif
+
   /* Allocate global sym .plt and .got entries, and space for global
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info);
@@ -4295,6 +4601,13 @@
   asection *sgotplt;
   asection *splt;
   asection *sreloc;
+  asection *srelgot;
+#ifdef USE_SH_TLS32
+  static Elf_Internal_Rela *tls_reloc[3];
+  enum tls_relndx {
+    GD_MOV = 0, LD_MOV, IE_MOV
+  };
+#endif
 
   htab = sh_elf_hash_table (info);
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
@@ -4306,6 +4619,7 @@
   sgotplt = htab->sgotplt;
   splt = htab->splt;
   sreloc = NULL;
+  srelgot = NULL;
 
   rel = relocs;
   relend = relocs + input_section->reloc_count;
@@ -4321,6 +4635,10 @@
       bfd_vma addend = (bfd_vma) 0;
       bfd_reloc_status_type r;
       int seen_stt_datalabel = 0;
+      bfd_vma off;
+#ifdef USE_SH_TLS32
+      int tls_type;
+#endif
 
       r_symndx = ELF32_R_SYM (rel->r_info);
 
@@ -4340,8 +4658,12 @@
 	      && r_type <= (int) R_SH_LAST_INVALID_RELOC)
 	  || (   r_type >= (int) R_SH_FIRST_INVALID_RELOC_3
 	      && r_type <= (int) R_SH_LAST_INVALID_RELOC_3)
+#ifdef USE_SH_TLS32
 	  || (   r_type >= (int) R_SH_FIRST_INVALID_RELOC_4
 	      && r_type <= (int) R_SH_LAST_INVALID_RELOC_4)
+#endif
+	  || (   r_type >= (int) R_SH_FIRST_INVALID_RELOC_5
+	      && r_type <= (int) R_SH_LAST_INVALID_RELOC_5)
 	  || (r_type >= (int) R_SH_FIRST_INVALID_RELOC_2
 	      && r_type <= (int) R_SH_LAST_INVALID_RELOC_2))
 	{
@@ -4512,7 +4834,13 @@
 			     with them here.  */
 			  || ((input_section->flags & SEC_DEBUGGING) != 0
 			      && (h->elf_link_hash_flags
-				  & ELF_LINK_HASH_DEF_DYNAMIC) != 0))))
+				  & ELF_LINK_HASH_DEF_DYNAMIC) != 0)))
+#ifdef USE_SH_TLS32
+		  || (sec->output_section == NULL
+		      && (sh_elf_hash_entry(h)->tls_type == GOT_TLS_IE
+			  || sh_elf_hash_entry(h)->tls_type == GOT_TLS_GD))
+#endif
+		  )
 		relocation = 0;
 	      else if (sec->output_section == NULL)
 		{
@@ -4520,7 +4848,7 @@
 		    (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"),
 		     bfd_archive_filename (input_bfd), h->root.root.string,
 		     bfd_get_section_name (input_bfd, input_section));
-		  relocation = 0;
+		  return false;
 		}
 	      else
 		relocation = ((h->root.u.def.value
@@ -4765,7 +5093,6 @@
 
 	  if (h != NULL)
 	    {
-	      bfd_vma off;
 	      boolean dyn;
 
 	      off = h->got.offset;
@@ -4823,8 +5150,6 @@
 	    }
 	  else
 	    {
-	      bfd_vma off;
-
 #ifdef INCLUDE_SHMEDIA
 	      if (rel->r_addend)
 		{
@@ -4858,11 +5183,14 @@
 
 		  if (info->shared)
 		    {
-		      asection *srelgot;
 		      Elf_Internal_Rela outrel;
 
-		      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
-		      BFD_ASSERT (srelgot != NULL);
+		      if (srelgot == NULL)
+			{
+			  srelgot = bfd_get_section_by_name (dynobj,
+							     ".rela.got");
+			  BFD_ASSERT (srelgot != NULL);
+			}
 
 		      outrel.r_offset = (sgot->output_section->vma
 					 + sgot->output_offset
@@ -4996,76 +5324,529 @@
 				   rel->r_offset, sec, start, end);
 	    break;
 	  }
-	}
-
-    relocation_done:
-      if (r != bfd_reloc_ok)
-	{
-	  switch (r)
-	    {
-	    default:
-	    case bfd_reloc_outofrange:
-	      abort ();
-	    case bfd_reloc_overflow:
-	      {
-		const char *name;
 
-		if (h != NULL)
-		  name = h->root.root.string;
-		else
-		  {
-		    name = (bfd_elf_string_from_elf_section
-			    (input_bfd, symtab_hdr->sh_link, sym->st_name));
-		    if (name == NULL)
-		      return false;
-		    if (*name == '\0')
-		      name = bfd_section_name (input_bfd, sec);
-		  }
-		if (! ((*info->callbacks->reloc_overflow)
-		       (info, name, howto->name, (bfd_vma) 0,
-			input_bfd, input_section, rel->r_offset)))
-		  return false;
-	      }
-	      break;
-	    }
-	}
-    }
+#ifdef USE_SH_TLS32
+	case R_SH_TLS_GD_MOV:
+	  BFD_ASSERT (tls_reloc[GD_MOV] == NULL);
+	  tls_reloc[GD_MOV] = rel;
+	  continue;
 
-  return true;
-}
+	case R_SH_TLS_LDM_MOV:
+	  BFD_ASSERT (tls_reloc[LD_MOV] == NULL);
+	  tls_reloc[LD_MOV] = rel;
+	  continue;
 
-/* This is a version of bfd_generic_get_relocated_section_contents
-   which uses sh_elf_relocate_section.  */
+	case R_SH_TLS_LDO_MOV:
+	  continue;
 
-static bfd_byte *
-sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
-				       data, relocateable, symbols)
-     bfd *output_bfd;
-     struct bfd_link_info *link_info;
-     struct bfd_link_order *link_order;
-     bfd_byte *data;
-     boolean relocateable;
-     asymbol **symbols;
-{
-  Elf_Internal_Shdr *symtab_hdr;
-  asection *input_section = link_order->u.indirect.section;
-  bfd *input_bfd = input_section->owner;
-  asection **sections = NULL;
-  Elf_Internal_Rela *internal_relocs = NULL;
-  Elf_Internal_Sym *isymbuf = NULL;
+	case R_SH_TLS_IE_MOV:
+	  BFD_ASSERT (tls_reloc[IE_MOV] == NULL);
+	  tls_reloc[IE_MOV] = rel;
+	  continue;
 
-  /* We only need to handle the case of relaxing, or of having a
-     particular set of section contents, specially.  */
-  if (relocateable
-      || elf_section_data (input_section)->this_hdr.contents == NULL)
-    return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
-						       link_order, data,
-						       relocateable,
-						       symbols);
+	case R_SH_TLS_GD_32:
+	case R_SH_TLS_IE_32:
+	  r_type = sh_elf_tls_transition (info, r_type, h == NULL);
+	  tls_type = GOT_UNKNOWN;
+	  if (h == NULL && local_got_offsets)
+	    tls_type = sh_elf_local_got_tls_type (input_bfd) [r_symndx];
+	  else if (h != NULL)
+	    {
+	      tls_type = sh_elf_hash_entry(h)->tls_type;
+	      if (! info->shared
+		  && (h->dynindx == -1
+		      || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
+		  && (tls_type == GOT_TLS_IE
+		      || sh_elf_hash_entry(h)->tls_tpoff32))
+		r_type = R_SH_TLS_LE_32;
+	    }
+
+	  if (r_type == R_SH_TLS_GD_32 && tls_type == GOT_TLS_IE)
+	    r_type = R_SH_TLS_IE_32;
+
+	  if (r_type == R_SH_TLS_LE_32)
+	    {
+	      bfd_vma offset, lim;
+	      unsigned short insn;
+	      int indx;
+	      Elf_Internal_Rela outrel;
 
-  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+	      if (ELF32_R_TYPE (rel->r_info) == R_SH_TLS_GD_32)
+		{
+		  /* GD->LE transition:
+		       mov.l .Ln,r4; mova .Lf,r0; mov.l .Lf,r1; add r0,r1;
+		       jsr @r1; add r12,r4; ...
+		       .Ln: .long x$TLSGD; .Lf: .long __tls_get_addr@PLT
+		     We change it into:
+		       mov.l .Ln,r4; stc gbr,r0; add r4,r0; nop;
+		       nop; nop; ...
+		       .Ln: .long x@TPOFF; .Lf: .long __tls_get_addr@PLT.  */
+
+		  BFD_ASSERT (tls_reloc[GD_MOV] != NULL);
+		  offset = tls_reloc[GD_MOV]->r_offset;
+		  lim = input_section->_raw_size;
+		  BFD_ASSERT (offset + 12 <= lim);
+
+		  insn = bfd_get_16 (input_bfd, contents + offset + 0);
+		  BFD_ASSERT ((insn & 0xff00) == 0xd400);
+		  insn = bfd_get_16 (input_bfd, contents + offset + 2);
+		  BFD_ASSERT ((insn & 0xff00) == 0xc700);
+		  insn = bfd_get_16 (input_bfd, contents + offset + 4);
+		  BFD_ASSERT ((insn & 0xff00) == 0xd100);
+		  insn = bfd_get_16 (input_bfd, contents + offset + 6);
+		  BFD_ASSERT (insn == 0x310c);
+		  insn = bfd_get_16 (input_bfd, contents + offset + 8);
+		  BFD_ASSERT (insn == 0x410b);
+		  insn = bfd_get_16 (input_bfd, contents + offset + 10);
+		  BFD_ASSERT (insn == 0x34cc);
+
+		  bfd_put_16 (output_bfd, 0x0012, contents + offset + 2);
+		  bfd_put_16 (output_bfd, 0x304c, contents + offset + 4);
+		  bfd_put_16 (output_bfd, 0x0009, contents + offset + 6);
+		  bfd_put_16 (output_bfd, 0x0009, contents + offset + 8);
+		  bfd_put_16 (output_bfd, 0x0009, contents + offset + 10);
 
-  memcpy (data, elf_section_data (input_section)->this_hdr.contents,
+		  tls_reloc[GD_MOV] = NULL;
+		}
+	      else
+		{
+		  int index;
+
+		  /* IE->LE transition:
+		     mov.l .Ln,r0; stc gbr,rN; mov.l @(r0,r12),rM; ...;
+		     We change it into:
+		     mov.l .Ln,rM; stc gbr,rN; nop; ...;.  */
+
+		  BFD_ASSERT (tls_reloc[IE_MOV] != NULL);
+		  lim = input_section->_raw_size;
+		  offset = tls_reloc[IE_MOV]->r_offset;
+		  BFD_ASSERT (offset + 8 <= lim);
+
+		  insn = bfd_get_16 (input_bfd, contents + offset + 0);
+		  BFD_ASSERT ((insn & 0xff00) == 0xd000);
+		  index = insn & 0x00ff;
+		  insn = bfd_get_16 (input_bfd, contents + offset + 2);
+		  BFD_ASSERT ((insn & 0xf0ff) == 0x0012);
+		  insn = bfd_get_16 (input_bfd, contents + offset + 4);
+		  BFD_ASSERT ((insn & 0xf0ff) == 0x00ce);
+		  insn = 0xd000 | (insn & 0x0f00) | index;
+		  bfd_put_16 (output_bfd, insn, contents + offset + 0);
+		  bfd_put_16 (output_bfd, 0x0009, contents + offset + 4);
+
+		  tls_reloc[IE_MOV] = NULL;
+		}
+
+	      if (sreloc == NULL)
+		{
+		  const char *name;
+
+		  name = (bfd_elf_string_from_elf_section
+			  (input_bfd,
+			   elf_elfheader (input_bfd)->e_shstrndx,
+			   elf_section_data (input_section)->rel_hdr.sh_name));
+		  if (name == NULL)
+		    return false;
+
+		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+			      && strcmp (bfd_get_section_name (input_bfd,
+							       input_section),
+					 name + 5) == 0);
+
+		  sreloc = bfd_get_section_by_name (dynobj, name);
+		  BFD_ASSERT (sreloc != NULL);
+		}
+
+	      indx = (h && h->dynindx != -1) ? h->dynindx : 0;
+	      outrel.r_offset = (input_section->output_section->vma
+				 + input_section->output_offset
+				 + rel->r_offset);
+	      outrel.r_info = ELF32_R_INFO (indx, R_SH_TLS_TPOFF32);
+	      if (indx == 0)
+		outrel.r_addend = relocation - dtpoff_base (info);
+	      else
+		outrel.r_addend = 0;
+	      bfd_elf32_swap_reloca_out (output_bfd, &outrel,
+					 (((Elf32_External_Rela *)
+					   sreloc->contents)
+					  + sreloc->reloc_count));
+	      ++sreloc->reloc_count;
+
+	      continue;
+	    }
+
+	  sgot = htab->sgot;
+	  if (sgot == NULL)
+	    abort ();
+
+	  if (h != NULL)
+	    off = h->got.offset;
+	  else
+	    {
+	      if (local_got_offsets == NULL)
+		abort ();
+
+	      off = local_got_offsets[r_symndx];
+	    }
+
+	  if ((off & 1) != 0)
+	    off &= ~1;
+          else
+	    {
+	      Elf_Internal_Rela outrel;
+	      Elf32_External_Rela *loc;
+	      int dr_type, indx;
+
+	      if (srelgot == NULL)
+		{
+		  srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+		  BFD_ASSERT (srelgot != NULL);
+		}
+
+	      outrel.r_offset = (sgot->output_section->vma
+				 + sgot->output_offset + off);
+
+	      indx = (h && h->dynindx != -1) ? h->dynindx : 0;
+	      dr_type = (r_type == R_SH_TLS_GD_32 ? R_SH_TLS_DTPMOD32 :
+			 R_SH_TLS_TPOFF32);
+	      if (dr_type == R_SH_TLS_TPOFF32 && indx == 0)
+		outrel.r_addend = relocation - dtpoff_base (info);
+	      else
+		outrel.r_addend = 0;
+	      outrel.r_info = ELF32_R_INFO (indx, dr_type);
+	      loc = (Elf32_External_Rela *) srelgot->contents;
+	      loc += srelgot->reloc_count++;
+	      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+
+	      if (r_type == R_SH_TLS_GD_32)
+		{
+		  if (indx == 0)
+		    {
+		      bfd_put_32 (output_bfd,
+				  relocation - dtpoff_base (info),
+				  sgot->contents + off + 4);
+		    }
+		  else
+		    {
+		      outrel.r_info = ELF32_R_INFO (indx,
+						    R_SH_TLS_DTPOFF32);
+		      outrel.r_offset += 4;
+		      outrel.r_addend = 0;
+		      srelgot->reloc_count++;
+		      loc++;
+		      bfd_elf32_swap_reloca_out (output_bfd, &outrel,
+						loc);
+		    }
+		}
+
+	      if (h != NULL)
+		h->got.offset |= 1;
+	      else
+		local_got_offsets[r_symndx] |= 1;
+	    }
+
+	  if (off >= (bfd_vma) -2)
+	    abort ();
+
+	  if (r_type == (int) ELF32_R_TYPE (rel->r_info))
+	    relocation = sgot->output_offset + off;
+	  else
+	    {
+	      bfd_vma offset, lim;
+	      unsigned short insn;
+
+	      /* GD->IE transition:
+		   mov.l .Ln,r4; mova .Lf,r0; mov.l .Lf,r1; add r0,r1;
+		   jsr @r1; add r12,r4; ...
+		   .Ln: .long x$TLSGD; .Lf: .long __tls_get_addr@PLT
+		 We change it into:
+		   mov.l .Ln,r0; stc gbr,r4; mov.l @(r0,r12),r0; add r4,r0;
+		   nop; nop; ...
+		   .Ln: .long x@TPOFF.  */
+
+	      BFD_ASSERT (tls_reloc[GD_MOV] != NULL);
+	      offset = tls_reloc[GD_MOV]->r_offset;
+	      lim = input_section->_raw_size;
+	      BFD_ASSERT (offset + 12 <= lim);
+
+	      insn = bfd_get_16 (input_bfd, contents + offset + 0);
+	      BFD_ASSERT ((insn & 0xff00) == 0xd400);
+
+	      /* Replace mov.l .Lx,Rn with mov.l .Lx,r0.  */
+	      bfd_put_16 (output_bfd, insn & 0xf0ff, contents + offset);
+
+	      insn = bfd_get_16 (input_bfd, contents + offset + 2);
+	      BFD_ASSERT ((insn & 0xff00) == 0xc700);
+	      insn = bfd_get_16 (input_bfd, contents + offset + 4);
+	      BFD_ASSERT ((insn & 0xff00) == 0xd100);
+	      insn = bfd_get_16 (input_bfd, contents + offset + 6);
+	      BFD_ASSERT (insn == 0x310c);
+	      insn = bfd_get_16 (input_bfd, contents + offset + 8);
+	      BFD_ASSERT (insn == 0x410b);
+	      insn = bfd_get_16 (input_bfd, contents + offset + 10);
+	      BFD_ASSERT (insn == 0x34cc);
+
+	      bfd_put_16 (output_bfd, 0x0412, contents + offset + 2);
+	      bfd_put_16 (output_bfd, 0x00ce, contents + offset + 4);
+	      bfd_put_16 (output_bfd, 0x304c, contents + offset + 6);
+	      bfd_put_16 (output_bfd, 0x0009, contents + offset + 8);
+	      bfd_put_16 (output_bfd, 0x0009, contents + offset + 10);
+
+	      bfd_put_32 (output_bfd, sgot->output_offset + off,
+			  contents + rel->r_offset);
+
+	      tls_reloc[GD_MOV] = NULL;
+
+	      continue;
+	  }
+
+	  addend = rel->r_addend;
+
+	  if (ELF32_R_TYPE (rel->r_info) == R_SH_TLS_GD_32)
+	    tls_reloc[GD_MOV] = NULL;
+	  else
+	    tls_reloc[IE_MOV] = NULL;
+
+	  goto final_link_relocate;
+
+	case R_SH_TLS_LD_32:
+	  if (! info->shared)
+	    {
+	      bfd_vma offset, lim;
+	      unsigned short insn;
+
+	      /* LD->LE transition:
+		   mov.l .Ln,r4; mova .Lf,r0; mov.l .Lf,r1; add r0,r1;
+		   jsr @r1; add r12,r4; ...
+		   .Ln: .long x$TLSLD; .Lf: .long __tls_get_addr@PLT
+		 We change it into:
+		   stc gbr,r0; nop; nop; nop;
+		   nop; nop;  */
+
+	      BFD_ASSERT (tls_reloc[LD_MOV] != NULL);
+	      offset = tls_reloc[LD_MOV]->r_offset;
+	      lim = input_section->_raw_size;
+	      BFD_ASSERT (offset + 12 <= lim);
+
+	      insn = bfd_get_16 (input_bfd, contents + offset + 0);
+	      BFD_ASSERT ((insn & 0xff00) == 0xd400);
+	      insn = bfd_get_16 (input_bfd, contents + offset + 2);
+	      BFD_ASSERT ((insn & 0xff00) == 0xc700);
+	      insn = bfd_get_16 (input_bfd, contents + offset + 4);
+	      BFD_ASSERT ((insn & 0xff00) == 0xd100);
+	      insn = bfd_get_16 (input_bfd, contents + offset + 6);
+	      BFD_ASSERT (insn == 0x310c);
+	      insn = bfd_get_16 (input_bfd, contents + offset + 8);
+	      BFD_ASSERT (insn == 0x410b);
+	      insn = bfd_get_16 (input_bfd, contents + offset + 10);
+	      BFD_ASSERT (insn == 0x34cc);
+
+	      bfd_put_16 (output_bfd, 0x0012, contents + offset + 0);
+	      bfd_put_16 (output_bfd, 0x0009, contents + offset + 2);
+	      bfd_put_16 (output_bfd, 0x0009, contents + offset + 4);
+	      bfd_put_16 (output_bfd, 0x0009, contents + offset + 6);
+	      bfd_put_16 (output_bfd, 0x0009, contents + offset + 8);
+	      bfd_put_16 (output_bfd, 0x0009, contents + offset + 10);
+
+	      tls_reloc[LD_MOV] = NULL;
+
+	      continue;
+	    }
+
+	  sgot = htab->sgot;
+	  if (sgot == NULL)
+	    abort ();
+
+	  off = htab->tls_ldm_got.offset;
+	  if (off & 1)
+	    off &= ~1;
+	  else
+	    {
+	      Elf_Internal_Rela outrel;
+	      Elf32_External_Rela *loc;
+
+	      srelgot = htab->srelgot;
+	      if (srelgot == NULL)
+		abort ();
+
+	      outrel.r_offset = (sgot->output_section->vma
+				 + sgot->output_offset + off);
+	      outrel.r_addend = 0;
+	      outrel.r_info = ELF32_R_INFO (0, R_SH_TLS_DTPMOD32);
+	      loc = (Elf32_External_Rela *) srelgot->contents;
+	      loc += srelgot->reloc_count++;
+	      bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+	      htab->tls_ldm_got.offset |= 1;
+	    }
+
+	  relocation = sgot->output_offset + off;
+	  addend = rel->r_addend;
+
+	  tls_reloc[LD_MOV] = NULL;
+
+	  goto final_link_relocate;
+
+	case R_SH_TLS_LDO_32:
+	  if (! info->shared)
+	    {
+	      int indx;
+	      Elf_Internal_Rela outrel;
+
+	      if (sreloc == NULL)
+		{
+		  const char *name;
+
+		  name = (bfd_elf_string_from_elf_section
+			  (input_bfd,
+			   elf_elfheader (input_bfd)->e_shstrndx,
+			   elf_section_data (input_section)->rel_hdr.sh_name));
+		  if (name == NULL)
+		    return false;
+
+		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+			      && strcmp (bfd_get_section_name (input_bfd,
+							       input_section),
+					 name + 5) == 0);
+
+		  sreloc = bfd_get_section_by_name (dynobj, name);
+		  BFD_ASSERT (sreloc != NULL);
+		}
+
+	      indx = (h && h->dynindx != -1) ? h->dynindx : 0;
+	      outrel.r_offset = (input_section->output_section->vma
+				 + input_section->output_offset
+				 + rel->r_offset);
+	      outrel.r_info = ELF32_R_INFO (indx, R_SH_TLS_TPOFF32);
+	      if (indx == 0)
+		outrel.r_addend = relocation - dtpoff_base (info);
+	      else
+		outrel.r_addend = 0;
+	      bfd_elf32_swap_reloca_out (output_bfd, &outrel,
+					 (((Elf32_External_Rela *)
+					   sreloc->contents)
+					  + sreloc->reloc_count));
+	      ++sreloc->reloc_count;
+
+	      continue;
+	    }
+	  else
+	    relocation -= dtpoff_base (info);
+
+	  addend = rel->r_addend;
+	  goto final_link_relocate;
+
+	case R_SH_TLS_LE_32:
+	  {
+	    int indx;
+	    Elf_Internal_Rela outrel;
+
+	    if (sreloc == NULL)
+	      {
+		const char *name;
+
+		name = (bfd_elf_string_from_elf_section
+			(input_bfd,
+			 elf_elfheader (input_bfd)->e_shstrndx,
+			 elf_section_data (input_section)->rel_hdr.sh_name));
+		if (name == NULL)
+		  return false;
+
+		BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+			    && strcmp (bfd_get_section_name (input_bfd,
+							     input_section),
+				       name + 5) == 0);
+
+		sreloc = bfd_get_section_by_name (dynobj, name);
+		BFD_ASSERT (sreloc != NULL);
+	      }
+
+	    indx = (h && h->dynindx != -1) ? h->dynindx : 0;
+	    outrel.r_offset = (input_section->output_section->vma
+			       + input_section->output_offset
+			       + rel->r_offset);
+	    outrel.r_info = ELF32_R_INFO (indx, R_SH_TLS_TPOFF32);
+	    if (indx == 0)
+	      outrel.r_addend = relocation - dtpoff_base (info);
+	    else
+	      outrel.r_addend = 0;
+	    bfd_elf32_swap_reloca_out (output_bfd, &outrel,
+				       (((Elf32_External_Rela *)
+					 sreloc->contents)
+					+ sreloc->reloc_count));
+	    ++sreloc->reloc_count;
+
+	    continue;
+	  }
+#endif
+	}
+
+    relocation_done:
+      if (r != bfd_reloc_ok)
+	{
+	  switch (r)
+	    {
+	    default:
+	    case bfd_reloc_outofrange:
+	      abort ();
+	    case bfd_reloc_overflow:
+	      {
+		const char *name;
+
+		if (h != NULL)
+		  name = h->root.root.string;
+		else
+		  {
+		    name = (bfd_elf_string_from_elf_section
+			    (input_bfd, symtab_hdr->sh_link, sym->st_name));
+		    if (name == NULL)
+		      return false;
+		    if (*name == '\0')
+		      name = bfd_section_name (input_bfd, sec);
+		  }
+		if (! ((*info->callbacks->reloc_overflow)
+		       (info, name, howto->name, (bfd_vma) 0,
+			input_bfd, input_section, rel->r_offset)))
+		  return false;
+	      }
+	      break;
+	    }
+	}
+    }
+
+  return true;
+}
+
+/* This is a version of bfd_generic_get_relocated_section_contents
+   which uses sh_elf_relocate_section.  */
+
+static bfd_byte *
+sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
+				       data, relocateable, symbols)
+     bfd *output_bfd;
+     struct bfd_link_info *link_info;
+     struct bfd_link_order *link_order;
+     bfd_byte *data;
+     boolean relocateable;
+     asymbol **symbols;
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  asection *input_section = link_order->u.indirect.section;
+  bfd *input_bfd = input_section->owner;
+  asection **sections = NULL;
+  Elf_Internal_Rela *internal_relocs = NULL;
+  Elf_Internal_Sym *isymbuf = NULL;
+
+  /* We only need to handle the case of relaxing, or of having a
+     particular set of section contents, specially.  */
+  if (relocateable
+      || elf_section_data (input_section)->this_hdr.contents == NULL)
+    return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
+						       link_order, data,
+						       relocateable,
+						       symbols);
+
+  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+
+  memcpy (data, elf_section_data (input_section)->this_hdr.contents,
 	  (size_t) input_section->_raw_size);
 
   if ((input_section->flags & SEC_RELOC) != 0
@@ -5143,6 +5924,22 @@
   return NULL;
 }
 
+#ifdef USE_SH_TLS32
+/* Return the base VMA address which should be subtracted from real addresses
+   when resolving @dtpoff relocation.
+   This is PT_TLS segment p_vaddr.  */
+
+static bfd_vma
+dtpoff_base (info)
+     struct bfd_link_info *info;
+{
+ /* If tls_segment is NULL, we should have signalled an error already.  */
+ if (elf_hash_table (info)->tls_segment == NULL)
+   return 0;
+  return elf_hash_table (info)->tls_segment->start;
+}
+#endif
+
 static asection *
 sh_elf_gc_mark_hook (sec, info, rel, h, sym)
      asection *sec;
@@ -5209,8 +6006,21 @@
 
   relend = relocs + sec->reloc_count;
   for (rel = relocs; rel < relend; rel++)
+#ifdef USE_SH_TLS32
+    switch (sh_elf_tls_transition (info, ELF32_R_TYPE (rel->r_info),
+				   ELF32_R_SYM (rel->r_info)
+				   >= symtab_hdr->sh_info))
+#else
     switch (ELF32_R_TYPE (rel->r_info))
+#endif
       {
+#ifdef USE_SH_TLS32
+      case R_SH_TLS_LD_32:
+	if (sh_elf_hash_table (info)->tls_ldm_got.refcount > 0)
+	  sh_elf_hash_table (info)->tls_ldm_got.refcount -= 1;
+	break;
+#endif
+
       case R_SH_GOT32:
       case R_SH_GOTOFF:
       case R_SH_GOTPC:
@@ -5230,6 +6040,10 @@
       case R_SH_GOTPC_MEDHI16:
       case R_SH_GOTPC_HI16:
 #endif
+#ifdef USE_SH_TLS32
+      case R_SH_TLS_GD_32:
+      case R_SH_TLS_IE_32:
+#endif
 	r_symndx = ELF32_R_SYM (rel->r_info);
 	if (r_symndx >= symtab_hdr->sh_info)
 	  {
@@ -5366,9 +6180,42 @@
       eind->dyn_relocs = NULL;
     }
 
+#ifdef USE_SH_TLS32
+  if (ind->root.type == bfd_link_hash_indirect
+      && dir->got.refcount <= 0)
+    {
+      edir->tls_type = eind->tls_type;
+      eind->tls_type = GOT_UNKNOWN;
+    }
+#endif
   _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
 }
 
+#ifdef USE_SH_TLS32
+static int
+sh_elf_tls_transition (info, r_type, is_local)
+     struct bfd_link_info *info;
+     int r_type;
+     int is_local;
+{
+  if (info->shared)
+    return r_type;
+
+  switch (r_type)
+    {
+    case R_SH_TLS_GD_32:
+    case R_SH_TLS_IE_32:
+      if (is_local)
+	return R_SH_TLS_LE_32;
+      return R_SH_TLS_IE_32;
+    case R_SH_TLS_LD_32:
+      return R_SH_TLS_LE_32;
+    }
+
+  return r_type;
+}
+#endif
+
 /* Look through the relocs for a section during the first phase.
    Since we don't do .gots or .plts, we just need to consider the
    virtual table relocs for gc.  */
@@ -5390,6 +6237,10 @@
   asection *sgot;
   asection *srelgot;
   asection *sreloc;
+  unsigned int r_type;
+#ifdef USE_SH_TLS32
+  int tls_type, old_tls_type;
+#endif
 
   sgot = NULL;
   srelgot = NULL;
@@ -5415,15 +6266,29 @@
       unsigned long r_symndx;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
+      r_type = ELF32_R_TYPE (rel->r_info);
+
       if (r_symndx < symtab_hdr->sh_info)
 	h = NULL;
       else
 	h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
+#ifdef USE_SH_TLS32
+      r_type = sh_elf_tls_transition (info, r_type, h == NULL);
+      if (! info->shared
+	  && r_type == R_SH_TLS_IE_32
+	  && h != NULL
+	  && h->root.type != bfd_link_hash_undefined
+	  && h->root.type != bfd_link_hash_undefweak
+	  && (h->dynindx == -1
+	      || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+	r_type = R_SH_TLS_LE_32;
+#endif
+
       /* Some relocs require a global offset table.  */
       if (htab->sgot == NULL)
 	{
-	  switch (ELF32_R_TYPE (rel->r_info))
+	  switch (r_type)
 	    {
 	    case R_SH_GOTPLT32:
 	    case R_SH_GOT32:
@@ -5451,6 +6316,11 @@
 	    case R_SH_GOTPC_MEDHI16:
 	    case R_SH_GOTPC_HI16:
 #endif
+#ifdef USE_SH_TLS32
+	    case R_SH_TLS_GD_32:
+	    case R_SH_TLS_LD_32:
+	    case R_SH_TLS_IE_32:
+#endif
 	      if (dynobj == NULL)
 		htab->root.dynobj = dynobj = abfd;
 	      if (! create_got_section (dynobj, info))
@@ -5462,7 +6332,7 @@
 	    }
 	}
 
-      switch (ELF32_R_TYPE (rel->r_info))
+      switch (r_type)
 	{
 	  /* This relocation describes the C++ object vtable hierarchy.
 	     Reconstruct it for later use during GC.  */
@@ -5479,6 +6349,13 @@
 	  break;
 
 	force_got:
+#ifdef USE_SH_TLS32
+	case R_SH_TLS_IE_32:
+	  if (info->shared)
+	    info->flags |= DF_STATIC_TLS;
+	  /* FALLTHROUGH */
+	case R_SH_TLS_GD_32:
+#endif
 	case R_SH_GOT32:
 #ifdef INCLUDE_SHMEDIA
 	case R_SH_GOT_LOW16:
@@ -5488,8 +6365,28 @@
 	case R_SH_GOT10BY4:
 	case R_SH_GOT10BY8:
 #endif
+#ifdef USE_SH_TLS32
+	  switch (r_type)
+	    {
+	    default:
+	      tls_type = GOT_NORMAL;
+	      break;
+	    case R_SH_TLS_GD_32:
+	      tls_type = GOT_TLS_GD;
+	      break;
+	    case R_SH_TLS_IE_32:
+	      tls_type = GOT_TLS_IE;
+	      break;
+	    }
+#endif
+
 	  if (h != NULL)
-	    h->got.refcount += 1;
+	    {
+	      h->got.refcount += 1;
+#ifdef USE_SH_TLS32
+	      old_tls_type = sh_elf_hash_entry(h)->tls_type;
+#endif
+	    }
 	  else
 	    {
 	      bfd_signed_vma *local_got_refcounts;
@@ -5508,15 +6405,61 @@
 		     codelabel local GOT offsets.  */
 		  size *= 2;
 #endif
+#ifdef USE_SH_TLS32
+		  size += symtab_hdr->sh_info * sizeof (char);
+#endif
 		  local_got_refcounts = ((bfd_signed_vma *)
 					 bfd_zalloc (abfd, size));
 		  if (local_got_refcounts == NULL)
 		    return false;
 		  elf_local_got_refcounts (abfd) = local_got_refcounts;
+#ifdef USE_SH_TLS32
+#ifdef 	INCLUDE_SHMEDIA
+		  sh_elf_local_got_tls_type (abfd)
+		    = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info);
+#else
+		  sh_elf_local_got_tls_type (abfd)
+		    = (char *) (local_got_refcounts + symtab_hdr->sh_info);
+#endif
+#endif
 		}
 	      local_got_refcounts[r_symndx] += 1;
+#ifdef USE_SH_TLS32
+	      old_tls_type = sh_elf_local_got_tls_type (abfd) [r_symndx];
+#endif
+	    }
+
+#ifdef USE_SH_TLS32
+	  /* If a TLS symbol is accessed using IE at least once,
+	     there is no point to use dynamic model for it.  */
+	  if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
+	      && (old_tls_type != GOT_TLS_GD || tls_type != GOT_TLS_IE))
+	    {
+	      if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD)
+		tls_type = GOT_TLS_IE;
+	      else
+		{
+		  (*_bfd_error_handler)
+		    (_("%s: `%s' accessed both as normal and thread local symbol"),
+		     bfd_archive_filename (abfd), h->root.root.string);
+		  return false;
+		}
+	    }
+
+	  if (old_tls_type != tls_type)
+	    {
+	      if (h != NULL)
+		sh_elf_hash_entry(h)->tls_type = tls_type;
+	      else
+		sh_elf_local_got_tls_type (abfd) [r_symndx] = tls_type;
 	    }
+
+	  break;
+
+	case R_SH_TLS_LD_32:
+	  sh_elf_hash_table(info)->tls_ldm_got.refcount += 1;
 	  break;
+#endif
 
 	case R_SH_GOTPLT32:
 #ifdef INCLUDE_SHMEDIA
@@ -5597,7 +6540,7 @@
 	     symbol.  */
 	  if ((info->shared
 	       && (sec->flags & SEC_ALLOC) != 0
-	       && (ELF32_R_TYPE (rel->r_info) != R_SH_REL32
+	       && (r_type != R_SH_REL32
 		   || (h != NULL
 		       && (! info->symbolic
 			   || h->root.type == bfd_link_hash_defweak
@@ -5687,11 +6630,112 @@
 		}
 
 	      p->count += 1;
-	      if (ELF32_R_TYPE (rel->r_info) == R_SH_REL32)
+	      if (r_type == R_SH_REL32)
 		p->pc_count += 1;
 	    }
 
 	  break;
+
+#ifdef USE_SH_TLS32
+	case R_SH_TLS_LE_32:
+	  if (info->shared)
+	    {
+	      (*_bfd_error_handler) (_("%s: TLS local exec code cannot be linked into shared objects"),
+				     bfd_archive_filename (abfd));
+	      return false;
+	    }
+
+	  if (ELF32_R_TYPE (rel->r_info) == R_SH_TLS_LD_32)
+	    break;
+
+	  /* FALLTHROUGH */
+	case R_SH_TLS_LDO_32:
+	  /* We make a R_SH_TLS_TPOFF32 relocation. Count it as a
+	     copy relocation.  */
+	  if (! info->shared)
+	    {
+	      struct elf_sh_dyn_relocs *p;
+	      struct elf_sh_dyn_relocs **head;
+
+	      if (dynobj == NULL)
+		htab->root.dynobj = dynobj = abfd;
+
+	      if (sreloc == NULL)
+		{
+		  const char *name;
+
+		  name = (bfd_elf_string_from_elf_section
+			  (abfd,
+			   elf_elfheader (abfd)->e_shstrndx,
+			   elf_section_data (sec)->rel_hdr.sh_name));
+		  if (name == NULL)
+		    return false;
+
+		  BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+			      && strcmp (bfd_get_section_name (abfd, sec),
+					 name + 5) == 0);
+
+		  sreloc = bfd_get_section_by_name (dynobj, name);
+		  if (sreloc == NULL)
+		    {
+		      flagword flags;
+
+		      sreloc = bfd_make_section (dynobj, name);
+		      flags = (SEC_HAS_CONTENTS | SEC_READONLY
+			       | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+		      if ((sec->flags & SEC_ALLOC) != 0)
+			flags |= SEC_ALLOC | SEC_LOAD;
+		      if (sreloc == NULL
+			  || ! bfd_set_section_flags (dynobj, sreloc, flags)
+			  || ! bfd_set_section_alignment (dynobj, sreloc, 2))
+			return false;
+		    }
+		  elf_section_data (sec)->sreloc = sreloc;
+		  if (sec->flags & SEC_READONLY)
+		    info->flags |= DF_TEXTREL;
+		}
+
+	      /* If this is a global symbol, we count the number of
+		 relocations we need for this symbol.  */
+	      if (h != NULL)
+		head = &((struct elf_sh_link_hash_entry *) h)->dyn_relocs;
+	      else
+		{
+		  asection *s;
+
+		  /* Track dynamic relocs needed for local syms too.  */
+		  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
+						 sec, r_symndx);
+		  if (s == NULL)
+		    return false;
+
+		  head = ((struct elf_sh_dyn_relocs **)
+			  &elf_section_data (s)->local_dynrel);
+		}
+
+	      p = *head;
+	      if (p == NULL || p->sec != sec)
+		{
+		  bfd_size_type amt = sizeof (*p);
+		  p = ((struct elf_sh_dyn_relocs *) bfd_alloc (dynobj, amt));
+		  if (p == NULL)
+		    return false;
+		  p->next = *head;
+		  *head = p;
+		  p->sec = sec;
+		  p->count = 0;
+		  p->pc_count = 0;
+		}
+
+	      p->count += 1;
+	      if (h)
+		sh_elf_hash_entry(h)->tls_tpoff32 = true;
+	    }
+	  break;
+#endif
+
+	default:
+	  break;
 	}
     }
 
@@ -5812,6 +6856,27 @@
 }
 #endif /* not sh_elf_merge_private_data */
 
+#ifdef USE_SH_TLS32
+static boolean
+sh_elf_object_p (abfd)
+  bfd *abfd;
+{
+  struct sh_elf_obj_tdata *new_tdata;
+  bfd_size_type amt = sizeof (struct sh_elf_obj_tdata);
+
+  if (sh_elf_set_mach_from_flags (abfd) == false)
+    return false;
+
+  /* Allocate our special target data.  */
+  new_tdata = bfd_zalloc (abfd, amt);
+  if (new_tdata == NULL)
+    return false;
+  new_tdata->root = *abfd->tdata.elf_obj_data;
+  abfd->tdata.any = new_tdata;
+  return true;
+}
+#endif
+
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
@@ -5968,7 +7033,12 @@
 	}
     }
 
-  if (h->got.offset != (bfd_vma) -1)
+  if (h->got.offset != (bfd_vma) -1
+#ifdef USE_SH_TLS32
+      && sh_elf_hash_entry(h)->tls_type != GOT_TLS_GD
+      && sh_elf_hash_entry(h)->tls_type != GOT_TLS_IE
+#endif
+      )
     {
       asection *sgot;
       asection *srel;
@@ -6257,7 +7327,12 @@
 #define elf_backend_relocate_section	sh_elf_relocate_section
 #define bfd_elf32_bfd_get_relocated_section_contents \
 					sh_elf_get_relocated_section_contents
+#ifdef USE_SH_TLS32
+#define bfd_elf32_mkobject		sh_elf_mkobject
+#define elf_backend_object_p		sh_elf_object_p
+#else
 #define elf_backend_object_p		sh_elf_set_mach_from_flags
+#endif
 #define bfd_elf32_bfd_set_private_bfd_flags \
 					sh_elf_set_private_flags
 #define bfd_elf32_bfd_copy_private_bfd_data \
diff -urN ORIG/src/bfd/reloc.c LOCAL/src/bfd/reloc.c
--- ORIG/src/bfd/reloc.c	Sat Sep 28 11:48:32 2002
+++ LOCAL/src/bfd/reloc.c	Tue Oct  1 07:54:30 2002
@@ -2575,6 +2575,30 @@
   BFD_RELOC_SH_IMM_HI16_PCREL
 ENUMX
   BFD_RELOC_SH_PT_16
+ENUMX
+  BFD_RELOC_SH_TLS_GD_32
+ENUMX
+  BFD_RELOC_SH_TLS_LD_32
+ENUMX
+  BFD_RELOC_SH_TLS_LDO_32
+ENUMX
+  BFD_RELOC_SH_TLS_IE_32
+ENUMX
+  BFD_RELOC_SH_TLS_LE_32
+ENUMX
+  BFD_RELOC_SH_TLS_DTPMOD32
+ENUMX
+  BFD_RELOC_SH_TLS_DTPOFF32
+ENUMX
+  BFD_RELOC_SH_TLS_TPOFF32
+ENUMX
+  BFD_RELOC_SH_TLS_GD_MOV
+ENUMX
+  BFD_RELOC_SH_TLS_LDM_MOV
+ENUMX
+  BFD_RELOC_SH_TLS_LDO_MOV
+ENUMX
+  BFD_RELOC_SH_TLS_IE_MOV
 ENUMDOC
   Hitachi SH relocs.  Not all of these appear in object files.
 
diff -urN ORIG/src/gas/config/tc-sh.c LOCAL/src/gas/config/tc-sh.c
--- ORIG/src/gas/config/tc-sh.c	Sat Sep 28 11:48:34 2002
+++ LOCAL/src/gas/config/tc-sh.c	Tue Oct  1 07:55:57 2002
@@ -52,6 +52,7 @@
 
 static void sh_count_relocs PARAMS ((bfd *, segT, PTR));
 static void sh_frob_section PARAMS ((bfd *, segT, PTR));
+static void sh_frob_tls_section PARAMS ((bfd *, segT, PTR));
 
 static void s_uacons PARAMS ((int));
 static sh_opcode_info *find_cooked_opcode PARAMS ((char **));
@@ -2896,6 +2897,84 @@
     }
 }
 
+static void
+sh_frob_tls_section (abfd, sec, ignore)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     segT sec;
+     PTR ignore ATTRIBUTE_UNUSED;
+{
+  segment_info_type *seginfo;
+  fixS *fix;
+  bfd_reloc_code_real_type r_type = BFD_RELOC_UNUSED;
+
+  seginfo = seg_info (sec);
+  if (seginfo == NULL)
+    return;
+
+  for (fix = seginfo->fix_root; fix != NULL; fix = fix->fx_next)
+    {
+      symbolS *sym;
+      bfd_vma val;
+      fixS *fscan;
+
+      if (fix->fx_r_type != BFD_RELOC_SH_PCRELIMM8BY4)
+	continue;
+
+      sym = fix->fx_addsy;
+      if (sym == NULL)
+	continue;
+
+      val = S_GET_VALUE (sym);
+
+      for (fscan = fix->fx_next; fscan != NULL; fscan = fscan->fx_next)
+	{
+	  if (fscan->fx_frag->fr_address + fscan->fx_where != val)
+	    continue;
+
+	  switch (fscan->fx_r_type)
+	    {
+	    case BFD_RELOC_SH_TLS_GD_32:
+	      r_type = BFD_RELOC_SH_TLS_GD_MOV;
+	      goto found;
+
+	    case BFD_RELOC_SH_TLS_LD_32:
+	      r_type = BFD_RELOC_SH_TLS_LDM_MOV;
+	      goto found;
+
+	    case BFD_RELOC_SH_TLS_LDO_32:
+	      r_type = BFD_RELOC_SH_TLS_LDO_MOV;
+	      goto found;
+
+	    case BFD_RELOC_SH_TLS_IE_32:
+	      r_type = BFD_RELOC_SH_TLS_IE_MOV;
+	      goto found;
+
+	    default:
+	      break;
+	    }
+	}
+
+    found:
+      if (fscan == NULL)
+	continue;
+
+      /* Generate a BFD_RELOC_SH_TLS_*_*MOV fixup here.  */
+      subseg_change (sec, 0);
+      {
+	fixS **seg_fix_tailP = &seg_info (now_seg)->fix_tail;
+	fixS *new, *otail = *seg_fix_tailP;
+
+	new = fix_new (fix->fx_frag, fix->fx_where, 2, fscan->fx_addsy,
+		       0, 0, r_type);
+
+	otail->fx_next = NULL;
+	*seg_fix_tailP = otail;
+	new->fx_next = fix->fx_next;
+	fix->fx_next = new;
+      }
+    }
+}
+
 /* This function is called after the symbol table has been completed,
    but before the relocs or section contents have been written out.
    If we have seen any .uses pseudo-ops, they point to an instruction
@@ -2913,6 +2992,10 @@
   shmedia_frob_file_before_adjust ();
 #endif
 
+#ifdef BFD_ASSEMBLER
+  bfd_map_over_sections (stdoutput, sh_frob_tls_section, (PTR) NULL);
+#endif
+
   if (! sh_relax)
     return;
 
@@ -3536,11 +3619,22 @@
 
     case BFD_RELOC_32_GOT_PCREL:
     case BFD_RELOC_SH_GOTPLT32:
+    case BFD_RELOC_SH_TLS_GD_32:
+    case BFD_RELOC_SH_TLS_LD_32:
+    case BFD_RELOC_SH_TLS_IE_32:
       * valP = 0; /* Fully resolved at runtime.  No addend.  */
       md_number_to_chars (buf, 0, 4);
       break;
 
+    case BFD_RELOC_SH_TLS_GD_MOV:
+    case BFD_RELOC_SH_TLS_LDM_MOV:
+    case BFD_RELOC_SH_TLS_LDO_MOV:
+    case BFD_RELOC_SH_TLS_IE_MOV:
+      break;
+
     case BFD_RELOC_32_GOTOFF:
+    case BFD_RELOC_SH_TLS_LDO_32:
+    case BFD_RELOC_SH_TLS_LE_32:
       md_number_to_chars (buf, val, 4);
       break;
 #endif
@@ -4006,6 +4100,16 @@
     reloc_type = BFD_RELOC_32_GOT_PCREL;
   else if ((next_end = sh_end_of_match (next + 1, "PLT")))
     reloc_type = BFD_RELOC_32_PLT_PCREL;
+  else if ((next_end = sh_end_of_match (next + 1, "TLSGD")))
+    reloc_type = BFD_RELOC_SH_TLS_GD_32;
+  else if ((next_end = sh_end_of_match (next + 1, "TLSLDM")))
+    reloc_type = BFD_RELOC_SH_TLS_LD_32;
+  else if ((next_end = sh_end_of_match (next + 1, "GOTTPOFF")))
+    reloc_type = BFD_RELOC_SH_TLS_IE_32;
+  else if ((next_end = sh_end_of_match (next + 1, "TPOFF")))
+    reloc_type = BFD_RELOC_SH_TLS_LE_32;
+  else if ((next_end = sh_end_of_match (next + 1, "DTPOFF")))
+    reloc_type = BFD_RELOC_SH_TLS_LDO_32;
   else
     goto no_suffix;
 
diff -urN ORIG/src/gas/testsuite/gas/sh/basic.exp LOCAL/src/gas/testsuite/gas/sh/basic.exp
--- ORIG/src/gas/testsuite/gas/sh/basic.exp	Sat Sep 28 11:48:35 2002
+++ LOCAL/src/gas/testsuite/gas/sh/basic.exp	Sat Sep 28 12:49:04 2002
@@ -136,4 +136,13 @@
     if {[istarget sh*-*elf] || [istarget sh*-linux*]} then {
 	run_dump_test "pic"
     }
+
+    if {[istarget "sh*-linux*"] && ![istarget sh64*-linux*]} then {
+	# Test TLS.
+	run_dump_test "tlsd"
+
+	run_dump_test "tlspic"
+
+	run_dump_test "tlsnopic"
+    }
 }
diff -urN ORIG/src/gas/testsuite/gas/sh/pcrel2.d LOCAL/src/gas/testsuite/gas/sh/pcrel2.d
--- ORIG/src/gas/testsuite/gas/sh/pcrel2.d	Sat Sep 28 09:41:27 2002
+++ LOCAL/src/gas/testsuite/gas/sh/pcrel2.d	Tue Oct  1 16:55:44 2002
@@ -1,5 +1,7 @@
 #as: -big
-#objdump: -r
+#objdump: -rj.text
 #name: PC-relative loads
 
 .*:     file format .*sh.*
+
+RELOCATION RECORDS FOR \[\.text\]: \(none\)
diff -urN ORIG/src/gas/testsuite/gas/sh/tlsd.d LOCAL/src/gas/testsuite/gas/sh/tlsd.d
--- ORIG/src/gas/testsuite/gas/sh/tlsd.d	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/gas/testsuite/gas/sh/tlsd.d	Sat Sep 28 12:51:27 2002
@@ -0,0 +1,58 @@
+#objdump: -dr
+#name: sh dynamic tls
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <fn>:
+   0:	2f c6 [ 	]*mov\.l	r12,@-r15
+   2:	2f e6 [ 	]*mov\.l	r14,@-r15
+   4:	4f 22 [ 	]*sts\.l	pr,@-r15
+   6:	c7 14 [ 	]*mova	58 <fn\+0x58>,r0
+   8:	dc 13 [ 	]*mov\.l	58 <fn\+0x58>,r12[ 	]+! 0x0
+   a:	3c 0c [ 	]*add	r0,r12
+   c:	6e f3 [ 	]*mov	r15,r14
+   e:	d4 04 [ 	]*mov\.l	20 <fn\+0x20>,r4[ 	]+! 0x0
+[ 	]+e: R_SH_TLS_GD_MOV	foo
+  10:	c7 04 [ 	]*mova	24 <fn\+0x24>,r0
+  12:	d1 04 [ 	]*mov\.l	24 <fn\+0x24>,r1[ 	]+! 0x0
+  14:	31 0c [ 	]*add	r0,r1
+  16:	41 0b [ 	]*jsr	@r1
+  18:	34 cc [ 	]*add	r12,r4
+  1a:	a0 05 [ 	]*bra	28 <fn\+0x28>
+  1c:	00 09 [ 	]*nop	
+  1e:	00 09 [ 	]*nop	
+	\.\.\.
+[ 	]+20: R_SH_TLS_GD_32	foo
+[ 	]+24: R_SH_PLT32	__tls_get_addr
+  28:	d4 03 [ 	]*mov\.l	38 <fn\+0x38>,r4[ 	]+! 0x0
+[ 	]+28: R_SH_TLS_LDM_MOV	bar
+  2a:	c7 04 [ 	]*mova	3c <fn\+0x3c>,r0
+  2c:	d1 03 [ 	]*mov\.l	3c <fn\+0x3c>,r1[ 	]+! 0x0
+  2e:	31 0c [ 	]*add	r0,r1
+  30:	41 0b [ 	]*jsr	@r1
+  32:	34 cc [ 	]*add	r12,r4
+  34:	a0 04 [ 	]*bra	40 <fn\+0x40>
+  36:	00 09 [ 	]*nop	
+	\.\.\.
+[ 	]+38: R_SH_TLS_LD_32	bar
+[ 	]+3c: R_SH_PLT32	__tls_get_addr
+  40:	e2 01 [ 	]*mov	#1,r2
+  42:	d1 06 [ 	]*mov\.l	5c <fn\+0x5c>,r1[ 	]+! 0x0
+[ 	]+42: R_SH_TLS_LDO_MOV	bar
+  44:	30 1c [ 	]*add	r1,r0
+  46:	20 22 [ 	]*mov\.l	r2,@r0
+  48:	d1 05 [ 	]*mov\.l	60 <fn\+0x60>,r1[ 	]+! 0x0
+[ 	]+48: R_SH_TLS_LDO_MOV	baz
+  4a:	30 1c [ 	]*add	r1,r0
+  4c:	6f e3 [ 	]*mov	r14,r15
+  4e:	4f 26 [ 	]*lds\.l	@r15\+,pr
+  50:	6e f6 [ 	]*mov\.l	@r15\+,r14
+  52:	00 0b [ 	]*rts	
+  54:	6c f6 [ 	]*mov\.l	@r15\+,r12
+  56:	00 09 [ 	]*nop	
+	\.\.\.
+[ 	]+58: R_SH_GOTPC	_GLOBAL_OFFSET_TABLE_
+[ 	]+5c: R_SH_TLS_LDO_32	bar
+[ 	]+60: R_SH_TLS_LDO_32	baz
diff -urN ORIG/src/gas/testsuite/gas/sh/tlsd.s LOCAL/src/gas/testsuite/gas/sh/tlsd.s
--- ORIG/src/gas/testsuite/gas/sh/tlsd.s	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/gas/testsuite/gas/sh/tlsd.s	Sat Sep 28 12:10:11 2002
@@ -0,0 +1,71 @@
+	.section	.tbss,"awT",@nobits
+	.align 2
+	.global	foo, bar
+	.hidden bar
+foo:	.long	25
+bar:	.long	27
+baz:	.long	29
+	.text
+	.align 1
+	.global	fn
+	.type	fn, @function
+fn:
+	mov.l	r12,@-r15
+	mov.l	r14,@-r15
+	sts.l	pr,@-r15
+	mova	.L3,r0
+	mov.l	.L3,r12
+	add	r0,r12
+	mov	r15,r14
+
+	! Dynamic TLS model, foo not known to be in the current object
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	foo@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+
+	! Dynamic TLS model, bar and baz known to be in the current object
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	bar@TLSLDM
+2:	.long	__tls_get_addr@PLT
+3:
+	! Just show that there can be arbitrary instructions here
+	mov	#1,r2
+
+	mov.l	.L4,r1
+	add	r1,r0
+	! r0 now contains &bar
+
+	! Again, arbitrary instructions
+	mov.l	r2,@r0
+
+	mov.l	.L5,r1
+	add	r1,r0
+	! r0 now contains &baz
+
+	mov	r14,r15
+	lds.l	@r15+,pr
+	mov.l	@r15+,r14
+	rts	
+	mov.l	@r15+,r12
+
+	.align	2
+.L3:	.long	_GLOBAL_OFFSET_TABLE_
+.L4:	.long	bar@DTPOFF
+.L5:	.long	baz@DTPOFF
diff -urN ORIG/src/gas/testsuite/gas/sh/tlsnopic.d LOCAL/src/gas/testsuite/gas/sh/tlsnopic.d
--- ORIG/src/gas/testsuite/gas/sh/tlsnopic.d	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/gas/testsuite/gas/sh/tlsnopic.d	Tue Oct  1 07:57:55 2002
@@ -0,0 +1,19 @@
+#objdump: -dr
+#name: sh non-pic tls
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <fn>:
+   0:	2f e6 [ 	]*mov\.l	r14,@-r15
+   2:	6e f3 [ 	]*mov	r15,r14
+   4:	01 12 [ 	]*stc	gbr,r1
+   6:	d0 02 [ 	]*mov\.l	10 <fn\+0x10>,r0[ 	]+! 0x0
+   8:	30 1c [ 	]*add	r1,r0
+   a:	6f e3 [ 	]*mov	r14,r15
+   c:	00 0b [ 	]*rts	
+   e:	6e f6 [ 	]*mov\.l	@r15\+,r14
+  10:	00 00 [ 	]*\.word 0x0+0
+[ 	]+10: R_SH_TLS_LE_32	foo
+	\.\.\.
diff -urN ORIG/src/gas/testsuite/gas/sh/tlsnopic.s LOCAL/src/gas/testsuite/gas/sh/tlsnopic.s
--- ORIG/src/gas/testsuite/gas/sh/tlsnopic.s	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/gas/testsuite/gas/sh/tlsnopic.s	Sat Sep 28 12:10:21 2002
@@ -0,0 +1,23 @@
+	.section	.tbss,"awT",@nobits
+	.align 2
+	.long	foo
+	.text
+	.align 1
+	.global	fn
+	.type	fn, @function
+fn:
+	! Main binary, no PIC
+	mov.l	r14,@-r15
+	mov	r15,r14
+
+	stc	gbr,r1
+	mov.l	.L2,r0
+	add	r1,r0
+	! r0 now contains &foo
+
+	mov	r14,r15
+	rts	
+	mov.l	@r15+,r14
+.L3:
+	.align 2
+.L2:	.long	foo@TPOFF
diff -urN ORIG/src/gas/testsuite/gas/sh/tlspic.d LOCAL/src/gas/testsuite/gas/sh/tlspic.d
--- ORIG/src/gas/testsuite/gas/sh/tlspic.d	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/gas/testsuite/gas/sh/tlspic.d	Sat Sep 28 12:52:25 2002
@@ -0,0 +1,33 @@
+#objdump: -dr
+#name: sh pic tls
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <fn>:
+   0:	2f c6 [ 	]*mov\.l	r12,@-r15
+   2:	2f e6 [ 	]*mov\.l	r14,@-r15
+   4:	6e f3 [ 	]*mov	r15,r14
+   6:	c7 08 [ 	]*mova	28 <fn\+0x28>,r0
+   8:	dc 07 [ 	]*mov\.l	28 <fn\+0x28>,r12[ 	]+! 0x0
+   a:	3c 0c [ 	]*add	r0,r12
+   c:	d0 02 [ 	]*mov\.l	18 <fn\+0x18>,r0[ 	]+! 0x0
+[ 	]+c: R_SH_TLS_IE_MOV	foo
+   e:	01 12 [ 	]*stc	gbr,r1
+  10:	00 ce [ 	]*mov\.l	@\(r0,r12\),r0
+  12:	a0 03 [ 	]*bra	1c <fn\+0x1c>
+  14:	31 0c [ 	]*add	r0,r1
+  16:	00 09 [ 	]*nop	
+  18:	00 00 [ 	]*\.word 0x0000
+[ 	]+18: R_SH_TLS_IE_32	foo
+  1a:	00 00 [ 	]*\.word 0x0000
+  1c:	60 13 [ 	]*mov	r1,r0
+  1e:	6f e3 [ 	]*mov	r14,r15
+  20:	6e f6 [ 	]*mov\.l	@r15\+,r14
+  22:	00 0b [ 	]*rts	
+  24:	6c f6 [ 	]*mov\.l	@r15\+,r12
+  26:	00 09 [ 	]*nop	
+  28:	00 00 [ 	]*\.word 0x0+0
+[ 	]+28: R_SH_GOTPC	_GLOBAL_OFFSET_TABLE_
+	\.\.\.
diff -urN ORIG/src/gas/testsuite/gas/sh/tlspic.s LOCAL/src/gas/testsuite/gas/sh/tlspic.s
--- ORIG/src/gas/testsuite/gas/sh/tlspic.s	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/gas/testsuite/gas/sh/tlspic.s	Sat Sep 28 12:43:48 2002
@@ -0,0 +1,30 @@
+	.text
+	.align 1
+	.global	fn
+	.type	fn, @function
+fn:
+	! Main binary, PIC
+	mov.l	r12,@-r15
+	mov.l	r14,@-r15
+	mov	r15,r14
+	mova	.L3,r0
+	mov.l	.L3,r12
+	add	r0,r12
+
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	foo@GOTTPOFF
+2:	! now r1 contains &foo
+
+	mov	r1,r0
+	mov	r14,r15
+	mov.l	@r15+,r14
+	rts	
+	mov.l	@r15+,r12
+
+	.align 2
+.L3:	.long	_GLOBAL_OFFSET_TABLE_
diff -urN ORIG/src/include/elf/sh.h LOCAL/src/include/elf/sh.h
--- ORIG/src/include/elf/sh.h	Sat Jun 29 10:30:15 2002
+++ LOCAL/src/include/elf/sh.h	Tue Oct  1 07:53:39 2002
@@ -167,7 +167,21 @@
   RELOC_NUMBER (R_SH_DIR10SL, 50)
   RELOC_NUMBER (R_SH_DIR10SQ, 51)
   FAKE_RELOC (R_SH_FIRST_INVALID_RELOC_3, 52)
-  FAKE_RELOC (R_SH_LAST_INVALID_RELOC_3, 159)
+  FAKE_RELOC (R_SH_LAST_INVALID_RELOC_3, 143)
+  RELOC_NUMBER (R_SH_TLS_GD_32, 144)
+  RELOC_NUMBER (R_SH_TLS_LD_32, 145)
+  RELOC_NUMBER (R_SH_TLS_LDO_32, 146)
+  RELOC_NUMBER (R_SH_TLS_IE_32, 147)
+  RELOC_NUMBER (R_SH_TLS_LE_32, 148)
+  RELOC_NUMBER (R_SH_TLS_DTPMOD32, 149)
+  RELOC_NUMBER (R_SH_TLS_DTPOFF32, 150)
+  RELOC_NUMBER (R_SH_TLS_TPOFF32, 151)
+  RELOC_NUMBER (R_SH_TLS_GD_MOV, 152)
+  RELOC_NUMBER (R_SH_TLS_LDM_MOV, 153)
+  RELOC_NUMBER (R_SH_TLS_LDO_MOV, 154)
+  RELOC_NUMBER (R_SH_TLS_IE_MOV, 155)
+  FAKE_RELOC (R_SH_FIRST_INVALID_RELOC_4, 156)
+  FAKE_RELOC (R_SH_LAST_INVALID_RELOC_4, 159)
   RELOC_NUMBER (R_SH_GOT32, 160)
   RELOC_NUMBER (R_SH_PLT32, 161)
   RELOC_NUMBER (R_SH_COPY, 162)
@@ -205,8 +219,8 @@
   RELOC_NUMBER (R_SH_GLOB_DAT64, 194)
   RELOC_NUMBER (R_SH_JMP_SLOT64, 195)
   RELOC_NUMBER (R_SH_RELATIVE64, 196)
-  FAKE_RELOC (R_SH_FIRST_INVALID_RELOC_4, 197)
-  FAKE_RELOC (R_SH_LAST_INVALID_RELOC_4, 241)
+  FAKE_RELOC (R_SH_FIRST_INVALID_RELOC_5, 197)
+  FAKE_RELOC (R_SH_LAST_INVALID_RELOC_5, 241)
   RELOC_NUMBER (R_SH_SHMEDIA_CODE, 242)
   RELOC_NUMBER (R_SH_PT_16, 243)
   RELOC_NUMBER (R_SH_IMMS16, 244)
diff -urN ORIG/src/ld/testsuite/ld-sh/sh-tls.exp LOCAL/src/ld/testsuite/ld-sh/sh-tls.exp
--- ORIG/src/ld/testsuite/ld-sh/sh-tls.exp	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/sh-tls.exp	Mon Sep 30 11:17:03 2002
@@ -0,0 +1,41 @@
+# Expect script for ld-sh TLS tests
+#   Copyright 2002 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+# Test SH TLS handling.
+
+if {! [istarget sh*-*-linux*] || [istarget sh64*-*-linux*]} {
+    # Currently only for 32-bit linux target.
+    return
+}
+
+set tlstests {
+    {"TLS -fpic -shared transitions" "-shared -mshlelf_linux"
+     "" {tlspic1.s tlspic2.s}
+     {{readelf -Ssrl tlspic.rd} {objdump -drj.text tlspic.dd}
+      {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
+      "libtlspic.so"}
+     {"Helper shared library" "-shared -mshlelf_linux"
+    "" {tlslib.s} {} "libtlslib.so"}
+    {"TLS -fpic and -fno-pic exec transitions"
+    "-mshlelf_linux tmpdir/libtlslib.so" "" {tlsbinpic.s tlsbin.s}
+    {{readelf -Ssrl tlsbin.rd} {objdump -drj.text tlsbin.dd}
+    {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
+    "tlsbin"}
+}
+
+run_ld_link_tests $tlstests
diff -urN ORIG/src/ld/testsuite/ld-sh/tlsbin.dd LOCAL/src/ld/testsuite/ld-sh/tlsbin.dd
--- ORIG/src/ld/testsuite/ld-sh/tlsbin.dd	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlsbin.dd	Mon Sep 30 09:29:31 2002
@@ -0,0 +1,295 @@
+#source: tlsbinpic.s
+#source: tlsbin.s
+#ld: -mshlelf_linux tmpdir/libtlslib.so
+#objdump: -drj.text
+#target: sh*-linux*
+
+.*: +file format elf32-sh-linux
+
+Disassembly of section \.text:
+
+0+401000 <fn2>:
+  401000:	c6 2f       	mov\.l	r12,@-r15
+  401002:	e6 2f       	mov\.l	r14,@-r15
+  401004:	22 4f       	sts\.l	pr,@-r15
+  401006:	5f c7       	mova	401184 <fn2\+0x184>,r0
+  401008:	5e dc       	mov\.l	401184 <fn2\+0x184>,r12	! 0x[0-9a-f]+
+  40100a:	0c 3c       	add	r0,r12
+  40100c:	f3 6e       	mov	r15,r14
+  40100e:	09 00       	nop	
+  401010:	09 00       	nop	
+  401012:	09 00       	nop	
+  401014:	09 00       	nop	
+  401016:	04 d0       	mov\.l	401028 <fn2\+0x28>,r0	! 0x1c
+  401018:	12 04       	stc	gbr,r4
+  40101a:	ce 00       	mov\.l	@\(r0,r12\),r0
+  40101c:	4c 30       	add	r4,r0
+  40101e:	09 00       	nop	
+  401020:	09 00       	nop	
+  401022:	05 a0       	bra	401030 <fn2\+0x30>
+  401024:	09 00       	nop	
+  401026:	09 00       	nop	
+  401028:	1c 00       	.*[ 	]*.*
+  40102a:	00 00       	.*[ 	]*.*
+  40102c:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  40102e:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  401030:	09 00       	nop	
+  401032:	09 00       	nop	
+  401034:	09 00       	nop	
+  401036:	09 00       	nop	
+  401038:	03 d0       	mov\.l	401048 <fn2\+0x48>,r0	! 0x14
+  40103a:	12 04       	stc	gbr,r4
+  40103c:	ce 00       	mov\.l	@\(r0,r12\),r0
+  40103e:	4c 30       	add	r4,r0
+  401040:	09 00       	nop	
+  401042:	09 00       	nop	
+  401044:	04 a0       	bra	401050 <fn2\+0x50>
+  401046:	09 00       	nop	
+  401048:	14 00       	.*[ 	]*.*
+  40104a:	00 00       	.*[ 	]*.*
+  40104c:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  40104e:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  401050:	09 00       	nop	
+  401052:	09 00       	nop	
+  401054:	09 00       	nop	
+  401056:	09 00       	nop	
+  401058:	03 d4       	mov\.l	401068 <fn2\+0x68>,r4	! 0x0
+  40105a:	12 00       	stc	gbr,r0
+  40105c:	4c 30       	add	r4,r0
+  40105e:	09 00       	nop	
+  401060:	09 00       	nop	
+  401062:	09 00       	nop	
+  401064:	04 a0       	bra	401070 <fn2\+0x70>
+  401066:	09 00       	nop	
+  401068:	00 00       	.*[ 	]*.*
+  40106a:	00 00       	.*[ 	]*.*
+  40106c:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  40106e:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  401070:	09 00       	nop	
+  401072:	09 00       	nop	
+  401074:	09 00       	nop	
+  401076:	09 00       	nop	
+  401078:	03 d4       	mov\.l	401088 <fn2\+0x88>,r4	! 0x0
+  40107a:	12 00       	stc	gbr,r0
+  40107c:	4c 30       	add	r4,r0
+  40107e:	09 00       	nop	
+  401080:	09 00       	nop	
+  401082:	09 00       	nop	
+  401084:	04 a0       	bra	401090 <fn2\+0x90>
+  401086:	09 00       	nop	
+  401088:	00 00       	.*[ 	]*.*
+  40108a:	00 00       	.*[ 	]*.*
+  40108c:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  40108e:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  401090:	09 00       	nop	
+  401092:	09 00       	nop	
+  401094:	09 00       	nop	
+  401096:	09 00       	nop	
+  401098:	03 d4       	mov\.l	4010a8 <fn2\+0xa8>,r4	! 0x0
+  40109a:	12 00       	stc	gbr,r0
+  40109c:	4c 30       	add	r4,r0
+  40109e:	09 00       	nop	
+  4010a0:	09 00       	nop	
+  4010a2:	09 00       	nop	
+  4010a4:	04 a0       	bra	4010b0 <fn2\+0xb0>
+  4010a6:	09 00       	nop	
+  4010a8:	00 00       	.*[ 	]*.*
+  4010aa:	00 00       	.*[ 	]*.*
+  4010ac:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  4010ae:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  4010b0:	09 00       	nop	
+  4010b2:	09 00       	nop	
+  4010b4:	09 00       	nop	
+  4010b6:	09 00       	nop	
+  4010b8:	12 00       	stc	gbr,r0
+  4010ba:	09 00       	nop	
+  4010bc:	09 00       	nop	
+  4010be:	09 00       	nop	
+  4010c0:	09 00       	nop	
+  4010c2:	09 00       	nop	
+  4010c4:	04 a0       	bra	4010d0 <fn2\+0xd0>
+  4010c6:	09 00       	nop	
+  4010c8:	00 00       	.*[ 	]*.*
+  4010ca:	00 00       	.*[ 	]*.*
+  4010cc:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  4010ce:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  4010d0:	09 00       	nop	
+  4010d2:	09 00       	nop	
+  4010d4:	2c d1       	mov\.l	401188 <fn2\+0x188>,r1	! 0x0
+  4010d6:	0c 31       	add	r0,r1
+  4010d8:	09 00       	nop	
+  4010da:	09 00       	nop	
+  4010dc:	2b d2       	mov\.l	40118c <fn2\+0x18c>,r2	! 0x0
+  4010de:	0c 32       	add	r0,r2
+  4010e0:	09 00       	nop	
+  4010e2:	09 00       	nop	
+  4010e4:	09 00       	nop	
+  4010e6:	09 00       	nop	
+  4010e8:	12 00       	stc	gbr,r0
+  4010ea:	09 00       	nop	
+  4010ec:	09 00       	nop	
+  4010ee:	09 00       	nop	
+  4010f0:	09 00       	nop	
+  4010f2:	09 00       	nop	
+  4010f4:	04 a0       	bra	401100 <fn2\+0x100>
+  4010f6:	09 00       	nop	
+  4010f8:	00 00       	.*[ 	]*.*
+  4010fa:	00 00       	.*[ 	]*.*
+  4010fc:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  4010fe:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+  401100:	09 00       	nop	
+  401102:	09 00       	nop	
+  401104:	22 d1       	mov\.l	401190 <fn2\+0x190>,r1	! 0x0
+  401106:	0c 31       	add	r0,r1
+  401108:	09 00       	nop	
+  40110a:	09 00       	nop	
+  40110c:	21 d2       	mov\.l	401194 <fn2\+0x194>,r2	! 0x0
+  40110e:	0c 32       	add	r0,r2
+  401110:	09 00       	nop	
+  401112:	09 00       	nop	
+  401114:	09 00       	nop	
+  401116:	09 00       	nop	
+  401118:	02 d0       	mov\.l	401124 <fn2\+0x124>,r0	! 0x14
+  40111a:	12 01       	stc	gbr,r1
+  40111c:	ce 00       	mov\.l	@\(r0,r12\),r0
+  40111e:	03 a0       	bra	401128 <fn2\+0x128>
+  401120:	0c 31       	add	r0,r1
+  401122:	09 00       	nop	
+  401124:	14 00       	.*[ 	]*.*
+  401126:	00 00       	.*[ 	]*.*
+  401128:	09 00       	nop	
+  40112a:	09 00       	nop	
+  40112c:	09 00       	nop	
+  40112e:	09 00       	nop	
+  401130:	02 d0       	mov\.l	40113c <fn2\+0x13c>,r0	! 0x18
+  401132:	12 01       	stc	gbr,r1
+  401134:	ce 00       	mov\.l	@\(r0,r12\),r0
+  401136:	03 a0       	bra	401140 <fn2\+0x140>
+  401138:	1c 30       	add	r1,r0
+  40113a:	09 00       	nop	
+  40113c:	18 00       	.*[ 	]*.*
+  40113e:	00 00       	.*[ 	]*.*
+  401140:	09 00       	nop	
+  401142:	09 00       	nop	
+  401144:	09 00       	nop	
+  401146:	09 00       	nop	
+  401148:	02 d0       	mov\.l	401154 <fn2\+0x154>,r0	! 0x0
+  40114a:	12 01       	stc	gbr,r1
+  40114c:	09 00       	nop	
+  40114e:	03 a0       	bra	401158 <fn2\+0x158>
+  401150:	0c 31       	add	r0,r1
+  401152:	09 00       	nop	
+  401154:	00 00       	.*[ 	]*.*
+  401156:	00 00       	.*[ 	]*.*
+  401158:	09 00       	nop	
+  40115a:	09 00       	nop	
+  40115c:	09 00       	nop	
+  40115e:	09 00       	nop	
+  401160:	02 d0       	mov\.l	40116c <fn2\+0x16c>,r0	! 0x0
+  401162:	12 01       	stc	gbr,r1
+  401164:	09 00       	nop	
+  401166:	03 a0       	bra	401170 <fn2\+0x170>
+  401168:	0c 31       	add	r0,r1
+  40116a:	09 00       	nop	
+  40116c:	00 00       	.*[ 	]*.*
+  40116e:	00 00       	.*[ 	]*.*
+  401170:	09 00       	nop	
+  401172:	09 00       	nop	
+  401174:	09 00       	nop	
+  401176:	09 00       	nop	
+  401178:	e3 6f       	mov	r14,r15
+  40117a:	26 4f       	lds\.l	@r15\+,pr
+  40117c:	f6 6e       	mov\.l	@r15\+,r14
+  40117e:	0b 00       	rts	
+  401180:	f6 6c       	mov\.l	@r15\+,r12
+  401182:	09 00       	nop	
+  401184:	3c 1f       	.*[ 	]*.*
+  401186:	01 00       	.*[ 	]*.*
+	\.\.\.
+
+00402000 <_start>:
+  402000:	c6 2f       	mov\.l	r12,@-r15
+  402002:	e6 2f       	mov\.l	r14,@-r15
+  402004:	f3 6e       	mov	r15,r14
+  402006:	27 c7       	mova	4020a4 <_start\+0xa4>,r0
+  402008:	26 dc       	mov\.l	4020a4 <_start\+0xa4>,r12	! 0x[0-9a-f]+
+  40200a:	0c 3c       	add	r0,r12
+  40200c:	09 00       	nop	
+  40200e:	09 00       	nop	
+  402010:	09 00       	nop	
+  402012:	09 00       	nop	
+  402014:	02 d0       	mov\.l	402020 <_start\+0x20>,r0	! 0x10
+  402016:	12 01       	stc	gbr,r1
+  402018:	ce 00       	mov\.l	@\(r0,r12\),r0
+  40201a:	03 a0       	bra	402024 <_start\+0x24>
+  40201c:	0c 31       	add	r0,r1
+  40201e:	09 00       	nop	
+  402020:	10 00       	.*[ 	]*.*
+  402022:	00 00       	.*[ 	]*.*
+  402024:	09 00       	nop	
+  402026:	09 00       	nop	
+  402028:	09 00       	nop	
+  40202a:	09 00       	nop	
+  40202c:	02 d0       	mov\.l	402038 <_start\+0x38>,r0	! 0x0
+  40202e:	12 01       	stc	gbr,r1
+  402030:	09 00       	nop	
+  402032:	03 a0       	bra	40203c <_start\+0x3c>
+  402034:	0c 31       	add	r0,r1
+  402036:	09 00       	nop	
+  402038:	00 00       	.*[ 	]*.*
+  40203a:	00 00       	.*[ 	]*.*
+  40203c:	09 00       	nop	
+  40203e:	09 00       	nop	
+  402040:	09 00       	nop	
+  402042:	09 00       	nop	
+  402044:	02 d0       	mov\.l	402050 <_start\+0x50>,r0	! 0x0
+  402046:	12 01       	stc	gbr,r1
+  402048:	09 00       	nop	
+  40204a:	03 a0       	bra	402054 <_start\+0x54>
+  40204c:	0c 31       	add	r0,r1
+  40204e:	09 00       	nop	
+  402050:	00 00       	.*[ 	]*.*
+  402052:	00 00       	.*[ 	]*.*
+  402054:	09 00       	nop	
+  402056:	09 00       	nop	
+  402058:	09 00       	nop	
+  40205a:	09 00       	nop	
+  40205c:	02 d0       	mov\.l	402068 <_start\+0x68>,r0	! 0x0
+  40205e:	12 01       	stc	gbr,r1
+  402060:	09 00       	nop	
+  402062:	03 a0       	bra	40206c <_start\+0x6c>
+  402064:	0c 31       	add	r0,r1
+  402066:	09 00       	nop	
+  402068:	00 00       	.*[ 	]*.*
+  40206a:	00 00       	.*[ 	]*.*
+  40206c:	09 00       	nop	
+  40206e:	09 00       	nop	
+  402070:	09 00       	nop	
+  402072:	09 00       	nop	
+  402074:	12 01       	stc	gbr,r1
+  402076:	0c d0       	mov\.l	4020a8 <_start\+0xa8>,r0	! 0x0
+  402078:	1c 30       	add	r1,r0
+  40207a:	09 00       	nop	
+  40207c:	09 00       	nop	
+  40207e:	09 00       	nop	
+  402080:	09 00       	nop	
+  402082:	12 01       	stc	gbr,r1
+  402084:	09 d0       	mov\.l	4020ac <_start\+0xac>,r0	! 0x0
+  402086:	1c 30       	add	r1,r0
+  402088:	09 00       	nop	
+  40208a:	09 00       	nop	
+  40208c:	09 00       	nop	
+  40208e:	09 00       	nop	
+  402090:	12 01       	stc	gbr,r1
+  402092:	07 d0       	mov\.l	4020b0 <_start\+0xb0>,r0	! 0x0
+  402094:	1c 30       	add	r1,r0
+  402096:	09 00       	nop	
+  402098:	09 00       	nop	
+  40209a:	09 00       	nop	
+  40209c:	09 00       	nop	
+  40209e:	e3 6f       	mov	r14,r15
+  4020a0:	0b 00       	rts	
+  4020a2:	f6 6e       	mov\.l	@r15\+,r14
+  4020a4:	1c 10       	.*[ 	]*.*
+  4020a6:	01 00       	.*[ 	]*.*
+	\.\.\.
diff -urN ORIG/src/ld/testsuite/ld-sh/tlsbin.rd LOCAL/src/ld/testsuite/ld-sh/tlsbin.rd
--- ORIG/src/ld/testsuite/ld-sh/tlsbin.rd	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlsbin.rd	Mon Sep 30 09:17:28 2002
@@ -0,0 +1,142 @@
+#source: tlsbinpic.s
+#source: tlsbin.s
+#ld: -mshlelf_linux tmpdir/libtlslib.so
+#readelf: -Ssrl
+#target: sh*-linux*
+
+There are 19 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.interp +.*
+  \[ 2\] \.hash +.*
+  \[ 3\] \.dynsym +.*
+  \[ 4\] \.dynstr +.*
+  \[ 5\] \.rela\.dyn +.*
+  \[ 6\] \.rela\.plt +.*
+  \[ 7\] \.plt +.*
+  \[ 8\] \.text +PROGBITS +0+401000 .*
+  \[ 9\] \.data +.*
+  \[10\] \.tdata +PROGBITS +0+413000 [0-9a-f]+ 0+018 00 WAT  0   0  1
+  \[11\] \.tbss +NOBITS +0+413018 [0-9a-f]+ 0+010 00 WAT  0   0  1
+  \[12\] \.dynamic +DYNAMIC +0+413018 .*
+  \[13\] \.got +PROGBITS +0+4130c0 .*
+  \[14\] \.sbss +.*
+  \[15\] \.bss +.*
+  \[16\] \.shstrtab +.*
+  \[17\] \.symtab +.*
+  \[18\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x402000
+There are 6 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  PHDR.*
+  INTERP.*
+.*Requesting program interpreter.*
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+  TLS +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x0+18 0x0+28 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections\.\.\.
+   00 +
+   01 +\.interp *
+   02 +\.interp \.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.plt \.text *
+   03 +\.tdata \.tbss \.dynamic \.got *
+   04 +\.tbss \.dynamic *
+   05 +\.tdata \.tbss *
+
+Relocation section '\.rela\.dyn' at offset 0x[0-9a-f]+ contains 19 entries:
+ Offset +Info +Type +Sym\.Value +Sym\. Name \+ Addend
+0+401068  00000097 R_SH_TLS_TPOFF32 +0+00
+0+401088  00000097 R_SH_TLS_TPOFF32 +0+08
+0+4010a8  00000097 R_SH_TLS_TPOFF32 +0+10
+0+401154  00000097 R_SH_TLS_TPOFF32 +0+00
+0+40116c  00000097 R_SH_TLS_TPOFF32 +0+10
+0+401188  00000097 R_SH_TLS_TPOFF32 +0+08
+0+40118c  00000097 R_SH_TLS_TPOFF32 +0+0c
+0+401190  00000097 R_SH_TLS_TPOFF32 +0+10
+0+401194  00000097 R_SH_TLS_TPOFF32 +0+14
+0+402038  00000097 R_SH_TLS_TPOFF32 +0+18
+0+402050  00000097 R_SH_TLS_TPOFF32 +0+24
+0+402068  00000097 R_SH_TLS_TPOFF32 +0+14
+0+4020a8  00000097 R_SH_TLS_TPOFF32 +0+00
+0+4020ac  00000097 R_SH_TLS_TPOFF32 +0+20
+0+4020b0  00000097 R_SH_TLS_TPOFF32 +0+10
+0+4130d0  00000197 R_SH_TLS_TPOFF32 +0+ +sG3 \+ 0
+0+4130d4  00000397 R_SH_TLS_TPOFF32 +0+ +sG2 \+ 0
+0+4130d8  00000497 R_SH_TLS_TPOFF32 +0+ +sG4 \+ 0
+0+4130dc  00000797 R_SH_TLS_TPOFF32 +0+ +sG1 \+ 0
+
+Relocation section '\.rela\.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ Offset +Info +Type +Sym\.Value +Sym\. Name \+ Addend
+0+4130cc  000005a4 R_SH_JMP_SLOT +[0-9a-f]+ +__tls_get_addr \+ 0
+
+Symbol table '\.dynsym' contains 12 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE +LOCAL +DEFAULT  UND *
+ +1: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +2: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +3: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +4: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +5: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT  UND __tls_get_addr
+ +6: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +7: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +8: [0-9a-f]+ +0 NOTYPE +GLOBAL DEFAULT  ABS _edata
+ +9: [0-9a-f]+ +0 OBJECT +GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +10: [0-9a-f]+ +0 NOTYPE +GLOBAL DEFAULT  ABS _end
+ +11: [0-9a-f]+ +0 NOTYPE +GLOBAL DEFAULT +9 __data_start
+
+Symbol table '\.symtab' contains 42 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +1: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +2: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +3: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +4: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +5: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +6: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +7: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +8: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +9: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +10: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +11: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +12: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +13: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +14: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +15: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +15 *
+ +16: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +16 *
+ +17: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +17 *
+ +18: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +18 *
+ +19: 00000008 +0 TLS +LOCAL  DEFAULT +10 sl1
+ +20: 0000000c +0 TLS +LOCAL  DEFAULT +10 sl2
+ +21: 00000020 +0 TLS +LOCAL  DEFAULT +11 bl1
+ +22: 00000024 +0 TLS +LOCAL  DEFAULT +11 bl2
+ +23: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +24: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +25: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +26: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +27: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT  UND __tls_get_addr
+ +28: 0+ +0 TLS +GLOBAL DEFAULT +10 sg1
+ +29: 0+402000 +0 FUNC +GLOBAL DEFAULT +8 _start
+ +30: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +31: 0+401000 +0 FUNC +GLOBAL DEFAULT +8 fn2
+ +32: 00000004 +0 TLS +GLOBAL DEFAULT +10 sg2
+ +33: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +34: 00000010 +0 TLS +GLOBAL HIDDEN +10 sh1
+ +35: 004130e0 +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +36: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +37: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +38: 00000014 +0 TLS +GLOBAL HIDDEN +10 sh2
+ +39: 0000001c +0 TLS +GLOBAL DEFAULT +11 bg2
+ +40: 00000018 +0 TLS +GLOBAL DEFAULT +11 bg1
+ +41: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT +9 __data_start
diff -urN ORIG/src/ld/testsuite/ld-sh/tlsbin.s LOCAL/src/ld/testsuite/ld-sh/tlsbin.s
--- ORIG/src/ld/testsuite/ld-sh/tlsbin.s	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlsbin.s	Mon Sep 30 08:42:40 2002
@@ -0,0 +1,90 @@
+	.section ".tbss", "awT", @nobits
+	.globl bg1, bg2
+bg1:	.space 4
+bg2:	.space 4
+bl1:	.space 4
+bl2:	.space 4
+	.text
+	.globl	_start
+	.type	_start,@function
+_start:
+	mov.l	r12,@-r15
+	mov.l	r14,@-r15
+	mov	r15,r14
+	! Set up .GOT pointer for non-pic @gottpoff sequences
+	mova	.L3,r0
+	mov.l	.L3,r12
+	add	r0,r12
+	nop;nop;nop;nop
+
+	! @GOTTPOFF IE against global var
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	sG3@GOTTPOFF
+2:
+	nop;nop;nop;nop
+
+	! @GOTTPOFF IE -> LE against global var defined in exec
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	bg1@GOTTPOFF
+2:
+	nop;nop;nop;nop
+
+	! @GOTTPOFF IE -> LE against local var
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	bl2@GOTTPOFF
+2:
+	nop;nop;nop;nop
+
+	! @GOTTPOFF IE -> LE against hidden but not local var
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	sh2@GOTTPOFF
+2:
+	nop;nop;nop;nop
+
+	! LE @TPOFF, global var defined in exec
+	stc	gbr,r1
+	mov.l	.L4,r0
+	add	r1,r0
+	nop;nop;nop;nop
+
+	! LE @TPOFF, local var
+	stc	gbr,r1
+	mov.l	.L5,r0
+	add	r1,r0
+	nop;nop;nop;nop
+
+	! LE @TPOFF, hidden var defined in exec
+	stc	gbr,r1
+	mov.l	.L6,r0
+	add	r1,r0
+	nop;nop;nop;nop
+
+	mov	r14,r15
+	rts	
+	mov.l	@r15+,r14
+
+	.align	2
+.L3:	.long	_GLOBAL_OFFSET_TABLE_
+.L4:	.long	sg1@TPOFF
+.L5:	.long	bl1@TPOFF
+.L6:	.long	sh1@TPOFF
diff -urN ORIG/src/ld/testsuite/ld-sh/tlsbin.sd LOCAL/src/ld/testsuite/ld-sh/tlsbin.sd
--- ORIG/src/ld/testsuite/ld-sh/tlsbin.sd	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlsbin.sd	Mon Sep 30 08:42:21 2002
@@ -0,0 +1,11 @@
+#source: tlsbinpic.s
+#source: tlsbin.s
+#ld: -mshlelf_linux tmpdir/libtlslib.so
+#objdump: -sj.got
+#target: sh*-linux*
+
+.*: +file format elf32-sh-linux
+
+Contents of section \.got:
+ 4130c0 [0-9a-f]+ 00000000 00000000 [0-9a-f]+  .*
+ 4130d0 00000000 00000000 00000000 00000000  .*
diff -urN ORIG/src/ld/testsuite/ld-sh/tlsbin.td LOCAL/src/ld/testsuite/ld-sh/tlsbin.td
--- ORIG/src/ld/testsuite/ld-sh/tlsbin.td	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlsbin.td	Mon Sep 30 08:42:21 2002
@@ -0,0 +1,11 @@
+#source: tlsbinpic.s
+#source: tlsbin.s
+#ld: -mshlelf_linux tmpdir/libtlslib.so
+#objdump: -sj.tdata
+#target: sh*-linux*
+
+.*: +file format elf32-sh-linux
+
+Contents of section .tdata:
+ 413000 11000000 12000000 41000000 42000000  .*
+ 413010 01010000 02010000 +.*
diff -urN ORIG/src/ld/testsuite/ld-sh/tlsbinpic.s LOCAL/src/ld/testsuite/ld-sh/tlsbinpic.s
--- ORIG/src/ld/testsuite/ld-sh/tlsbinpic.s	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlsbinpic.s	Mon Sep 30 08:42:45 2002
@@ -0,0 +1,206 @@
+	! Force .got aligned to 4K, so it very likely gets at 0x413000
+	.data
+	.balign	4096
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2
+	.globl sh1, sh2
+	.hidden sh1, sh2
+sg1:	.long 17
+sg2:	.long 18
+sl1:	.long 65
+sl2:	.long 66
+sh1:	.long 257
+sh2:	.long 258
+	! Force .text aligned to 4K, so it very likely gets at 0x401000.
+	.text
+	.balign	4096
+	.globl	fn2
+	.type	fn2,@function
+fn2:
+	mov.l	r12,@-r15
+	mov.l	r14,@-r15
+	sts.l	pr,@-r15
+	mova	.L3,r0
+	mov.l	.L3,r12
+	add	r0,r12
+	mov	r15,r14
+	nop;nop;nop;nop
+
+	! GD -> IE because variable is not defined in executable
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sG1@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! GD -> IE because variable is not defined in executable where
+	!   the variable is referenced through @gottpoff too
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sG2@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! GD -> LE with global variable defined in executable
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sg1@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! GD -> LE with local variable defined in executable
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sl1@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! GD -> LE with hidden variable defined in executable
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sh1@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! LD -> LE with local variable defined in executable
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sl1@TLSLDM
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop
+	mov.l	.L4,r1
+	add	r0,r1
+	nop;nop
+	mov.l	.L5,r2
+	add	r0,r2
+	nop;nop;nop;nop
+
+	! LD -> LE against hidden variables
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sh1@TLSLDM
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop
+	mov.l	.L6,r1
+	add	r0,r1
+	nop;nop
+	mov.l	.L7,r2
+	add	r0,r2
+	nop;nop;nop;nop
+
+	! @GOTTPOFF IE against global var
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	sG2@GOTTPOFF
+2:
+	nop;nop;nop;nop
+
+	! @GOTTPOFF IE against global var
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r1,r0
+	.align	2
+1:	.long	sG4@GOTTPOFF
+2:
+	nop;nop;nop;nop
+
+	! @GOTTPOFF IE -> LE against global var defined in exec
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	sg1@GOTTPOFF
+2:
+	nop;nop;nop;nop
+
+	! @GOTTPOFF IE -> LE against hidden var
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	sh1@GOTTPOFF
+2:
+	nop;nop;nop;nop
+
+	mov	r14,r15
+	lds.l	@r15+,pr
+	mov.l	@r15+,r14
+	rts	
+	mov.l	@r15+,r12
+
+	.align 2
+.L3:	.long	_GLOBAL_OFFSET_TABLE_
+.L4:	.long	sl1@DTPOFF
+.L5:	.long	sl2@DTPOFF
+.L6:	.long	sh1@DTPOFF
+.L7:	.long	sh2@DTPOFF
+	! Fill page with 0.
+	.space	.L8-.
+	.balign	4096
+.L8:
diff -urN ORIG/src/ld/testsuite/ld-sh/tlslib.s LOCAL/src/ld/testsuite/ld-sh/tlslib.s
--- ORIG/src/ld/testsuite/ld-sh/tlslib.s	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlslib.s	Sat Sep 28 21:19:59 2002
@@ -0,0 +1,20 @@
+	.section ".tdata", "awT", @progbits
+	.globl sG1, sG2, sG3, sG4, sG5, sG6, sG7, sG8
+sG1:	.long 513
+sG2:	.long 514
+sG3:	.long 515
+sG4:	.long 516
+sG5:	.long 517
+sG6:	.long 518
+sG7:	.long 519
+sG8:	.long 520
+
+	.text
+	.align	1
+	! Dummy.
+	.globl __tls_get_addr
+	.type   __tls_get_addr,@function
+__tls_get_addr:
+	rts
+	nop
+
diff -urN ORIG/src/ld/testsuite/ld-sh/tlspic.dd LOCAL/src/ld/testsuite/ld-sh/tlspic.dd
--- ORIG/src/ld/testsuite/ld-sh/tlspic.dd	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlspic.dd	Mon Sep 30 11:18:28 2002
@@ -0,0 +1,291 @@
+#source: tlspic1.s
+#source: tlspic2.s
+#ld: -shared -mshlelf_linux
+#objdump: -drj.text
+#target: sh*-linux*
+
+.*: +file format elf32-sh-linux
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <fn1>:
+ [0-9a-f]+:	c6 2f       	mov\.l	r12,@-r15
+ [0-9a-f]+:	e6 2f       	mov\.l	r14,@-r15
+ [0-9a-f]+:	22 4f       	sts\.l	pr,@-r15
+ [0-9a-f]+:	83 c7       	mova	624 <fn1\+0x214>,r0
+ [0-9a-f]+:	82 dc       	mov\.l	624 <fn1\+0x214>,r12	! 0x[0-9a-f]+
+ [0-9a-f]+:	0c 3c       	add	r0,r12
+ [0-9a-f]+:	f3 6e       	mov	r15,r14
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	04 d4       	mov\.l	438 <fn1\+0x28>,r4	! 0x30
+ [0-9a-f]+:	04 c7       	mova	43c <fn1\+0x2c>,r0
+ [0-9a-f]+:	04 d1       	mov\.l	43c <fn1\+0x2c>,r1	! 0x[0-9a-f]+
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	0b 41       	jsr	@r1
+ [0-9a-f]+:	cc 34       	add	r12,r4
+ [0-9a-f]+:	05 a0       	bra	440 <fn1\+0x30>
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	30 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	03 d0       	mov\.l	458 <fn1\+0x48>,r0	! 0x38
+ [0-9a-f]+:	12 04       	stc	gbr,r4
+ [0-9a-f]+:	ce 00       	mov\.l	@\(r0,r12\),r0
+ [0-9a-f]+:	4c 30       	add	r4,r0
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	04 a0       	bra	460 <fn1\+0x50>
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	38 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	03 d4       	mov\.l	478 <fn1\+0x68>,r4	! 0x10
+ [0-9a-f]+:	04 c7       	mova	47c <fn1\+0x6c>,r0
+ [0-9a-f]+:	03 d1       	mov\.l	47c <fn1\+0x6c>,r1	! 0x[0-9a-f]+
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	0b 41       	jsr	@r1
+ [0-9a-f]+:	cc 34       	add	r12,r4
+ [0-9a-f]+:	04 a0       	bra	480 <fn1\+0x70>
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	10 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	03 d0       	mov\.l	498 <fn1\+0x88>,r0	! 0x18
+ [0-9a-f]+:	12 04       	stc	gbr,r4
+ [0-9a-f]+:	ce 00       	mov\.l	@\(r0,r12\),r0
+ [0-9a-f]+:	4c 30       	add	r4,r0
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	04 a0       	bra	4a0 <fn1\+0x90>
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	18 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	03 d4       	mov\.l	4b8 <fn1\+0xa8>,r4	! 0x3c
+ [0-9a-f]+:	04 c7       	mova	4bc <fn1\+0xac>,r0
+ [0-9a-f]+:	03 d1       	mov\.l	4bc <fn1\+0xac>,r1	! 0x[0-9a-f]+
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	0b 41       	jsr	@r1
+ [0-9a-f]+:	cc 34       	add	r12,r4
+ [0-9a-f]+:	04 a0       	bra	4c0 <fn1\+0xb0>
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	3c 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	03 d0       	mov\.l	4d8 <fn1\+0xc8>,r0	! 0x44
+ [0-9a-f]+:	12 04       	stc	gbr,r4
+ [0-9a-f]+:	ce 00       	mov\.l	@\(r0,r12\),r0
+ [0-9a-f]+:	4c 30       	add	r4,r0
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	04 a0       	bra	4e0 <fn1\+0xd0>
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	44 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	03 d4       	mov\.l	4f8 <fn1\+0xe8>,r4	! 0x24
+ [0-9a-f]+:	04 c7       	mova	4fc <fn1\+0xec>,r0
+ [0-9a-f]+:	03 d1       	mov\.l	4fc <fn1\+0xec>,r1	! 0x[0-9a-f]+
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	0b 41       	jsr	@r1
+ [0-9a-f]+:	cc 34       	add	r12,r4
+ [0-9a-f]+:	04 a0       	bra	500 <fn1\+0xf0>
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	24 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	03 d0       	mov\.l	518 <fn1\+0x108>,r0	! 0x2c
+ [0-9a-f]+:	12 04       	stc	gbr,r4
+ [0-9a-f]+:	ce 00       	mov\.l	@\(r0,r12\),r0
+ [0-9a-f]+:	4c 30       	add	r4,r0
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	04 a0       	bra	520 <fn1\+0x110>
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	2c 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	03 d4       	mov\.l	538 <fn1\+0x128>,r4	! 0x1c
+ [0-9a-f]+:	04 c7       	mova	53c <fn1\+0x12c>,r0
+ [0-9a-f]+:	03 d1       	mov\.l	53c <fn1\+0x12c>,r1	! 0x[0-9a-f]+
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	0b 41       	jsr	@r1
+ [0-9a-f]+:	cc 34       	add	r12,r4
+ [0-9a-f]+:	04 a0       	bra	540 <fn1\+0x130>
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	1c 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	38 d1       	mov\.l	628 <fn1\+0x218>,r1	! 0x8
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	37 d2       	mov\.l	62c <fn1\+0x21c>,r2	! 0xc
+ [0-9a-f]+:	0c 32       	add	r0,r2
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	03 d4       	.*[ 	]*.*
+ [0-9a-f]+:	04 c7       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	0b 41       	jsr	@r1
+ [0-9a-f]+:	cc 34       	add	r12,r4
+ [0-9a-f]+:	04 a0       	bra	570 <fn1\+0x160>
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	1c 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	2e d1       	mov\.l	630 <fn1\+0x220>,r1	! 0x10
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	2d d2       	mov\.l	634 <fn1\+0x224>,r2	! 0x14
+ [0-9a-f]+:	0c 32       	add	r0,r2
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	03 d4       	mov\.l	598 <fn1\+0x188>,r4	! 0x1c
+ [0-9a-f]+:	04 c7       	mova	59c <fn1\+0x18c>,r0
+ [0-9a-f]+:	03 d1       	mov\.l	59c <fn1\+0x18c>,r1	! 0x[0-9a-f]+
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	0b 41       	jsr	@r1
+ [0-9a-f]+:	cc 34       	add	r12,r4
+ [0-9a-f]+:	04 a0       	bra	5a0 <fn1\+0x190>
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	1c 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	[0-9a-f]+ [0-9a-f]+       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	24 d1       	mov\.l	638 <fn1\+0x228>,r1	! 0x18
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	23 d2       	mov\.l	63c <fn1\+0x22c>,r2	! 0x1c
+ [0-9a-f]+:	0c 32       	add	r0,r2
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	02 d0       	mov\.l	5c4 <fn1\+0x1b4>,r0	! 0x38
+ [0-9a-f]+:	12 01       	stc	gbr,r1
+ [0-9a-f]+:	ce 00       	mov\.l	@\(r0,r12\),r0
+ [0-9a-f]+:	03 a0       	bra	5c8 <fn1\+0x1b8>
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	38 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	02 d0       	mov\.l	5dc <fn1\+0x1cc>,r0	! 0x18
+ [0-9a-f]+:	12 01       	stc	gbr,r1
+ [0-9a-f]+:	ce 00       	mov\.l	@\(r0,r12\),r0
+ [0-9a-f]+:	03 a0       	bra	5e0 <fn1\+0x1d0>
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	18 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	02 d0       	mov\.l	5f4 <fn1\+0x1e4>,r0	! 0x44
+ [0-9a-f]+:	12 01       	stc	gbr,r1
+ [0-9a-f]+:	ce 00       	mov\.l	@\(r0,r12\),r0
+ [0-9a-f]+:	03 a0       	bra	5f8 <fn1\+0x1e8>
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	44 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	02 d0       	mov\.l	60c <fn1\+0x1fc>,r0	! 0x2c
+ [0-9a-f]+:	12 01       	stc	gbr,r1
+ [0-9a-f]+:	ce 00       	mov\.l	@\(r0,r12\),r0
+ [0-9a-f]+:	03 a0       	bra	610 <fn1\+0x200>
+ [0-9a-f]+:	0c 31       	add	r0,r1
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	2c 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	e3 6f       	mov	r14,r15
+ [0-9a-f]+:	26 4f       	lds\.l	@r15\+,pr
+ [0-9a-f]+:	f6 6e       	mov\.l	@r15\+,r14
+ [0-9a-f]+:	0b 00       	rts	
+ [0-9a-f]+:	f6 6c       	mov\.l	@r15\+,r12
+ [0-9a-f]+:	09 00       	nop	
+ [0-9a-f]+:	cc 00       	.*[ 	]*.*
+ [0-9a-f]+:	01 00       	.*[ 	]*.*
+ [0-9a-f]+:	08 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	0c 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	10 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	14 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	18 00       	.*[ 	]*.*
+ [0-9a-f]+:	00 00       	.*[ 	]*.*
+ [0-9a-f]+:	1c 00       	.*[ 	]*.*
+	\.\.\.
diff -urN ORIG/src/ld/testsuite/ld-sh/tlspic.rd LOCAL/src/ld/testsuite/ld-sh/tlspic.rd
--- ORIG/src/ld/testsuite/ld-sh/tlspic.rd	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlspic.rd	Mon Sep 30 11:16:22 2002
@@ -0,0 +1,132 @@
+#source: tlspic1.s
+#source: tlsbin2.s
+#ld: -shared -mshlelf_linux
+#readelf: -Ssrl
+#target: sh*-linux*
+
+There are 18 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rela\.dyn +.*
+  \[ 5\] \.rela\.plt +.*
+  \[ 6\] \.plt +.*
+  \[ 7\] \.text +PROGBITS +0+410 .*
+  \[ 8\] \.data +.*
+  \[ 9\] \.tdata +PROGBITS +0+10640 [0-9a-f]+ 0+018 00 WAT  0   0  1
+  \[10\] \.tbss +NOBITS +0+10658 [0-9a-f]+ 0+008 00 WAT  0   0  1
+  \[11\] \.dynamic +DYNAMIC +0+10658 .*
+  \[12\] \.got +PROGBITS +0+106f0 .*
+  \[13\] \.sbss +.*
+  \[14\] \.bss +.*
+  \[15\] \.shstrtab +.*
+  \[16\] \.symtab +.*
+  \[17\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x410
+There are 4 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+  TLS +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x0+18 0x0+20 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections\.\.\.
+   00 +\.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.plt \.text *
+   01 +\.tdata \.tbss \.dynamic \.got *
+   02 +\.tbss \.dynamic *
+   03 +\.tdata \.tbss *
+
+Relocation section '\.rela\.dyn' at offset 0x[0-9a-f]+ contains 10 entries:
+ Offset +Info +Type +Sym\.Value +Sym\. Name \+ Addend
+0+10700  00000095 R_SH_TLS_DTPMOD32 +0+00
+0+10708  00000097 R_SH_TLS_TPOFF32 +0+0c
+0+1070c  00000095 R_SH_TLS_DTPMOD32 +0+00
+0+10714  00000095 R_SH_TLS_DTPMOD32 +0+00
+0+1071c  00000097 R_SH_TLS_TPOFF32 +0+1c
+0+1072c  00000095 R_SH_TLS_DTPMOD32 +0+00
+0+10734  00000097 R_SH_TLS_TPOFF32 +0+14
+0+10720  00001195 R_SH_TLS_DTPMOD32 +0+ +sg1 \+ 0
+0+10724  00001196 R_SH_TLS_DTPOFF32 +0+ +sg1 \+ 0
+0+10728  00001497 R_SH_TLS_TPOFF32 +0+04 +sg2 \+ 0
+
+Relocation section '\.rela\.plt' at offset 0x[0-9a-f]+ contains 1 entries:
+ Offset +Info +Type +Sym\.Value +Sym\. Name \+ Addend
+0+106fc  000010a4 R_SH_JMP_SLOT +[0-9a-f]+ +__tls_get_addr \+ 0
+
+Symbol table '\.dynsym' contains 25 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE +LOCAL +DEFAULT  UND *
+ +1: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT    1 *
+ +2: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +3: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +4: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +5: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +6: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +7: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +8: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +9: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +10: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +11: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +12: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +13: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +14: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +15: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +16: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
+ +17: 0+00 +0 TLS +GLOBAL DEFAULT +9 sg1
+ +18: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +19: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +20: 0+04 +0 TLS +GLOBAL DEFAULT +9 sg2
+ +21: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +22: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +23: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +24: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT +8 __data_start
+
+Symbol table '\.symtab' contains 34 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +1: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +2: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +3: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +4: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +5: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +6: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +7: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +8: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +9: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +10: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +11: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +12: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +13: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +14: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +15: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +15 *
+ +16: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +16 *
+ +17: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +17 *
+ +18: 0+08 +0 TLS +LOCAL  DEFAULT +9 sl1
+ +19: 0+0c +0 TLS +LOCAL  DEFAULT +9 sl2
+ +20: 0+18 +0 TLS +LOCAL  HIDDEN +10 sH1
+ +21: 0+1c +0 TLS +LOCAL  HIDDEN +10 sH2
+ +22: 0+10 +0 TLS +LOCAL  HIDDEN +9 sh1
+ +23: 0+14 +0 TLS +LOCAL  HIDDEN +9 sh2
+ +24: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _DYNAMIC
+ +25: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
+ +26: 0+00 +0 TLS +GLOBAL DEFAULT +9 sg1
+ +27: [0-9a-f]+ +0 FUNC    GLOBAL DEFAULT +7 fn1
+ +28: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +29: 0+04 +0 TLS +GLOBAL DEFAULT +9 sg2
+ +30: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +31: [0-9a-f]+ +0 OBJECT  GLOBAL DEFAULT  ABS _GLOBAL_OFFSET_TABLE_
+ +32: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +33: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT +8 __data_start
diff -urN ORIG/src/ld/testsuite/ld-sh/tlspic.sd LOCAL/src/ld/testsuite/ld-sh/tlspic.sd
--- ORIG/src/ld/testsuite/ld-sh/tlspic.sd	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlspic.sd	Mon Sep 30 11:16:22 2002
@@ -0,0 +1,14 @@
+#source: tlspic1.s
+#source: tlsbin2.s
+#ld: -shared -mshlelf_linux
+#objdump: -sj.got
+#target: sh*-linux*
+
+.*: +file format elf32-sh-linux
+
+Contents of section \.got:
+ 106f0 [0-9a-f]+ 00000000 00000000 [0-9a-f]+  .*
+ 10700 00000000 08000000 00000000 00000000  .*
+ 10710 00000000 00000000 18000000 00000000  .*
+ 10720 00000000 00000000 00000000 00000000  .*
+ 10730 10000000 00000000 +.*
diff -urN ORIG/src/ld/testsuite/ld-sh/tlspic.td LOCAL/src/ld/testsuite/ld-sh/tlspic.td
--- ORIG/src/ld/testsuite/ld-sh/tlspic.td	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlspic.td	Mon Sep 30 11:16:22 2002
@@ -0,0 +1,11 @@
+#source: tlspic1.s
+#source: tlsbin2.s
+#ld: -shared -mshlelf_linux
+#objdump: -sj.tdata
+#target: sh*-linux*
+
+.*: +file format elf32-sh-linux
+
+Contents of section \.tdata:
+ 10640 11000000 12000000 41000000 42000000  .*
+ 10650 01010000 02010000 +.*
diff -urN ORIG/src/ld/testsuite/ld-sh/tlspic1.s LOCAL/src/ld/testsuite/ld-sh/tlspic1.s
--- ORIG/src/ld/testsuite/ld-sh/tlspic1.s	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlspic1.s	Sun Sep 29 07:37:19 2002
@@ -0,0 +1,267 @@
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2
+	.globl sh1, sh2
+	.hidden sh1, sh2
+sg1:	.long 17
+sg2:	.long 18
+sl1:	.long 65
+sl2:	.long 66
+sh1:	.long 257
+sh2:	.long 258
+	.text
+	.align	1
+	.globl	fn1
+	.type	fn1,@function
+fn1:
+	mov.l	r12,@-r15
+	mov.l	r14,@-r15
+	sts.l	pr,@-r15
+	mova	.L3,r0
+	mov.l	.L3,r12
+	add	r0,r12
+	mov	r15,r14
+	nop;nop;nop;nop
+
+	! GD
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sg1@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! GD -> IE because variable is referenced through @GOTTPOFF too
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sg2@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! GD against local variable
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sl1@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! GD -> IE against local variable referenced through @GOTTPOFF too
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sl2@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! GD against hidden and local variable
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sh1@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! GD -> IE against hidden and local variable referenced through
+	! @GOTTPOFF too
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sh2@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! GD against hidden but not local variable
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sH1@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! GD -> IE against hidden but not local variable referenced through
+	! @GOTTPOFF too
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sH2@TLSGD
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop;nop;nop
+
+	! LD
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sl1@TLSLDM
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop
+	mov.l	.L4,r1
+	add	r0,r1
+	nop;nop
+	mov.l	.L5,r2
+	add	r0,r2
+	nop;nop;nop;nop
+
+	! LD against hidden and local variables
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sl1@TLSLDM
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop
+	mov.l	.L6,r1
+	add	r0,r1
+	nop;nop
+	mov.l	.L7,r2
+	add	r0,r2
+	nop;nop;nop;nop
+
+	! LD against hidden but not local variables
+	mov.l	1f,r4
+	mova	2f,r0
+	mov.l	2f,r1
+	add	r0,r1
+	jsr	@r1
+	add	r12,r4
+	bra	3f
+	nop
+	.align	2
+1:	.long	sH1@TLSLDM
+2:	.long	__tls_get_addr@PLT
+3:
+	nop;nop
+	mov.l	.L8,r1
+	add	r0,r1
+	nop;nop
+	mov.l	.L9,r2
+	add	r0,r2
+	nop;nop;nop;nop
+
+	! @GOTTPOFF IE against global var
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	sg2@GOTTPOFF
+2:
+	nop;nop;nop;nop
+
+	! @GOTTPOFF IE against local var
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	sl2@GOTTPOFF
+2:
+	nop;nop;nop;nop
+
+	! @GOTTPOFF IE against hidden and local var
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	sh2@GOTTPOFF
+2:
+	nop;nop;nop;nop
+
+	! @GOTTPOFF IE against hidden but not local var
+	mov.l	1f,r0
+	stc	gbr,r1
+	mov.l	@(r0,r12),r0
+	bra	2f
+	add	r0,r1
+	.align	2
+1:	.long	sH2@GOTTPOFF
+2:
+	nop;nop;nop;nop
+
+	mov	r14,r15
+	lds.l	@r15+,pr
+	mov.l	@r15+,r14
+	rts	
+	mov.l	@r15+,r12
+
+	.align 2
+.L3:	.long	_GLOBAL_OFFSET_TABLE_
+.L4:	.long	sl1@DTPOFF
+.L5:	.long	sl1@DTPOFF + 4
+.L6:	.long	sh1@DTPOFF
+.L7:	.long	sh2@DTPOFF
+.L8:	.long	sH1@DTPOFF
+.L9:	.long	sH2@DTPOFF
diff -urN ORIG/src/ld/testsuite/ld-sh/tlspic2.s LOCAL/src/ld/testsuite/ld-sh/tlspic2.s
--- ORIG/src/ld/testsuite/ld-sh/tlspic2.s	Thu Jan  1 09:00:00 1970
+++ LOCAL/src/ld/testsuite/ld-sh/tlspic2.s	Sun Sep 29 07:37:19 2002
@@ -0,0 +1,5 @@
+	.section ".tbss", "awT", @nobits
+	.globl sH1, sH2
+	.hidden sH1, sH2
+sH1:	.space 4
+sH2:	.space 4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]