From 5f7b9df841aafadecb9956b3f42d3e2be8044bee Mon Sep 17 00:00:00 2001 From: rth Date: Sat, 1 Jun 2002 00:19:10 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@54125 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 46 ++++ gcc/config/alpha/alpha-protos.h | 6 + gcc/config/alpha/alpha.c | 556 ++++++++++++++++++++++++++++++++++++---- gcc/config/alpha/alpha.h | 34 ++- gcc/config/alpha/alpha.md | 227 +++++++++++++++- gcc/config/alpha/unicosmk.h | 13 - gcc/configure | 48 +++- gcc/configure.in | 22 ++ 8 files changed, 862 insertions(+), 90 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7e5103ee9e1..efd25dd4126 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,49 @@ +2002-05-31 Richard Henderson + + * 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. + 2002-05-31 Zack Weinberg * cppinit.c (append_include_chain): Always pay attention to diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index 2eb195a503d..cbe8e3437b0 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -61,6 +61,12 @@ extern int local_symbolic_operand PARAMS ((rtx, enum machine_mode)); 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)); diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 9681d929e4e..bee3dc1d555 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -69,6 +69,10 @@ enum alpha_fp_rounding_mode alpha_fprm; 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= */ @@ -77,6 +81,7 @@ const char *alpha_tp_string; /* -mtrap-precision=[p|s|i] */ 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. */ @@ -113,6 +118,10 @@ int alpha_this_literal_sequence_number; 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 @@ -125,8 +134,6 @@ static int some_small_symbolic_operand_1 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 @@ -147,6 +154,10 @@ static const char *get_trap_mode_suffix 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 @@ -173,14 +184,12 @@ static void alpha_elf_select_rtx_section 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)); @@ -266,6 +275,9 @@ static void unicosmk_unique_section PARAMS ((tree, int)); #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. */ @@ -385,6 +397,18 @@ override_options () 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); @@ -527,12 +551,10 @@ override_options () /* 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. */ @@ -857,7 +879,9 @@ input_operand (op, mode) symbolic operands to be reconstructed from their high/lo_sum form. */ return (small_symbolic_operand (op, mode) - || global_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. */ @@ -946,29 +970,13 @@ direct_call_operand (op, mode) /* 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; { + const char *str; + if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; @@ -983,7 +991,26 @@ local_symbolic_operand (op, mode) if (GET_CODE (op) != SYMBOL_REF) return 0; - return local_symbol_p (op); + /* 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 @@ -1015,7 +1042,7 @@ small_symbolic_operand (op, mode) else { str = XSTR (op, 0); - return str[0] == '@' && str[1] == 's'; + return str[0] == '@' && str[1] == 'S'; } } @@ -1027,6 +1054,8 @@ global_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; @@ -1038,7 +1067,12 @@ global_symbolic_operand (op, mode) if (GET_CODE (op) != SYMBOL_REF) return 0; - return ! local_symbol_p (op); + 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. */ @@ -1091,6 +1125,110 @@ symbolic_operand (op, mode) 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. */ @@ -1561,6 +1699,54 @@ alpha_tablejump_best_label (insn) 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. */ @@ -1622,7 +1808,8 @@ alpha_encode_section_info (decl, first) int first ATTRIBUTE_UNUSED; { const char *symbol_str; - bool is_local, is_small; + bool is_local; + char encoding = 0; rtx rtl, symbol; rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl); @@ -1659,18 +1846,56 @@ alpha_encode_section_info (decl, first) /* 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); + /* 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 (is_local) + if (encoding) { char *newstr; size_t len; - if (symbol_str[0] == '@') + if (symbol_str[0] == (is_local ? '@' : '%')) { - if (symbol_str[1] == (is_small ? 's' : 'v')) + if (symbol_str[1] == encoding) return; symbol_str += 2; } @@ -1678,18 +1903,12 @@ alpha_encode_section_info (decl, first) len = strlen (symbol_str) + 1; newstr = alloca (len + 2); - newstr[0] = '@'; - newstr[1] = (is_small ? 's' : 'v'); + newstr[0] = (is_local ? '@' : '%'); + newstr[1] = encoding; 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. */ @@ -1698,7 +1917,7 @@ static const char * alpha_strip_name_encoding (str) const char *str; { - if (str[0] == '@') + if (str[0] == '@' || str[0] == '%') str += 2; if (str[0] == '*') str++; @@ -1799,7 +2018,9 @@ alpha_legitimate_address_p (mode, x, strict) return false; /* The symbol must be local. */ - if (local_symbolic_operand (ofs, Pmode)) + if (local_symbolic_operand (ofs, Pmode) + || dtp32_symbolic_operand (ofs, Pmode) + || tp32_symbolic_operand (ofs, Pmode)) return true; } } @@ -1865,6 +2086,100 @@ alpha_legitimize_address (x, scratch, mode) /* 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)) @@ -2589,6 +2904,8 @@ alpha_expand_mov (mode, operands) tmp = alpha_legitimize_address (operands[1], operands[0], mode); if (tmp) { + if (tmp == operands[0]) + return true; operands[1] = tmp; return false; } @@ -4906,10 +5223,31 @@ alpha_multipass_dfa_lookahead () 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. */ -#if TARGET_ABI_UNICOSMK static void alpha_init_machine_status (p) struct function *p; @@ -4917,10 +5255,15 @@ alpha_init_machine_status (p) 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 @@ -4931,8 +5274,10 @@ alpha_mark_machine_status (p) if (machine) { +#if TARGET_ABI_UNICOSMK ggc_mark_rtx (machine->first_ciw); ggc_mark_rtx (machine->addr_list); +#endif } } @@ -4943,7 +5288,6 @@ alpha_free_machine_status (p) free (p->machine); p->machine = NULL; } -#endif /* TARGET_ABI_UNICOSMK */ /* Functions to save and restore alpha_return_addr_rtx. */ @@ -5087,6 +5431,45 @@ get_round_mode_suffix () 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 @@ -5104,6 +5487,10 @@ print_operand (file, x, code) assemble_name (file, alpha_fnname); break; + case '&': + assemble_name (file, get_some_local_dynamic_name ()); + break; + case '/': { const char *trap = get_trap_mode_suffix (); @@ -5145,13 +5532,30 @@ print_operand (file, x, code) 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"); + { + 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': @@ -5385,6 +5789,19 @@ print_operand (file, x, code) 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; @@ -5414,7 +5831,36 @@ print_operand_address (file, addr) if (GET_CODE (addr) == LO_SUM) { - output_addr_const (file, XEXP (addr, 1)); + 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); @@ -5431,7 +5877,7 @@ print_operand_address (file, addr) abort (); fprintf (file, "($%d)\t\t!%s", basereg, - (basereg == 29 ? "gprel" : "gprellow")); + (basereg == 29 ? reloc16 : reloclo)); return; } diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index fc9ba92aaca..94e773295b9 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -137,6 +137,7 @@ extern int target_flags; 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. */ @@ -208,6 +209,10 @@ extern enum alpha_fp_trap_mode alpha_fptm; #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) @@ -251,6 +256,9 @@ extern enum alpha_fp_trap_mode alpha_fptm; #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, @@ -293,6 +301,8 @@ extern enum alpha_fp_trap_mode alpha_fptm; 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, ""} } @@ -316,6 +326,7 @@ extern const char *alpha_fprm_string; /* For -mfp-rounding-mode=[n|m|c|d] */ 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 \ { \ @@ -331,6 +342,8 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */ 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 @@ -681,7 +694,7 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */ class that represents their union. */ enum reg_class { - NO_REGS, R24_REG, R25_REG, R27_REG, + NO_REGS, R0_REG, R24_REG, R25_REG, R27_REG, GENERAL_REGS, FLOAT_REGS, ALL_REGS, LIM_REG_CLASSES }; @@ -690,8 +703,8 @@ enum reg_class { /* Give names of register classes as strings for dump file. */ -#define REG_CLASS_NAMES \ - {"NO_REGS", "R24_REG", "R25_REG", "R27_REG", \ +#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. @@ -700,6 +713,7 @@ enum reg_class { #define REG_CLASS_CONTENTS \ { {0x00000000, 0x00000000}, /* NO_REGS */ \ + {0x00000001, 0x00000000}, /* R0_REG */ \ {0x01000000, 0x00000000}, /* R24_REG */ \ {0x02000000, 0x00000000}, /* R25_REG */ \ {0x08000000, 0x00000000}, /* R27_REG */ \ @@ -713,7 +727,8 @@ enum reg_class { or could index an array. */ #define REGNO_REG_CLASS(REGNO) \ - ((REGNO) == 24 ? R24_REG \ + ((REGNO) == 0 ? R0_REG \ + : (REGNO) == 24 ? R24_REG \ : (REGNO) == 25 ? R25_REG \ : (REGNO) == 27 ? R27_REG \ : (REGNO) >= 32 && (REGNO) <= 62 ? FLOAT_REGS \ @@ -730,6 +745,7 @@ enum reg_class { : (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. */ @@ -1710,7 +1726,7 @@ do { \ #define ASM_OUTPUT_LABELREF(STREAM, NAME) \ do { \ const char *name_ = NAME; \ - if (*name_ == '@') \ + if (*name_ == '@' || *name == '%') \ name_ += 2; \ if (*name_ == '*') \ name_++; \ @@ -1893,7 +1909,7 @@ do { \ #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ ((CODE) == '/' || (CODE) == ',' || (CODE) == '-' || (CODE) == '~' \ - || (CODE) == '#' || (CODE) == '*') + || (CODE) == '#' || (CODE) == '*' || (CODE) == '&') /* Print a memory address as an operand to reference that memory location. */ @@ -1929,6 +1945,12 @@ do { \ {"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}}, \ diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 1df715ad0c2..85e5f4cfcc5 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -1,6 +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. +;; 2000, 2001, 2002 Free Software Foundation, Inc. ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) ;; ;; This file is part of GNU CC. @@ -40,6 +40,15 @@ (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,6 +66,7 @@ (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 @@ -335,6 +345,48 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none" "" "") +(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") @@ -4805,6 +4857,43 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none" "!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 @@ -5282,6 +5371,75 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none" } }) +(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"))] @@ -6720,7 +6878,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none" (plus:DI (pc) (const_int 4))) (unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE) (use (match_operand 3 "" "")) - (use (match_operand 4 "const_int_operand" ""))] + (use (match_operand 4 "" ""))] "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF" "jsr $26,(%1),%3%J4" [(set_attr "type" "jsr")]) @@ -6740,6 +6898,70 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none" [(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")) @@ -6815,4 +7037,3 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi,none" "TARGET_ABI_UNICOSMK" "jsr $26,(%1)" [(set_attr "type" "jsr")]) - diff --git a/gcc/config/alpha/unicosmk.h b/gcc/config/alpha/unicosmk.h index a8c8915d406..d21ba8844c4 100644 --- a/gcc/config/alpha/unicosmk.h +++ b/gcc/config/alpha/unicosmk.h @@ -293,19 +293,6 @@ do { \ #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) \ diff --git a/gcc/configure b/gcc/configure index 5defdaa0a03..e9bdc235b51 100755 --- a/gcc/configure +++ b/gcc/configure @@ -7399,6 +7399,28 @@ conftest_s= tls_first_major= tls_first_minor= case "$target" in + 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-*-*) conftest_s=' .section ".tdata","awT",@progbits @@ -7463,7 +7485,7 @@ case "$target" in # All TARGET_ABI_OSF targets. alpha*-*-osf* | alpha*-*-linux* | alpha*-*-*bsd*) echo $ac_n "checking assembler supports explicit relocations""... $ac_c" 1>&6 -echo "configure:7467: checking assembler supports explicit relocations" >&5 +echo "configure:7489: checking assembler supports explicit relocations" >&5 if eval "test \"`echo '$''{'gcc_cv_as_explicit_relocs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7513,7 +7535,7 @@ EOF ;; sparc*-*-*) echo $ac_n "checking assembler .register pseudo-op support""... $ac_c" 1>&6 -echo "configure:7517: checking assembler .register pseudo-op support" >&5 +echo "configure:7539: checking assembler .register pseudo-op support" >&5 if eval "test \"`echo '$''{'gcc_cv_as_register_pseudo_op'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7541,7 +7563,7 @@ EOF fi echo $ac_n "checking assembler supports -relax""... $ac_c" 1>&6 -echo "configure:7545: checking assembler supports -relax" >&5 +echo "configure:7567: checking assembler supports -relax" >&5 if eval "test \"`echo '$''{'gcc_cv_as_relax_opt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7569,7 +7591,7 @@ EOF fi echo $ac_n "checking assembler and linker support unaligned pc related relocs""... $ac_c" 1>&6 -echo "configure:7573: checking assembler and linker support unaligned pc related relocs" >&5 +echo "configure:7595: checking assembler and linker support unaligned pc related relocs" >&5 if eval "test \"`echo '$''{'gcc_cv_as_sparc_ua_pcrel'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7596,7 +7618,7 @@ EOF fi echo $ac_n "checking assembler and linker support unaligned pc related relocs against hidden symbols""... $ac_c" 1>&6 -echo "configure:7600: checking assembler and linker support unaligned pc related relocs against hidden symbols" >&5 +echo "configure:7622: checking assembler and linker support unaligned pc related relocs against hidden symbols" >&5 if eval "test \"`echo '$''{'gcc_cv_as_sparc_ua_pcrel_hidden'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7637,7 +7659,7 @@ EOF if test "x$gcc_cv_as_flags64" != xno; then echo $ac_n "checking for assembler offsetable %lo() support""... $ac_c" 1>&6 -echo "configure:7641: checking for assembler offsetable %lo() support" >&5 +echo "configure:7663: checking for assembler offsetable %lo() support" >&5 if eval "test \"`echo '$''{'gcc_cv_as_offsetable_lo10'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7677,7 +7699,7 @@ EOF i[34567]86-*-* | x86_64-*-*) echo $ac_n "checking assembler instructions""... $ac_c" 1>&6 -echo "configure:7681: checking assembler instructions" >&5 +echo "configure:7703: checking assembler instructions" >&5 gcc_cv_as_instructions= if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 9 -o "$gcc_cv_gas_major_version" -gt 2; then @@ -7704,7 +7726,7 @@ EOF echo "$ac_t""$gcc_cv_as_instructions" 1>&6 echo $ac_n "checking assembler GOTOFF in data directives""... $ac_c" 1>&6 -echo "configure:7708: checking assembler GOTOFF in data directives" >&5 +echo "configure:7730: checking assembler GOTOFF in data directives" >&5 gcc_cv_as_gotoff_in_data=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x then @@ -7734,7 +7756,7 @@ EOF esac echo $ac_n "checking assembler dwarf2 debug_line support""... $ac_c" 1>&6 -echo "configure:7738: checking assembler dwarf2 debug_line support" >&5 +echo "configure:7760: checking assembler dwarf2 debug_line support" >&5 gcc_cv_as_dwarf2_debug_line=no # ??? Not all targets support dwarf2 debug_line, even within a version # of gas. Moreover, we need to emit a valid instruction to trigger any @@ -7790,7 +7812,7 @@ fi echo "$ac_t""$gcc_cv_as_dwarf2_debug_line" 1>&6 echo $ac_n "checking assembler --gdwarf2 support""... $ac_c" 1>&6 -echo "configure:7794: checking assembler --gdwarf2 support" >&5 +echo "configure:7816: checking assembler --gdwarf2 support" >&5 gcc_cv_as_gdwarf2_flag=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then @@ -7819,7 +7841,7 @@ fi echo "$ac_t""$gcc_cv_as_gdwarf2_flag" 1>&6 echo $ac_n "checking assembler --gstabs support""... $ac_c" 1>&6 -echo "configure:7823: checking assembler --gstabs support" >&5 +echo "configure:7845: checking assembler --gstabs support" >&5 gcc_cv_as_gstabs_flag=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then @@ -7847,7 +7869,7 @@ fi echo "$ac_t""$gcc_cv_as_gstabs_flag" 1>&6 echo $ac_n "checking linker PT_GNU_EH_FRAME support""... $ac_c" 1>&6 -echo "configure:7851: checking linker PT_GNU_EH_FRAME support" >&5 +echo "configure:7873: checking linker PT_GNU_EH_FRAME support" >&5 gcc_cv_ld_eh_frame_hdr=no if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 12 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then @@ -8010,7 +8032,7 @@ fi echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 -echo "configure:8014: checking whether to enable maintainer-specific portions of Makefiles" >&5 +echo "configure:8036: checking whether to enable maintainer-specific portions of Makefiles" >&5 # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then enableval="$enable_maintainer_mode" diff --git a/gcc/configure.in b/gcc/configure.in index a76dac824f0..c28efa0e620 100644 --- a/gcc/configure.in +++ b/gcc/configure.in @@ -1725,6 +1725,28 @@ tls_first_major= 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=' -- 2.11.4.GIT