public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch, microblaze]: Add support for TLS in MicroBlaze
@ 2013-03-12 20:47 David Holsgrove
  2013-03-13 15:34 ` Michael Eager
  0 siblings, 1 reply; 4+ messages in thread
From: David Holsgrove @ 2013-03-12 20:47 UTC (permalink / raw)
  To: gcc-patches
  Cc: Michael Eager, Edgar Iglesias, John Williams, Vinod Kathail,
	Vidhumouli Hunsigida, Nagaraju Mekala, Tom Shui

[-- Attachment #1: Type: text/plain, Size: 2170 bytes --]

Add support for thread local storage (general dynamic and local dynamic models) in MicroBlaze.


gcc/Changelog

2013-03-13  Edgar E. Iglesias <edgar.iglesias@xilinx.com>
            David Holsgrove <david.holsgrove@xilinx.com>

 * config/microblaze/microblaze-protos.h: (microblaze_cannot_force_const_mem,
   microblaze_tls_referenced_p, symbol_mentioned_p,
   label_mentioned_p): Add prototypes.
 * config/microblaze/microblaze.c (microblaze_address_type): Add ADDRESS_TLS
   and tls_reloc address types.
   (microblaze_address_info): Add tls_reloc.
   (TARGET_HAVE_TLS): Define.
   (get_tls_get_addr, microblaze_tls_symbol_p, microblaze_tls_operand_p_1,
    microblaze_tls_referenced_p, microblaze_cannot_force_const_mem,
    symbol_mentioned_p, label_mentioned_p, tls_mentioned_p, load_tls_operand,
    microblaze_call_tls_get_addr, microblaze_legitimize_tls_address): New functions.
   (microblaze_classify_unspec): Handle UNSPEC_TLS.
   (get_base_reg): Use microblaze_tls_symbol_p.
   (microblaze_classify_address): Handle TLS.
   (microblaze_legitimate_pic_operand): Use symbol_mentioned_p, label_mentioned_p
    and microblaze_tls_referenced_p.
   (microblaze_legitimize_address): Handle TLS.
   (microblaze_address_insns): Handle ADDRESS_TLS.
   (pic_address_needs_scratch): Handle TLS.
   (print_operand_address): Handle TLS.
   (microblaze_expand_prologue): Check TLS_NEEDS_GOT.
   (microblaze_expand_move): Handle TLS.
   (microblaze_legitimate_constant_p): Check microblaze_cannot_force_const_mem
    and microblaze_tls_symbol_p.
   (TARGET_CANNOT_FORCE_CONST_MEM): Define.
 * config/microblaze/microblaze.h (TLS_NEEDS_GOT): Define
   (PIC_OFFSET_TABLE_REGNUM): Set.
 * config/microblaze/linux.h (TLS_NEEDS_GOT): Define.
 * config/microblaze/microblaze.md (UNSPEC_TLS): Define.
   (addsi3, movsi_internal2, movdf_internal): Update constraints
 * config/microblaze/predicates.md (arith_plus_operand): Define
   (move_operand): Redefine as move_src_operand, check microblaze_tls_referenced_p.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>


[-- Attachment #2: 0001-Patch-microblaze-Add-support-for-TLS.patch --]
[-- Type: application/octet-stream, Size: 33107 bytes --]

From 3c611a0704a851ae3c43b2e4b32307df26961b1e Mon Sep 17 00:00:00 2001
From: Gopi <gopi@linux69.(none)>
Date: Mon, 15 Mar 2010 12:46:09 +0530
Subject: [PATCH] [Patch, microblaze]: Add support for TLS

Changelog

2013-03-08  Edgar E. Iglesias <edgar.iglesias@xilinx.com>
            David Holsgrove <david.holsgrove@xilinx.com>

 * config/microblaze/microblaze-protos.h: (microblaze_cannot_force_const_mem,
   microblaze_tls_referenced_p, symbol_mentioned_p,
   label_mentioned_p): Add prototypes.
 * config/microblaze/microblaze.c (microblaze_address_type): Add ADDRESS_TLS
   and tls_reloc address types.
   (microblaze_address_info): Add tls_reloc.
   (TARGET_HAVE_TLS): Define.
   (get_tls_get_addr, microblaze_tls_symbol_p, microblaze_tls_operand_p_1,
    microblaze_tls_referenced_p, microblaze_cannot_force_const_mem,
    symbol_mentioned_p, label_mentioned_p, tls_mentioned_p, load_tls_operand,
    microblaze_call_tls_get_addr, microblaze_legitimize_tls_address): New functions.
   (microblaze_classify_unspec): Handle UNSPEC_TLS.
   (get_base_reg): Use microblaze_tls_symbol_p.
   (microblaze_classify_address): Handle TLS.
   (microblaze_legitimate_pic_operand): Use symbol_mentioned_p, label_mentioned_p
    and microblaze_tls_referenced_p.
   (microblaze_legitimize_address): Handle TLS.
   (microblaze_address_insns): Handle ADDRESS_TLS.
   (pic_address_needs_scratch): Handle TLS.
   (print_operand_address): Handle TLS.
   (microblaze_expand_prologue): Check TLS_NEEDS_GOT.
   (microblaze_expand_move): Handle TLS.
   (microblaze_legitimate_constant_p): Check microblaze_cannot_force_const_mem
    and microblaze_tls_symbol_p.
   (TARGET_CANNOT_FORCE_CONST_MEM): Define.
 * config/microblaze/microblaze.h (TLS_NEEDS_GOT): Define
   (PIC_OFFSET_TABLE_REGNUM): Set.
 * config/microblaze/linux.h (TLS_NEEDS_GOT): Define.
 * config/microblaze/microblaze.md (UNSPEC_TLS): Define.
   (addsi3, movsi_internal2, movdf_internal): Update constraints
 * config/microblaze/predicates.md (arith_plus_operand): Define
   (move_operand): Redefine as move_src_operand, check microblaze_tls_referenced_p.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
---
 gcc/config/microblaze/linux.h             |    3 +
 gcc/config/microblaze/microblaze-protos.h |    4 +
 gcc/config/microblaze/microblaze.c        |  624 +++++++++++++++++++++++------
 gcc/config/microblaze/microblaze.h        |    7 +-
 gcc/config/microblaze/microblaze.md       |   19 +-
 gcc/config/microblaze/predicates.md       |   54 +++-
 6 files changed, 573 insertions(+), 138 deletions(-)

diff --git a/gcc/config/microblaze/linux.h b/gcc/config/microblaze/linux.h
index eca7776..a7b7a1a 100644
--- a/gcc/config/microblaze/linux.h
+++ b/gcc/config/microblaze/linux.h
@@ -22,6 +22,9 @@
 #undef TARGET_SUPPORTS_PIC
 #define TARGET_SUPPORTS_PIC 1
 
+#undef TLS_NEEDS_GOT
+#define TLS_NEEDS_GOT 1
+
 #define DYNAMIC_LINKER "/lib/ld.so.1"
 #undef  SUBTARGET_EXTRA_SPECS
 #define SUBTARGET_EXTRA_SPECS \
diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
index e19939f..34be76f 100644
--- a/gcc/config/microblaze/microblaze-protos.h
+++ b/gcc/config/microblaze/microblaze-protos.h
@@ -50,6 +50,10 @@ extern void microblaze_declare_object (FILE *, const char *, const char *,
    const char *, int);
 extern void microblaze_asm_output_ident (const char *);
 extern int microblaze_legitimate_pic_operand (rtx);
+extern bool microblaze_tls_referenced_p (rtx);
+extern int symbol_mentioned_p (rtx);
+extern int label_mentioned_p (rtx);
+extern bool microblaze_cannot_force_const_mem (enum machine_mode, rtx);
 #endif  /* RTX_CODE */
 
 /* Declare functions in microblaze-c.c.  */
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index 3a52994..ced4136 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -84,7 +84,8 @@ enum microblaze_address_type
   ADDRESS_CONST_INT,
   ADDRESS_SYMBOLIC,
   ADDRESS_GOTOFF,
-  ADDRESS_PLT
+  ADDRESS_PLT,
+  ADDRESS_TLS
 };
 
 /* Classifies symbols
@@ -98,6 +99,15 @@ enum microblaze_symbol_type
   SYMBOL_TYPE_GENERAL
 };
 
+/* TLS Address Type */
+enum tls_reloc {
+  TLS_GD,
+  TLS_LDM,
+  TLS_DTPREL,
+  TLS_IE,
+  TLS_LE
+};
+
 /* Classification of a MicroBlaze address.  */
 struct microblaze_address_info
 {
@@ -108,6 +118,7 @@ struct microblaze_address_info
   rtx offset; 	/* Contains valid values on ADDRESS_CONST_INT and ADDRESS_REG.  */
   rtx symbol; 	/* Contains valid values on ADDRESS_SYMBOLIC.  */
   enum microblaze_symbol_type symbol_type;
+  enum tls_reloc tls_type;
 };
 
 /* Structure to be filled in by compute_frame_size with register
@@ -215,6 +226,11 @@ static int microblaze_interrupt_function_p (tree);
 
 section *sdata2_section;
 
+#ifdef HAVE_AS_TLS
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS true
+#endif
+
 /* Return truth value if a CONST_DOUBLE is ok to be a legitimate constant.  */
 static bool
 microblaze_const_double_ok (rtx op, enum machine_mode mode)
@@ -287,6 +303,9 @@ simple_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
       plus0 = XEXP (addr, 0);
       plus1 = XEXP (addr, 1);
 
+      if (GET_CODE (plus0) != REG)
+	return 0;
+
       if (GET_CODE (plus0) == REG && GET_CODE (plus1) == CONST_INT
 	  && SMALL_INT (plus1))
 	{
@@ -386,6 +405,227 @@ microblaze_valid_base_register_p (rtx x,
 	  && microblaze_regno_ok_for_base_p (REGNO (x), strict));
 }
 
+/* Build the SYMBOL_REF for __tls_get_addr.  */
+
+static GTY(()) rtx tls_get_addr_libfunc;
+
+static rtx
+get_tls_get_addr (void)
+{
+  if (!tls_get_addr_libfunc)
+    tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr");
+  return tls_get_addr_libfunc;
+}
+
+/* Return TRUE if X is a thread-local symbol.  */
+bool
+microblaze_tls_symbol_p (rtx x)
+{
+  if (! TARGET_HAVE_TLS)
+    return false;
+
+  if (GET_CODE (x) != SYMBOL_REF)
+    return false;
+
+  return SYMBOL_REF_TLS_MODEL (x) != 0;
+}
+
+static int
+microblaze_tls_operand_p_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
+{
+  if (GET_CODE (*x) == SYMBOL_REF)
+    return SYMBOL_REF_TLS_MODEL (*x) != 0;
+
+  /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are
+     TLS offsets, not real symbol references.  */
+  if (GET_CODE (*x) == UNSPEC
+      && XINT (*x, 1) == UNSPEC_TLS)
+    return -1;
+
+  return 0;
+}
+
+/* Return TRUE if X contains any TLS symbol references.  */
+
+bool
+microblaze_tls_referenced_p (rtx x)
+{
+  if (! TARGET_HAVE_TLS)
+    return false;
+
+  return for_each_rtx (&x, microblaze_tls_operand_p_1, NULL);
+}
+
+bool
+microblaze_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+	return microblaze_tls_referenced_p(x);
+}
+
+/* Return TRUE if X references a SYMBOL_REF.  */
+int
+symbol_mentioned_p (rtx x)
+{
+  const char * fmt;
+  int i;
+
+  if (GET_CODE (x) == SYMBOL_REF)
+    return 1;
+
+  /* UNSPEC entries for a symbol include the SYMBOL_REF, but they
+     are constant offsets, not symbols.  */
+  if (GET_CODE (x) == UNSPEC)
+    return 0;
+
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
+
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'E')
+	{
+	  int j;
+
+	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+	    if (symbol_mentioned_p (XVECEXP (x, i, j)))
+	      return 1;
+	}
+      else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i)))
+	return 1;
+    }
+
+  return 0;
+}
+
+/* Return TRUE if X references a LABEL_REF.  */
+int
+label_mentioned_p (rtx x)
+{
+  const char * fmt;
+  int i;
+
+  if (GET_CODE (x) == LABEL_REF)
+    return 1;
+
+  /* UNSPEC entries for a symbol include a LABEL_REF for the referencing
+     instruction, but they are constant offsets, not symbols.  */
+  if (GET_CODE (x) == UNSPEC)
+    return 0;
+
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'E')
+	{
+	  int j;
+
+	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+	    if (label_mentioned_p (XVECEXP (x, i, j)))
+	      return 1;
+	}
+      else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
+	return 1;
+    }
+
+  return 0;
+}
+
+int
+tls_mentioned_p (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case CONST:
+      return tls_mentioned_p (XEXP (x, 0));
+
+    case UNSPEC:
+      if (XINT (x, 1) == UNSPEC_TLS)
+	return 1;
+
+    default:
+      return 0;
+    }
+}
+
+static rtx
+load_tls_operand (rtx x, rtx reg)
+{
+  rtx tmp;
+
+  if (reg == NULL_RTX)
+    reg = gen_reg_rtx (Pmode);
+
+  tmp = gen_rtx_CONST (Pmode, x);
+
+  emit_insn (gen_rtx_SET (VOIDmode,
+			  reg,
+			  gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp)));
+
+  return reg;
+}
+
+static rtx
+microblaze_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
+{
+  rtx insns, tls_entry;
+
+  df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
+
+  start_sequence ();
+
+  tls_entry = gen_rtx_UNSPEC (Pmode,
+           gen_rtvec (2, x, GEN_INT (reloc)) , UNSPEC_TLS);
+
+  reg = load_tls_operand (tls_entry, reg);
+
+  *valuep = emit_library_call_value (get_tls_get_addr (), NULL_RTX, LCT_PURE, /* LCT_CONST?  */
+                    Pmode, 1, reg, Pmode);
+
+  insns = get_insns ();
+  end_sequence ();
+
+  return insns;
+}
+
+rtx
+microblaze_legitimize_tls_address(rtx x, rtx reg)
+{
+  rtx dest, insns, ret, eqv, addend;
+  enum tls_model model;
+  model = SYMBOL_REF_TLS_MODEL (x);
+
+  switch (model)
+    {
+       case TLS_MODEL_LOCAL_DYNAMIC:
+       case TLS_MODEL_GLOBAL_DYNAMIC:
+       case TLS_MODEL_INITIAL_EXEC:
+           insns = microblaze_call_tls_get_addr (x, reg, &ret, TLS_GD);
+           dest = gen_reg_rtx (Pmode);
+           emit_libcall_block (insns, dest, ret, x);
+           break;
+
+       case TLS_MODEL_LOCAL_EXEC:
+           insns = microblaze_call_tls_get_addr (x, reg, &ret, TLS_LDM);
+
+           /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
+             share the LDM result with other LD model accesses.  */
+           eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx),
+                    UNSPEC_TLS);
+           dest = gen_reg_rtx (Pmode);
+           emit_libcall_block (insns, dest, ret, eqv);
+
+           /* Load the addend.  */
+           addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (TLS_DTPREL)),
+                  UNSPEC_TLS);
+           addend = force_reg (SImode, gen_rtx_CONST (SImode, addend));
+           dest = gen_rtx_PLUS (Pmode, dest, addend);
+           break;
+
+       default:
+           gcc_unreachable ();
+    }
+  return dest;
+}
+
 static bool
 microblaze_classify_unspec (struct microblaze_address_info *info, rtx x)
 {
@@ -401,6 +641,11 @@ microblaze_classify_unspec (struct microblaze_address_info *info, rtx x)
     {
       info->type = ADDRESS_PLT;
     }
+  else if (XINT (x, 1) == UNSPEC_TLS)
+    {
+      info->type = ADDRESS_TLS;
+      info->tls_type = tls_reloc INTVAL(XVECEXP(x, 0, 1));
+    }
   else
     {
       return false;
@@ -431,7 +676,12 @@ static int
 get_base_reg (rtx x)
 {
   tree decl;
-  int base_reg = (flag_pic ? MB_ABI_PIC_ADDR_REGNUM : MB_ABI_BASE_REGNUM);
+  int base_reg;
+
+  if (!flag_pic || microblaze_tls_symbol_p(x))
+    base_reg = MB_ABI_BASE_REGNUM;
+  else if (flag_pic)
+    base_reg = MB_ABI_PIC_ADDR_REGNUM;
 
   if (TARGET_XLGPOPT
       && GET_CODE (x) == SYMBOL_REF
@@ -509,28 +759,61 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
 	      }
 	    else if (GET_CODE (xplus1) == UNSPEC)
 	      {
+                /* Need offsettable address */
+                if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+		  return false;
+
 		return microblaze_classify_unspec (info, xplus1);
 	      }
 	    else if ((GET_CODE (xplus1) == SYMBOL_REF ||
-		      GET_CODE (xplus1) == LABEL_REF) && flag_pic == 2)
-	      {
-		return false;
-	      }
-	    else if (GET_CODE (xplus1) == SYMBOL_REF ||
-		     GET_CODE (xplus1) == LABEL_REF ||
-		     GET_CODE (xplus1) == CONST)
+		      GET_CODE (xplus1) == LABEL_REF))
 	      {
-		if (GET_CODE (XEXP (xplus1, 0)) == UNSPEC)
-		  return microblaze_classify_unspec (info, XEXP (xplus1, 0));
-		else if (flag_pic == 2)
-		  {
-		    return false;
-		  }
+		if (flag_pic == 2 || microblaze_tls_symbol_p(xplus1))
+                  return false;
 		info->type = ADDRESS_SYMBOLIC;
 		info->symbol = xplus1;
 		info->symbol_type = SYMBOL_TYPE_GENERAL;
 		return true;
 	      }
+	    else if (GET_CODE (xplus1) == CONST)
+	      {
+		rtx xconst0 = XEXP(xplus1, 0);
+
+		/* base + unspec */
+		if (GET_CODE (xconst0) == UNSPEC)
+                  {
+                    /* Need offsettable address */
+                    if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+		      return false;
+		    return microblaze_classify_unspec(info, xconst0);
+                  }
+
+                /* for (plus x const_int) just look at x */
+                if (GET_CODE (xconst0) == PLUS &&
+		    GET_CODE ( XEXP (xconst0, 1) ) == CONST_INT &&
+                    SMALL_INT ( XEXP (xconst0, 1)) )
+                  {
+                    /* This is ok as info->symbol is set to xplus1 the full
+                       const-expression below */
+                    xconst0 = XEXP (xconst0, 0);
+                  }
+
+                if (GET_CODE (xconst0) == SYMBOL_REF ||
+                      GET_CODE (xconst0) == LABEL_REF)
+                  {
+		    if (flag_pic == 2 || microblaze_tls_symbol_p(xconst0))
+		      return false;
+
+		    info->type = ADDRESS_SYMBOLIC;
+		    info->symbol = xplus1;
+		    info->symbol_type = SYMBOL_TYPE_GENERAL;
+		    return true;
+                  }
+
+                /* Not base + symbol || base + UNSPEC */
+		return false;
+
+	      }
 	    else if (GET_CODE (xplus1) == REG
 		     && microblaze_valid_index_register_p (xplus1, mode,
 							   strict)
@@ -560,14 +843,21 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
 	info->symbol = x;
 	info->regA = gen_rtx_raw_REG (mode, get_base_reg (x));
 
-	if (GET_CODE (x) == CONST)
-	  {
-	    return !(flag_pic && pic_address_needs_scratch (x));
-	  }
-	else if (flag_pic == 2)
-	  {
-	    return false;
-	  }
+        if (GET_CODE (x) == CONST)
+         {
+	    if (GET_CODE (XEXP (x, 0)) == UNSPEC)
+             {
+                info->regA = gen_rtx_raw_REG (mode,
+                                  get_base_reg ( XVECEXP ( XEXP(x,0), 0, 0) ));
+	        return microblaze_classify_unspec (info, XEXP (x, 0));
+             }
+	     return !(flag_pic && pic_address_needs_scratch (x));
+         }
+
+        if (flag_pic == 2)
+          return false;
+        else if (microblaze_tls_symbol_p(x))
+          return false;
 
 	return true;
       }
@@ -616,11 +906,10 @@ microblaze_valid_pic_const (rtx x)
 int
 microblaze_legitimate_pic_operand (rtx x)
 {
-  struct microblaze_address_info addr;
-
-  if (pic_address_needs_scratch (x))
+  if (flag_pic == 2 && (symbol_mentioned_p(x) || label_mentioned_p(x) ))
     return 0;
-  if (!microblaze_valid_pic_const(x))
+
+  if ( microblaze_tls_referenced_p(x) )
     return 0;
 
   return 1;
@@ -706,7 +995,7 @@ microblaze_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
 	  return result;
 	}
 
-      if (code0 == REG && REG_OK_FOR_BASE_P (xplus0) && flag_pic == 2)
+      if (code0 == REG && REG_OK_FOR_BASE_P (xplus0))
 	{
 	  if (reload_in_progress)
 	    df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
@@ -717,26 +1006,56 @@ microblaze_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
 	    }
 	  if (code1 == SYMBOL_REF)
 	    {
-	      result =
-		gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xplus1), UNSPEC_GOTOFF);
-	      result = gen_rtx_CONST (Pmode, result);
-	      result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
-	      result = gen_const_mem (Pmode, result);
-	      result = gen_rtx_PLUS (Pmode, xplus0, result);
-	      return result;
+             if (microblaze_tls_symbol_p(xplus1) )
+               {
+                 rtx tls_ref, reg;
+                 reg = gen_reg_rtx (Pmode);
+
+                 tls_ref = microblaze_legitimize_tls_address (xplus1, NULL_RTX);
+                 emit_move_insn (reg, tls_ref);
+
+	         result = gen_rtx_PLUS (Pmode, xplus0, reg);
+
+                 return result;
+               }
+             else if (flag_pic == 2)
+               {
+                 rtx pic_ref, reg;
+                 reg = gen_reg_rtx (Pmode);
+
+                 pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xplus1), UNSPEC_GOTOFF);
+                 pic_ref = gen_rtx_CONST (Pmode, pic_ref);
+                 pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref);
+                 pic_ref = gen_const_mem (Pmode, pic_ref);
+                 emit_move_insn (reg, pic_ref);
+                 result = gen_rtx_PLUS (Pmode, xplus0, reg);
+                 return result;
+               }
 	    }
 	}
     }
 
   if (GET_CODE (xinsn) == SYMBOL_REF)
     {
-      if (reload_in_progress)
-	df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-      result = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF);
-      result = gen_rtx_CONST (Pmode, result);
-      result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
-      result = gen_const_mem (Pmode, result);
-      return result;
+      rtx reg;
+      if (microblaze_tls_symbol_p(xinsn) )
+        {
+          reg = microblaze_legitimize_tls_address (xinsn, NULL_RTX);
+        }
+      else
+        {
+          rtx pic_ref;
+
+          if (reload_in_progress)
+            df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
+
+          pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF);
+          pic_ref = gen_rtx_CONST (Pmode, pic_ref);
+          pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref);
+          pic_ref = gen_const_mem (Pmode, pic_ref);
+          reg = pic_ref;
+        }
+      return reg;
     }
 
   return x;
@@ -1061,10 +1380,26 @@ microblaze_address_insns (rtx x, enum machine_mode mode)
 	  else
 	    return 2;
 	case ADDRESS_REG_INDEX:
-	case ADDRESS_SYMBOLIC:
 	  return 1;
+	case ADDRESS_SYMBOLIC:
 	case ADDRESS_GOTOFF:
 	  return 2;
+        case ADDRESS_TLS:
+          switch (addr.tls_type)
+            {
+              case TLS_GD:
+			return 2;
+                break;
+              case TLS_LDM:
+			return 2;
+                break;
+              case TLS_DTPREL:
+			return 1;
+                break;
+              default :
+                abort();
+                break;
+            }
 	default:
 	  break;
 	}
@@ -1088,13 +1423,18 @@ microblaze_address_cost (rtx addr, enum machine_mode mode ATTRIBUTE_UNUSED,
 int
 pic_address_needs_scratch (rtx x)
 {
-  /* An address which is a symbolic plus a non SMALL_INT needs a temp reg.  */
-  if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
-      && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
-      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
-      && (flag_pic == 2 || !SMALL_INT (XEXP (XEXP (x, 0), 1))))
-    return 1;
+  if (GET_CODE (x) == CONST && GET_CODE (XEXP (x,0)) == PLUS)
+    {
+     rtx p0, p1;
 
+      p0 = XEXP( XEXP (x, 0), 0 );
+      p1 = XEXP( XEXP (x, 0), 1 );
+
+      if ( (GET_CODE (p0) == SYMBOL_REF || GET_CODE (p0) == LABEL_REF) &&
+           (GET_CODE (p1) == CONST_INT) &&
+           (flag_pic == 2 || microblaze_tls_symbol_p (p0) || !SMALL_INT (p1)) )
+        return 1;
+    }
   return 0;
 }
 
@@ -1918,6 +2258,7 @@ print_operand (FILE * file, rtx op, int letter)
 	    case ADDRESS_CONST_INT:
 	    case ADDRESS_SYMBOLIC:
 	    case ADDRESS_GOTOFF:
+	    case ADDRESS_TLS:
 	      fputs ("i", file);
 	      break;
 	    case ADDRESS_REG_INDEX:
@@ -2034,10 +2375,19 @@ print_operand (FILE * file, rtx op, int letter)
   else if (letter == 't')
     fputs (code == EQ ? "t" : "f", file);
 
-  else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG)
+  else if (code == CONST &&
+           (GET_CODE (XEXP (op, 0)) == REG ||
+            GET_CODE (XEXP (op, 0)) == UNSPEC))
     {
       print_operand (file, XEXP (op, 0), letter);
     }
+  else if (code == CONST &&
+           (GET_CODE (XEXP (op, 0)) == PLUS) &&
+           (GET_CODE (XEXP (XEXP (op, 0), 0)) == REG) &&
+           (GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST) )
+    {
+      print_operand_address (file, XEXP (op, 0) );
+    }
   else if (letter == 'm')
     fprintf (file, HOST_WIDE_INT_PRINT_DEC, (1L << INTVAL (op)));
   else
@@ -2098,6 +2448,7 @@ print_operand_address (FILE * file, rtx addr)
     case ADDRESS_SYMBOLIC:
     case ADDRESS_GOTOFF:
     case ADDRESS_PLT:
+    case ADDRESS_TLS:
       if (info.regA)
 	fprintf (file, "%s,", reg_names[REGNO (info.regA)]);
       output_addr_const (file, info.symbol);
@@ -2109,6 +2460,24 @@ print_operand_address (FILE * file, rtx addr)
 	{
 	  fputs ("@PLT", file);
 	}
+      else if (type == ADDRESS_TLS)
+        {
+          switch (info.tls_type)
+            {
+              case TLS_GD:
+                fputs ("@TLSGD", file);
+                break;
+              case TLS_LDM:
+                fputs ("@TLSLDM", file);
+                break;
+              case TLS_DTPREL:
+                fputs ("@TLSDTPREL", file);
+                break;
+              default :
+                abort();
+                break;
+           }
+        }
       break;
     case ADDRESS_INVALID:
       fatal_insn ("invalid address", addr);
@@ -2471,7 +2840,7 @@ microblaze_expand_prologue (void)
 	}
     }
 
-  if (flag_pic == 2 && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM))
+  if ((flag_pic == 2 || TLS_NEEDS_GOT ) && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM))
     {
       SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM);
       emit_insn (gen_set_got (pic_offset_table_rtx));	/* setting GOT.  */
@@ -2701,84 +3070,62 @@ expand_pic_symbol_ref (enum machine_mode mode ATTRIBUTE_UNUSED, rtx op)
 bool
 microblaze_expand_move (enum machine_mode mode, rtx operands[])
 {
+  rtx op0, op1;
+
+  op0 = operands[0];
+  op1 = operands[1];
+
+  if ( ! register_operand (op0, SImode)
+      && ! register_operand (op1, SImode)
+      && (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 0))
+    {
+      rtx temp = force_reg (SImode, op1);
+      emit_move_insn (op0, temp);
+      return true;
+    }
   /* If operands[1] is a constant address invalid for pic, then we need to
      handle it just like LEGITIMIZE_ADDRESS does.  */
-  if (flag_pic)
+  if (GET_CODE (op1) == SYMBOL_REF || GET_CODE (op1) == LABEL_REF)
     {
-      if (GET_CODE (operands[0]) == MEM)
-	{
-	  rtx addr = XEXP (operands[0], 0);
-	  if (GET_CODE (addr) == SYMBOL_REF)
-	    {
-	      rtx ptr_reg, result;
-
-	      if (reload_in_progress)
-		df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-
-	      addr = expand_pic_symbol_ref (mode, addr);
-	      ptr_reg = gen_reg_rtx (Pmode);
-	      emit_move_insn (ptr_reg, addr);
-	      result = gen_rtx_MEM (mode, ptr_reg);
-	      operands[0] = result;
-	    }
-	}
-      if (GET_CODE (operands[1]) == SYMBOL_REF
-	  || GET_CODE (operands[1]) == LABEL_REF)
-	{
-	  rtx result;
-	  if (reload_in_progress)
-	    df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-	  result = expand_pic_symbol_ref (mode, operands[1]);
-	  if (GET_CODE (operands[0]) != REG)
-	    {
-	      rtx ptr_reg = gen_reg_rtx (Pmode);
-	      emit_move_insn (ptr_reg, result);
-	      emit_move_insn (operands[0], ptr_reg);
-	    }
-	  else
-	    {
-	      emit_move_insn (operands[0], result);
-	    }
+      rtx result;
+      if (microblaze_tls_symbol_p(op1))
+        {
+          result = microblaze_legitimize_tls_address (op1, NULL_RTX);
+          emit_move_insn (op0, result);
 	  return true;
-	}
-      else if (GET_CODE (operands[1]) == MEM &&
-	       GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
-	{
-	  rtx result;
-	  rtx ptr_reg;
-	  if (reload_in_progress)
-	    df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-	  result = expand_pic_symbol_ref (mode, XEXP (operands[1], 0));
+        }
+      else if (flag_pic)
+        {
+          if (reload_in_progress)
+            df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
+          result = expand_pic_symbol_ref (mode, op1);
+          emit_move_insn (op0, result);
+          return true;
+        }
+    }
+  /* Handle Case of (const (plus symbol const_int)) */
+  if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1,0)) == PLUS)
+    {
+      rtx p0, p1;
 
-	  ptr_reg = gen_reg_rtx (Pmode);
+      p0 = XEXP( XEXP (op1, 0), 0 );
+      p1 = XEXP( XEXP (op1, 0), 1 );
 
-	  emit_move_insn (ptr_reg, result);
-	  result = gen_rtx_MEM (mode, ptr_reg);
-	  emit_move_insn (operands[0], result);
-	  return true;
-	}
-      else if (pic_address_needs_scratch (operands[1]))
-	{
-	  rtx temp = force_reg (SImode, XEXP (XEXP (operands[1], 0), 0));
-	  rtx temp2 = XEXP (XEXP (operands[1], 0), 1);
+      if ( (GET_CODE (p1) == CONST_INT) &&
+           ( (GET_CODE (p0) == UNSPEC) ||
+           ( (GET_CODE (p0) == SYMBOL_REF || GET_CODE (p0) == LABEL_REF) &&
+             (flag_pic == 2 || microblaze_tls_symbol_p (p0) || !SMALL_INT (p1)) ) ))
+        {
+	  rtx temp = force_reg (SImode, p0);
+	  rtx temp2 = p1;
 
-	  if (reload_in_progress)
+	  if (flag_pic && reload_in_progress)
 	    df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-	  emit_move_insn (operands[0], gen_rtx_PLUS (SImode, temp, temp2));
+	  emit_move_insn (op0, gen_rtx_PLUS (SImode, temp, temp2));
 	  return true;
-	}
-    }
-
-  if ((reload_in_progress | reload_completed) == 0
-      && !register_operand (operands[0], SImode)
-      && !register_operand (operands[1], SImode)
-      && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))
-    {
-      rtx temp = force_reg (SImode, operands[1]);
-      emit_move_insn (operands[0], temp);
-      return true;
-    }
-  return false;
+        }
+     }
+   return false;
 }
 
 /* Expand shift operations.  */
@@ -3048,10 +3395,40 @@ microblaze_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link,
    At present, GAS doesn't understand li.[sd], so don't allow it
    to be generated at present.  */
 static bool
-microblaze_legitimate_constant_p (enum machine_mode mode, rtx x)
+microblaze_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
 {
-  return GET_CODE (x) != CONST_DOUBLE || microblaze_const_double_ok (x, mode);
+
+  if (microblaze_cannot_force_const_mem(mode, x))
+        return false;
+
+  if (GET_CODE (x) == CONST_DOUBLE)
+    {
+      return microblaze_const_double_ok (x, GET_MODE (x));
+    }
+
+   /* Handle Case of (const (plus unspec const_int)) */
+   if (GET_CODE (x) == CONST && GET_CODE (XEXP (x,0)) == PLUS)
+     {
+        rtx p0, p1;
+
+        p0 = XEXP( XEXP (x, 0), 0 );
+        p1 = XEXP( XEXP (x, 0), 1 );
+
+        if (GET_CODE(p1) == CONST_INT)
+          {
+            /* Const offset from UNSPEC is not supported */
+            if ( (GET_CODE (p0) == UNSPEC) )
+              return false;
+
+            if ( (GET_CODE (p0) == SYMBOL_REF || GET_CODE (p0) == LABEL_REF) &&
+                 (microblaze_tls_symbol_p (p0) || !SMALL_INT (p1)) )
+              return false;
+          }
+      }
+
+  return true;
 }
+
 \f
 #undef TARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO      microblaze_encode_section_info
@@ -3068,6 +3445,9 @@ microblaze_legitimate_constant_p (enum machine_mode mode, rtx x)
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS                microblaze_rtx_costs
 
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM   microblaze_cannot_force_const_mem
+
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST             microblaze_address_cost
 
diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h
index 8fbe5bf..bc4d9a1 100644
--- a/gcc/config/microblaze/microblaze.h
+++ b/gcc/config/microblaze/microblaze.h
@@ -65,6 +65,9 @@ extern enum pipeline_type microblaze_pipe;
 /* The default is to support PIC.  */
 #define TARGET_SUPPORTS_PIC 1
 
+/* The default is to not need GOT for TLS.  */
+#define TLS_NEEDS_GOT 0
+
 /* What is the default setting for -mcpu= . We set it to v4.00.a even though 
    we are actually ahead. This is safest version that has generate code 
    compatible for the original ISA */
@@ -326,9 +329,7 @@ extern char microblaze_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
 
 #define NO_FUNCTION_CSE                 1
 
-#define PIC_OFFSET_TABLE_REGNUM         \
-        (flag_pic ? (GP_REG_FIRST + MB_ABI_PIC_ADDR_REGNUM) : \
-        INVALID_REGNUM)
+#define PIC_OFFSET_TABLE_REGNUM   (GP_REG_FIRST + MB_ABI_PIC_ADDR_REGNUM)
 
 enum reg_class
 {
diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
index 0285787..3618cad 100644
--- a/gcc/config/microblaze/microblaze.md
+++ b/gcc/config/microblaze/microblaze.md
@@ -40,6 +40,7 @@
   (UNSPEC_PLT           103)    ;; jump table
   (UNSPEC_CMP		104)    ;; signed compare
   (UNSPEC_CMPU		105)    ;; unsigned compare
+  (UNSPEC_TLS           106)    ;; jump table
 ])
 
 
@@ -459,7 +460,7 @@
 (define_insn "addsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d,d")
 	(plus:SI (match_operand:SI 1 "reg_or_0_operand" "%dJ,dJ,dJ")
-		 (match_operand:SI 2 "arith_operand" "d,I,i")))]
+		 (match_operand:SI 2 "arith_plus_operand" "d,I,i")))]
   ""
   "@
    addk\t%0,%z1,%2
@@ -892,8 +893,8 @@
 
 
 (define_insn "*movdi_internal"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")
-	(match_operand:DI 1 "general_operand"      " d,i,J,R,m,d,d"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,o")
+	(match_operand:DI 1 "general_operand"      " d,i,J,R,o,d,d"))]
   ""
   { 
     switch (which_alternative)
@@ -999,13 +1000,9 @@
   (set_attr "length"	"4")])
 
 (define_insn "*movsi_internal2"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,   d,d,R, T")
-	(match_operand:SI 1 "move_operand"         " d,I,Mnis,R,m,dJ,dJ"))]
-  "(register_operand (operands[0], SImode)
-    || register_operand (operands[1], SImode) 
-    || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))
-    && (flag_pic != 2 || (GET_CODE (operands[1]) != SYMBOL_REF 
-                         && GET_CODE (operands[1]) != LABEL_REF))"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,   d,d,R,m")
+	(match_operand:SI 1 "move_src_operand"         " d,I,Mnis,R,m,dJ,dJ"))]
+  ""
   "@
    addk\t%0,%1,r0
    addik\t%0,r0,%1\t# %X1
@@ -1196,7 +1193,7 @@
 ;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT
 ;;
 (define_insn "*movdf_internal"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,To")
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,o")
         (match_operand:DF 1 "general_operand" "dG,o,F,T,d"))]
   ""
   {
diff --git a/gcc/config/microblaze/predicates.md b/gcc/config/microblaze/predicates.md
index e6e9983..e5ed390 100644
--- a/gcc/config/microblaze/predicates.md
+++ b/gcc/config/microblaze/predicates.md
@@ -30,6 +30,49 @@
        (and (match_code "const_int,const_double")
 	    (match_test "LARGE_INT (op)"))))
 
+(define_predicate "arith_plus_operand"
+ (match_operand 0 "general_operand")
+{
+  switch (GET_CODE (op)) {
+    default:
+      return 0;
+    case CONST_INT:
+    case REG:
+      return 1;
+    case SYMBOL_REF:
+    case LABEL_REF:
+      if (flag_pic || microblaze_tls_referenced_p(op))
+        return 0;
+      return 1;
+    case CONST:
+      {
+        rtx const0;
+        const0 = XEXP (op, 0);
+
+        switch ( GET_CODE(const0) ) {
+          default:
+            return 0;
+          case UNSPEC :
+            return 1;
+
+          case PLUS :
+            {
+              rtx p0, p1;
+              p0 = XEXP (const0, 0);
+              p1 = XEXP (const0, 1);
+
+              if ( (GET_CODE(p0) == SYMBOL_REF || GET_CODE (p0) == LABEL_REF) &&
+                   GET_CODE(p1) == CONST_INT )
+                {
+                  return arith_plus_operand (p0, GET_MODE(p0));
+                }
+            }
+          }
+        }
+      }
+    return 0;
+})
+
 (define_predicate "const_0_operand"
   (and (match_code "const_int,const_double")
        (match_test "op == CONST0_RTX (GET_MODE (op))")))
@@ -54,14 +97,21 @@
        (match_test "GET_CODE (op) == REG || GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST_INT")))
 
 ;; Return if OPERAND is valid as a source operand for a move instruction.
-(define_predicate "move_operand"
+(define_predicate "move_src_operand"
   (and (
      not (
        and (match_code "plus")
            (not (match_test "(GET_CODE (XEXP (op, 0)) == REG) ^ (GET_CODE (XEXP (op,1)) == REG)"))
 	 )
        )
-       (match_operand 0 "general_operand")))
+       (match_operand 0 "general_operand"))
+{
+  if (microblaze_tls_referenced_p(op) ||
+      (flag_pic && (symbol_mentioned_p(op) || label_mentioned_p(op))) )
+    return false;
+
+  return true;
+})
 
 ;; Test for valid PIC call operand
 (define_predicate "call_insn_plt_operand"
-- 
1.7.0.4


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Patch, microblaze]: Add support for TLS in MicroBlaze
  2013-03-12 20:47 [Patch, microblaze]: Add support for TLS in MicroBlaze David Holsgrove
@ 2013-03-13 15:34 ` Michael Eager
  2013-03-14  8:08   ` David Holsgrove
  0 siblings, 1 reply; 4+ messages in thread
From: Michael Eager @ 2013-03-13 15:34 UTC (permalink / raw)
  To: David Holsgrove
  Cc: gcc-patches, Edgar Iglesias, John Williams, Vinod Kathail,
	Vidhumouli Hunsigida, Nagaraju Mekala, Tom Shui

On 03/12/2013 01:47 PM, David Holsgrove wrote:
> Add support for thread local storage (general dynamic and local dynamic models) in MicroBlaze.
>
>
> gcc/Changelog
>
> 2013-03-13  Edgar E. Iglesias <edgar.iglesias@xilinx.com>
>              David Holsgrove <david.holsgrove@xilinx.com>
>
>   * config/microblaze/microblaze-protos.h: (microblaze_cannot_force_const_mem,
>     microblaze_tls_referenced_p, symbol_mentioned_p,
>     label_mentioned_p): Add prototypes.
>   * config/microblaze/microblaze.c (microblaze_address_type): Add ADDRESS_TLS
>     and tls_reloc address types.
>     (microblaze_address_info): Add tls_reloc.
>     (TARGET_HAVE_TLS): Define.
>     (get_tls_get_addr, microblaze_tls_symbol_p, microblaze_tls_operand_p_1,
>      microblaze_tls_referenced_p, microblaze_cannot_force_const_mem,
>      symbol_mentioned_p, label_mentioned_p, tls_mentioned_p, load_tls_operand,
>      microblaze_call_tls_get_addr, microblaze_legitimize_tls_address): New functions.
>     (microblaze_classify_unspec): Handle UNSPEC_TLS.
>     (get_base_reg): Use microblaze_tls_symbol_p.
>     (microblaze_classify_address): Handle TLS.
>     (microblaze_legitimate_pic_operand): Use symbol_mentioned_p, label_mentioned_p
>      and microblaze_tls_referenced_p.
>     (microblaze_legitimize_address): Handle TLS.
>     (microblaze_address_insns): Handle ADDRESS_TLS.
>     (pic_address_needs_scratch): Handle TLS.
>     (print_operand_address): Handle TLS.
>     (microblaze_expand_prologue): Check TLS_NEEDS_GOT.
>     (microblaze_expand_move): Handle TLS.
>     (microblaze_legitimate_constant_p): Check microblaze_cannot_force_const_mem
>      and microblaze_tls_symbol_p.
>     (TARGET_CANNOT_FORCE_CONST_MEM): Define.
>   * config/microblaze/microblaze.h (TLS_NEEDS_GOT): Define
>     (PIC_OFFSET_TABLE_REGNUM): Set.
>   * config/microblaze/linux.h (TLS_NEEDS_GOT): Define.
>   * config/microblaze/microblaze.md (UNSPEC_TLS): Define.
>     (addsi3, movsi_internal2, movdf_internal): Update constraints
>   * config/microblaze/predicates.md (arith_plus_operand): Define
>     (move_operand): Redefine as move_src_operand, check microblaze_tls_referenced_p.
>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>

Hi David --

The patch is OK except for a number of minor formatting problems to meet GNU standards.
- Comments are supposed to end with ".  */".
- Extra spacing around parens or between "!" and "TARGET...".
- && or || at start of line continuing a condition rather that at end of previous line
- Some places where the indenting is incorrect

Should this patch be combined with the other patch adding TLS checking to configure?


-- 
Michael Eager	 eager@eagercon.com
1960 Park Blvd., Palo Alto, CA 94306  650-325-8077

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [Patch, microblaze]: Add support for TLS in MicroBlaze
  2013-03-13 15:34 ` Michael Eager
@ 2013-03-14  8:08   ` David Holsgrove
  2013-03-14 15:46     ` Michael Eager
  0 siblings, 1 reply; 4+ messages in thread
From: David Holsgrove @ 2013-03-14  8:08 UTC (permalink / raw)
  To: Michael Eager
  Cc: gcc-patches, Edgar Iglesias, John Williams, Vinod Kathail,
	Vidhumouli Hunsigida, Nagaraju Mekala, Tom Shui

[-- Attachment #1: Type: text/plain, Size: 3952 bytes --]

Hi Michael,

> -----Original Message-----
> From: Michael Eager [mailto:eager@eagerm.com]
> Sent: Thursday, 14 March 2013 1:34 am
> To: David Holsgrove
> Cc: gcc-patches@gcc.gnu.org; Edgar Iglesias; John Williams; Vinod Kathail;
> Vidhumouli Hunsigida; Nagaraju Mekala; Tom Shui
> Subject: Re: [Patch, microblaze]: Add support for TLS in MicroBlaze
> 
> On 03/12/2013 01:47 PM, David Holsgrove wrote:
> > Add support for thread local storage (general dynamic and local dynamic
> models) in MicroBlaze.
> >
> >
> > gcc/Changelog
> >
> > 2013-03-13  Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> >              David Holsgrove <david.holsgrove@xilinx.com>
> >
[--snip--]
> >
> > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> > Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
> 
> Hi David --
> 
> The patch is OK except for a number of minor formatting problems to meet GNU
> standards.
> - Comments are supposed to end with ".  */".
> - Extra spacing around parens or between "!" and "TARGET...".
> - && or || at start of line continuing a condition rather that at end of previous line
> - Some places where the indenting is incorrect
> 

Thanks for the review, we inherited some of the style deviations when basing off
of other archs TLS functions I'm afraid. I've fixed the formatting in v2 of the patch
attached.

> Should this patch be combined with the other patch adding TLS checking to
> configure?
> 

I've combined both patches into the attached - looking back at the ARM TLS patch
it was submitted this way, so we'll follow precedence there if that’s okay with
you.

Updated Changelog would be;

2013-03-14 Edgar E. Iglesias <edgar.iglesias@xilinx.com>
           David Holsgrove <david.holsgrove@xilinx.com>

 * configure.ac: Add MicroBlaze TLS support detection.
 * configure: Regenerate.
 * config/microblaze/microblaze-protos.h: (microblaze_cannot_force_const_mem,
   microblaze_tls_referenced_p, symbol_mentioned_p,
   label_mentioned_p): Add prototypes.
 * config/microblaze/microblaze.c (microblaze_address_type): Add ADDRESS_TLS
   and tls_reloc address types.
   (microblaze_address_info): Add tls_reloc.
   (TARGET_HAVE_TLS): Define.
   (get_tls_get_addr, microblaze_tls_symbol_p, microblaze_tls_operand_p_1,
    microblaze_tls_referenced_p, microblaze_cannot_force_const_mem,
    symbol_mentioned_p, label_mentioned_p, tls_mentioned_p, load_tls_operand,
    microblaze_call_tls_get_addr, microblaze_legitimize_tls_address): New functions.
   (microblaze_classify_unspec): Handle UNSPEC_TLS.
   (get_base_reg): Use microblaze_tls_symbol_p.
   (microblaze_classify_address): Handle TLS.
   (microblaze_legitimate_pic_operand): Use symbol_mentioned_p, label_mentioned_p
    and microblaze_tls_referenced_p.
   (microblaze_legitimize_address): Handle TLS.
   (microblaze_address_insns): Handle ADDRESS_TLS.
   (pic_address_needs_scratch): Handle TLS.
   (print_operand_address): Handle TLS.
   (microblaze_expand_prologue): Check TLS_NEEDS_GOT.
   (microblaze_expand_move): Handle TLS.
   (microblaze_legitimate_constant_p): Check microblaze_cannot_force_const_mem
    and microblaze_tls_symbol_p.
   (TARGET_CANNOT_FORCE_CONST_MEM): Define.
 * config/microblaze/microblaze.h (TLS_NEEDS_GOT): Define
   (PIC_OFFSET_TABLE_REGNUM): Set.
 * config/microblaze/linux.h (TLS_NEEDS_GOT): Define.
 * config/microblaze/microblaze.md (UNSPEC_TLS): Define.
   (addsi3, movsi_internal2, movdf_internal): Update constraints
 * config/microblaze/predicates.md (arith_plus_operand): Define
   (move_operand): Redefine as move_src_operand, check microblaze_tls_referenced_p.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>


thanks again,
David

> 
> --
> Michael Eager	 eager@eagercon.com
> 1960 Park Blvd., Palo Alto, CA 94306  650-325-8077




[-- Attachment #2: 0001-Patch-microblaze-Add-support-for-TLS-in-MicroBlaze.patch --]
[-- Type: application/octet-stream, Size: 33279 bytes --]

From 087397aa335c082f26156d19fd316cd4e069815d Mon Sep 17 00:00:00 2001
From: Gopi <gopi@linux69.(none)>
Date: Mon, 15 Mar 2010 12:46:09 +0530
Subject: [PATCH] [Patch, microblaze]: Add support for TLS in MicroBlaze

Changelog

2013-03-14 Edgar E. Iglesias <edgar.iglesias@xilinx.com>
           David Holsgrove <david.holsgrove@xilinx.com>

 * configure.ac: Add MicroBlaze TLS support detection.
 * configure: Regenerate.
 * config/microblaze/microblaze-protos.h: (microblaze_cannot_force_const_mem,
   microblaze_tls_referenced_p, symbol_mentioned_p,
   label_mentioned_p): Add prototypes.
 * config/microblaze/microblaze.c (microblaze_address_type): Add ADDRESS_TLS
   and tls_reloc address types.
   (microblaze_address_info): Add tls_reloc.
   (TARGET_HAVE_TLS): Define.
   (get_tls_get_addr, microblaze_tls_symbol_p, microblaze_tls_operand_p_1,
    microblaze_tls_referenced_p, microblaze_cannot_force_const_mem,
    symbol_mentioned_p, label_mentioned_p, tls_mentioned_p, load_tls_operand,
    microblaze_call_tls_get_addr, microblaze_legitimize_tls_address): New functions.
   (microblaze_classify_unspec): Handle UNSPEC_TLS.
   (get_base_reg): Use microblaze_tls_symbol_p.
   (microblaze_classify_address): Handle TLS.
   (microblaze_legitimate_pic_operand): Use symbol_mentioned_p, label_mentioned_p
    and microblaze_tls_referenced_p.
   (microblaze_legitimize_address): Handle TLS.
   (microblaze_address_insns): Handle ADDRESS_TLS.
   (pic_address_needs_scratch): Handle TLS.
   (print_operand_address): Handle TLS.
   (microblaze_expand_prologue): Check TLS_NEEDS_GOT.
   (microblaze_expand_move): Handle TLS.
   (microblaze_legitimate_constant_p): Check microblaze_cannot_force_const_mem
    and microblaze_tls_symbol_p.
   (TARGET_CANNOT_FORCE_CONST_MEM): Define.
 * config/microblaze/microblaze.h (TLS_NEEDS_GOT): Define
   (PIC_OFFSET_TABLE_REGNUM): Set.
 * config/microblaze/linux.h (TLS_NEEDS_GOT): Define.
 * config/microblaze/microblaze.md (UNSPEC_TLS): Define.
   (addsi3, movsi_internal2, movdf_internal): Update constraints
 * config/microblaze/predicates.md (arith_plus_operand): Define
   (move_operand): Redefine as move_src_operand, check microblaze_tls_referenced_p.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
---
 gcc/config/microblaze/linux.h             |    3 +
 gcc/config/microblaze/microblaze-protos.h |    4 +
 gcc/config/microblaze/microblaze.c        |  598 +++++++++++++++++++++++------
 gcc/config/microblaze/microblaze.h        |    7 +-
 gcc/config/microblaze/microblaze.md       |   19 +-
 gcc/config/microblaze/predicates.md       |   57 +++-
 gcc/configure                             |   12 +
 gcc/configure.ac                          |   12 +
 8 files changed, 587 insertions(+), 125 deletions(-)

diff --git a/gcc/config/microblaze/linux.h b/gcc/config/microblaze/linux.h
index eca7776..a7b7a1a 100644
--- a/gcc/config/microblaze/linux.h
+++ b/gcc/config/microblaze/linux.h
@@ -22,6 +22,9 @@
 #undef TARGET_SUPPORTS_PIC
 #define TARGET_SUPPORTS_PIC 1
 
+#undef TLS_NEEDS_GOT
+#define TLS_NEEDS_GOT 1
+
 #define DYNAMIC_LINKER "/lib/ld.so.1"
 #undef  SUBTARGET_EXTRA_SPECS
 #define SUBTARGET_EXTRA_SPECS \
diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
index e19939f..34be76f 100644
--- a/gcc/config/microblaze/microblaze-protos.h
+++ b/gcc/config/microblaze/microblaze-protos.h
@@ -50,6 +50,10 @@ extern void microblaze_declare_object (FILE *, const char *, const char *,
    const char *, int);
 extern void microblaze_asm_output_ident (const char *);
 extern int microblaze_legitimate_pic_operand (rtx);
+extern bool microblaze_tls_referenced_p (rtx);
+extern int symbol_mentioned_p (rtx);
+extern int label_mentioned_p (rtx);
+extern bool microblaze_cannot_force_const_mem (enum machine_mode, rtx);
 #endif  /* RTX_CODE */
 
 /* Declare functions in microblaze-c.c.  */
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index 3a52994..0556365 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -84,7 +84,8 @@ enum microblaze_address_type
   ADDRESS_CONST_INT,
   ADDRESS_SYMBOLIC,
   ADDRESS_GOTOFF,
-  ADDRESS_PLT
+  ADDRESS_PLT,
+  ADDRESS_TLS
 };
 
 /* Classifies symbols
@@ -98,6 +99,15 @@ enum microblaze_symbol_type
   SYMBOL_TYPE_GENERAL
 };
 
+/* TLS Address Type.  */
+enum tls_reloc {
+  TLS_GD,
+  TLS_LDM,
+  TLS_DTPREL,
+  TLS_IE,
+  TLS_LE
+};
+
 /* Classification of a MicroBlaze address.  */
 struct microblaze_address_info
 {
@@ -108,6 +118,7 @@ struct microblaze_address_info
   rtx offset; 	/* Contains valid values on ADDRESS_CONST_INT and ADDRESS_REG.  */
   rtx symbol; 	/* Contains valid values on ADDRESS_SYMBOLIC.  */
   enum microblaze_symbol_type symbol_type;
+  enum tls_reloc tls_type;
 };
 
 /* Structure to be filled in by compute_frame_size with register
@@ -215,6 +226,11 @@ static int microblaze_interrupt_function_p (tree);
 
 section *sdata2_section;
 
+#ifdef HAVE_AS_TLS
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS true
+#endif
+
 /* Return truth value if a CONST_DOUBLE is ok to be a legitimate constant.  */
 static bool
 microblaze_const_double_ok (rtx op, enum machine_mode mode)
@@ -287,6 +303,9 @@ simple_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
       plus0 = XEXP (addr, 0);
       plus1 = XEXP (addr, 1);
 
+      if (GET_CODE (plus0) != REG)
+        return 0;
+
       if (GET_CODE (plus0) == REG && GET_CODE (plus1) == CONST_INT
 	  && SMALL_INT (plus1))
 	{
@@ -386,6 +405,227 @@ microblaze_valid_base_register_p (rtx x,
 	  && microblaze_regno_ok_for_base_p (REGNO (x), strict));
 }
 
+/* Build the SYMBOL_REF for __tls_get_addr.  */
+
+static GTY(()) rtx tls_get_addr_libfunc;
+
+static rtx
+get_tls_get_addr (void)
+{
+  if (!tls_get_addr_libfunc)
+    tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr");
+  return tls_get_addr_libfunc;
+}
+
+/* Return TRUE if X is a thread-local symbol.  */
+bool
+microblaze_tls_symbol_p (rtx x)
+{
+  if (!TARGET_HAVE_TLS)
+    return false;
+
+  if (GET_CODE (x) != SYMBOL_REF)
+    return false;
+
+  return SYMBOL_REF_TLS_MODEL (x) != 0;
+}
+
+static int
+microblaze_tls_operand_p_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
+{
+  if (GET_CODE (*x) == SYMBOL_REF)
+    return SYMBOL_REF_TLS_MODEL (*x) != 0;
+
+  /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are
+     TLS offsets, not real symbol references.  */
+  if (GET_CODE (*x) == UNSPEC && XINT (*x, 1) == UNSPEC_TLS)
+    return -1;
+
+  return 0;
+}
+
+/* Return TRUE if X contains any TLS symbol references.  */
+
+bool
+microblaze_tls_referenced_p (rtx x)
+{
+  if (!TARGET_HAVE_TLS)
+    return false;
+
+  return for_each_rtx (&x, microblaze_tls_operand_p_1, NULL);
+}
+
+bool
+microblaze_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  return microblaze_tls_referenced_p(x);
+}
+
+/* Return TRUE if X references a SYMBOL_REF.  */
+int
+symbol_mentioned_p (rtx x)
+{
+  const char * fmt;
+  int i;
+
+  if (GET_CODE (x) == SYMBOL_REF)
+    return 1;
+
+  /* UNSPEC entries for a symbol include the SYMBOL_REF, but they
+     are constant offsets, not symbols.  */
+  if (GET_CODE (x) == UNSPEC)
+    return 0;
+
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
+
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'E')
+        {
+          int j;
+
+          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+            if (symbol_mentioned_p (XVECEXP (x, i, j)))
+              return 1;
+        }
+      else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i)))
+        return 1;
+    }
+
+  return 0;
+}
+
+/* Return TRUE if X references a LABEL_REF.  */
+int
+label_mentioned_p (rtx x)
+{
+  const char * fmt;
+  int i;
+
+  if (GET_CODE (x) == LABEL_REF)
+    return 1;
+
+  /* UNSPEC entries for a symbol include a LABEL_REF for the referencing
+     instruction, but they are constant offsets, not symbols.  */
+  if (GET_CODE (x) == UNSPEC)
+    return 0;
+
+  fmt = GET_RTX_FORMAT (GET_CODE (x));
+  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'E')
+        {
+          int j;
+
+          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+            if (label_mentioned_p (XVECEXP (x, i, j)))
+              return 1;
+        }
+      else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
+        return 1;
+    }
+
+  return 0;
+}
+
+int
+tls_mentioned_p (rtx x)
+{
+  switch (GET_CODE (x))
+    {
+      case CONST:
+        return tls_mentioned_p (XEXP (x, 0));
+
+      case UNSPEC:
+        if (XINT (x, 1) == UNSPEC_TLS)
+          return 1;
+
+      default:
+        return 0;
+    }
+}
+
+static rtx
+load_tls_operand (rtx x, rtx reg)
+{
+  rtx tmp;
+
+  if (reg == NULL_RTX)
+    reg = gen_reg_rtx (Pmode);
+
+  tmp = gen_rtx_CONST (Pmode, x);
+
+  emit_insn (gen_rtx_SET (VOIDmode, reg,
+                          gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp)));
+
+  return reg;
+}
+
+static rtx
+microblaze_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
+{
+  rtx insns, tls_entry;
+
+  df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
+
+  start_sequence ();
+
+  tls_entry = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (reloc)),
+                                     UNSPEC_TLS);
+
+  reg = load_tls_operand (tls_entry, reg);
+
+  *valuep = emit_library_call_value (get_tls_get_addr (), NULL_RTX,
+                                     LCT_PURE, /* LCT_CONST?  */
+                                     Pmode, 1, reg, Pmode);
+
+  insns = get_insns ();
+  end_sequence ();
+
+  return insns;
+}
+
+rtx
+microblaze_legitimize_tls_address(rtx x, rtx reg)
+{
+  rtx dest, insns, ret, eqv, addend;
+  enum tls_model model;
+  model = SYMBOL_REF_TLS_MODEL (x);
+
+  switch (model)
+    {
+       case TLS_MODEL_LOCAL_DYNAMIC:
+       case TLS_MODEL_GLOBAL_DYNAMIC:
+       case TLS_MODEL_INITIAL_EXEC:
+           insns = microblaze_call_tls_get_addr (x, reg, &ret, TLS_GD);
+           dest = gen_reg_rtx (Pmode);
+           emit_libcall_block (insns, dest, ret, x);
+           break;
+
+       case TLS_MODEL_LOCAL_EXEC:
+           insns = microblaze_call_tls_get_addr (x, reg, &ret, TLS_LDM);
+
+           /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
+             share the LDM result with other LD model accesses.  */
+           eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx),
+                    UNSPEC_TLS);
+           dest = gen_reg_rtx (Pmode);
+           emit_libcall_block (insns, dest, ret, eqv);
+
+           /* Load the addend.  */
+           addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x,
+                                           GEN_INT (TLS_DTPREL)),
+                                           UNSPEC_TLS);
+           addend = force_reg (SImode, gen_rtx_CONST (SImode, addend));
+           dest = gen_rtx_PLUS (Pmode, dest, addend);
+           break;
+
+       default:
+           gcc_unreachable ();
+    }
+  return dest;
+}
+
 static bool
 microblaze_classify_unspec (struct microblaze_address_info *info, rtx x)
 {
@@ -401,6 +641,11 @@ microblaze_classify_unspec (struct microblaze_address_info *info, rtx x)
     {
       info->type = ADDRESS_PLT;
     }
+  else if (XINT (x, 1) == UNSPEC_TLS)
+    {
+      info->type = ADDRESS_TLS;
+      info->tls_type = tls_reloc INTVAL(XVECEXP(x, 0, 1));
+    }
   else
     {
       return false;
@@ -431,7 +676,12 @@ static int
 get_base_reg (rtx x)
 {
   tree decl;
-  int base_reg = (flag_pic ? MB_ABI_PIC_ADDR_REGNUM : MB_ABI_BASE_REGNUM);
+  int base_reg;
+
+  if (!flag_pic || microblaze_tls_symbol_p(x))
+    base_reg = MB_ABI_BASE_REGNUM;
+  else if (flag_pic)
+    base_reg = MB_ABI_PIC_ADDR_REGNUM;
 
   if (TARGET_XLGPOPT
       && GET_CODE (x) == SYMBOL_REF
@@ -509,28 +759,61 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
 	      }
 	    else if (GET_CODE (xplus1) == UNSPEC)
 	      {
+		/* Need offsettable address.  */
+		if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+		  return false;
+
 		return microblaze_classify_unspec (info, xplus1);
 	      }
 	    else if ((GET_CODE (xplus1) == SYMBOL_REF ||
-		      GET_CODE (xplus1) == LABEL_REF) && flag_pic == 2)
-	      {
-		return false;
-	      }
-	    else if (GET_CODE (xplus1) == SYMBOL_REF ||
-		     GET_CODE (xplus1) == LABEL_REF ||
-		     GET_CODE (xplus1) == CONST)
+		      GET_CODE (xplus1) == LABEL_REF))
 	      {
-		if (GET_CODE (XEXP (xplus1, 0)) == UNSPEC)
-		  return microblaze_classify_unspec (info, XEXP (xplus1, 0));
-		else if (flag_pic == 2)
-		  {
-		    return false;
-		  }
+		if (flag_pic == 2 || microblaze_tls_symbol_p(xplus1))
+		  return false;
 		info->type = ADDRESS_SYMBOLIC;
 		info->symbol = xplus1;
 		info->symbol_type = SYMBOL_TYPE_GENERAL;
 		return true;
 	      }
+	    else if (GET_CODE (xplus1) == CONST)
+	      {
+		rtx xconst0 = XEXP(xplus1, 0);
+
+		/* base + unspec.  */
+		if (GET_CODE (xconst0) == UNSPEC)
+		  {
+		    /* Need offsettable address.  */
+		    if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+		      return false;
+		    return microblaze_classify_unspec(info, xconst0);
+		  }
+
+		/* for (plus x const_int) just look at x.  */
+		if (GET_CODE (xconst0) == PLUS
+		    && GET_CODE (XEXP (xconst0, 1)) == CONST_INT
+		    && SMALL_INT (XEXP (xconst0, 1)))
+		  {
+		    /* This is ok as info->symbol is set to xplus1 the full
+		       const-expression below.  */
+		    xconst0 = XEXP (xconst0, 0);
+		  }
+
+		if (GET_CODE (xconst0) == SYMBOL_REF
+		    || GET_CODE (xconst0) == LABEL_REF)
+		  {
+		    if (flag_pic == 2 || microblaze_tls_symbol_p(xconst0))
+		      return false;
+
+		    info->type = ADDRESS_SYMBOLIC;
+		    info->symbol = xplus1;
+		    info->symbol_type = SYMBOL_TYPE_GENERAL;
+		    return true;
+		  }
+
+		/* Not base + symbol || base + UNSPEC.  */
+		return false;
+
+	      }
 	    else if (GET_CODE (xplus1) == REG
 		     && microblaze_valid_index_register_p (xplus1, mode,
 							   strict)
@@ -562,13 +845,20 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
 
 	if (GET_CODE (x) == CONST)
 	  {
-	    return !(flag_pic && pic_address_needs_scratch (x));
-	  }
-	else if (flag_pic == 2)
-	  {
-	    return false;
+	    if (GET_CODE (XEXP (x, 0)) == UNSPEC)
+	     {
+		info->regA = gen_rtx_raw_REG (mode,
+				  get_base_reg (XVECEXP (XEXP (x,0), 0, 0)));
+		return microblaze_classify_unspec (info, XEXP (x, 0));
+	     }
+	     return !(flag_pic && pic_address_needs_scratch (x));
 	  }
 
+	if (flag_pic == 2)
+	  return false;
+	else if (microblaze_tls_symbol_p(x))
+	  return false;
+
 	return true;
       }
 
@@ -616,11 +906,10 @@ microblaze_valid_pic_const (rtx x)
 int
 microblaze_legitimate_pic_operand (rtx x)
 {
-  struct microblaze_address_info addr;
-
-  if (pic_address_needs_scratch (x))
+  if (flag_pic == 2 && (symbol_mentioned_p(x) || label_mentioned_p(x)))
     return 0;
-  if (!microblaze_valid_pic_const(x))
+
+  if (microblaze_tls_referenced_p(x))
     return 0;
 
   return 1;
@@ -706,7 +995,7 @@ microblaze_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
 	  return result;
 	}
 
-      if (code0 == REG && REG_OK_FOR_BASE_P (xplus0) && flag_pic == 2)
+      if (code0 == REG && REG_OK_FOR_BASE_P (xplus0))
 	{
 	  if (reload_in_progress)
 	    df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
@@ -717,26 +1006,58 @@ microblaze_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
 	    }
 	  if (code1 == SYMBOL_REF)
 	    {
-	      result =
-		gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xplus1), UNSPEC_GOTOFF);
-	      result = gen_rtx_CONST (Pmode, result);
-	      result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
-	      result = gen_const_mem (Pmode, result);
-	      result = gen_rtx_PLUS (Pmode, xplus0, result);
-	      return result;
+	      if (microblaze_tls_symbol_p(xplus1) )
+		{
+		  rtx tls_ref, reg;
+		  reg = gen_reg_rtx (Pmode);
+
+		  tls_ref = microblaze_legitimize_tls_address (xplus1,
+							       NULL_RTX);
+		  emit_move_insn (reg, tls_ref);
+
+		  result = gen_rtx_PLUS (Pmode, xplus0, reg);
+
+		  return result;
+		}
+	      else if (flag_pic == 2)
+		{
+		  rtx pic_ref, reg;
+		  reg = gen_reg_rtx (Pmode);
+
+		  pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xplus1),
+					    UNSPEC_GOTOFF);
+		  pic_ref = gen_rtx_CONST (Pmode, pic_ref);
+		  pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref);
+		  pic_ref = gen_const_mem (Pmode, pic_ref);
+		  emit_move_insn (reg, pic_ref);
+		  result = gen_rtx_PLUS (Pmode, xplus0, reg);
+		  return result;
+		}
 	    }
 	}
     }
 
   if (GET_CODE (xinsn) == SYMBOL_REF)
     {
-      if (reload_in_progress)
-	df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-      result = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF);
-      result = gen_rtx_CONST (Pmode, result);
-      result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
-      result = gen_const_mem (Pmode, result);
-      return result;
+	rtx reg;
+	if (microblaze_tls_symbol_p(xinsn) )
+	  {
+	    reg = microblaze_legitimize_tls_address (xinsn, NULL_RTX);
+	  }
+	else
+	  {
+	    rtx pic_ref;
+
+	    if (reload_in_progress)
+	      df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
+
+	    pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF);
+	    pic_ref = gen_rtx_CONST (Pmode, pic_ref);
+	    pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref);
+	    pic_ref = gen_const_mem (Pmode, pic_ref);
+	    reg = pic_ref;
+	  }
+	return reg;
     }
 
   return x;
@@ -1061,10 +1382,22 @@ microblaze_address_insns (rtx x, enum machine_mode mode)
 	  else
 	    return 2;
 	case ADDRESS_REG_INDEX:
-	case ADDRESS_SYMBOLIC:
 	  return 1;
+	case ADDRESS_SYMBOLIC:
 	case ADDRESS_GOTOFF:
 	  return 2;
+	case ADDRESS_TLS:
+	  switch (addr.tls_type)
+	    {
+	      case TLS_GD:
+		return 2;
+	      case TLS_LDM:
+		return 2;
+	      case TLS_DTPREL:
+		return 1;
+	      default :
+		abort();
+	    }
 	default:
 	  break;
 	}
@@ -1088,13 +1421,18 @@ microblaze_address_cost (rtx addr, enum machine_mode mode ATTRIBUTE_UNUSED,
 int
 pic_address_needs_scratch (rtx x)
 {
-  /* An address which is a symbolic plus a non SMALL_INT needs a temp reg.  */
-  if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
-      && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
-      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
-      && (flag_pic == 2 || !SMALL_INT (XEXP (XEXP (x, 0), 1))))
-    return 1;
+  if (GET_CODE (x) == CONST && GET_CODE (XEXP (x,0)) == PLUS)
+    {
+     rtx p0, p1;
 
+      p0 = XEXP (XEXP (x, 0), 0);
+      p1 = XEXP (XEXP (x, 0), 1);
+
+      if ((GET_CODE (p0) == SYMBOL_REF || GET_CODE (p0) == LABEL_REF)
+          && (GET_CODE (p1) == CONST_INT)
+          && (flag_pic == 2 || microblaze_tls_symbol_p (p0) || !SMALL_INT (p1)))
+        return 1;
+    }
   return 0;
 }
 
@@ -1918,6 +2256,7 @@ print_operand (FILE * file, rtx op, int letter)
 	    case ADDRESS_CONST_INT:
 	    case ADDRESS_SYMBOLIC:
 	    case ADDRESS_GOTOFF:
+	    case ADDRESS_TLS:
 	      fputs ("i", file);
 	      break;
 	    case ADDRESS_REG_INDEX:
@@ -2034,10 +2373,19 @@ print_operand (FILE * file, rtx op, int letter)
   else if (letter == 't')
     fputs (code == EQ ? "t" : "f", file);
 
-  else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG)
+  else if (code == CONST
+           && ((GET_CODE (XEXP (op, 0)) == REG)
+               || (GET_CODE (XEXP (op, 0)) == UNSPEC)))
     {
       print_operand (file, XEXP (op, 0), letter);
     }
+  else if (code == CONST
+           && (GET_CODE (XEXP (op, 0)) == PLUS)
+           && (GET_CODE (XEXP (XEXP (op, 0), 0)) == REG)
+           && (GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST))
+    {
+      print_operand_address (file, XEXP (op, 0) );
+    }
   else if (letter == 'm')
     fprintf (file, HOST_WIDE_INT_PRINT_DEC, (1L << INTVAL (op)));
   else
@@ -2098,6 +2446,7 @@ print_operand_address (FILE * file, rtx addr)
     case ADDRESS_SYMBOLIC:
     case ADDRESS_GOTOFF:
     case ADDRESS_PLT:
+    case ADDRESS_TLS:
       if (info.regA)
 	fprintf (file, "%s,", reg_names[REGNO (info.regA)]);
       output_addr_const (file, info.symbol);
@@ -2109,6 +2458,24 @@ print_operand_address (FILE * file, rtx addr)
 	{
 	  fputs ("@PLT", file);
 	}
+      else if (type == ADDRESS_TLS)
+	{
+	  switch (info.tls_type)
+	    {
+	      case TLS_GD:
+		fputs ("@TLSGD", file);
+		break;
+	      case TLS_LDM:
+		fputs ("@TLSLDM", file);
+		break;
+	      case TLS_DTPREL:
+		fputs ("@TLSDTPREL", file);
+		break;
+	      default :
+		abort();
+		break;
+	    }
+	}
       break;
     case ADDRESS_INVALID:
       fatal_insn ("invalid address", addr);
@@ -2471,7 +2838,8 @@ microblaze_expand_prologue (void)
 	}
     }
 
-  if (flag_pic == 2 && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM))
+  if ((flag_pic == 2 || TLS_NEEDS_GOT )
+      && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM))
     {
       SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM);
       emit_insn (gen_set_got (pic_offset_table_rtx));	/* setting GOT.  */
@@ -2701,83 +3069,62 @@ expand_pic_symbol_ref (enum machine_mode mode ATTRIBUTE_UNUSED, rtx op)
 bool
 microblaze_expand_move (enum machine_mode mode, rtx operands[])
 {
+  rtx op0, op1;
+
+  op0 = operands[0];
+  op1 = operands[1];
+
+  if (!register_operand (op0, SImode)
+      && !register_operand (op1, SImode)
+      && (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 0))
+    {
+      rtx temp = force_reg (SImode, op1);
+      emit_move_insn (op0, temp);
+      return true;
+    }
   /* If operands[1] is a constant address invalid for pic, then we need to
      handle it just like LEGITIMIZE_ADDRESS does.  */
-  if (flag_pic)
+  if (GET_CODE (op1) == SYMBOL_REF || GET_CODE (op1) == LABEL_REF)
     {
-      if (GET_CODE (operands[0]) == MEM)
+      rtx result;
+      if (microblaze_tls_symbol_p(op1))
 	{
-	  rtx addr = XEXP (operands[0], 0);
-	  if (GET_CODE (addr) == SYMBOL_REF)
-	    {
-	      rtx ptr_reg, result;
-
-	      if (reload_in_progress)
-		df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-
-	      addr = expand_pic_symbol_ref (mode, addr);
-	      ptr_reg = gen_reg_rtx (Pmode);
-	      emit_move_insn (ptr_reg, addr);
-	      result = gen_rtx_MEM (mode, ptr_reg);
-	      operands[0] = result;
-	    }
+	  result = microblaze_legitimize_tls_address (op1, NULL_RTX);
+	  emit_move_insn (op0, result);
+	  return true;
 	}
-      if (GET_CODE (operands[1]) == SYMBOL_REF
-	  || GET_CODE (operands[1]) == LABEL_REF)
+      else if (flag_pic)
 	{
-	  rtx result;
 	  if (reload_in_progress)
 	    df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-	  result = expand_pic_symbol_ref (mode, operands[1]);
-	  if (GET_CODE (operands[0]) != REG)
-	    {
-	      rtx ptr_reg = gen_reg_rtx (Pmode);
-	      emit_move_insn (ptr_reg, result);
-	      emit_move_insn (operands[0], ptr_reg);
-	    }
-	  else
-	    {
-	      emit_move_insn (operands[0], result);
-	    }
+	  result = expand_pic_symbol_ref (mode, op1);
+	  emit_move_insn (op0, result);
 	  return true;
 	}
-      else if (GET_CODE (operands[1]) == MEM &&
-	       GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
-	{
-	  rtx result;
-	  rtx ptr_reg;
-	  if (reload_in_progress)
-	    df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-	  result = expand_pic_symbol_ref (mode, XEXP (operands[1], 0));
+    }
+  /* Handle Case of (const (plus symbol const_int)).  */
+  if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1,0)) == PLUS)
+    {
+      rtx p0, p1;
 
-	  ptr_reg = gen_reg_rtx (Pmode);
+      p0 = XEXP (XEXP (op1, 0), 0);
+      p1 = XEXP (XEXP (op1, 0), 1);
 
-	  emit_move_insn (ptr_reg, result);
-	  result = gen_rtx_MEM (mode, ptr_reg);
-	  emit_move_insn (operands[0], result);
-	  return true;
-	}
-      else if (pic_address_needs_scratch (operands[1]))
+      if ((GET_CODE (p1) == CONST_INT)
+	  && ((GET_CODE (p0) == UNSPEC)
+	      || ((GET_CODE (p0) == SYMBOL_REF || GET_CODE (p0) == LABEL_REF)
+	          && (flag_pic == 2 || microblaze_tls_symbol_p (p0)
+		      || !SMALL_INT (p1)))))
 	{
-	  rtx temp = force_reg (SImode, XEXP (XEXP (operands[1], 0), 0));
-	  rtx temp2 = XEXP (XEXP (operands[1], 0), 1);
+	  rtx temp = force_reg (SImode, p0);
+	  rtx temp2 = p1;
 
-	  if (reload_in_progress)
+	  if (flag_pic && reload_in_progress)
 	    df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-	  emit_move_insn (operands[0], gen_rtx_PLUS (SImode, temp, temp2));
+	  emit_move_insn (op0, gen_rtx_PLUS (SImode, temp, temp2));
 	  return true;
 	}
     }
-
-  if ((reload_in_progress | reload_completed) == 0
-      && !register_operand (operands[0], SImode)
-      && !register_operand (operands[1], SImode)
-      && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))
-    {
-      rtx temp = force_reg (SImode, operands[1]);
-      emit_move_insn (operands[0], temp);
-      return true;
-    }
   return false;
 }
 
@@ -3048,10 +3395,40 @@ microblaze_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link,
    At present, GAS doesn't understand li.[sd], so don't allow it
    to be generated at present.  */
 static bool
-microblaze_legitimate_constant_p (enum machine_mode mode, rtx x)
+microblaze_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
 {
-  return GET_CODE (x) != CONST_DOUBLE || microblaze_const_double_ok (x, mode);
+
+  if (microblaze_cannot_force_const_mem(mode, x))
+        return false;
+
+  if (GET_CODE (x) == CONST_DOUBLE)
+    {
+      return microblaze_const_double_ok (x, GET_MODE (x));
+    }
+
+   /* Handle Case of (const (plus unspec const_int)).  */
+   if (GET_CODE (x) == CONST && GET_CODE (XEXP (x,0)) == PLUS)
+     {
+        rtx p0, p1;
+
+        p0 = XEXP (XEXP (x, 0), 0);
+        p1 = XEXP (XEXP (x, 0), 1);
+
+        if (GET_CODE(p1) == CONST_INT)
+          {
+            /* Const offset from UNSPEC is not supported.  */
+            if ((GET_CODE (p0) == UNSPEC))
+              return false;
+
+            if ((GET_CODE (p0) == SYMBOL_REF || GET_CODE (p0) == LABEL_REF)
+                 && (microblaze_tls_symbol_p (p0) || !SMALL_INT (p1)))
+              return false;
+          }
+      }
+
+  return true;
 }
+
 \f
 #undef TARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO      microblaze_encode_section_info
@@ -3068,6 +3445,9 @@ microblaze_legitimate_constant_p (enum machine_mode mode, rtx x)
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS                microblaze_rtx_costs
 
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM   microblaze_cannot_force_const_mem
+
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST             microblaze_address_cost
 
diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h
index 8fbe5bf..bc4d9a1 100644
--- a/gcc/config/microblaze/microblaze.h
+++ b/gcc/config/microblaze/microblaze.h
@@ -65,6 +65,9 @@ extern enum pipeline_type microblaze_pipe;
 /* The default is to support PIC.  */
 #define TARGET_SUPPORTS_PIC 1
 
+/* The default is to not need GOT for TLS.  */
+#define TLS_NEEDS_GOT 0
+
 /* What is the default setting for -mcpu= . We set it to v4.00.a even though 
    we are actually ahead. This is safest version that has generate code 
    compatible for the original ISA */
@@ -326,9 +329,7 @@ extern char microblaze_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
 
 #define NO_FUNCTION_CSE                 1
 
-#define PIC_OFFSET_TABLE_REGNUM         \
-        (flag_pic ? (GP_REG_FIRST + MB_ABI_PIC_ADDR_REGNUM) : \
-        INVALID_REGNUM)
+#define PIC_OFFSET_TABLE_REGNUM   (GP_REG_FIRST + MB_ABI_PIC_ADDR_REGNUM)
 
 enum reg_class
 {
diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
index 0285787..3618cad 100644
--- a/gcc/config/microblaze/microblaze.md
+++ b/gcc/config/microblaze/microblaze.md
@@ -40,6 +40,7 @@
   (UNSPEC_PLT           103)    ;; jump table
   (UNSPEC_CMP		104)    ;; signed compare
   (UNSPEC_CMPU		105)    ;; unsigned compare
+  (UNSPEC_TLS           106)    ;; jump table
 ])
 
 
@@ -459,7 +460,7 @@
 (define_insn "addsi3"
   [(set (match_operand:SI 0 "register_operand" "=d,d,d")
 	(plus:SI (match_operand:SI 1 "reg_or_0_operand" "%dJ,dJ,dJ")
-		 (match_operand:SI 2 "arith_operand" "d,I,i")))]
+		 (match_operand:SI 2 "arith_plus_operand" "d,I,i")))]
   ""
   "@
    addk\t%0,%z1,%2
@@ -892,8 +893,8 @@
 
 
 (define_insn "*movdi_internal"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")
-	(match_operand:DI 1 "general_operand"      " d,i,J,R,m,d,d"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,o")
+	(match_operand:DI 1 "general_operand"      " d,i,J,R,o,d,d"))]
   ""
   { 
     switch (which_alternative)
@@ -999,13 +1000,9 @@
   (set_attr "length"	"4")])
 
 (define_insn "*movsi_internal2"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,   d,d,R, T")
-	(match_operand:SI 1 "move_operand"         " d,I,Mnis,R,m,dJ,dJ"))]
-  "(register_operand (operands[0], SImode)
-    || register_operand (operands[1], SImode) 
-    || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))
-    && (flag_pic != 2 || (GET_CODE (operands[1]) != SYMBOL_REF 
-                         && GET_CODE (operands[1]) != LABEL_REF))"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,   d,d,R,m")
+	(match_operand:SI 1 "move_src_operand"         " d,I,Mnis,R,m,dJ,dJ"))]
+  ""
   "@
    addk\t%0,%1,r0
    addik\t%0,r0,%1\t# %X1
@@ -1196,7 +1193,7 @@
 ;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT
 ;;
 (define_insn "*movdf_internal"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,To")
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,o")
         (match_operand:DF 1 "general_operand" "dG,o,F,T,d"))]
   ""
   {
diff --git a/gcc/config/microblaze/predicates.md b/gcc/config/microblaze/predicates.md
index e6e9983..5fd1bd4 100644
--- a/gcc/config/microblaze/predicates.md
+++ b/gcc/config/microblaze/predicates.md
@@ -30,6 +30,52 @@
        (and (match_code "const_int,const_double")
 	    (match_test "LARGE_INT (op)"))))
 
+(define_predicate "arith_plus_operand"
+ (match_operand 0 "general_operand")
+{
+  switch (GET_CODE (op))
+    {
+      default:
+        return 0;
+      case CONST_INT:
+      case REG:
+        return 1;
+      case SYMBOL_REF:
+      case LABEL_REF:
+        if (flag_pic || microblaze_tls_referenced_p(op))
+          return 0;
+        return 1;
+      case CONST:
+        {
+          rtx const0;
+          const0 = XEXP (op, 0);
+
+          switch (GET_CODE(const0))
+            {
+              default:
+                return 0;
+              case UNSPEC :
+                return 1;
+
+              case PLUS :
+                {
+                  rtx p0, p1;
+                  p0 = XEXP (const0, 0);
+                  p1 = XEXP (const0, 1);
+
+                  if ((GET_CODE(p0) == SYMBOL_REF
+                       || GET_CODE (p0) == LABEL_REF)
+                      && GET_CODE(p1) == CONST_INT)
+                    {
+                      return arith_plus_operand (p0, GET_MODE(p0));
+                    }
+                }
+            }
+        }
+    }
+  return 0;
+})
+
 (define_predicate "const_0_operand"
   (and (match_code "const_int,const_double")
        (match_test "op == CONST0_RTX (GET_MODE (op))")))
@@ -54,14 +100,21 @@
        (match_test "GET_CODE (op) == REG || GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST_INT")))
 
 ;; Return if OPERAND is valid as a source operand for a move instruction.
-(define_predicate "move_operand"
+(define_predicate "move_src_operand"
   (and (
      not (
        and (match_code "plus")
            (not (match_test "(GET_CODE (XEXP (op, 0)) == REG) ^ (GET_CODE (XEXP (op,1)) == REG)"))
 	 )
        )
-       (match_operand 0 "general_operand")))
+       (match_operand 0 "general_operand"))
+{
+  if (microblaze_tls_referenced_p(op)
+      || (flag_pic && (symbol_mentioned_p(op) || label_mentioned_p(op))))
+    return false;
+
+  return true;
+})
 
 ;; Test for valid PIC call operand
 (define_predicate "call_insn_plt_operand"
diff --git a/gcc/configure b/gcc/configure
index d4f49bb..e12a180 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -23205,6 +23205,18 @@ foo:	data8	25
 	tls_first_minor=13
 	tls_as_opt=--fatal-warnings
 	;;
+  microblaze*-*-*)
+    conftest_s='
+	.section .tdata,"awT",@progbits
+x:
+	.word 2
+	.text
+	addik r5,r20,x@TLSGD
+	addik r5,r20,x@TLSLDM'
+	tls_first_major=2
+	tls_first_minor=20
+	tls_as_opt='--fatal-warnings'
+	;;
   mips*-*-*)
     conftest_s='
 	.section .tdata,"awT",@progbits
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 811c296..eba3577 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -2968,6 +2968,18 @@ foo:	data8	25
 	tls_first_minor=13
 	tls_as_opt=--fatal-warnings
 	;;
+  microblaze*-*-*)
+    conftest_s='
+	.section .tdata,"awT",@progbits
+x:
+	.word 2
+	.text
+	addik r5,r20,x@TLSGD
+	addik r5,r20,x@TLSLDM'
+	tls_first_major=2
+	tls_first_minor=20
+	tls_as_opt='--fatal-warnings'
+	;;
   mips*-*-*)
     conftest_s='
 	.section .tdata,"awT",@progbits
-- 
1.7.0.4


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Patch, microblaze]: Add support for TLS in MicroBlaze
  2013-03-14  8:08   ` David Holsgrove
@ 2013-03-14 15:46     ` Michael Eager
  0 siblings, 0 replies; 4+ messages in thread
From: Michael Eager @ 2013-03-14 15:46 UTC (permalink / raw)
  To: David Holsgrove
  Cc: gcc-patches, Edgar Iglesias, John Williams, Vinod Kathail,
	Vidhumouli Hunsigida, Nagaraju Mekala, Tom Shui

On 03/14/2013 01:07 AM, David Holsgrove wrote:
> Hi Michael,
>
>> -----Original Message-----
>> From: Michael Eager [mailto:eager@eagerm.com]
>> Sent: Thursday, 14 March 2013 1:34 am
>> To: David Holsgrove
>> Cc: gcc-patches@gcc.gnu.org; Edgar Iglesias; John Williams; Vinod Kathail;
>> Vidhumouli Hunsigida; Nagaraju Mekala; Tom Shui
>> Subject: Re: [Patch, microblaze]: Add support for TLS in MicroBlaze
>>
>> On 03/12/2013 01:47 PM, David Holsgrove wrote:
>>> Add support for thread local storage (general dynamic and local dynamic
>> models) in MicroBlaze.
>>>
>>>
>>> gcc/Changelog
>>>
>>> 2013-03-13  Edgar E. Iglesias <edgar.iglesias@xilinx.com>
>>>               David Holsgrove <david.holsgrove@xilinx.com>
>>>
> [--snip--]
>>>
>>> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
>>> Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
>>
>> Hi David --
>>
>> The patch is OK except for a number of minor formatting problems to meet GNU
>> standards.
>> - Comments are supposed to end with ".  */".
>> - Extra spacing around parens or between "!" and "TARGET...".
>> - && or || at start of line continuing a condition rather that at end of previous line
>> - Some places where the indenting is incorrect
>>
>
> Thanks for the review, we inherited some of the style deviations when basing off
> of other archs TLS functions I'm afraid. I've fixed the formatting in v2 of the patch
> attached.
>
>> Should this patch be combined with the other patch adding TLS checking to
>> configure?
>>
>
> I've combined both patches into the attached - looking back at the ARM TLS patch
> it was submitted this way, so we'll follow precedence there if that’s okay with
> you.
>
> Updated Changelog would be;
>
> 2013-03-14 Edgar E. Iglesias <edgar.iglesias@xilinx.com>
>             David Holsgrove <david.holsgrove@xilinx.com>
>
>   * configure.ac: Add MicroBlaze TLS support detection.
>   * configure: Regenerate.
>   * config/microblaze/microblaze-protos.h: (microblaze_cannot_force_const_mem,
>     microblaze_tls_referenced_p, symbol_mentioned_p,
>     label_mentioned_p): Add prototypes.
>   * config/microblaze/microblaze.c (microblaze_address_type): Add ADDRESS_TLS
>     and tls_reloc address types.
>     (microblaze_address_info): Add tls_reloc.
>     (TARGET_HAVE_TLS): Define.
>     (get_tls_get_addr, microblaze_tls_symbol_p, microblaze_tls_operand_p_1,
>      microblaze_tls_referenced_p, microblaze_cannot_force_const_mem,
>      symbol_mentioned_p, label_mentioned_p, tls_mentioned_p, load_tls_operand,
>      microblaze_call_tls_get_addr, microblaze_legitimize_tls_address): New functions.
>     (microblaze_classify_unspec): Handle UNSPEC_TLS.
>     (get_base_reg): Use microblaze_tls_symbol_p.
>     (microblaze_classify_address): Handle TLS.
>     (microblaze_legitimate_pic_operand): Use symbol_mentioned_p, label_mentioned_p
>      and microblaze_tls_referenced_p.
>     (microblaze_legitimize_address): Handle TLS.
>     (microblaze_address_insns): Handle ADDRESS_TLS.
>     (pic_address_needs_scratch): Handle TLS.
>     (print_operand_address): Handle TLS.
>     (microblaze_expand_prologue): Check TLS_NEEDS_GOT.
>     (microblaze_expand_move): Handle TLS.
>     (microblaze_legitimate_constant_p): Check microblaze_cannot_force_const_mem
>      and microblaze_tls_symbol_p.
>     (TARGET_CANNOT_FORCE_CONST_MEM): Define.
>   * config/microblaze/microblaze.h (TLS_NEEDS_GOT): Define
>     (PIC_OFFSET_TABLE_REGNUM): Set.
>   * config/microblaze/linux.h (TLS_NEEDS_GOT): Define.
>   * config/microblaze/microblaze.md (UNSPEC_TLS): Define.
>     (addsi3, movsi_internal2, movdf_internal): Update constraints
>   * config/microblaze/predicates.md (arith_plus_operand): Define
>     (move_operand): Redefine as move_src_operand, check microblaze_tls_referenced_p.
>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>

Thanks for cleaning up the patch.  There were a few other places where I fixed
indent and other formatting issues.

Committed revision 196659.

-- 
Michael Eager	 eager@eagercon.com
1960 Park Blvd., Palo Alto, CA 94306  650-325-8077

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-03-14 15:46 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-12 20:47 [Patch, microblaze]: Add support for TLS in MicroBlaze David Holsgrove
2013-03-13 15:34 ` Michael Eager
2013-03-14  8:08   ` David Holsgrove
2013-03-14 15:46     ` Michael Eager

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).