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]

alpha tls support


	* configure.in (HAVE_AS_TLS): Add alpha tests.
	* configure: Rebuild.
	* config/alpha/alpha.c (TARGET_AS_TLS): New.
	(alpha_tls_size, alpha_tls_size_string): New.
	(overide_options): Set it.  Always install machine_status hooks.
	(input_operand): Accept got tls predicates.
	(local_symbol_p): Merge into ...
	(local_symbolic_operand): ... here.  Reject tls symbols.
	(global_symbolic_operand): Likewise.
	(tls_symbolic_operand_1, dtp16_symbolic_operand): New.
	(dtp32_symbolic_operand, gotdtp_symbolic_operand): New.
	(tp16_symbolic_operand, tp32_symbolic_operand): New.
	(gottp_symbolic_operand, tls_symbolic_operand_type): New.
	(alpha_encode_section_info): Handle TLS symbols.
	(alpha_strip_name_encoding): Likewise.
	(alpha_legitimate_address_p): Likewise.
	(alpha_legitimize_address): Likewise.
	(alpha_expand_mov): Early exit to avoid nop moves.
	(struct machine_function): Move from unicosmk.h.  Add some_ld_name.
	(alpha_init_machine_status, alpha_mark_machine_status,
	alpha_free_machine_status): Always define.
	(get_some_local_dynamic_name, get_some_local_dynamic_name_1): New.
	(print_operand, print_operand_address): Add TLS relocs.
	* config/alpha/alpha.h (HAVE_AS_TLS): Default 0.
	(MASK_TLS_KERNEL, TARGET_TLS_KERNEL): New.
	(TARGET_SWITCHES): Add -mtls-kernel.
	(alpha_tls_size, alpha_tls_size_string): New.
	(TARGET_OPTIONS): Add -mtls-size=.
	(reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS,
	REGNO_REG_CLASS, REG_CLASS_FROM_LETTER): Add R0_REG.
	(ASM_OUTPUT_LABELREF): Skip %.
	(PRINT_OPERAND_PUNCT_VALID_P): Add &.
	(PREDICATE_CODES): Update.
	* config/alpha/alpha.md (UNSPEC_TLSGD_CALL, UNSPEC_TLSLDM_CALL,
	UNSPEC_TLSGD, UNSPEC_TLSLDM, UNSPEC_DTPREL, UNSPEC_TPREL,
	UNSPEC_TP, UNSPECV_SET_TP): New.
	(adddi_er_lo16_dtp, adddi_er_hi32_dtp, adddi_er_lo32_dtp,
	adddi_er_lo16_tp, adddi_er_hi32_tp, adddi_er_lo32_tp, load_tp,
	set_tp, movdi_er_tlsgd, movdi_er_tlsldm, movdi_er_gotdtp,
	movdi_er_gottp, call_value_osf_tlsgd, call_value_osf_tlsldm): New.
	(call_value_osf_2_er): Accept anything as op4.
	* config/alpha/alpha-protos.h: Update.
	* config/alpha/unicosmk.h (struct machine_function): Move to alpha.c.

Index: gcc/configure.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/configure.in,v
retrieving revision 1.595
diff -c -p -d -r1.595 configure.in
*** gcc/configure.in	31 May 2002 20:11:46 -0000	1.595
--- gcc/configure.in	1 Jun 2002 00:11:16 -0000
*************** tls_first_major=
*** 1725,1730 ****
--- 1725,1752 ----
  tls_first_minor=
  case "$target" in
  changequote(,)dnl
+   alpha*-*-*)
+     conftest_s='
+ 	.section ".tdata","awT",@progbits
+ foo:	.long	25
+ 	.text
+ 	ldq	$27,__tls_get_addr($29)		!literal!1
+ 	lda	$16,foo($29)			!tlsgd!1
+ 	jsr	$26,($27),__tls_get_addr	!lituse_tlsgd!1
+ 	ldq	$27,__tls_get_addr($29)		!literal!2
+ 	lda	$16,foo($29)			!tlsldm!2
+ 	jsr	$26,($27),__tls_get_addr	!lituse_tlsldm!2
+ 	ldq	$1,foo($29)			!gotdtprel
+ 	ldah	$2,foo($29)			!dtprelhi
+ 	lda	$3,foo($2)			!dtprello
+ 	lda	$4,foo($29)			!dtprel
+ 	ldq	$1,foo($29)			!gottprel
+ 	ldah	$2,foo($29)			!tprelhi
+ 	lda	$3,foo($2)			!tprello
+ 	lda	$4,foo($29)			!tprel'
+ 	tls_first_major=2
+ 	tls_first_minor=13
+ 	;;
    i[34567]86-*-*)
  changequote([,])dnl
      conftest_s='
Index: gcc/config/alpha/alpha-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha-protos.h,v
retrieving revision 1.33
diff -c -p -d -r1.33 alpha-protos.h
*** gcc/config/alpha/alpha-protos.h	19 May 2002 05:22:58 -0000	1.33
--- gcc/config/alpha/alpha-protos.h	1 Jun 2002 00:11:16 -0000
*************** extern int local_symbolic_operand PARAMS
*** 61,66 ****
--- 61,72 ----
  extern int small_symbolic_operand PARAMS ((rtx, enum machine_mode));
  extern int some_small_symbolic_operand PARAMS ((rtx, enum machine_mode));
  extern int global_symbolic_operand PARAMS ((rtx, enum machine_mode));
+ extern int dtp16_symbolic_operand PARAMS ((rtx, enum machine_mode));
+ extern int dtp32_symbolic_operand PARAMS ((rtx, enum machine_mode));
+ extern int gotdtp_symbolic_operand PARAMS ((rtx, enum machine_mode));
+ extern int tp16_symbolic_operand PARAMS ((rtx, enum machine_mode));
+ extern int tp32_symbolic_operand PARAMS ((rtx, enum machine_mode));
+ extern int gottp_symbolic_operand PARAMS ((rtx, enum machine_mode));
  extern int call_operand PARAMS ((rtx, enum machine_mode));
  extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
  extern int alpha_comparison_operator PARAMS ((rtx, enum machine_mode));
Index: gcc/config/alpha/alpha.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.c,v
retrieving revision 1.255
diff -c -p -d -r1.255 alpha.c
*** gcc/config/alpha/alpha.c	28 May 2002 08:42:20 -0000	1.255
--- gcc/config/alpha/alpha.c	1 Jun 2002 00:11:16 -0000
*************** enum alpha_fp_rounding_mode alpha_fprm;
*** 69,74 ****
--- 69,78 ----
  
  enum alpha_fp_trap_mode alpha_fptm;
  
+ /* Specify bit size of immediate TLS offsets.  */
+ 
+ int alpha_tls_size = 32;
+ 
  /* Strings decoded into the above options.  */
  
  const char *alpha_cpu_string;	/* -mcpu= */
*************** const char *alpha_tp_string;	/* -mtrap-p
*** 77,82 ****
--- 81,87 ----
  const char *alpha_fprm_string;	/* -mfp-rounding-mode=[n|m|c|d] */
  const char *alpha_fptm_string;	/* -mfp-trap-mode=[n|u|su|sui] */
  const char *alpha_mlat_string;	/* -mmemory-latency= */
+ const char *alpha_tls_size_string; /* -mtls-size=[16|32|64] */
  
  /* Save information from a "cmpxx" operation until the branch or scc is
     emitted.  */
*************** int alpha_this_literal_sequence_number;
*** 113,118 ****
--- 118,127 ----
  int alpha_this_gpdisp_sequence_number;
  
  /* Declarations of static functions.  */
+ static int tls_symbolic_operand_1
+   PARAMS ((rtx, enum machine_mode, int, int));
+ static enum tls_model tls_symbolic_operand_type
+   PARAMS ((rtx));
  static bool decl_in_text_section
    PARAMS ((tree));
  static bool alpha_in_small_data_p
*************** static int some_small_symbolic_operand_1
*** 125,132 ****
    PARAMS ((rtx *, void *));
  static int split_small_symbolic_operand_1
    PARAMS ((rtx *, void *));
- static bool local_symbol_p
-   PARAMS ((rtx));
  static void alpha_set_memflags_1
    PARAMS ((rtx, int, int, int));
  static rtx alpha_emit_set_const_1
--- 134,139 ----
*************** static const char *get_trap_mode_suffix
*** 147,152 ****
--- 154,163 ----
    PARAMS ((void));
  static const char *get_round_mode_suffix
    PARAMS ((void));
+ static const char *get_some_local_dynamic_name
+   PARAMS ((void));
+ static int get_some_local_dynamic_name_1
+   PARAMS ((rtx *, void *));
  static rtx set_frame_related_p
    PARAMS ((void));
  static const char *alpha_lookup_xfloating_lib_func
*************** static void alpha_elf_select_rtx_section
*** 173,186 ****
    PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT));
  #endif
  
- #if TARGET_ABI_UNICOSMK
  static void alpha_init_machine_status
    PARAMS ((struct function *p));
  static void alpha_mark_machine_status
    PARAMS ((struct function *p));
  static void alpha_free_machine_status
    PARAMS ((struct function *p));
- #endif
  
  static void unicosmk_output_deferred_case_vectors PARAMS ((FILE *));
  static void unicosmk_gen_dsib PARAMS ((unsigned long *imaskP));
--- 184,195 ----
*************** static void unicosmk_unique_section PARA
*** 266,271 ****
--- 275,283 ----
  #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
    alpha_multipass_dfa_lookahead
  
+ #undef TARGET_HAVE_TLS
+ #define TARGET_HAVE_TLS HAVE_AS_TLS
+ 
  struct gcc_target targetm = TARGET_INITIALIZER;
  
  /* Parse target option strings.  */
*************** override_options ()
*** 385,390 ****
--- 397,414 ----
  	error ("bad value `%s' for -mfp-trap-mode switch", alpha_fptm_string);
      }
  
+   if (alpha_tls_size_string)
+     {
+       if (strcmp (alpha_tls_size_string, "16") == 0)
+ 	alpha_tls_size = 16;
+       else if (strcmp (alpha_tls_size_string, "32") == 0)
+ 	alpha_tls_size = 32;
+       else if (strcmp (alpha_tls_size_string, "64") == 0)
+ 	alpha_tls_size = 64;
+       else
+ 	error ("bad value `%s' for -mtls-size switch", alpha_tls_size_string);
+     }
+ 
    alpha_cpu
      = TARGET_CPU_DEFAULT & MASK_CPU_EV6 ? PROCESSOR_EV6
        : (TARGET_CPU_DEFAULT & MASK_CPU_EV5 ? PROCESSOR_EV5 : PROCESSOR_EV4);
*************** override_options ()
*** 527,538 ****
  
    /* Register variables and functions with the garbage collector.  */
  
- #if TARGET_ABI_UNICOSMK
    /* Set up function hooks.  */
    init_machine_status = alpha_init_machine_status;
    mark_machine_status = alpha_mark_machine_status;
    free_machine_status = alpha_free_machine_status;
- #endif
  }
  
  /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones.  */
--- 551,560 ----
*************** input_operand (op, mode)
*** 857,863 ****
  	     symbolic operands to be reconstructed from their high/lo_sum
  	     form.  */
  	  return (small_symbolic_operand (op, mode)
! 		  || global_symbolic_operand (op, mode));
  	}
  
        /* This handles both the Windows/NT and OSF cases.  */
--- 879,887 ----
  	     symbolic operands to be reconstructed from their high/lo_sum
  	     form.  */
  	  return (small_symbolic_operand (op, mode)
! 		  || global_symbolic_operand (op, mode)
! 		  || gotdtp_symbolic_operand (op, mode)
! 		  || gottp_symbolic_operand (op, mode));
  	}
  
        /* This handles both the Windows/NT and OSF cases.  */
*************** direct_call_operand (op, mode)
*** 946,974 ****
  /* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
     a variable known to be defined in this file.  */
  
- static bool
- local_symbol_p (op)
-      rtx op;
- {
-   const char *str = XSTR (op, 0);
- 
-   /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we
-      run into problems with the rtl inliner in that the symbol was
-      once external, but is local after inlining, which results in
-      unrecognizable insns.  */
- 
-   return (CONSTANT_POOL_ADDRESS_P (op)
- 	  /* If @, then alpha_encode_section_info sez it's local.  */
- 	  || str[0] == '@'
- 	  /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local.  */
- 	  || (str[0] == '*' && str[1] == '$'));
- }
- 
  int
  local_symbolic_operand (op, mode)
       rtx op;
       enum machine_mode mode;
  {
    if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
      return 0;
  
--- 970,982 ----
  /* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
     a variable known to be defined in this file.  */
  
  int
  local_symbolic_operand (op, mode)
       rtx op;
       enum machine_mode mode;
  {
+   const char *str;
+ 
    if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
      return 0;
  
*************** local_symbolic_operand (op, mode)
*** 983,989 ****
    if (GET_CODE (op) != SYMBOL_REF)
      return 0;
  
!   return local_symbol_p (op);
  }
  
  /* Return true if OP is a SYMBOL_REF or CONST referencing a variable
--- 991,1016 ----
    if (GET_CODE (op) != SYMBOL_REF)
      return 0;
  
!   /* Easy pickings.  */
!   if (CONSTANT_POOL_ADDRESS_P (op) || STRING_POOL_ADDRESS_P (op))
!     return 1;
! 
!   /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we
!      run into problems with the rtl inliner in that the symbol was
!      once external, but is local after inlining, which results in
!      unrecognizable insns.  */
! 
!   str = XSTR (op, 0);
! 
!   /* If @[VS], then alpha_encode_section_info sez it's local.  */
!   if (str[0] == '@' && (str[1] == 'L' || str[1] == 'S'))
!     return 1;
! 
!   /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local.  */
!   if (str[0] == '*' && str[1] == '$')
!     return 1;
! 
!   return 0;
  }
  
  /* Return true if OP is a SYMBOL_REF or CONST referencing a variable
*************** small_symbolic_operand (op, mode)
*** 1015,1021 ****
    else
      {
        str = XSTR (op, 0);
!       return str[0] == '@' && str[1] == 's';
      }
  }
  
--- 1042,1048 ----
    else
      {
        str = XSTR (op, 0);
!       return str[0] == '@' && str[1] == 'S';
      }
  }
  
*************** global_symbolic_operand (op, mode)
*** 1027,1032 ****
--- 1054,1061 ----
       rtx op;
       enum machine_mode mode;
  {
+   const char *str;
+ 
    if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
      return 0;
  
*************** global_symbolic_operand (op, mode)
*** 1038,1044 ****
    if (GET_CODE (op) != SYMBOL_REF)
      return 0;
  
!   return ! local_symbol_p (op);
  }
  
  /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
--- 1067,1078 ----
    if (GET_CODE (op) != SYMBOL_REF)
      return 0;
  
!   if (local_symbolic_operand (op, mode))
!     return 0;
! 
!   /* Also verify that it's not a TLS symbol.  */
!   str = XSTR (op, 0);
!   return str[0] != '%' && str[0] != '@';
  }
  
  /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
*************** symbolic_operand (op, mode)
*** 1091,1096 ****
--- 1125,1234 ----
    return 0;
  }
  
+ /* Return true if OP is valid for a particular TLS relocation.  */
+ 
+ static int
+ tls_symbolic_operand_1 (op, mode, size, unspec)
+      rtx op;
+      enum machine_mode mode;
+      int size, unspec;
+ {
+   const char *str;
+   int letter;
+ 
+   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
+     return 0;
+ 
+   if (GET_CODE (op) != CONST)
+     return 0;
+   op = XEXP (op, 0);
+ 
+   if (GET_CODE (op) != UNSPEC || XINT (op, 1) != unspec)
+     return 0;
+   op = XVECEXP (op, 0, 0);
+ 
+   if (GET_CODE (op) != SYMBOL_REF)
+     return 0;
+   str = XSTR (op, 0);
+ 
+   if (str[0] == '%')
+     {
+       if (size != 64)
+ 	return 0;
+     }
+   else if (str[0] == '@')
+     {
+       if (alpha_tls_size > size)
+ 	return 0;
+     }
+   else
+     return 0;
+ 
+   letter = (unspec == UNSPEC_DTPREL ? 'D' : 'T');
+ 
+   return str[1] == letter;
+ }
+ 
+ /* Return true if OP is valid for 16-bit DTP relative relocations.  */
+ 
+ int
+ dtp16_symbolic_operand (op, mode)
+       rtx op;
+       enum machine_mode mode;
+ {
+   return tls_symbolic_operand_1 (op, mode, 16, UNSPEC_DTPREL);
+ }
+ 
+ /* Return true if OP is valid for 32-bit DTP relative relocations.  */
+ 
+ int
+ dtp32_symbolic_operand (op, mode)
+       rtx op;
+       enum machine_mode mode;
+ {
+   return tls_symbolic_operand_1 (op, mode, 32, UNSPEC_DTPREL);
+ }
+ 
+ /* Return true if OP is valid for 64-bit DTP relative relocations.  */
+ 
+ int
+ gotdtp_symbolic_operand (op, mode)
+       rtx op;
+       enum machine_mode mode;
+ {
+   return tls_symbolic_operand_1 (op, mode, 64, UNSPEC_DTPREL);
+ }
+ 
+ /* Return true if OP is valid for 16-bit TP relative relocations.  */
+ 
+ int
+ tp16_symbolic_operand (op, mode)
+       rtx op;
+       enum machine_mode mode;
+ {
+   return tls_symbolic_operand_1 (op, mode, 16, UNSPEC_TPREL);
+ }
+ 
+ /* Return true if OP is valid for 32-bit TP relative relocations.  */
+ 
+ int
+ tp32_symbolic_operand (op, mode)
+       rtx op;
+       enum machine_mode mode;
+ {
+   return tls_symbolic_operand_1 (op, mode, 32, UNSPEC_TPREL);
+ }
+ 
+ /* Return true if OP is valid for 64-bit TP relative relocations.  */
+ 
+ int
+ gottp_symbolic_operand (op, mode)
+       rtx op;
+       enum machine_mode mode;
+ {
+   return tls_symbolic_operand_1 (op, mode, 64, UNSPEC_TPREL);
+ }
+ 
  /* Return 1 if OP is a valid Alpha comparison operator.  Here we know which
     comparisons are valid in which insn.  */
  
*************** alpha_tablejump_best_label (insn)
*** 1561,1566 ****
--- 1699,1752 ----
  
    return best_label ? best_label : const0_rtx;
  }
+ 
+ /* Return the TLS model to use for SYMBOL.  */
+ 
+ static enum tls_model
+ tls_symbolic_operand_type (symbol)
+      rtx symbol;
+ {
+   const char *str;
+ 
+   if (GET_CODE (symbol) != SYMBOL_REF)
+     return 0;
+   str = XSTR (symbol, 0);
+ 
+   if (str[0] == '%')
+     {
+       /* ??? Be prepared for -ftls-model=local-dynamic.  Perhaps we shouldn't
+ 	 have separately encoded local-ness.  On well, maybe the user will use
+ 	 attribute visibility next time.  At least we don't crash...  */
+       if (str[1] == 'G' || str[1] == 'D')
+ 	return TLS_MODEL_GLOBAL_DYNAMIC;
+       if (str[1] == 'T')
+ 	return TLS_MODEL_INITIAL_EXEC;
+     }
+   else if (str[0] == '@')
+     {
+       if (str[1] == 'D')
+ 	{
+ 	  /* Local dynamic is a waste if we're not going to combine
+ 	     the __tls_get_addr calls.  So avoid it if not optimizing.  */
+ 	  if (optimize)
+ 	    return TLS_MODEL_LOCAL_DYNAMIC;
+ 	  else
+ 	    return TLS_MODEL_GLOBAL_DYNAMIC;
+ 	}
+       if (str[1] == 'T')
+ 	{
+ 	  /* 64-bit local exec is the same as initial exec except without
+ 	     the dynamic relocation.  In either case we use a got entry.  */
+ 	  if (alpha_tls_size == 64)
+ 	    return TLS_MODEL_INITIAL_EXEC;
+ 	  else
+ 	    return TLS_MODEL_LOCAL_EXEC;
+ 	}
+     }
+ 
+   return 0;
+ }
+ 
  
  /* Return true if the function DECL will be placed in the default text
     section.  */
*************** alpha_encode_section_info (decl, first)
*** 1622,1628 ****
       int first ATTRIBUTE_UNUSED;
  {
    const char *symbol_str;
!   bool is_local, is_small;
    rtx rtl, symbol;
  
    rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
--- 1808,1815 ----
       int first ATTRIBUTE_UNUSED;
  {
    const char *symbol_str;
!   bool is_local;
!   char encoding = 0;
    rtx rtl, symbol;
  
    rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl);
*************** alpha_encode_section_info (decl, first)
*** 1659,1676 ****
    /* A variable is considered "local" if it is defined in this module.  */
    is_local = (*targetm.binds_local_p) (decl);
  
!   /* Determine if DECL will wind up in .sdata/.sbss.  */
!   is_small = alpha_in_small_data_p (decl);
  
    /* Finally, encode this into the symbol string.  */
!   if (is_local)
      {
        char *newstr;
        size_t len;
  
!       if (symbol_str[0] == '@')
  	{
! 	  if (symbol_str[1] == (is_small ? 's' : 'v'))
  	    return;
  	  symbol_str += 2;
  	}
--- 1846,1901 ----
    /* A variable is considered "local" if it is defined in this module.  */
    is_local = (*targetm.binds_local_p) (decl);
  
!   /* Care for TLS variables.  */
!   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;
! 
!       switch (kind)
! 	{
! 	case TLS_MODEL_GLOBAL_DYNAMIC:
! 	  encoding = 'G';
! 	  break;
! 	case TLS_MODEL_LOCAL_DYNAMIC:
! 	  encoding = 'D';
! 	  break;
! 	case TLS_MODEL_INITIAL_EXEC:
! 	case TLS_MODEL_LOCAL_EXEC:
! 	  encoding = 'T';
! 	  break;
! 	}
!     }
!   else if (is_local)
!     {
!       /* Determine if DECL will wind up in .sdata/.sbss.  */
!       if (alpha_in_small_data_p (decl))
! 	encoding = 'S';
!       else
! 	encoding = 'L';
!     }
  
    /* Finally, encode this into the symbol string.  */
!   if (encoding)
      {
        char *newstr;
        size_t len;
  
!       if (symbol_str[0] == (is_local ? '@' : '%'))
  	{
! 	  if (symbol_str[1] == encoding)
  	    return;
  	  symbol_str += 2;
  	}
*************** alpha_encode_section_info (decl, first)
*** 1678,1695 ****
        len = strlen (symbol_str) + 1;
        newstr = alloca (len + 2);
  
!       newstr[0] = '@';
!       newstr[1] = (is_small ? 's' : 'v');
        memcpy (newstr + 2, symbol_str, len);
  	  
        XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1);
      }
-   else if (symbol_str[0] == '@')
-     {
-       /* We're hosed.  This can happen when the user adds a weak
- 	 attribute after rtl generation.  They should have gotten
- 	 a warning about unspecified behaviour from varasm.c.  */
-     }
  }
  
  /* Undo the effects of the above.  */
--- 1903,1914 ----
        len = strlen (symbol_str) + 1;
        newstr = alloca (len + 2);
  
!       newstr[0] = (is_local ? '@' : '%');
!       newstr[1] = encoding;
        memcpy (newstr + 2, symbol_str, len);
  	  
        XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1);
      }
  }
  
  /* Undo the effects of the above.  */
*************** static const char *
*** 1698,1704 ****
  alpha_strip_name_encoding (str)
       const char *str;
  {
!   if (str[0] == '@')
      str += 2;
    if (str[0] == '*')
      str++;
--- 1917,1923 ----
  alpha_strip_name_encoding (str)
       const char *str;
  {
!   if (str[0] == '@' || str[0] == '%')
      str += 2;
    if (str[0] == '*')
      str++;
*************** alpha_legitimate_address_p (mode, x, str
*** 1799,1805 ****
  	    return false;
  
  	  /* The symbol must be local.  */
! 	  if (local_symbolic_operand (ofs, Pmode))
  	    return true;
  	}
      }
--- 2018,2026 ----
  	    return false;
  
  	  /* The symbol must be local.  */
! 	  if (local_symbolic_operand (ofs, Pmode)
! 	      || dtp32_symbolic_operand (ofs, Pmode)
! 	      || tp32_symbolic_operand (ofs, Pmode))
  	    return true;
  	}
      }
*************** alpha_legitimize_address (x, scratch, mo
*** 1865,1870 ****
--- 2086,2185 ----
    /* If this is a local symbol, split the address into HIGH/LO_SUM parts.  */
    if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode))
      {
+       rtx r0, r16, eqv, tga, tp, insn, dest, seq;
+ 
+       switch (tls_symbolic_operand_type (x))
+ 	{
+ 	case TLS_MODEL_GLOBAL_DYNAMIC:
+ 	  start_sequence ();
+ 
+ 	  r0 = gen_rtx_REG (Pmode, 0);
+ 	  r16 = gen_rtx_REG (Pmode, 16);
+ 	  tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
+ 	  dest = gen_reg_rtx (Pmode);
+ 	  seq = GEN_INT (alpha_next_sequence_number++);
+ 	  
+ 	  emit_insn (gen_movdi_er_tlsgd (r16, pic_offset_table_rtx, x, seq));
+ 	  insn = gen_call_value_osf_tlsgd (r0, tga, seq);
+ 	  insn = emit_call_insn (insn);
+ 	  CONST_OR_PURE_CALL_P (insn) = 1;
+ 	  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
+ 
+           insn = get_insns ();
+ 	  end_sequence ();
+ 
+ 	  emit_libcall_block (insn, dest, r0, x);
+ 	  return dest;
+ 
+ 	case TLS_MODEL_LOCAL_DYNAMIC:
+ 	  start_sequence ();
+ 
+ 	  r0 = gen_rtx_REG (Pmode, 0);
+ 	  r16 = gen_rtx_REG (Pmode, 16);
+ 	  tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr");
+ 	  scratch = gen_reg_rtx (Pmode);
+ 	  seq = GEN_INT (alpha_next_sequence_number++);
+ 
+ 	  emit_insn (gen_movdi_er_tlsldm (r16, pic_offset_table_rtx, seq));
+ 	  insn = gen_call_value_osf_tlsldm (r0, tga, seq);
+ 	  insn = emit_call_insn (insn);
+ 	  CONST_OR_PURE_CALL_P (insn) = 1;
+ 	  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
+ 
+           insn = get_insns ();
+ 	  end_sequence ();
+ 
+ 	  eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+ 				UNSPEC_TLSLDM_CALL);
+ 	  emit_libcall_block (insn, scratch, r0, eqv);
+ 
+ 	  eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPREL);
+ 	  eqv = gen_rtx_CONST (Pmode, eqv);
+ 
+ 	  if (alpha_tls_size == 64)
+ 	    {
+ 	      dest = gen_reg_rtx (Pmode);
+ 	      emit_insn (gen_rtx_SET (VOIDmode, dest, eqv));
+ 	      emit_insn (gen_adddi3 (dest, dest, scratch));
+ 	      return dest;
+ 	    }
+ 	  if (alpha_tls_size == 32)
+ 	    {
+ 	      insn = gen_rtx_HIGH (Pmode, eqv);
+ 	      insn = gen_rtx_PLUS (Pmode, scratch, insn);
+ 	      scratch = gen_reg_rtx (Pmode);
+ 	      emit_insn (gen_rtx_SET (VOIDmode, scratch, insn));
+ 	    }
+ 	  return gen_rtx_LO_SUM (Pmode, scratch, eqv);
+ 
+ 	case TLS_MODEL_INITIAL_EXEC:
+ 	  eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL);
+ 	  eqv = gen_rtx_CONST (Pmode, eqv);
+ 	  tp = gen_reg_rtx (Pmode);
+ 	  scratch = gen_reg_rtx (Pmode);
+ 	  dest = gen_reg_rtx (Pmode);
+ 
+ 	  emit_insn (gen_load_tp (tp));
+ 	  emit_insn (gen_rtx_SET (VOIDmode, scratch, eqv));
+ 	  emit_insn (gen_adddi3 (dest, tp, scratch));
+ 	  return dest;
+ 
+ 	case TLS_MODEL_LOCAL_EXEC:
+ 	  eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL);
+ 	  eqv = gen_rtx_CONST (Pmode, eqv);
+ 	  tp = gen_reg_rtx (Pmode);
+ 
+ 	  emit_insn (gen_load_tp (tp));
+ 	  if (alpha_tls_size == 32)
+ 	    {
+ 	      insn = gen_rtx_HIGH (Pmode, eqv);
+ 	      insn = gen_rtx_PLUS (Pmode, tp, insn);
+ 	      tp = gen_reg_rtx (Pmode);
+ 	      emit_insn (gen_rtx_SET (VOIDmode, tp, insn));
+ 	    }
+ 	  return gen_rtx_LO_SUM (Pmode, tp, eqv);
+ 	}
+ 
        if (local_symbolic_operand (x, Pmode))
  	{
  	  if (small_symbolic_operand (x, Pmode))
*************** alpha_expand_mov (mode, operands)
*** 2589,2594 ****
--- 2904,2911 ----
        tmp = alpha_legitimize_address (operands[1], operands[0], mode);
        if (tmp)
  	{
+ 	  if (tmp == operands[0])
+ 	    return true;
  	  operands[1] = tmp;
  	  return false;
  	}
*************** alpha_multipass_dfa_lookahead ()
*** 4906,4915 ****
    return (alpha_cpu == PROCESSOR_EV6 ? 4 : 2);
  }
  
  /* Register global variables and machine-specific functions with the
     garbage collector.  */
  
- #if TARGET_ABI_UNICOSMK
  static void
  alpha_init_machine_status (p)
       struct function *p;
--- 5223,5253 ----
    return (alpha_cpu == PROCESSOR_EV6 ? 4 : 2);
  }
  
+ /* Machine-specific function data.  */
+ 
+ struct machine_function
+ {
+ #if TARGET_ABI_UNICOSMK
+   /* List of call information words for calls from this function.  */
+   struct rtx_def *first_ciw;
+   struct rtx_def *last_ciw;
+   int ciw_count;
+ 
+   /* List of deferred case vectors.  */
+   struct rtx_def *addr_list;
+ #else
+ #if TARGET_ABI_OSF
+   const char *some_ld_name;
+ #else
+   /* Non-empty struct.  */
+   char dummy;
+ #endif
+ #endif
+ };
+ 
  /* Register global variables and machine-specific functions with the
     garbage collector.  */
  
  static void
  alpha_init_machine_status (p)
       struct function *p;
*************** alpha_init_machine_status (p)
*** 4917,4926 ****
--- 5255,5269 ----
    p->machine =
      (struct machine_function *) xcalloc (1, sizeof (struct machine_function));
  
+ #if TARGET_ABI_UNICOSMK
    p->machine->first_ciw = NULL_RTX;
    p->machine->last_ciw = NULL_RTX;
    p->machine->ciw_count = 0;
    p->machine->addr_list = NULL_RTX;
+ #endif
+ #if TARGET_ABI_OSF
+   p->machine->some_ld_name = NULL;
+ #endif
  }
  
  static void
*************** alpha_mark_machine_status (p)
*** 4931,4938 ****
--- 5274,5283 ----
  
    if (machine)
      {
+ #if TARGET_ABI_UNICOSMK
        ggc_mark_rtx (machine->first_ciw);
        ggc_mark_rtx (machine->addr_list);
+ #endif
      }
  }
  
*************** alpha_free_machine_status (p)
*** 4943,4949 ****
    free (p->machine);
    p->machine = NULL;
  }
- #endif /* TARGET_ABI_UNICOSMK */
  
  /* Functions to save and restore alpha_return_addr_rtx.  */
  
--- 5288,5293 ----
*************** get_round_mode_suffix ()
*** 5087,5092 ****
--- 5431,5475 ----
    abort ();
  }
  
+ /* Locate some local-dynamic symbol still in use by this function
+    so that we can print its name in some movdi_er_tlsldm pattern.  */
+ 
+ static const char *
+ get_some_local_dynamic_name ()
+ {
+   rtx insn;
+ 
+   if (cfun->machine->some_ld_name)
+     return cfun->machine->some_ld_name;
+ 
+   for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
+     if (INSN_P (insn)
+ 	&& for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
+       return cfun->machine->some_ld_name;
+ 
+   abort ();
+ }
+ 
+ static int
+ get_some_local_dynamic_name_1 (px, data)
+      rtx *px;
+      void *data ATTRIBUTE_UNUSED;
+ {
+   rtx x = *px;
+ 
+   if (GET_CODE (x) == SYMBOL_REF)
+     {
+       const char *str = XSTR (x, 0);
+       if (str[0] == '@' && str[1] == 'D')
+ 	{
+           cfun->machine->some_ld_name = str;
+           return 1;
+ 	}
+     }
+ 
+   return 0;
+ }
+ 
  /* Print an operand.  Recognize special options, documented below.  */
  
  void
*************** print_operand (file, x, code)
*** 5104,5109 ****
--- 5487,5496 ----
        assemble_name (file, alpha_fnname);
        break;
  
+     case '&':
+       assemble_name (file, get_some_local_dynamic_name ());
+       break;
+ 
      case '/':
        {
  	const char *trap = get_trap_mode_suffix ();
*************** print_operand (file, x, code)
*** 5145,5157 ****
        break;
  
      case 'J':
!       if (GET_CODE (x) == CONST_INT)
! 	{
! 	  if (INTVAL (x) != 0)
! 	    fprintf (file, "\t\t!lituse_jsr!%d", (int) INTVAL (x));
! 	}
!       else
! 	output_operand_lossage ("invalid %%J value");
        break;
  
      case 'r':
--- 5532,5561 ----
        break;
  
      case 'J':
!       {
! 	const char *lituse;
! 
!         if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSGD_CALL)
! 	  {
! 	    x = XVECEXP (x, 0, 0);
! 	    lituse = "lituse_tlsgd";
! 	  }
! 	else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSLDM_CALL)
! 	  {
! 	    x = XVECEXP (x, 0, 0);
! 	    lituse = "lituse_tlsldm";
! 	  }
! 	else if (GET_CODE (x) == CONST_INT)
! 	  lituse = "lituse_jsr";
! 	else
! 	  {
! 	    output_operand_lossage ("invalid %%J value");
! 	    break;
! 	  }
! 
! 	if (x != const0_rtx)
! 	  fprintf (file, "\t\t!%s!%d", lituse, (int) INTVAL (x));
!       }
        break;
  
      case 'r':
*************** print_operand (file, x, code)
*** 5385,5390 ****
--- 5789,5807 ----
  	fprintf (file, "%s", reg_names[REGNO (x)]);
        else if (GET_CODE (x) == MEM)
  	output_address (XEXP (x, 0));
+       else if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC)
+ 	{
+ 	  switch (XINT (XEXP (x, 0), 1))
+ 	    {
+ 	    case UNSPEC_DTPREL:
+ 	    case UNSPEC_TPREL:
+ 	      output_addr_const (file, XVECEXP (XEXP (x, 0), 0, 0));
+ 	      break;
+ 	    default:
+ 	      output_operand_lossage ("unknown relocation unspec");
+ 	      break;
+ 	    }
+ 	}
        else
  	output_addr_const (file, x);
        break;
*************** print_operand_address (file, addr)
*** 5414,5420 ****
  
    if (GET_CODE (addr) == LO_SUM)
      {
!       output_addr_const (file, XEXP (addr, 1));
        if (offset)
  	{
  	  fputc ('+', file);
--- 5831,5866 ----
  
    if (GET_CODE (addr) == LO_SUM)
      {
!       const char *reloc16, *reloclo;
!       rtx op1 = XEXP (addr, 1);
! 
!       if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1, 0)) == UNSPEC)
! 	{
! 	  op1 = XEXP (op1, 0);
! 	  switch (XINT (op1, 1))
! 	    {
! 	    case UNSPEC_DTPREL:
! 	      reloc16 = NULL;
! 	      reloclo = (alpha_tls_size == 16 ? "dtprel" : "dtprello");
! 	      break;
! 	    case UNSPEC_TPREL:
! 	      reloc16 = NULL;
! 	      reloclo = (alpha_tls_size == 16 ? "tprel" : "tprello");
! 	      break;
! 	    default:
! 	      output_operand_lossage ("unknown relocation unspec");
! 	      return;
! 	    }
! 
! 	  output_addr_const (file, XVECEXP (op1, 0, 0));
! 	}
!       else
! 	{
! 	  reloc16 = "gprel";
! 	  reloclo = "gprellow";
! 	  output_addr_const (file, op1);
! 	}
! 
        if (offset)
  	{
  	  fputc ('+', file);
*************** print_operand_address (file, addr)
*** 5431,5437 ****
  	abort ();
  
        fprintf (file, "($%d)\t\t!%s", basereg,
! 	       (basereg == 29 ? "gprel" : "gprellow"));
        return;
      }
  
--- 5877,5883 ----
  	abort ();
  
        fprintf (file, "($%d)\t\t!%s", basereg,
! 	       (basereg == 29 ? reloc16 : reloclo));
        return;
      }
  
Index: gcc/config/alpha/alpha.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.h,v
retrieving revision 1.166
diff -c -p -d -r1.166 alpha.h
*** gcc/config/alpha/alpha.h	19 May 2002 21:53:53 -0000	1.166
--- gcc/config/alpha/alpha.h	1 Jun 2002 00:11:16 -0000
*************** extern int target_flags;
*** 137,142 ****
--- 137,143 ----
  extern enum alpha_trap_precision alpha_tp;
  extern enum alpha_fp_rounding_mode alpha_fprm;
  extern enum alpha_fp_trap_mode alpha_fptm;
+ extern int alpha_tls_size;
  
  /* This means that floating-point support exists in the target implementation
     of the Alpha architecture.  This is usually the default.  */
*************** extern enum alpha_fp_trap_mode alpha_fpt
*** 208,213 ****
--- 209,218 ----
  #define MASK_SMALL_DATA (1 << 13)
  #define TARGET_SMALL_DATA (target_flags & MASK_SMALL_DATA)
  
+ /* This means emit thread pointer loads for kernel not user.  */
+ #define MASK_TLS_KERNEL	(1 << 14)
+ #define TARGET_TLS_KERNEL (target_flags & MASK_TLS_KERNEL)
+ 
  /* This means that the processor is an EV5, EV56, or PCA56.
     Unlike alpha_cpu this is not affected by -mtune= setting.  */
  #define MASK_CPU_EV5	(1 << 28)
*************** extern enum alpha_fp_trap_mode alpha_fpt
*** 251,256 ****
--- 256,264 ----
  #ifndef TARGET_FIXUP_EV5_PREFETCH
  #define TARGET_FIXUP_EV5_PREFETCH 0
  #endif
+ #ifndef HAVE_AS_TLS
+ #define HAVE_AS_TLS 0
+ #endif
  
  /* Macro to define tables used to set the flags.
     This is a list in braces of pairs in braces,
*************** extern enum alpha_fp_trap_mode alpha_fpt
*** 293,298 ****
--- 301,308 ----
       N_("Emit 16-bit relocations to the small data areas")},		\
      {"large-data", -MASK_SMALL_DATA,					\
       N_("Emit 32-bit relocations to the small data areas")},		\
+     {"tls-kernel", MASK_TLS_KERNEL,					\
+      N_("Emit rdval instead of rduniq for thread pointer")},		\
      {"", TARGET_DEFAULT | TARGET_CPU_DEFAULT				\
  	 | TARGET_DEFAULT_EXPLICIT_RELOCS, ""} }
  
*************** extern const char *alpha_fprm_string;	/*
*** 316,321 ****
--- 326,332 ----
  extern const char *alpha_fptm_string;	/* For -mfp-trap-mode=[n|u|su|sui]  */
  extern const char *alpha_tp_string;	/* For -mtrap-precision=[p|f|i] */
  extern const char *alpha_mlat_string;	/* For -mmemory-latency= */
+ extern const char *alpha_tls_size_string; /* For -mtls-size= */
  
  #define TARGET_OPTIONS					\
  {							\
*************** extern const char *alpha_mlat_string;	/*
*** 331,336 ****
--- 342,349 ----
     N_("Control the precision given to fp exceptions")},	\
    {"memory-latency=",	&alpha_mlat_string,		\
     N_("Tune expected memory latency")},			\
+   {"tls-size=",		&alpha_tls_size_string,		\
+    N_("Specify bit size of immediate TLS offsets")},	\
  }
  
  /* This macro defines names of additional specifications to put in the
*************** extern const char *alpha_mlat_string;	/*
*** 681,687 ****
     class that represents their union.  */
     
  enum reg_class {
!   NO_REGS, R24_REG, R25_REG, R27_REG,
    GENERAL_REGS, FLOAT_REGS, ALL_REGS,
    LIM_REG_CLASSES
  };
--- 694,700 ----
     class that represents their union.  */
     
  enum reg_class {
!   NO_REGS, R0_REG, R24_REG, R25_REG, R27_REG,
    GENERAL_REGS, FLOAT_REGS, ALL_REGS,
    LIM_REG_CLASSES
  };
*************** enum reg_class {
*** 690,697 ****
  
  /* Give names of register classes as strings for dump file.  */
  
! #define REG_CLASS_NAMES				\
!  {"NO_REGS", "R24_REG", "R25_REG", "R27_REG",	\
    "GENERAL_REGS", "FLOAT_REGS", "ALL_REGS" }
  
  /* Define which registers fit in which classes.
--- 703,710 ----
  
  /* Give names of register classes as strings for dump file.  */
  
! #define REG_CLASS_NAMES					\
!  {"NO_REGS", "R0_REG", "R24_REG", "R25_REG", "R27_REG",	\
    "GENERAL_REGS", "FLOAT_REGS", "ALL_REGS" }
  
  /* Define which registers fit in which classes.
*************** enum reg_class {
*** 700,705 ****
--- 713,719 ----
  
  #define REG_CLASS_CONTENTS				\
  { {0x00000000, 0x00000000},	/* NO_REGS */		\
+   {0x00000001, 0x00000000},	/* R0_REG */		\
    {0x01000000, 0x00000000},	/* R24_REG */		\
    {0x02000000, 0x00000000},	/* R25_REG */		\
    {0x08000000, 0x00000000},	/* R27_REG */		\
*************** enum reg_class {
*** 713,719 ****
     or could index an array.  */
  
  #define REGNO_REG_CLASS(REGNO)			\
!  ((REGNO) == 24 ? R24_REG			\
    : (REGNO) == 25 ? R25_REG			\
    : (REGNO) == 27 ? R27_REG			\
    : (REGNO) >= 32 && (REGNO) <= 62 ? FLOAT_REGS	\
--- 727,734 ----
     or could index an array.  */
  
  #define REGNO_REG_CLASS(REGNO)			\
!  ((REGNO) == 0 ? R0_REG				\
!   : (REGNO) == 24 ? R24_REG			\
    : (REGNO) == 25 ? R25_REG			\
    : (REGNO) == 27 ? R27_REG			\
    : (REGNO) >= 32 && (REGNO) <= 62 ? FLOAT_REGS	\
*************** enum reg_class {
*** 730,735 ****
--- 745,751 ----
    : (C) == 'b' ? R25_REG		\
    : (C) == 'c' ? R27_REG		\
    : (C) == 'f' ? FLOAT_REGS		\
+   : (C) == 'v' ? R0_REG			\
    : NO_REGS)
  
  /* Define this macro to change register usage conditional on target flags.  */
*************** do {									     \
*** 1710,1716 ****
  #define ASM_OUTPUT_LABELREF(STREAM, NAME)	\
  do {						\
    const char *name_ = NAME;			\
!   if (*name_ == '@')				\
      name_ += 2;					\
    if (*name_ == '*')				\
      name_++;					\
--- 1726,1732 ----
  #define ASM_OUTPUT_LABELREF(STREAM, NAME)	\
  do {						\
    const char *name_ = NAME;			\
!   if (*name_ == '@' || *name == '%')		\
      name_ += 2;					\
    if (*name_ == '*')				\
      name_++;					\
*************** do {						\
*** 1893,1899 ****
  
  #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
    ((CODE) == '/' || (CODE) == ',' || (CODE) == '-' || (CODE) == '~' \
!    || (CODE) == '#' || (CODE) == '*')
  
  /* Print a memory address as an operand to reference that memory location.  */
  
--- 1909,1915 ----
  
  #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
    ((CODE) == '/' || (CODE) == ',' || (CODE) == '-' || (CODE) == '~' \
!    || (CODE) == '#' || (CODE) == '*' || (CODE) == '&')
  
  /* Print a memory address as an operand to reference that memory location.  */
  
*************** do {						\
*** 1929,1934 ****
--- 1945,1956 ----
    {"local_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}},		\
    {"small_symbolic_operand", {SYMBOL_REF, CONST}},			\
    {"global_symbolic_operand", {SYMBOL_REF, CONST}},			\
+   {"dtp16_symbolic_operand", {CONST}},					\
+   {"dtp32_symbolic_operand", {CONST}},					\
+   {"gotdtp_symbolic_operand", {CONST}},					\
+   {"tp16_symbolic_operand", {CONST}},					\
+   {"tp32_symbolic_operand", {CONST}},					\
+   {"gottp_symbolic_operand", {CONST}},					\
    {"call_operand", {REG, SYMBOL_REF}},					\
    {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,		\
  		     SYMBOL_REF, CONST, LABEL_REF, HIGH}},		\
Index: gcc/config/alpha/alpha.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.md,v
retrieving revision 1.187
diff -c -p -d -r1.187 alpha.md
*** gcc/config/alpha/alpha.md	5 May 2002 21:54:38 -0000	1.187
--- gcc/config/alpha/alpha.md	1 Jun 2002 00:11:16 -0000
***************
*** 1,6 ****
  ;; Machine description for DEC Alpha for GNU C compiler
  ;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
! ;; 2000, 2001 Free Software Foundation, Inc.
  ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
  ;;
  ;; This file is part of GNU CC.
--- 1,6 ----
  ;; Machine description for DEC Alpha for GNU C compiler
  ;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
! ;; 2000, 2001, 2002 Free Software Foundation, Inc.
  ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
  ;;
  ;; This file is part of GNU CC.
***************
*** 40,45 ****
--- 40,54 ----
     (UNSPEC_LITUSE	12)
     (UNSPEC_SIBCALL	13)
     (UNSPEC_SYMBOL	14)
+ 
+    ;; TLS Support
+    (UNSPEC_TLSGD_CALL	15)
+    (UNSPEC_TLSLDM_CALL	16)
+    (UNSPEC_TLSGD	17)
+    (UNSPEC_TLSLDM	18)
+    (UNSPEC_DTPREL	19)
+    (UNSPEC_TPREL	20)
+    (UNSPEC_TP		21)
    ])
  
  ;; UNSPEC_VOLATILE:
***************
*** 57,62 ****
--- 66,72 ----
     (UNSPECV_FORCE_MOV	9)
     (UNSPECV_LDGP1	10)
     (UNSPECV_PLDGP2	11)	; prologue ldgp
+    (UNSPECV_SET_TP	12)
    ])
  
  ;; Where necessary, the suffixes _le and _be are used to distinguish between
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 335,340 ****
--- 345,392 ----
    ""
    "")
  
+ (define_insn "*adddi_er_lo16_dtp"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ 		   (match_operand:DI 2 "dtp16_symbolic_operand" "")))]
+   "HAVE_AS_TLS"
+   "lda %0,%2(%1)\t\t!dtprel")
+ 
+ (define_insn "*adddi_er_hi32_dtp"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(plus:DI (match_operand:DI 1 "register_operand" "r")
+ 		 (high:DI (match_operand:DI 2 "dtp32_symbolic_operand" ""))))]
+   "HAVE_AS_TLS"
+   "ldah %0,%2(%1)\t\t!dtprelhi")
+ 
+ (define_insn "*adddi_er_lo32_dtp"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ 		   (match_operand:DI 2 "dtp32_symbolic_operand" "")))]
+   "HAVE_AS_TLS"
+   "lda %0,%2(%1)\t\t!dtprello")
+ 
+ (define_insn "*adddi_er_lo16_tp"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ 		   (match_operand:DI 2 "tp16_symbolic_operand" "")))]
+   "HAVE_AS_TLS"
+   "lda %0,%2(%1)\t\t!tprel")
+ 
+ (define_insn "*adddi_er_hi32_tp"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(plus:DI (match_operand:DI 1 "register_operand" "r")
+ 		 (high:DI (match_operand:DI 2 "tp32_symbolic_operand" ""))))]
+   "HAVE_AS_TLS"
+   "ldah %0,%2(%1)\t\t!tprelhi")
+ 
+ (define_insn "*adddi_er_lo32_tp"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
+ 		   (match_operand:DI 2 "tp32_symbolic_operand" "")))]
+   "HAVE_AS_TLS"
+   "lda %0,%2(%1)\t\t!tprello")
+ 
  (define_insn "*adddi_er_high_l"
    [(set (match_operand:DI 0 "register_operand" "=r")
  	(plus:DI (match_operand:DI 1 "register_operand" "r")
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 4805,4810 ****
--- 4857,4899 ----
    "!TARGET_ABI_WINDOWS_NT"
    "call_pal 0x81"
    [(set_attr "type" "ibr")])
+ 
+ ;; For userland, we load the thread pointer from the TCB.
+ ;; For the kernel, we load the per-cpu private value.
+ 
+ (define_insn "load_tp"
+   [(set (match_operand:DI 0 "register_operand" "=v")
+ 	(unspec:DI [(const_int 0)] UNSPEC_TP))]
+   "TARGET_ABI_OSF"
+ {
+   if (TARGET_TLS_KERNEL)
+     return "call_pal 0x32";
+   else
+     return "call_pal 0x9e";
+ }
+   [(set_attr "type" "ibr")])
+ 
+ ;; For completeness, and possibly a __builtin function, here's how to
+ ;; set the thread pointer.  Since we don't describe enough of this
+ ;; quantity for CSE, we have to use a volatile unspec, and then there's
+ ;; not much point in creating an R16_REG register class.
+ 
+ (define_expand "set_tp"
+   [(set (reg:DI 16) (match_operand:DI 0 "input_operand" ""))
+    (unspec_volatile [(reg:DI 16)] UNSPECV_SET_TP)]
+   "TARGET_ABI_OSF"
+   "")
+ 
+ (define_insn "*set_tp"
+   [(unspec_volatile [(reg:DI 16)] UNSPECV_SET_TP)]
+   "TARGET_ABI_OSF"
+ {
+   if (TARGET_TLS_KERNEL)
+     return "call_pal 0x31";
+   else
+     return "call_pal 0x9f";
+ }
+   [(set_attr "type" "ibr")])
  
  ;; Finally, we have the basic data motion insns.  The byte and word insns
  ;; are done via define_expand.  Start with the floating-point insns, since
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 5282,5287 ****
--- 5371,5445 ----
      }
  })
  
+ (define_insn "movdi_er_tlsgd"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(unspec:DI [(match_operand:DI 1 "register_operand" "r")
+ 		    (match_operand:DI 2 "symbolic_operand" "")
+ 		    (match_operand 3 "const_int_operand" "")]
+ 		   UNSPEC_TLSGD))]
+   "HAVE_AS_TLS"
+ {
+   if (INTVAL (operands[3]) == 0)
+     return "lda %0,%2(%1)\t\t!tlsgd";
+   else
+     return "lda %0,%2(%1)\t\t!tlsgd!%3";
+ })
+ 
+ (define_insn "movdi_er_tlsldm"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(unspec:DI [(match_operand:DI 1 "register_operand" "r")
+ 		    (match_operand 2 "const_int_operand" "")]
+ 		   UNSPEC_TLSLDM))]
+   "HAVE_AS_TLS"
+ {
+   if (INTVAL (operands[2]) == 0)
+     return "lda %0,%&(%1)\t\t!tlsldm";
+   else
+     return "lda %0,%&(%1)\t\t!tlsldm!%2";
+ })
+ 
+ (define_insn "*movdi_er_gotdtp"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(unspec:DI [(match_operand:DI 1 "register_operand" "r")
+ 		    (match_operand:DI 2 "symbolic_operand" "")]
+ 		   UNSPEC_DTPREL))]
+   "HAVE_AS_TLS"
+   "ldq %0,%2(%1)\t\t!gotdtprel"
+   [(set_attr "type" "ild")])
+ 
+ (define_split
+   [(set (match_operand:DI 0 "register_operand" "")
+ 	(match_operand:DI 1 "gotdtp_symbolic_operand" ""))]
+   "HAVE_AS_TLS && reload_completed"
+   [(set (match_dup 0)
+ 	(unspec:DI [(match_dup 2)
+ 		    (match_dup 1)] UNSPEC_DTPREL))]
+ {
+   operands[1] = XVECEXP (XEXP (operands[1], 0), 0, 0);
+   operands[2] = pic_offset_table_rtx;
+ })
+ 
+ (define_insn "*movdi_er_gottp"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(unspec:DI [(match_operand:DI 1 "register_operand" "r")
+ 		    (match_operand:DI 2 "symbolic_operand" "")]
+ 		   UNSPEC_TPREL))]
+   "HAVE_AS_TLS"
+   "ldq %0,%2(%1)\t\t!gottprel"
+   [(set_attr "type" "ild")])
+ 
+ (define_split
+   [(set (match_operand:DI 0 "register_operand" "")
+ 	(match_operand:DI 1 "gottp_symbolic_operand" ""))]
+   "HAVE_AS_TLS && reload_completed"
+   [(set (match_dup 0)
+ 	(unspec:DI [(match_dup 2)
+ 		    (match_dup 1)] UNSPEC_TPREL))]
+ {
+   operands[1] = XVECEXP (XEXP (operands[1], 0), 0, 0);
+   operands[2] = pic_offset_table_rtx;
+ })
+ 
  (define_insn "*movdi_er_nofix"
    [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q")
  	(match_operand:DI 1 "input_operand" "rJ,K,L,T,s,m,rJ,*fJ,Q,*f"))]
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 6720,6726 ****
  	(plus:DI (pc) (const_int 4)))
     (unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE)
     (use (match_operand 3 "" ""))
!    (use (match_operand 4 "const_int_operand" ""))]
    "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
    "jsr $26,(%1),%3%J4"
    [(set_attr "type" "jsr")])
--- 6878,6884 ----
  	(plus:DI (pc) (const_int 4)))
     (unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE)
     (use (match_operand 3 "" ""))
!    (use (match_operand 4 "" ""))]
    "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
    "jsr $26,(%1),%3%J4"
    [(set_attr "type" "jsr")])
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 6740,6745 ****
--- 6898,6967 ----
    [(set_attr "type" "jsr")
     (set_attr "length" "*,*,8")])
  
+ (define_insn_and_split "call_value_osf_tlsgd"
+   [(set (match_operand 0 "" "")
+ 	(call (mem:DI (match_operand:DI 1 "symbolic_operand" ""))
+ 	      (const_int 0)))
+    (unspec [(match_operand:DI 2 "const_int_operand" "")] UNSPEC_TLSGD_CALL)
+    (use (reg:DI 29))
+    (clobber (reg:DI 26))]
+   "HAVE_AS_TLS"
+   "#"
+   "&& reload_completed"
+   [(set (match_dup 3)
+ 	(unspec:DI [(match_dup 5)
+ 		    (match_dup 1)
+ 		    (match_dup 2)] UNSPEC_LITERAL))
+    (parallel [(set (match_dup 0)
+ 		   (call (mem:DI (match_dup 3))
+ 			 (const_int 0)))
+ 	      (set (reg:DI 26) (plus:DI (pc) (const_int 4)))
+ 	      (unspec_volatile [(match_dup 5)] UNSPECV_BLOCKAGE)
+ 	      (use (match_dup 1))
+ 	      (use (unspec [(match_dup 2)] UNSPEC_TLSGD_CALL))])
+    (set (match_dup 5)
+ 	(unspec_volatile:DI [(reg:DI 26) (match_dup 4)] UNSPECV_LDGP1))
+    (set (match_dup 5)
+ 	(unspec:DI [(match_dup 5) (match_dup 4)] UNSPEC_LDGP2))]
+ {
+   operands[3] = gen_rtx_REG (Pmode, 27);
+   operands[4] = GEN_INT (alpha_next_sequence_number++);
+   operands[5] = pic_offset_table_rtx;
+ }
+   [(set_attr "type" "multi")])
+ 
+ (define_insn_and_split "call_value_osf_tlsldm"
+   [(set (match_operand 0 "" "")
+ 	(call (mem:DI (match_operand:DI 1 "symbolic_operand" ""))
+ 	      (const_int 0)))
+    (unspec [(match_operand:DI 2 "const_int_operand" "")] UNSPEC_TLSLDM_CALL)
+    (use (reg:DI 29))
+    (clobber (reg:DI 26))]
+   "HAVE_AS_TLS"
+   "#"
+   "&& reload_completed"
+   [(set (match_dup 3)
+ 	(unspec:DI [(match_dup 5)
+ 		    (match_dup 1)
+ 		    (match_dup 2)] UNSPEC_LITERAL))
+    (parallel [(set (match_dup 0)
+ 		   (call (mem:DI (match_dup 3))
+ 			 (const_int 0)))
+ 	      (set (reg:DI 26) (plus:DI (pc) (const_int 4)))
+ 	      (unspec_volatile [(match_dup 5)] UNSPECV_BLOCKAGE)
+ 	      (use (match_dup 1))
+ 	      (use (unspec [(match_dup 2)] UNSPEC_TLSLDM_CALL))])
+    (set (reg:DI 29)
+ 	(unspec_volatile:DI [(reg:DI 26) (match_dup 4)] UNSPECV_LDGP1))
+    (set (reg:DI 29)
+ 	(unspec:DI [(reg:DI 29) (match_dup 4)] UNSPEC_LDGP2))]
+ {
+   operands[3] = gen_rtx_REG (Pmode, 27);
+   operands[4] = GEN_INT (alpha_next_sequence_number++);
+   operands[5] = pic_offset_table_rtx;
+ }
+   [(set_attr "type" "multi")])
+ 
  (define_insn "*call_value_osf_1"
    [(set (match_operand 0 "" "")
  	(call (mem:DI (match_operand:DI 1 "call_operand" "c,R,s"))
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 6815,6818 ****
    "TARGET_ABI_UNICOSMK"
    "jsr $26,(%1)"
    [(set_attr "type" "jsr")])
- 
--- 7037,7039 ----
Index: gcc/config/alpha/unicosmk.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/unicosmk.h,v
retrieving revision 1.12
diff -c -p -d -r1.12 unicosmk.h
*** gcc/config/alpha/unicosmk.h	18 May 2002 19:27:43 -0000	1.12
--- gcc/config/alpha/unicosmk.h	1 Jun 2002 00:11:16 -0000
*************** do {								\
*** 293,311 ****
  #undef EPILOGUE_USES
  #define EPILOGUE_USES(REGNO)  ((REGNO) == 26 || (REGNO) == 15)
  
- /* Machine-specific function data.  */
- 
- struct machine_function
- {
-   /* List of call information words for calls from this function.  */
-   struct rtx_def *first_ciw;
-   struct rtx_def *last_ciw;
-   int ciw_count;
- 
-   /* List of deferred case vectors.  */
-   struct rtx_def *addr_list;
- };
- 
  /* Would have worked, only the stack doesn't seem to be executable
  #undef TRAMPOLINE_TEMPLATE
  #define TRAMPOLINE_TEMPLATE(FILE)			\
--- 293,298 ----


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