Index: xcoffout.c
===================================================================
--- xcoffout.c	(revision 194435)
+++ xcoffout.c	(working copy)
@@ -67,6 +67,7 @@
 char *xcoff_bss_section_name;
 char *xcoff_private_data_section_name;
 char *xcoff_tls_data_section_name;
+char *xcoff_tbss_section_name;
 char *xcoff_read_only_section_name;

 /* Last source file name mentioned in a NOTE insn.  */
Index: xcoffout.h
===================================================================
--- xcoffout.h	(revision 194435)
+++ xcoffout.h	(working copy)
@@ -127,6 +127,7 @@
 extern char *xcoff_bss_section_name;
 extern char *xcoff_private_data_section_name;
 extern char *xcoff_tls_data_section_name;
+extern char *xcoff_tbss_section_name;
 extern char *xcoff_read_only_section_name;

 /* Last source file name mentioned in a NOTE insn.  */
Index: config/rs6000/xcoff.h
===================================================================
--- config/rs6000/xcoff.h	(revision 194435)
+++ config/rs6000/xcoff.h	(working copy)
@@ -98,6 +98,7 @@
 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
 #define TARGET_STRIP_NAME_ENCODING  rs6000_xcoff_strip_name_encoding
 #define TARGET_SECTION_TYPE_FLAGS  rs6000_xcoff_section_type_flags
+#define TARGET_ENCODE_SECTION_INFO rs6000_xcoff_encode_section_info

 /* FP save and restore routines.  */
 #define	SAVE_FP_PREFIX "._savef"
@@ -308,8 +309,8 @@
 #define ASM_OUTPUT_TLS_COMMON(FILE, DECL, NAME, SIZE)	\
   do { fputs(COMMON_ASM_OP, (FILE));			\
        RS6000_OUTPUT_BASENAME ((FILE), (NAME));		\
-       fputs("[UL]", (FILE));					\
-       fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED"\n", (SIZE)); \
+       fprintf ((FILE), "[UL],"HOST_WIDE_INT_PRINT_UNSIGNED"\n", \
+       (SIZE));						\
   } while (0)
 #endif

Index: config/rs6000/rs6000.c
===================================================================
--- config/rs6000/rs6000.c	(revision 194435)
+++ config/rs6000/rs6000.c	(working copy)
@@ -209,6 +209,7 @@ static short cached_can_issue_more;
 static GTY(()) section *read_only_data_section;
 static GTY(()) section *private_data_section;
 static GTY(()) section *tls_data_section;
+static GTY(()) section *tls_private_data_section;
 static GTY(()) section *read_only_private_data_section;
 static GTY(()) section *sdata2_section;
 static GTY(()) section *toc_section;
@@ -22316,23 +22317,39 @@ output_toc (FILE *file, rtx x, int labelno, enum m
     output_addr_const (file, x);

 #if HAVE_AS_TLS
-  if (TARGET_XCOFF && GET_CODE (base) == SYMBOL_REF)
+  if (TARGET_XCOFF && GET_CODE (base) == SYMBOL_REF
+      && SYMBOL_REF_TLS_MODEL (base) != 0)
     {
+      tree decl = SYMBOL_REF_DECL (base);
+      if (DECL_INITIAL (decl) == NULL_TREE
+		   || DECL_INITIAL (decl) == error_mark_node
+		   || (flag_zero_initialized_in_bss
+		       /* Leave constant zeroes in .rodata so they
+			  can be shared.  */
+		       && !TREE_READONLY (decl)
+		       && initializer_zerop (DECL_INITIAL (decl))))
+	fputs ("[UL]", file);
+      else
+	fputs ("[TL]", file);
+
       if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_LOCAL_EXEC)
-	fputs ("[TL]@le", file);
+	fputs ("@le", file);
       else if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_INITIAL_EXEC)
-	fputs ("[TL]@ie", file);
+	fputs ("@ie", file);
       /* Use global-dynamic for local-dynamic.  */
       else if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_GLOBAL_DYNAMIC
 	       || SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_LOCAL_DYNAMIC)
 	{
-	  fputs ("[TL]\n", file);
+	  putc ('\n', file);
 	  (*targetm.asm_out.internal_label) (file, "LCM", labelno);
 	  fputs ("\t.tc .", file);
 	  RS6000_OUTPUT_BASENAME (file, name);
 	  fputs ("[TC],", file);
 	  output_addr_const (file, x);
-	  fputs ("[TL]@m", file);
+	  if (TREE_PUBLIC (SYMBOL_REF_DECL (base)))
+	    fputs ("[TL]@m", file);
+	  else
+	    fputs ("[UL]@m", file);
 	}
     }
 #endif
@@ -25705,6 +25722,11 @@ rs6000_xcoff_asm_init_sections (void)
 			   rs6000_xcoff_output_tls_section_asm_op,
 			   &xcoff_tls_data_section_name);

+  tls_private_data_section
+    = get_unnamed_section (SECTION_TLS,
+			   rs6000_xcoff_output_tls_section_asm_op,
+			   &xcoff_private_data_section_name);
+
   read_only_private_data_section
     = get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
 			   &xcoff_private_data_section_name);
@@ -25758,7 +25780,24 @@ rs6000_xcoff_select_section (tree decl, int reloc,
     {
 #if HAVE_AS_TLS
       if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
-	return tls_data_section;
+	{
+	  if (TREE_PUBLIC (decl))
+	    return tls_data_section;
+	  else if (DECL_INITIAL (decl) == NULL_TREE
+		   || DECL_INITIAL (decl) == error_mark_node
+		   || (flag_zero_initialized_in_bss
+		       /* Leave constant zeroes in .rodata so they
+			  can be shared.  */
+		       && !TREE_READONLY (decl)
+		       && initializer_zerop (DECL_INITIAL (decl))))
+	    {
+	      /* Convert to COMMON to emit in BSS.  */
+	      DECL_COMMON (decl) = 1;
+	      return tls_comm_section;
+	    }
+	  else
+	    return tls_private_data_section;
+	}
       else
 #endif
 	if (TREE_PUBLIC (decl))
@@ -25857,10 +25896,12 @@ rs6000_xcoff_file_start (void)
 			   main_input_filename, ".bss_");
   rs6000_gen_section_name (&xcoff_private_data_section_name,
 			   main_input_filename, ".rw_");
+  rs6000_gen_section_name (&xcoff_read_only_section_name,
+			   main_input_filename, ".ro_");
   rs6000_gen_section_name (&xcoff_tls_data_section_name,
 			   main_input_filename, ".tls_");
-  rs6000_gen_section_name (&xcoff_read_only_section_name,
-			   main_input_filename, ".ro_");
+  rs6000_gen_section_name (&xcoff_tbss_section_name,
+			   main_input_filename, ".tbss_[UL]");

   fputs ("\t.file\t", asm_out_file);
   output_quoted_string (asm_out_file, main_input_filename);
@@ -25886,6 +25927,29 @@ rs6000_xcoff_file_end (void)
 	 ? "\t.long _section_.text\n" : "\t.llong _section_.text\n",
 	 asm_out_file);
 }
+
+static void
+rs6000_xcoff_encode_section_info (tree decl, rtx rtl, int first)
+{
+  rtx symbol;
+  int flags;
+
+  default_encode_section_info (decl, rtl, first);
+
+  /* Careful not to prod global register variables.  */
+  if (!MEM_P (rtl))
+    return;
+  symbol = XEXP (rtl, 0);
+  if (GET_CODE (symbol) != SYMBOL_REF)
+    return;
+
+  flags = SYMBOL_REF_FLAGS (symbol);
+
+  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
+    flags &= ~SYMBOL_FLAG_HAS_BLOCK_INFO;
+
+  SYMBOL_REF_FLAGS (symbol) = flags;
+}
 #endif /* TARGET_XCOFF */

 /* Compute a (partial) cost for rtx X.  Return true if the complete
