This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

ia64 tls support



	* configure.in (HAVE_AS_TLS): Add ia64 test.
	* configure: Rebuild.
	* config/ia64/ia64.c (ia64_tls_size_string, ia64_tls_size): New.
	(override_options): Set it.
	(TARGET_HAVE_TLS): New.
	(sdata_symbolic_operand): Look for 's'.
	(tls_symbolic_operand): New.
	(ia64_expand_load_address): Abort for tls symbols.
	(gen_tls_get_addr): New.
	(gen_thread_pointer): New.
	(ia64_expand_move): Split out from movdi.  Handle tls symbols.
	(rtx_needs_barrier): Add new unspecs.
	(ia64_encode_section_info): Handle tls symbols.
	(ia64_strip_name_encoding): Strip two encoding chars.
	* config/ia64/ia64.h (ia64_tls_size, ia64_tls_size_string): New.
	(TARGET_TLS14, TARGET_TLS22, TARGET_TLS64): New.
	(TARGET_OPTIONS): Add tls-size.
	(ENCODE_SECTION_INFO_CHAR): Rename from SDATA_NAME_FLAG_CHAR.
	* config/ia64/ia64.md (UNSPEC_LTOFF_DTPMOD, UNSPEC_LTOFF_DTPREL,
	UNSPEC_DTPREL, UNSPEC_LTOFF_TPREL, UNSPEC_TPREL, UNSPEC_LD_BASE): New.
	(movqi, movhi, movsi, movdi, movti): Use ia64_expand_move.
	(movsf, movdf): Likewise.
	(movdi_symbolic): Use match_scratch.  Don't split if we won't
	have a scratch availiable.
	(load_ltoff_dtpmod, load_dtprel, load_dtprel64, load_dtprel22,
	add_dtprel, add_dtprel14, add_dtprel22, load_ltoff_tprel, load_tprel,
	load_tprel64, load_tprel22, add_tprel, add_tprel14, add_tprel22): New.
	* config/ia64/ia64-protos.h: Update.
	* config/ia64/sysv4.h (ASM_OUTPUT_ALIGNED_DECL_LOCAL): Use
	sdata_symbolic_operand.
	(ASM_OUTPUT_LABELREF): Strip two characters.

Index: gcc/configure.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/configure.in,v
retrieving revision 1.592
diff -c -p -d -u -r1.592 configure.in
--- gcc/configure.in	23 May 2002 21:55:23 -0000	1.592
+++ gcc/configure.in	25 May 2002 02:06:36 -0000
@@ -1743,6 +1743,23 @@ foo:	.long	25
 	tls_first_major=2
 	tls_first_minor=13
 	;;
+  ia64-*-*)
+    conftest_s='
+	.section ".tdata","awT",@progbits
+foo:	data8	25
+	.text
+	addl	r16 = @ltoff(@dtpmod(foo#)), gp
+	addl	r17 = @ltoff(@dtprel(foo#)), gp
+	addl	r18 = @ltoff(@tprel(foo#)), gp
+	addl	r19 = @dtprel(foo#), gp
+	adds	r21 = @dtprel(foo#), r13
+	movl	r23 = @dtprel(foo#)
+	addl	r20 = @tprel(foo#), gp
+	adds	r22 = @tprel(foo#), r13
+	movl	r24 = @tprel(foo#)'
+	tls_first_major=2
+	tls_first_minor=13
+	;;
 esac
 if test -z "$tls_first_major"; then
   :
Index: gcc/config/ia64/ia64-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64-protos.h,v
retrieving revision 1.41
diff -c -p -d -u -r1.41 ia64-protos.h
--- gcc/config/ia64/ia64-protos.h	19 May 2002 05:23:11 -0000	1.41
+++ gcc/config/ia64/ia64-protos.h	25 May 2002 02:06:36 -0000
@@ -31,6 +31,7 @@ extern int call_operand PARAMS((rtx, enu
 extern int sdata_symbolic_operand PARAMS((rtx, enum machine_mode));
 extern int got_symbolic_operand PARAMS((rtx, enum machine_mode));
 extern int symbolic_operand PARAMS((rtx, enum machine_mode));
+extern int tls_symbolic_operand PARAMS((rtx, enum machine_mode));
 extern int function_operand PARAMS((rtx, enum machine_mode));
 extern int setjmp_operand PARAMS((rtx, enum machine_mode));
 extern int move_operand PARAMS((rtx, enum machine_mode));
@@ -68,6 +69,7 @@ extern int destination_tfmode_operand PA
 extern int tfreg_or_fp01_operand PARAMS((rtx, enum machine_mode));
 extern int basereg_operand PARAMS((rtx, enum machine_mode));
 
+extern rtx ia64_expand_move PARAMS ((rtx, rtx));
 extern int ia64_move_ok PARAMS((rtx, rtx));
 extern int ia64_depz_field_mask PARAMS((rtx, rtx));
 extern rtx ia64_gp_save_reg PARAMS((int));
Index: gcc/config/ia64/ia64.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64.c,v
retrieving revision 1.171
diff -c -p -d -u -r1.171 ia64.c
--- gcc/config/ia64/ia64.c	24 May 2002 22:54:28 -0000	1.171
+++ gcc/config/ia64/ia64.c	25 May 2002 02:06:36 -0000
@@ -94,6 +94,13 @@ static const char * const ia64_output_re
 /* String used with the -mfixed-range= option.  */
 const char *ia64_fixed_range_string;
 
+/* Determines whether we use adds, addl, or movl to generate our
+   TLS immediate offsets.  */
+int ia64_tls_size = 22;
+
+/* String used with the -mtls-size= option.  */
+const char *ia64_tls_size_string;
+
 /* Determines whether we run our final scheduling pass or not.  We always
    avoid the normal second scheduling pass.  */
 static int ia64_flag_schedule_insns2;
@@ -103,6 +110,8 @@ static int ia64_flag_schedule_insns2;
 
 unsigned int ia64_section_threshold;
 
+static rtx gen_tls_get_addr PARAMS ((void));
+static rtx gen_thread_pointer PARAMS ((void));
 static int find_gr_spill PARAMS ((int));
 static int next_scratch_gr_reg PARAMS ((void));
 static void mark_reg_gr_used_mask PARAMS ((rtx, void *));
@@ -230,6 +239,11 @@ static const struct attribute_spec ia64_
 #undef TARGET_SCHED_REORDER2
 #define TARGET_SCHED_REORDER2 ia64_sched_reorder2
 
+#ifdef HAVE_AS_TLS
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS true
+#endif
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
@@ -266,7 +280,10 @@ sdata_symbolic_operand (op, mode)
       if (CONSTANT_POOL_ADDRESS_P (op))
 	return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold;
       else
-        return XSTR (op, 0)[0] == SDATA_NAME_FLAG_CHAR;
+	{
+	  const char *str = XSTR (op, 0);
+          return (str[0] == ENCODE_SECTION_INFO_CHAR && str[1] == 's');
+	}
 
     default:
       break;
@@ -340,6 +357,35 @@ symbolic_operand (op, mode)
   return 0;
 }
 
+/* Return tls_model if OP refers to a TLS symbol.  */
+
+int
+tls_symbolic_operand (op, mode)
+     rtx op;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  const char *str;
+
+  if (GET_CODE (op) != SYMBOL_REF)
+    return 0;
+  str = XSTR (op, 0);
+  if (str[0] != ENCODE_SECTION_INFO_CHAR)
+    return 0;
+  switch (str[1])
+    {
+    case 'G':
+      return TLS_MODEL_GLOBAL_DYNAMIC;
+    case 'L':
+      return TLS_MODEL_LOCAL_DYNAMIC;
+    case 'i':
+      return TLS_MODEL_INITIAL_EXEC;
+    case 'l':
+      return TLS_MODEL_LOCAL_EXEC;
+    }
+  return 0;
+}
+
+
 /* Return 1 if OP refers to a function.  */
 
 int
@@ -953,6 +999,9 @@ ia64_expand_load_address (dest, src, scr
   else
     temp = dest;
 
+  if (tls_symbolic_operand (src, Pmode))
+    abort ();
+
   if (TARGET_AUTO_PIC)
     emit_insn (gen_load_gprel64 (temp, src));
   else if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_FLAG (src))
@@ -995,6 +1044,185 @@ ia64_expand_load_address (dest, src, scr
     emit_move_insn (dest, temp);
 }
 
+static rtx
+gen_tls_get_addr ()
+{
+  static rtx tga;
+  if (!tga)
+    {
+      tga = init_one_libfunc ("__tls_get_addr");
+      ggc_add_rtx_root (&tga, 1);
+    }
+  return tga;
+}
+
+static rtx
+gen_thread_pointer ()
+{
+  static rtx tp;
+  if (!tp)
+    {
+      tp = gen_rtx_REG (Pmode, 13);
+      RTX_UNCHANGING_P (tp);
+      ggc_add_rtx_root (&tp, 1);
+    }
+  return tp;
+}
+
+rtx
+ia64_expand_move (op0, op1)
+     rtx op0, op1;
+{
+  enum machine_mode mode = GET_MODE (op0);
+
+  if (!reload_in_progress && !reload_completed && !ia64_move_ok (op0, op1))
+    op1 = force_reg (mode, op1);
+
+  if (mode == Pmode)
+    {
+      enum tls_model tls_kind;
+      if ((tls_kind = tls_symbolic_operand (op1, Pmode)))
+	{
+	  rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns;
+
+	  switch (tls_kind)
+	    {
+	    case TLS_MODEL_GLOBAL_DYNAMIC:
+	      start_sequence ();
+
+	      tga_op1 = gen_reg_rtx (Pmode);
+	      emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
+	      tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
+	      RTX_UNCHANGING_P (tga_op1) = 1;
+
+	      tga_op2 = gen_reg_rtx (Pmode);
+	      emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
+	      tga_op2 = gen_rtx_MEM (Pmode, tga_op2);
+	      RTX_UNCHANGING_P (tga_op2) = 1;
+	      
+	      tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
+						 LCT_CONST, Pmode, 2, tga_op1,
+						 Pmode, tga_op2, Pmode);
+
+	      insns = get_insns ();
+	      end_sequence ();
+
+	      emit_libcall_block (insns, op0, tga_ret, op1);
+	      return NULL_RTX;
+
+	    case TLS_MODEL_LOCAL_DYNAMIC:
+	      /* ??? This isn't the completely proper way to do local-dynamic
+		 If the call to __tls_get_addr is used only by a single symbol,
+		 then we should (somehow) move the dtprel to the second arg
+		 to avoid the extra add.  */
+	      start_sequence ();
+
+	      tga_op1 = gen_reg_rtx (Pmode);
+	      emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
+	      tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
+	      RTX_UNCHANGING_P (tga_op1) = 1;
+
+	      tga_op2 = const0_rtx;
+
+	      tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
+						 LCT_CONST, Pmode, 2, tga_op1,
+						 Pmode, tga_op2, Pmode);
+
+	      insns = get_insns ();
+	      end_sequence ();
+
+	      tga_eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+					UNSPEC_LD_BASE);
+	      tmp = gen_reg_rtx (Pmode);
+	      emit_libcall_block (insns, tmp, tga_ret, tga_eqv);
+
+	      if (register_operand (op0, Pmode))
+		tga_ret = op0;
+	      else
+		tga_ret = gen_reg_rtx (Pmode);
+	      if (TARGET_TLS64)
+		{
+		  emit_insn (gen_load_dtprel (tga_ret, op1));
+		  emit_insn (gen_adddi3 (tga_ret, tmp, tga_ret));
+		}
+	      else
+		emit_insn (gen_add_dtprel (tga_ret, tmp, op1));
+	      if (tga_ret == op0)
+		return NULL_RTX;
+	      op1 = tga_ret;
+	      break;
+
+	    case TLS_MODEL_INITIAL_EXEC:
+	      tmp = gen_reg_rtx (Pmode);
+	      emit_insn (gen_load_ltoff_tprel (tmp, op1));
+	      tmp = gen_rtx_MEM (Pmode, tmp);
+	      RTX_UNCHANGING_P (tmp) = 1;
+	      tmp = force_reg (Pmode, tmp);
+
+	      if (register_operand (op0, Pmode))
+		op1 = op0;
+	      else
+		op1 = gen_reg_rtx (Pmode);
+	      emit_insn (gen_adddi3 (op1, tmp, gen_thread_pointer ()));
+	      if (op1 == op0)
+		return NULL_RTX;
+	      break;
+
+	    case TLS_MODEL_LOCAL_EXEC:
+	      if (register_operand (op0, Pmode))
+		tmp = op0;
+	      else
+		tmp = gen_reg_rtx (Pmode);
+	      if (TARGET_TLS64)
+		{
+		  emit_insn (gen_load_tprel (tmp, op1));
+		  emit_insn (gen_adddi3 (tmp, gen_thread_pointer (), tmp));
+		}
+	      else
+		emit_insn (gen_add_tprel (tmp, gen_thread_pointer (), op1));
+	      if (tmp == op0)
+		return NULL_RTX;
+	      op1 = tmp;
+	      break;
+
+	    default:
+	      abort ();
+	    }
+	}
+      else if (!TARGET_NO_PIC && symbolic_operand (op1, DImode))
+	{
+	  /* Before optimization starts, delay committing to any particular
+	     type of PIC address load.  If this function gets deferred, we
+	     may acquire information that changes the value of the
+	     sdata_symbolic_operand predicate.
+
+	     But don't delay for function pointers.  Loading a function address
+	     actually loads the address of the descriptor not the function.
+	     If we represent these as SYMBOL_REFs, then they get cse'd with
+	     calls, and we end up with calls to the descriptor address instead
+	     of calls to the function address.  Functions are not candidates
+	     for sdata anyways.
+
+	     Don't delay for LABEL_REF because the splitter loses REG_LABEL
+	     notes.  Don't delay for pool addresses on general principals;
+	     they'll never become non-local behind our back.  */
+
+	  if (rtx_equal_function_value_matters
+	      && GET_CODE (op1) != LABEL_REF
+	      && ! (GET_CODE (op1) == SYMBOL_REF
+		    && (SYMBOL_REF_FLAG (op1)
+			|| CONSTANT_POOL_ADDRESS_P (op1)
+			|| STRING_POOL_ADDRESS_P (op1))))
+	    emit_insn (gen_movdi_symbolic (op0, op1));
+	  else
+	    ia64_expand_load_address (op0, op1, NULL_RTX);
+	  return NULL_RTX;
+	}
+    }
+
+  return op1;
+}
+
 rtx
 ia64_gp_save_reg (setjmp_p)
      int setjmp_p;
@@ -3975,6 +4203,16 @@ ia64_override_options ()
   if (ia64_fixed_range_string)
     fix_range (ia64_fixed_range_string);
 
+  if (ia64_tls_size_string)
+    {
+      char *end;
+      unsigned long tmp = strtoul (ia64_tls_size_string, &end, 10);
+      if (*end || (tmp != 14 && tmp != 22 && tmp != 64))
+	error ("bad value (%s) for -mtls-size= switch", ia64_tls_size_string);
+      else
+	ia64_tls_size = tmp;
+    }
+
   ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
   flag_schedule_insns_after_reload = 0;
 
@@ -4595,6 +4833,20 @@ rtx_needs_barrier (x, flags, pred)
     case UNSPEC:
       switch (XINT (x, 1))
 	{
+	case UNSPEC_LTOFF_DTPMOD:
+	case UNSPEC_LTOFF_DTPREL:
+	case UNSPEC_DTPREL:
+	case UNSPEC_LTOFF_TPREL:
+	case UNSPEC_TPREL:
+	case UNSPEC_PRED_REL_MUTEX:
+	case UNSPEC_PIC_CALL:
+        case UNSPEC_MF:
+        case UNSPEC_FETCHADD_ACQ:
+	case UNSPEC_BSP_VALUE:
+	case UNSPEC_FLUSHRS:
+	case UNSPEC_BUNDLE_SELECTOR:
+          break;
+
 	case UNSPEC_GR_SPILL:
 	case UNSPEC_GR_RESTORE:
 	  {
@@ -4614,15 +4866,6 @@ rtx_needs_barrier (x, flags, pred)
 	  need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
 	  break;
 
-	case UNSPEC_PRED_REL_MUTEX:
-	case UNSPEC_PIC_CALL:
-        case UNSPEC_MF:
-        case UNSPEC_FETCHADD_ACQ:
-	case UNSPEC_BSP_VALUE:
-	case UNSPEC_FLUSHRS:
-	case UNSPEC_BUNDLE_SELECTOR:
-          break;
-
         case UNSPEC_ADDP4:
 	  need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
 	  break;
@@ -6910,8 +7153,9 @@ ia64_encode_section_info (decl, first)
      int first ATTRIBUTE_UNUSED;
 {
   const char *symbol_str;
-  bool is_local, is_small;
+  bool is_local;
   rtx symbol;
+  char encoding = 0;
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
     {
@@ -6930,40 +7174,66 @@ ia64_encode_section_info (decl, first)
 
   is_local = (*targetm.binds_local_p) (decl);
 
+  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
+    {
+      enum tls_model kind;
+      if (!flag_pic)
+	{
+	  if (is_local)
+	    kind = TLS_MODEL_LOCAL_EXEC;
+	  else
+	    kind = TLS_MODEL_INITIAL_EXEC;
+	}
+      else if (is_local)
+	kind = TLS_MODEL_LOCAL_DYNAMIC;
+      else
+	kind = TLS_MODEL_GLOBAL_DYNAMIC;
+      if (kind < flag_tls_default)
+	kind = flag_tls_default;
+
+      encoding = " GLil"[kind];
+    }
   /* Determine if DECL will wind up in .sdata/.sbss.  */
-  is_small = ia64_in_small_data_p (decl);
+  else if (is_local && ia64_in_small_data_p (decl))
+    encoding = 's';
 
   /* Finally, encode this into the symbol string.  */
-  if (is_local && is_small)
+  if (encoding)
     {
       char *newstr;
       size_t len;
 
-      if (symbol_str[0] == SDATA_NAME_FLAG_CHAR)
-	return;
+      if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR)
+	{
+	  if (encoding == symbol_str[1])
+	    return;
+	  /* ??? Sdata became thread or thread becaome not thread.  Lose.  */
+	  abort ();
+	}
 
-      len = strlen (symbol_str) + 1;
-      newstr = alloca (len + 1);
-      newstr[0] = SDATA_NAME_FLAG_CHAR;
-      memcpy (newstr + 1, symbol_str, len);
+      len = strlen (symbol_str);
+      newstr = alloca (len + 3);
+      newstr[0] = ENCODE_SECTION_INFO_CHAR;
+      newstr[1] = encoding;
+      memcpy (newstr + 2, symbol_str, len + 1);
 
-      XSTR (symbol, 0) = ggc_alloc_string (newstr, len);
+      XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2);
     }
 
-  /* This decl is marked as being in small data/bss but it shouldn't
-     be; one likely explanation for this is that the decl has been
-     moved into a different section from the one it was in when
-     targetm.encode_section_info was first called.  Remove the '@'.  */
-  else if (symbol_str[0] == SDATA_NAME_FLAG_CHAR)
-    XSTR (symbol, 0) = ggc_strdup (symbol_str + 1);
+  /* This decl is marked as being in small data/bss but it shouldn't be;
+     one likely explanation for this is that the decl has been moved into
+     a different section from the one it was in when encode_section_info
+     was first called.  Remove the encoding.  */
+  else if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR)
+    XSTR (symbol, 0) = ggc_strdup (symbol_str + 2);
 }
 
 static const char *
 ia64_strip_name_encoding (str)
      const char *str;
 {
-  if (str[0] == SDATA_NAME_FLAG_CHAR)
-    str++;
+  if (str[0] == ENCODE_SECTION_INFO_CHAR)
+    str += 2;
   if (str[0] == '*')
     str++;
   return str;
Index: gcc/config/ia64/ia64.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64.h,v
retrieving revision 1.116
diff -c -p -d -u -r1.116 ia64.h
--- gcc/config/ia64/ia64.h	19 May 2002 07:55:35 -0000	1.116
+++ gcc/config/ia64/ia64.h	25 May 2002 02:06:36 -0000
@@ -109,6 +109,11 @@ extern int target_flags;
 
 #define TARGET_DWARF2_ASM	(target_flags & MASK_DWARF2_ASM)
 
+extern int ia64_tls_size;
+#define TARGET_TLS14		(ia64_tls_size == 14)
+#define TARGET_TLS22		(ia64_tls_size == 22)
+#define TARGET_TLS64		(ia64_tls_size == 64)
+
 /* This macro defines names of command options to set and clear bits in
    `target_flags'.  Its definition is an initializer with a subgrouping for
    each command option.  */
@@ -177,10 +182,13 @@ extern int target_flags;
    subgrouping for each command option.  */
 
 extern const char *ia64_fixed_range_string;
+extern const char *ia64_tls_size_string;
 #define TARGET_OPTIONS \
 {									\
   { "fixed-range=", 	&ia64_fixed_range_string,			\
       N_("Specify range of registers to make fixed")},			\
+  { "tls-size=",	&ia64_tls_size_string,				\
+      N_("Specify bit size of immediate TLS offsets")},			\
 }
 
 /* Sometimes certain combinations of command options do not make sense on a
@@ -1774,7 +1782,7 @@ do {									\
 
 #define BSS_SECTION_ASM_OP "\t.bss"
 
-#define SDATA_NAME_FLAG_CHAR '@'
+#define ENCODE_SECTION_INFO_CHAR '@'
 
 #define IA64_DEFAULT_GVALUE 8
 
Index: gcc/config/ia64/ia64.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64.md,v
retrieving revision 1.86
diff -c -p -d -u -r1.86 ia64.md
--- gcc/config/ia64/ia64.md	17 May 2002 07:51:56 -0000	1.86
+++ gcc/config/ia64/ia64.md	25 May 2002 02:06:36 -0000
@@ -49,20 +49,28 @@
 ;; ??? Need a better way to describe alternate fp status registers.
 
 (define_constants
-  [(UNSPEC_GR_SPILL		1)
-   (UNSPEC_GR_RESTORE		2)
-   (UNSPEC_FR_SPILL		3)
-   (UNSPEC_FR_RESTORE		4)
-   (UNSPEC_FR_RECIP_APPROX	5)
-   (UNSPEC_PRED_REL_MUTEX	7)
-   (UNSPEC_POPCNT		8)
-   (UNSPEC_PIC_CALL		9)
-   (UNSPEC_MF			12)
-   (UNSPEC_CMPXCHG_ACQ		13)
-   (UNSPEC_FETCHADD_ACQ		19)
-   (UNSPEC_BSP_VALUE		20)
-   (UNSPEC_FLUSHRS		21)
-   (UNSPEC_BUNDLE_SELECTOR	22)
+  [; Relocations
+   (UNSPEC_LTOFF_DTPMOD		0)
+   (UNSPEC_LTOFF_DTPREL		1)
+   (UNSPEC_DTPREL		2)
+   (UNSPEC_LTOFF_TPREL		3)
+   (UNSPEC_TPREL		4)
+
+   (UNSPEC_LD_BASE		9)
+   (UNSPEC_GR_SPILL		10)
+   (UNSPEC_GR_RESTORE		11)
+   (UNSPEC_FR_SPILL		12)
+   (UNSPEC_FR_RESTORE		13)
+   (UNSPEC_FR_RECIP_APPROX	14)
+   (UNSPEC_PRED_REL_MUTEX	15)
+   (UNSPEC_POPCNT		16)
+   (UNSPEC_PIC_CALL		17)
+   (UNSPEC_MF			18)
+   (UNSPEC_CMPXCHG_ACQ		19)
+   (UNSPEC_FETCHADD_ACQ		20)
+   (UNSPEC_BSP_VALUE		21)
+   (UNSPEC_FLUSHRS		22)
+   (UNSPEC_BUNDLE_SELECTOR	23)
    (UNSPEC_ADDP4		24)
    (UNSPEC_PROLOGUE_USE		25)
   ])
@@ -72,9 +80,9 @@
    (UNSPECV_BLOCKAGE		1)
    (UNSPECV_INSN_GROUP_BARRIER	2)
    (UNSPECV_BREAK		3)
-   (UNSPECV_SET_BSP		5)
-   (UNSPECV_PSAC_ALL		8)	; pred.safe_across_calls
-   (UNSPECV_PSAC_NORMAL		9)
+   (UNSPECV_SET_BSP		4)
+   (UNSPECV_PSAC_ALL		5)	; pred.safe_across_calls
+   (UNSPECV_PSAC_NORMAL		6)
   ])
 
 ;; ::::::::::::::::::::
@@ -276,9 +284,10 @@
 	(match_operand:QI 1 "general_operand" ""))]
   ""
 {
-  if (! reload_in_progress && ! reload_completed
-      && ! ia64_move_ok (operands[0], operands[1]))
-    operands[1] = force_reg (QImode, operands[1]);
+  rtx op1 = ia64_expand_move (operands[0], operands[1]);
+  if (!op1)
+    DONE;
+  operands[1] = op1;
 })
 
 (define_insn "*movqi_internal"
@@ -300,9 +309,10 @@
 	(match_operand:HI 1 "general_operand" ""))]
   ""
 {
-  if (! reload_in_progress && ! reload_completed
-      && ! ia64_move_ok (operands[0], operands[1]))
-    operands[1] = force_reg (HImode, operands[1]);
+  rtx op1 = ia64_expand_move (operands[0], operands[1]);
+  if (!op1)
+    DONE;
+  operands[1] = op1;
 })
 
 (define_insn "*movhi_internal"
@@ -324,9 +334,10 @@
 	(match_operand:SI 1 "general_operand" ""))]
   ""
 {
-  if (! reload_in_progress && ! reload_completed
-      && ! ia64_move_ok (operands[0], operands[1]))
-    operands[1] = force_reg (SImode, operands[1]);
+  rtx op1 = ia64_expand_move (operands[0], operands[1]);
+  if (!op1)
+    DONE;
+  operands[1] = op1;
 })
 
 (define_insn "*movsi_internal"
@@ -352,30 +363,10 @@
 	(match_operand:DI 1 "general_operand" ""))]
   ""
 {
-  if (! reload_in_progress && ! reload_completed
-      && ! ia64_move_ok (operands[0], operands[1]))
-    operands[1] = force_reg (DImode, operands[1]);
-  if (! TARGET_NO_PIC && symbolic_operand (operands[1], DImode))
-    {
-      /* Before optimization starts, delay committing to any particular
-	 type of PIC address load.  If this function gets deferred, we
-	 may acquire information that changes the value of the
-	 sdata_symbolic_operand predicate.  */
-      /* But don't delay for function pointers.  Loading a function address
-	 actually loads the address of the descriptor not the function.
-	 If we represent these as SYMBOL_REFs, then they get cse'd with
-	 calls, and we end up with calls to the descriptor address instead of
-	 calls to the function address.  Functions are not candidates for
-	 sdata anyways.  */
-      if (rtx_equal_function_value_matters
-	  && ! (GET_CODE (operands[1]) == SYMBOL_REF
-		&& SYMBOL_REF_FLAG (operands[1])))
-	emit_insn (gen_movdi_symbolic (operands[0], operands[1],
-				       gen_reg_rtx (DImode)));
-      else
-        ia64_expand_load_address (operands[0], operands[1], NULL_RTX);
-      DONE;
-    }
+  rtx op1 = ia64_expand_move (operands[0], operands[1]);
+  if (!op1)
+    DONE;
+  operands[1] = op1;
 })
 
 ;; This is used during early compilation to delay the decision on
@@ -384,19 +375,22 @@
 ;; deferred functions, since we may acquire additional information
 ;; on the variables used in the meantime.
 
-;; ??? This causes us to lose REG_LABEL notes, because the insn splitter
-;; does not attempt to preserve any REG_NOTES on the input instruction.
-
 (define_insn_and_split "movdi_symbolic"
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(match_operand:DI 1 "symbolic_operand" "s"))
-   (clobber (match_operand:DI  2 "register_operand" "+r"))
+   (clobber (match_scratch:DI 2 "=r"))
    (use (reg:DI 1))]
   ""
   "* abort ();"
-  ""
+  "!no_new_pseudos || reload_completed"
   [(const_int 0)]
-  { ia64_expand_load_address (operands[0], operands[1], operands[2]); DONE; })
+{
+  rtx scratch = operands[2];
+  if (!reload_completed)
+    gen_reg_rtx (Pmode);
+  ia64_expand_load_address (operands[0], operands[1], scratch); 
+  DONE;
+})
 
 (define_insn "*movdi_internal"
   [(set (match_operand:DI 0 "destination_operand"
@@ -505,6 +499,131 @@
   "addl %0 = @ltoff(%1), gp"
   [(set_attr "itanium_class" "ialu")])
 
+(define_insn "load_ltoff_dtpmod"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (reg:DI 1)
+		 (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+			    UNSPEC_LTOFF_DTPMOD)))]
+  ""
+  "addl %0 = @ltoff(@dtpmod(%1)), gp"
+  [(set_attr "itanium_class" "ialu")])
+
+(define_insn "load_ltoff_dtprel"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (reg:DI 1)
+		 (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+			    UNSPEC_LTOFF_DTPREL)))]
+  ""
+  "addl %0 = @ltoff(@dtprel(%1)), gp"
+  [(set_attr "itanium_class" "ialu")])
+
+(define_expand "load_dtprel"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+		   UNSPEC_DTPREL))]
+  ""
+  "")
+
+(define_insn "*load_dtprel64"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+		   UNSPEC_DTPREL))]
+  "TARGET_TLS64"
+  "movl %0 = @dtprel(%1)"
+  [(set_attr "itanium_class" "long_i")])
+
+(define_insn "*load_dtprel22"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+		   UNSPEC_DTPREL))]
+  ""
+  "addl %0 = @dtprel(%1), r0"
+  [(set_attr "itanium_class" "ialu")])
+
+(define_expand "add_dtprel"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(plus:DI (match_operand:DI 1 "register_operand" "")
+		 (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+			    UNSPEC_DTPREL)))]
+  "!TARGET_TLS64"
+  "")
+
+(define_insn "*add_dtprel14"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (match_operand:DI 1 "register_operand" "r")
+		 (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+			    UNSPEC_DTPREL)))]
+  "TARGET_TLS14"
+  "adds %0 = @dtprel(%2), %1"
+  [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*add_dtprel22"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (match_operand:DI 1 "register_operand" "a")
+		 (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+			    UNSPEC_DTPREL)))]
+  "TARGET_TLS22"
+  "addl %0 = @dtprel(%2), %1"
+  [(set_attr "itanium_class" "ialu")])
+
+(define_insn "load_ltoff_tprel"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (reg:DI 1)
+		 (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+			    UNSPEC_LTOFF_TPREL)))]
+  ""
+  "addl %0 = @ltoff(@tprel(%1)), gp"
+  [(set_attr "itanium_class" "ialu")])
+
+(define_expand "load_tprel"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+		   UNSPEC_TPREL))]
+  ""
+  "")
+
+(define_insn "*load_tprel64"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+		   UNSPEC_TPREL))]
+  "TARGET_TLS64"
+  "movl %0 = @tprel(%1)"
+  [(set_attr "itanium_class" "long_i")])
+
+(define_insn "*load_tprel22"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+		   UNSPEC_TPREL))]
+  ""
+  "addl %0 = @tprel(%1), r0"
+  [(set_attr "itanium_class" "ialu")])
+
+(define_expand "add_tprel"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(plus:DI (match_operand:DI 1 "register_operand" "")
+		 (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+			    UNSPEC_TPREL)))]
+  "!TARGET_TLS64"
+  "")
+
+(define_insn "*add_tprel14"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (match_operand:DI 1 "register_operand" "r")
+		 (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+			    UNSPEC_TPREL)))]
+  "TARGET_TLS14"
+  "adds %0 = @tprel(%2), %1"
+  [(set_attr "itanium_class" "ialu")])
+
+(define_insn "*add_tprel22"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(plus:DI (match_operand:DI 1 "register_operand" "a")
+		 (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+			    UNSPEC_TPREL)))]
+  "TARGET_TLS22"
+  "addl %0 = @tprel(%2), %1"
+  [(set_attr "itanium_class" "ialu")])
+
 ;; With no offsettable memory references, we've got to have a scratch
 ;; around to play with the second word.
 (define_expand "movti"
@@ -513,9 +632,10 @@
 	      (clobber (match_scratch:DI 2 ""))])]
   ""
 {
-  if (! reload_in_progress && ! reload_completed
-      && ! ia64_move_ok (operands[0], operands[1]))
-    operands[1] = force_reg (TImode, operands[1]);
+  rtx op1 = ia64_expand_move (operands[0], operands[1]);
+  if (!op1)
+    DONE;
+  operands[1] = op1;
 })
 
 (define_insn_and_split "*movti_internal"
@@ -630,9 +750,10 @@
 	(match_operand:SF 1 "general_operand" ""))]
   ""
 {
-  if (! reload_in_progress && ! reload_completed
-      && ! ia64_move_ok (operands[0], operands[1]))
-    operands[1] = force_reg (SFmode, operands[1]);
+  rtx op1 = ia64_expand_move (operands[0], operands[1]);
+  if (!op1)
+    DONE;
+  operands[1] = op1;
 })
 
 (define_insn "*movsf_internal"
@@ -655,9 +776,10 @@
 	(match_operand:DF 1 "general_operand" ""))]
   ""
 {
-  if (! reload_in_progress && ! reload_completed
-      && ! ia64_move_ok (operands[0], operands[1]))
-    operands[1] = force_reg (DFmode, operands[1]);
+  rtx op1 = ia64_expand_move (operands[0], operands[1]);
+  if (!op1)
+    DONE;
+  operands[1] = op1;
 })
 
 (define_insn "*movdf_internal"
Index: gcc/config/ia64/sysv4.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/sysv4.h,v
retrieving revision 1.25
diff -c -p -d -u -r1.25 sysv4.h
--- gcc/config/ia64/sysv4.h	18 May 2002 23:47:13 -0000	1.25
+++ gcc/config/ia64/sysv4.h	25 May 2002 02:06:36 -0000
@@ -42,8 +42,7 @@ extern int size_directive_output;
 #undef ASM_OUTPUT_ALIGNED_LOCAL
 #define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
 do {									\
-  if ((DECL)								\
-      && XSTR (XEXP (DECL_RTL (DECL), 0), 0)[0] == SDATA_NAME_FLAG_CHAR) \
+  if ((DECL) && sdata_symbolic_operand (XEXP (DECL_RTL (DECL), 0), Pmode)) \
     sbss_section ();							\
   else									\
     bss_section ();							\
@@ -62,8 +61,8 @@ do {									\
 #define ASM_OUTPUT_LABELREF(STREAM, NAME)	\
 do {						\
   const char *name_ = NAME;			\
-  if (*name_ == SDATA_NAME_FLAG_CHAR)		\
-    name_++;					\
+  if (*name_ == ENCODE_SECTION_INFO_CHAR)	\
+    name_ += 2;					\
   if (*name_ == '*')				\
     name_++;					\
   else						\


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