From fd3cd001d57652cb50451eaa7763e1bd29bac8c4 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Fri, 24 Jan 2003 17:10:22 +0000 Subject: [PATCH] configure.in (HAVE_AS_TLS): Add s390-*-* and s390x-*-* cases. * configure.in (HAVE_AS_TLS): Add s390-*-* and s390x-*-* cases. * configure: Regenerate. * config/s390/s390-protos.h (tls_symbolic_operand): Add prototype. (tls_symbolic_reference_mentioned_p): Add prototype. (s390_tls_get_offset): Add prototype. (emit_pic_move): Remove prototype, replace by ... (emit_symbolic_move): .. this new prototype. * config/s390/s390.c (TARGET_HAVE_TLS): Conditionally define. (tls_model_chars): New global variable. (s390_encode_section_info): Encode TLS model. Use targetm.binds_local_p to check for local symbols. (s390_strip_name_encoding): New function. (TARGET_STRIP_NAME_ENCODING): Define. (get_thread_pointer): New function. (legitimize_tls_address): New function. (legitimize_address): Call it. (emit_pic_move): Remove, replace by ... (emit_symbolic_move): ... this new function. (larl_operand): Handle TLS operands. (legitimate_constant_p): Likewise. (s390_decompose_address): Likewise. (s390_cannot_force_const_mem): New function. (TARGET_CANNOT_FORCE_CONST_MEM): Define. (s390_output_symbolic_const): Handle TLS unspecs. (print_operand): New code 'J'. (machine_function): Add struct member 'some_ld_name'. (get_some_local_dynamic_name, get_some_local_dynamic_name_1): New. (enum s390_builtin): New type. (code_for_builtin_64, code_for_builtin_31): New global variables. (s390_init_builtins, s390_expand_builtin): New functions. (TARGET_INIT_BUILTINS, TARGET_EXPAND_BUILTIN): Define. * config/s390/s390.h (TLS_SYMBOLIC_CONST): New macro. (ASM_OUTPUT_LABELREF): Define. (ASM_OUTPUT_SPECIAL_POOL_ENTRY): Handle TLS constants. * config/s390/s390.md: Define TLS UNSPEC constants. ("movdi", "movsi"): Handle TLS operands. ("get_tp_64", "get_tp_31", "set_tp_64", "set_tp_31"): New insns. ("*tls_load_64", "*tls_load_31"): New insns. ("call_value_tls", "call_value_tls_exp"): New expanders. ("brasl_tls", "bras_tls", "basr_tls_64", "basr_tls_31", "bas_tls_64", "bas_tls_31"): New insns. From-SVN: r61714 --- gcc/ChangeLog | 52 +++ gcc/config/s390/s390-protos.h | 5 +- gcc/config/s390/s390.c | 707 ++++++++++++++++++++++++++++++++-- gcc/config/s390/s390.h | 15 +- gcc/config/s390/s390.md | 230 ++++++++++- gcc/configure | 65 +++- gcc/configure.in | 35 ++ 7 files changed, 1044 insertions(+), 65 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index befde2e1760..f054621f384 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,55 @@ +2003-01-24 Ulrich Weigand + + * configure.in (HAVE_AS_TLS): Add s390-*-* and s390x-*-* cases. + * configure: Regenerate. + + * config/s390/s390-protos.h (tls_symbolic_operand): Add prototype. + (tls_symbolic_reference_mentioned_p): Add prototype. + (s390_tls_get_offset): Add prototype. + (emit_pic_move): Remove prototype, replace by ... + (emit_symbolic_move): .. this new prototype. + + * config/s390/s390.c (TARGET_HAVE_TLS): Conditionally define. + (tls_model_chars): New global variable. + (s390_encode_section_info): Encode TLS model. + Use targetm.binds_local_p to check for local symbols. + (s390_strip_name_encoding): New function. + (TARGET_STRIP_NAME_ENCODING): Define. + + (get_thread_pointer): New function. + (legitimize_tls_address): New function. + (legitimize_address): Call it. + (emit_pic_move): Remove, replace by ... + (emit_symbolic_move): ... this new function. + + (larl_operand): Handle TLS operands. + (legitimate_constant_p): Likewise. + (s390_decompose_address): Likewise. + (s390_cannot_force_const_mem): New function. + (TARGET_CANNOT_FORCE_CONST_MEM): Define. + + (s390_output_symbolic_const): Handle TLS unspecs. + (print_operand): New code 'J'. + (machine_function): Add struct member 'some_ld_name'. + (get_some_local_dynamic_name, get_some_local_dynamic_name_1): New. + + (enum s390_builtin): New type. + (code_for_builtin_64, code_for_builtin_31): New global variables. + (s390_init_builtins, s390_expand_builtin): New functions. + (TARGET_INIT_BUILTINS, TARGET_EXPAND_BUILTIN): Define. + + * config/s390/s390.h (TLS_SYMBOLIC_CONST): New macro. + (ASM_OUTPUT_LABELREF): Define. + (ASM_OUTPUT_SPECIAL_POOL_ENTRY): Handle TLS constants. + + * config/s390/s390.md: Define TLS UNSPEC constants. + ("movdi", "movsi"): Handle TLS operands. + ("get_tp_64", "get_tp_31", "set_tp_64", "set_tp_31"): New insns. + ("*tls_load_64", "*tls_load_31"): New insns. + ("call_value_tls", "call_value_tls_exp"): New expanders. + ("brasl_tls", "bras_tls", "basr_tls_64", "basr_tls_31", + "bas_tls_64", "bas_tls_31"): New insns. + 2003-01-24 Nathan Sidwell * config/rs6000/rs6000.c (rs6000_parse_abi_options): Make sure diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 0784a16b39f..3e315dd369a 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -43,11 +43,14 @@ extern int s390_single_hi PARAMS ((rtx, enum machine_mode, int)); extern int s390_extract_hi PARAMS ((rtx, enum machine_mode, int)); extern int s390_single_qi PARAMS ((rtx, enum machine_mode, int)); extern int s390_extract_qi PARAMS ((rtx, enum machine_mode, int)); +extern int tls_symbolic_operand PARAMS ((rtx)); extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode)); extern enum machine_mode s390_tm_ccmode PARAMS ((rtx, rtx, int)); extern enum machine_mode s390_select_ccmode PARAMS ((enum rtx_code, rtx, rtx)); extern int symbolic_reference_mentioned_p PARAMS ((rtx)); +extern int tls_symbolic_reference_mentioned_p PARAMS ((rtx)); +extern rtx s390_tls_get_offset PARAMS ((void)); extern int legitimate_la_operand_p PARAMS ((rtx)); extern int preferred_la_operand_p PARAMS ((rtx)); extern int legitimate_pic_operand_p PARAMS ((rtx)); @@ -60,7 +63,7 @@ extern enum reg_class s390_preferred_reload_class PARAMS ((rtx, enum reg_class)) extern enum reg_class s390_secondary_input_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx)); extern int s390_plus_operand PARAMS ((rtx, enum machine_mode)); extern void s390_expand_plus_operand PARAMS ((rtx, rtx, rtx)); -extern void emit_pic_move PARAMS ((rtx *, enum machine_mode)); +extern void emit_symbolic_move PARAMS ((rtx *)); extern void s390_load_address PARAMS ((rtx, rtx)); extern void s390_expand_movstr PARAMS ((rtx, rtx, rtx)); extern void s390_expand_clrstr PARAMS ((rtx, rtx)); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 8bea2edcd9d..b22c9c420d9 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -54,6 +54,11 @@ static bool s390_assemble_integer PARAMS ((rtx, unsigned int, int)); static void s390_select_rtx_section PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT)); static void s390_encode_section_info PARAMS ((tree, int)); +static const char *s390_strip_name_encoding PARAMS ((const char *)); +static bool s390_cannot_force_const_mem PARAMS ((rtx)); +static void s390_init_builtins PARAMS ((void)); +static rtx s390_expand_builtin PARAMS ((tree, rtx, rtx, + enum machine_mode, int)); static void s390_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree)); static enum attr_type s390_safe_attr_type PARAMS ((rtx)); @@ -81,6 +86,20 @@ static int s390_use_dfa_pipeline_interface PARAMS ((void)); #undef TARGET_ENCODE_SECTION_INFO #define TARGET_ENCODE_SECTION_INFO s390_encode_section_info +#undef TARGET_STRIP_NAME_ENCODING +#define TARGET_STRIP_NAME_ENCODING s390_strip_name_encoding + +#ifdef HAVE_AS_TLS +#undef TARGET_HAVE_TLS +#define TARGET_HAVE_TLS true +#endif +#undef TARGET_CANNOT_FORCE_CONST_MEM +#define TARGET_CANNOT_FORCE_CONST_MEM s390_cannot_force_const_mem + +#undef TARGET_INIT_BUILTINS +#define TARGET_INIT_BUILTINS s390_init_builtins +#undef TARGET_EXPAND_BUILTIN +#define TARGET_EXPAND_BUILTIN s390_expand_builtin #undef TARGET_ASM_OUTPUT_MI_THUNK #define TARGET_ASM_OUTPUT_MI_THUNK s390_output_mi_thunk @@ -106,6 +125,9 @@ static int s390_sr_alias_set = 0; emitted. */ rtx s390_compare_op0, s390_compare_op1; +/* The encoding characters for the four TLS models present in ELF. */ +static char const tls_model_chars[] = " GLil"; + /* Structure used to hold the components of a S/390 memory address. A legitimate address on S/390 is of the general form @@ -149,6 +171,9 @@ struct machine_function GTY(()) /* Size of stack frame. */ HOST_WIDE_INT frame_size; + + /* Some local-dynamic TLS symbol name. */ + const char *some_ld_name; }; static int s390_match_ccmode_set PARAMS ((rtx, enum machine_mode)); @@ -157,6 +182,10 @@ static const char *s390_branch_condition_mnemonic PARAMS ((rtx, int)); static int check_mode PARAMS ((rtx, enum machine_mode *)); static int general_s_operand PARAMS ((rtx, enum machine_mode, int)); static int s390_decompose_address PARAMS ((rtx, struct s390_address *)); +static rtx get_thread_pointer PARAMS ((void)); +static rtx legitimize_tls_address PARAMS ((rtx, rtx)); +static const char *get_some_local_dynamic_name PARAMS ((void)); +static int get_some_local_dynamic_name_1 PARAMS ((rtx *, void *)); static int reg_used_in_mem_p PARAMS ((int, rtx)); static int addr_generation_dependency_p PARAMS ((rtx, rtx)); static int s390_split_branches PARAMS ((rtx, bool *)); @@ -1012,6 +1041,7 @@ larl_operand (op, mode) if (GET_CODE (op) == LABEL_REF) return 1; if (GET_CODE (op) == SYMBOL_REF + && !tls_symbolic_operand (op) && (!flag_pic || SYMBOL_REF_FLAG (op) || CONSTANT_POOL_ADDRESS_P (op))) return 1; @@ -1034,17 +1064,22 @@ larl_operand (op, mode) if (GET_CODE (op) == LABEL_REF) return 1; if (GET_CODE (op) == SYMBOL_REF + && !tls_symbolic_operand (op) && (!flag_pic || SYMBOL_REF_FLAG (op) || CONSTANT_POOL_ADDRESS_P (op))) return 1; - /* Now we must have a @GOTENT offset or @PLT stub. */ + /* Now we must have a @GOTENT offset or @PLT stub + or an @INDNTPOFF TLS offset. */ if (GET_CODE (op) == UNSPEC && XINT (op, 1) == 111) return 1; if (GET_CODE (op) == UNSPEC && XINT (op, 1) == 113) return 1; + if (GET_CODE (op) == UNSPEC + && XINT (op, 1) == UNSPEC_INDNTPOFF) + return 1; return 0; } @@ -1193,6 +1228,23 @@ bras_sym_operand (op, mode) return 0; } +/* If OP is a SYMBOL_REF of a thread-local symbol, return its TLS mode, + otherwise return 0. */ + +int +tls_symbolic_operand (op) + register rtx op; +{ + const char *symbol_str; + + if (GET_CODE (op) != SYMBOL_REF) + return 0; + symbol_str = XSTR (op, 0); + + if (symbol_str[0] != '%') + return 0; + return strchr (tls_model_chars, symbol_str[1]) - tls_model_chars; +} /* Return true if OP is a load multiple operation. It is known to be a PARALLEL and the first section will be tested. @@ -1352,6 +1404,37 @@ symbolic_reference_mentioned_p (op) return 0; } +/* Return true if OP contains a reference to a thread-local symbol. */ + +int +tls_symbolic_reference_mentioned_p (op) + rtx op; +{ + register const char *fmt; + register int i; + + if (GET_CODE (op) == SYMBOL_REF) + return tls_symbolic_operand (op); + + fmt = GET_RTX_FORMAT (GET_CODE (op)); + for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--) + { + if (fmt[i] == 'E') + { + register int j; + + for (j = XVECLEN (op, i) - 1; j >= 0; j--) + if (tls_symbolic_reference_mentioned_p (XVECEXP (op, i, j))) + return 1; + } + + else if (fmt[i] == 'e' && tls_symbolic_reference_mentioned_p (XEXP (op, i))) + return 1; + } + + return 0; +} + /* Return true if OP is a legitimate general operand when generating PIC code. It is given that flag_pic is on @@ -1366,7 +1449,7 @@ legitimate_pic_operand_p (op) return 1; /* Reject everything else; must be handled - via emit_pic_move. */ + via emit_symbolic_move. */ return 0; } @@ -1381,22 +1464,87 @@ legitimate_constant_p (op) if (!SYMBOLIC_CONST (op)) return 1; - /* In the PIC case, symbolic constants must *not* be - forced into the literal pool. We accept them here, - so that they will be handled by emit_pic_move. */ - if (flag_pic) + /* Accept immediate LARL operands. */ + if (TARGET_64BIT && larl_operand (op, VOIDmode)) return 1; - /* Even in the non-PIC case, we can accept immediate - LARL operands here. */ - if (TARGET_64BIT) - return larl_operand (op, VOIDmode); + /* Thread-local symbols are never legal constants. This is + so that emit_call knows that computing such addresses + might require a function call. */ + if (TLS_SYMBOLIC_CONST (op)) + return 0; + + /* In the PIC case, symbolic constants must *not* be + forced into the literal pool. We accept them here, + so that they will be handled by emit_symbolic_move. */ + if (flag_pic) + return 1; /* All remaining non-PIC symbolic constants are forced into the literal pool. */ return 0; } +/* Determine if it's legal to put X into the constant pool. This + is not possible if X contains the address of a symbol that is + not constant (TLS) or not known at final link time (PIC). */ + +static bool +s390_cannot_force_const_mem (x) + rtx x; +{ + switch (GET_CODE (x)) + { + case CONST_INT: + case CONST_DOUBLE: + /* Accept all non-symbolic constants. */ + return false; + + case LABEL_REF: + /* Labels are OK iff we are non-PIC. */ + return flag_pic != 0; + + case SYMBOL_REF: + /* 'Naked' TLS symbol references are never OK, + non-TLS symbols are OK iff we are non-PIC. */ + if (tls_symbolic_operand (x)) + return true; + else + return flag_pic != 0; + + case CONST: + return s390_cannot_force_const_mem (XEXP (x, 0)); + case PLUS: + case MINUS: + return s390_cannot_force_const_mem (XEXP (x, 0)) + || s390_cannot_force_const_mem (XEXP (x, 1)); + + case UNSPEC: + switch (XINT (x, 1)) + { + /* Only lt-relative or GOT-relative UNSPECs are OK. */ + case 100: + case 104: + case 112: + case 114: + case UNSPEC_TLSGD: + case UNSPEC_TLSLDM: + case UNSPEC_NTPOFF: + case UNSPEC_DTPOFF: + case UNSPEC_GOTNTPOFF: + case UNSPEC_INDNTPOFF: + return false; + + default: + return true; + } + break; + + default: + abort (); + } +} + /* Returns true if the constant value OP is a legitimate general operand during and after reload. The difference to legitimate_constant_p is that this function will not accept @@ -1726,10 +1874,11 @@ s390_decompose_address (addr, out) } /* In the small-PIC case, the linker converts @GOT12 - offsets to possible displacements. */ + and @GOTNTPOFF offsets to possible displacements. */ else if (GET_CODE (disp) == CONST && GET_CODE (XEXP (disp, 0)) == UNSPEC - && XINT (XEXP (disp, 0), 1) == 110) + && (XINT (XEXP (disp, 0), 1) == 110 + || XINT (XEXP (disp, 0), 1) == UNSPEC_GOTNTPOFF)) { if (flag_pic != 1) return FALSE; @@ -1779,12 +1928,6 @@ s390_decompose_address (addr, out) || !CONSTANT_POOL_ADDRESS_P (disp)) return FALSE; - /* In 64-bit PIC mode we cannot accept symbolic - constants in the constant pool. */ - if (TARGET_64BIT && flag_pic - && SYMBOLIC_CONST (get_pool_constant (disp))) - return FALSE; - /* If we have an offset, make sure it does not exceed the size of the constant pool entry. */ if (offset && offset >= GET_MODE_SIZE (get_pool_mode (disp))) @@ -2196,18 +2339,237 @@ legitimize_pic_address (orig, reg) return new; } +/* Load the thread pointer into a register. */ + +static rtx +get_thread_pointer () +{ + rtx tp; + + tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP); + tp = force_reg (Pmode, tp); + mark_reg_pointer (tp, BITS_PER_WORD); + + return tp; +} + +/* Construct the SYMBOL_REF for the tls_get_offset function. */ + +static GTY(()) rtx s390_tls_symbol; +rtx +s390_tls_get_offset () +{ + if (!s390_tls_symbol) + s390_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_offset"); + + return s390_tls_symbol; +} + +/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute + this (thread-local) address. REG may be used as temporary. */ + +static rtx +legitimize_tls_address (addr, reg) + rtx addr; + rtx reg; +{ + rtx new, tls_call, temp, base, r2, insn; + + if (GET_CODE (addr) == SYMBOL_REF) + switch (tls_symbolic_operand (addr)) + { + case TLS_MODEL_GLOBAL_DYNAMIC: + start_sequence (); + r2 = gen_rtx_REG (Pmode, 2); + tls_call = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_TLSGD); + new = gen_rtx_CONST (Pmode, tls_call); + new = force_const_mem (Pmode, new); + emit_move_insn (r2, new); + emit_call_insn (gen_call_value_tls (r2, tls_call)); + insn = get_insns (); + end_sequence (); + + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_NTPOFF); + temp = gen_reg_rtx (Pmode); + emit_libcall_block (insn, temp, r2, new); + + new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp); + if (reg != 0) + { + s390_load_address (reg, new); + new = reg; + } + break; + + case TLS_MODEL_LOCAL_DYNAMIC: + start_sequence (); + r2 = gen_rtx_REG (Pmode, 2); + tls_call = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TLSLDM); + new = gen_rtx_CONST (Pmode, tls_call); + new = force_const_mem (Pmode, new); + emit_move_insn (r2, new); + emit_call_insn (gen_call_value_tls (r2, tls_call)); + insn = get_insns (); + end_sequence (); + + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TLSLDM_NTPOFF); + temp = gen_reg_rtx (Pmode); + emit_libcall_block (insn, temp, r2, new); + + new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp); + base = gen_reg_rtx (Pmode); + s390_load_address (base, new); + + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_DTPOFF); + new = gen_rtx_CONST (Pmode, new); + new = force_const_mem (Pmode, new); + temp = gen_reg_rtx (Pmode); + emit_move_insn (temp, new); + + new = gen_rtx_PLUS (Pmode, base, temp); + if (reg != 0) + { + s390_load_address (reg, new); + new = reg; + } + break; + + case TLS_MODEL_INITIAL_EXEC: + if (flag_pic == 1) + { + /* Assume GOT offset < 4k. This is handled the same way + in both 31- and 64-bit code. */ + + if (reload_in_progress || reload_completed) + regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1; + + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTNTPOFF); + new = gen_rtx_CONST (Pmode, new); + new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new); + new = gen_rtx_MEM (Pmode, new); + RTX_UNCHANGING_P (new) = 1; + temp = gen_reg_rtx (Pmode); + emit_move_insn (temp, new); + } + else if (TARGET_64BIT) + { + /* If the GOT offset might be >= 4k, we determine the position + of the GOT entry via a PC-relative LARL. */ + + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_INDNTPOFF); + new = gen_rtx_CONST (Pmode, new); + temp = gen_reg_rtx (Pmode); + emit_move_insn (temp, new); + + new = gen_rtx_MEM (Pmode, temp); + RTX_UNCHANGING_P (new) = 1; + temp = gen_reg_rtx (Pmode); + emit_move_insn (temp, new); + } + else if (flag_pic) + { + /* If the GOT offset might be >= 4k, we have to load it + from the literal pool. */ + + if (reload_in_progress || reload_completed) + regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1; + + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTNTPOFF); + new = gen_rtx_CONST (Pmode, new); + new = force_const_mem (Pmode, new); + temp = gen_reg_rtx (Pmode); + emit_move_insn (temp, new); + + new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp); + new = gen_rtx_MEM (Pmode, new); + RTX_UNCHANGING_P (new) = 1; + + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new, addr), UNSPEC_TLS_LOAD); + temp = gen_reg_rtx (Pmode); + emit_insn (gen_rtx_SET (Pmode, temp, new)); + } + else + { + /* In position-dependent code, load the absolute address of + the GOT entry from the literal pool. */ + + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_INDNTPOFF); + new = gen_rtx_CONST (Pmode, new); + new = force_const_mem (Pmode, new); + temp = gen_reg_rtx (Pmode); + emit_move_insn (temp, new); + + new = temp; + new = gen_rtx_MEM (Pmode, new); + RTX_UNCHANGING_P (new) = 1; + + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new, addr), UNSPEC_TLS_LOAD); + temp = gen_reg_rtx (Pmode); + emit_insn (gen_rtx_SET (Pmode, temp, new)); + } + + new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp); + if (reg != 0) + { + s390_load_address (reg, new); + new = reg; + } + break; + + case TLS_MODEL_LOCAL_EXEC: + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_NTPOFF); + new = gen_rtx_CONST (Pmode, new); + new = force_const_mem (Pmode, new); + temp = gen_reg_rtx (Pmode); + emit_move_insn (temp, new); + + new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp); + if (reg != 0) + { + s390_load_address (reg, new); + new = reg; + } + break; + + default: + abort (); + } + + else if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == UNSPEC) + { + switch (XINT (XEXP (addr, 0), 1)) + { + case UNSPEC_INDNTPOFF: + if (TARGET_64BIT) + new = addr; + else + abort (); + break; + + default: + abort (); + } + } + + else + abort (); /* for now ... */ + + return new; +} + /* Emit insns to move operands[1] into operands[0]. */ void -emit_pic_move (operands, mode) +emit_symbolic_move (operands) rtx *operands; - enum machine_mode mode ATTRIBUTE_UNUSED; { rtx temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); - if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1])) + if (GET_CODE (operands[0]) == MEM) operands[1] = force_reg (Pmode, operands[1]); - else + else if (TLS_SYMBOLIC_CONST (operands[1])) + operands[1] = legitimize_tls_address (operands[1], temp); + else if (flag_pic) operands[1] = legitimize_pic_address (operands[1], temp); } @@ -2230,7 +2592,14 @@ legitimize_address (x, oldx, mode) { rtx constant_term = const0_rtx; - if (flag_pic) + if (TLS_SYMBOLIC_CONST (x)) + { + x = legitimize_tls_address (x, 0); + + if (legitimate_address_p (mode, x, FALSE)) + return x; + } + else if (flag_pic) { if (SYMBOLIC_CONST (x) || (GET_CODE (x) == PLUS @@ -2642,6 +3011,48 @@ s390_simplify_dwarf_addr (orig_x) return orig_x; } +/* Locate some local-dynamic symbol still in use by this function + so that we can print its name in local-dynamic base patterns. */ + +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 && CONSTANT_POOL_ADDRESS_P (x)) + { + x = get_pool_constant (x); + return for_each_rtx (&x, get_some_local_dynamic_name_1, 0); + } + + if (GET_CODE (x) == SYMBOL_REF + && tls_symbolic_operand (x) == TLS_MODEL_LOCAL_DYNAMIC) + { + cfun->machine->some_ld_name = XSTR (x, 0); + return 1; + } + + return 0; +} + /* Output symbolic constant X in assembler syntax to stdio stream FILE. */ @@ -2714,6 +3125,30 @@ s390_output_symbolic_const (file, x) fprintf (file, "@PLT-"); s390_output_symbolic_const (file, cfun->machine->literal_pool_label); break; + case UNSPEC_TLSGD: + s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); + fprintf (file, "@TLSGD"); + break; + case UNSPEC_TLSLDM: + assemble_name (file, get_some_local_dynamic_name ()); + fprintf (file, "@TLSLDM"); + break; + case UNSPEC_DTPOFF: + s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); + fprintf (file, "@DTPOFF"); + break; + case UNSPEC_NTPOFF: + s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); + fprintf (file, "@NTPOFF"); + break; + case UNSPEC_GOTNTPOFF: + s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); + fprintf (file, "@GOTNTPOFF"); + break; + case UNSPEC_INDNTPOFF: + s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); + fprintf (file, "@INDNTPOFF"); + break; default: output_operand_lossage ("invalid UNSPEC as operand (2)"); break; @@ -2759,6 +3194,7 @@ print_operand_address (file, addr) 'C': print opcode suffix for branch condition. 'D': print opcode suffix for inverse branch condition. + 'J': print tls_load/tls_gdcall/tls_ldcall suffix 'O': print only the displacement of a memory reference. 'R': print only the base register of a memory reference. 'N': print the second word of a DImode operand. @@ -2784,6 +3220,26 @@ print_operand (file, x, code) fprintf (file, s390_branch_condition_mnemonic (x, TRUE)); return; + case 'J': + if (GET_CODE (x) == SYMBOL_REF) + { + fprintf (file, "%s", ":tls_load:"); + output_addr_const (file, x); + } + else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSGD) + { + fprintf (file, "%s", ":tls_gdcall:"); + output_addr_const (file, XVECEXP (x, 0, 0)); + } + else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSLDM) + { + fprintf (file, "%s", ":tls_ldcall:"); + assemble_name (file, get_some_local_dynamic_name ()); + } + else + abort (); + return; + case 'O': { struct s390_address ad; @@ -5530,6 +5986,134 @@ s390_va_arg (valist, type) } +/* Builtins. */ + +enum s390_builtin +{ + S390_BUILTIN_THREAD_POINTER, + S390_BUILTIN_SET_THREAD_POINTER, + + S390_BUILTIN_max +}; + +static unsigned int const code_for_builtin_64[S390_BUILTIN_max] = { + CODE_FOR_get_tp_64, + CODE_FOR_set_tp_64 +}; + +static unsigned int const code_for_builtin_31[S390_BUILTIN_max] = { + CODE_FOR_get_tp_31, + CODE_FOR_set_tp_31 +}; + +static void +s390_init_builtins () +{ + tree ftype; + + ftype = build_function_type (ptr_type_node, void_list_node); + builtin_function ("__builtin_thread_pointer", ftype, + S390_BUILTIN_THREAD_POINTER, BUILT_IN_MD, + NULL, NULL_TREE); + + ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); + builtin_function ("__builtin_set_thread_pointer", ftype, + S390_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD, + NULL, NULL_TREE); +} + +/* Expand an expression EXP that calls a built-in function, + with result going to TARGET if that's convenient + (and in mode MODE if that's convenient). + SUBTARGET may be used as the target for computing one of EXP's operands. + IGNORE is nonzero if the value is to be ignored. */ + +static rtx +s390_expand_builtin (exp, target, subtarget, mode, ignore) + tree exp; + rtx target; + rtx subtarget ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; + int ignore ATTRIBUTE_UNUSED; +{ +#define MAX_ARGS 2 + + unsigned int const *code_for_builtin = + TARGET_64BIT ? code_for_builtin_64 : code_for_builtin_31; + + tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + unsigned int fcode = DECL_FUNCTION_CODE (fndecl); + tree arglist = TREE_OPERAND (exp, 1); + enum insn_code icode; + rtx op[MAX_ARGS], pat; + int arity; + bool nonvoid; + + if (fcode >= S390_BUILTIN_max) + internal_error ("bad builtin fcode"); + icode = code_for_builtin[fcode]; + if (icode == 0) + internal_error ("bad builtin fcode"); + + nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node; + + for (arglist = TREE_OPERAND (exp, 1), arity = 0; + arglist; + arglist = TREE_CHAIN (arglist), arity++) + { + const struct insn_operand_data *insn_op; + + tree arg = TREE_VALUE (arglist); + if (arg == error_mark_node) + return NULL_RTX; + if (arity > MAX_ARGS) + return NULL_RTX; + + insn_op = &insn_data[icode].operand[arity + nonvoid]; + + op[arity] = expand_expr (arg, NULL_RTX, insn_op->mode, 0); + + if (!(*insn_op->predicate) (op[arity], insn_op->mode)) + op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]); + } + + if (nonvoid) + { + enum machine_mode tmode = insn_data[icode].operand[0].mode; + if (!target + || GET_MODE (target) != tmode + || !(*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + } + + switch (arity) + { + case 0: + pat = GEN_FCN (icode) (target); + break; + case 1: + if (nonvoid) + pat = GEN_FCN (icode) (target, op[0]); + else + pat = GEN_FCN (icode) (op[0]); + break; + case 2: + pat = GEN_FCN (icode) (target, op[0], op[1]); + break; + default: + abort (); + } + if (!pat) + return NULL_RTX; + emit_insn (pat); + + if (nonvoid) + return target; + else + return const0_rtx; +} + + /* Output assembly code for the trampoline template to stdio stream FILE. @@ -5689,28 +6273,85 @@ s390_select_rtx_section (mode, x, align) function_section (current_function_decl); } -/* If using PIC, mark a SYMBOL_REF for a non-global symbol so that we - may access it directly in the GOT. */ +/* Encode symbol attributes (local vs. global, tls model) of a SYMBOL_REF + into its name and SYMBOL_REF_FLAG. */ static void s390_encode_section_info (decl, first) tree decl; int first ATTRIBUTE_UNUSED; { - if (flag_pic) - { - rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd' - ? TREE_CST_RTL (decl) : DECL_RTL (decl)); + bool local_p = (*targetm.binds_local_p) (decl); + rtx rtl, symbol; - if (GET_CODE (rtl) == MEM) + rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl); + if (GET_CODE (rtl) != MEM) + return; + symbol = XEXP (rtl, 0); + if (GET_CODE (symbol) != SYMBOL_REF) + return; + + /* When using PIC, SYMBOL_REF_FLAG marks non-global symbols + that can be accessed directly. */ + if (flag_pic) + SYMBOL_REF_FLAG (symbol) = local_p; + + /* Encode thread-local data with %[GLil] for "global dynamic", + "local dynamic", "initial exec" or "local exec" TLS models, + respectively. */ + + if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) + { + const char *symbol_str = XSTR (symbol, 0); + char *newstr; + size_t len; + enum tls_model kind = decl_tls_model (decl); + + if (!flag_pic) { - SYMBOL_REF_FLAG (XEXP (rtl, 0)) - = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd' - || ! TREE_PUBLIC (decl)); + /* We don't allow non-pic code for shared libraries, + so don't generate GD/LD TLS models for non-pic code. */ + switch (kind) + { + case TLS_MODEL_GLOBAL_DYNAMIC: + kind = TLS_MODEL_INITIAL_EXEC; break; + case TLS_MODEL_LOCAL_DYNAMIC: + kind = TLS_MODEL_LOCAL_EXEC; break; + default: + break; + } } + + if (symbol_str[0] == '%') + { + if (symbol_str[1] == tls_model_chars[kind]) + return; + symbol_str += 2; + } + len = strlen (symbol_str) + 1; + newstr = alloca (len + 2); + + newstr[0] = '%'; + newstr[1] = tls_model_chars[kind]; + memcpy (newstr + 2, symbol_str, len); + + XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1); } } +/* Undo the above when printing symbol names. */ + +static const char * +s390_strip_name_encoding (str) + const char *str; +{ + if (str[0] == '%') + str += 2; + if (str[0] == '*') + str += 1; + return str; +} + /* Output thunk to FILE that implements a C++ virtual function call (with multiple inheritance) to FUNCTION. The thunk adjusts the this pointer by DELTA, and unless VCALL_OFFSET is zero, applies an additional adjustment diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index f0b7b3503b6..b9ea747c963 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -793,6 +793,10 @@ CUMULATIVE_ARGS; || GET_CODE (X) == LABEL_REF \ || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X))) +#define TLS_SYMBOLIC_CONST(X) \ +((GET_CODE (X) == SYMBOL_REF && tls_symbolic_operand (X)) \ + || (GET_CODE (X) == CONST && tls_symbolic_reference_mentioned_p (X))) + /* Condition codes. */ @@ -970,6 +974,10 @@ extern int flag_pic; #define ASM_OUTPUT_SKIP(FILE, SIZE) \ fprintf ((FILE), "\t.set\t.,.+%u\n", (SIZE)) +/* Output a reference to a user-level label named NAME. */ +#define ASM_OUTPUT_LABELREF(FILE, NAME) \ + asm_fprintf ((FILE), "%U%s", (*targetm.strip_name_encoding) (NAME)) + /* The LOCAL_LABEL_PREFIX variable is used by dbxelf.h. */ #define LOCAL_LABEL_PREFIX "." @@ -1051,10 +1059,9 @@ extern int s390_nr_constants; \ case MODE_INT: \ case MODE_PARTIAL_INT: \ - if (flag_pic \ - && (GET_CODE (EXP) == CONST \ - || GET_CODE (EXP) == SYMBOL_REF \ - || GET_CODE (EXP) == LABEL_REF )) \ + if (GET_CODE (EXP) == CONST \ + || GET_CODE (EXP) == SYMBOL_REF \ + || GET_CODE (EXP) == LABEL_REF) \ { \ fputs (integer_asm_op (UNITS_PER_WORD, TRUE), FILE); \ s390_output_symbolic_const (FILE, EXP); \ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 8f72baffad8..fc8e33bfe23 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -44,6 +44,35 @@ ;; s_operand -- Matches a valid S operand in a RS, SI or SS type instruction. ;; +;; +;; UNSPEC usage +;; + +(define_constants + [; TLS relocation specifiers + (UNSPEC_TLSGD 500) + (UNSPEC_TLSLDM 501) + (UNSPEC_NTPOFF 502) + (UNSPEC_DTPOFF 503) + (UNSPEC_GOTNTPOFF 504) + (UNSPEC_INDNTPOFF 505) + + ; TLS support + (UNSPEC_TP 510) + (UNSPEC_TLSLDM_NTPOFF 511) + (UNSPEC_TLS_LOAD 512) + ]) + +;; +;; UNSPEC_VOLATILE usage +;; + +(define_constants + [; TLS support + (UNSPECV_SET_TP 500) + ]) + + ;; Processor type. This attribute must exactly match the processor_type ;; enumeration in s390.h. @@ -938,18 +967,15 @@ ; movdi instruction pattern(s). ; -;; If generating PIC code and operands[1] is a symbolic CONST, emit a -;; move to get the address of the symbolic object from the GOT. - (define_expand "movdi" [(set (match_operand:DI 0 "general_operand" "") (match_operand:DI 1 "general_operand" ""))] "" " { - /* Handle PIC symbolic constants. */ - if (TARGET_64BIT && flag_pic && SYMBOLIC_CONST (operands[1])) - emit_pic_move (operands, DImode); + /* Handle symbolic constants. */ + if (TARGET_64BIT && SYMBOLIC_CONST (operands[1])) + emit_symbolic_move (operands); /* During and after reload, we need to force constants to the literal pool ourselves, if necessary. */ @@ -1099,18 +1125,15 @@ ; movsi instruction pattern(s). ; -;; If generating PIC code and operands[1] is a symbolic CONST, emit a -;; move to get the address of the symbolic object from the GOT. - (define_expand "movsi" [(set (match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "general_operand" ""))] "" " { - /* Handle PIC symbolic constants. */ - if (!TARGET_64BIT && flag_pic && SYMBOLIC_CONST (operands[1])) - emit_pic_move (operands, SImode); + /* Handle symbolic constants. */ + if (!TARGET_64BIT && SYMBOLIC_CONST (operands[1])) + emit_symbolic_move (operands); /* expr.c tries to load an effective address using force_reg. This fails because we don't have a @@ -6461,6 +6484,189 @@ (set_attr "type" "jsr")]) +;; +;;- Thread-local storage support. +;; + +(define_insn "get_tp_64" + [(set (match_operand:DI 0 "nonimmediate_operand" "=??d,Q") + (unspec:DI [(const_int 0)] UNSPEC_TP))] + "TARGET_64BIT" + "@ + ear\\t%0,%%a0\;sllg\\t%0,%0,32\;ear\\t%0,%%a1 + stam\\t%%a0,%%a1,%0" + [(set_attr "op_type" "NN,RS") + (set_attr "atype" "reg,*") + (set_attr "type" "o3,*") + (set_attr "length" "14,*")]) + +(define_insn "get_tp_31" + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,Q") + (unspec:SI [(const_int 0)] UNSPEC_TP))] + "!TARGET_64BIT" + "@ + ear\\t%0,%%a0 + stam\\t%%a0,%%a0,%0" + [(set_attr "op_type" "RRE,RS")]) + +(define_insn "set_tp_64" + [(unspec_volatile [(match_operand:DI 0 "general_operand" "??d,Q")] UNSPECV_SET_TP) + (clobber (match_scratch:SI 1 "=d,X"))] + "TARGET_64BIT" + "@ + sar\\t%%a1,%0\;srlg\\t%1,%0,32\;sar\\t%%a0,%1 + lam\\t%%a0,%%a1,%0" + [(set_attr "op_type" "NN,RS") + (set_attr "atype" "reg,*") + (set_attr "type" "o3,*") + (set_attr "length" "14,*")]) + +(define_insn "set_tp_31" + [(unspec_volatile [(match_operand:SI 0 "general_operand" "d,Q")] UNSPECV_SET_TP)] + "!TARGET_64BIT" + "@ + sar\\t%%a0,%0 + lam\\t%%a0,%%a0,%0" + [(set_attr "op_type" "RRE,RS")]) + +(define_insn "*tls_load_64" + [(set (match_operand:DI 0 "register_operand" "=d") + (unspec:DI [(match_operand:DI 1 "memory_operand" "m") + (match_operand:DI 2 "" "")] + UNSPEC_TLS_LOAD))] + "TARGET_64BIT" + "lg\\t%0,%1%J2" + [(set_attr "op_type" "RXE")]) + +(define_insn "*tls_load_31" + [(set (match_operand:SI 0 "register_operand" "=d") + (unspec:SI [(match_operand:SI 1 "memory_operand" "m") + (match_operand:SI 2 "" "")] + UNSPEC_TLS_LOAD))] + "!TARGET_64BIT" + "l\\t%0,%1%J2" + [(set_attr "op_type" "RX")]) + +(define_expand "call_value_tls" + [(set (match_operand 0 "" "") + (call (const_int 0) (const_int 0))) + (use (match_operand 1 "" ""))] + "" + " +{ + rtx insn, sym; + + if (!flag_pic) + abort (); + + sym = s390_tls_get_offset (); + sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), 113); + sym = gen_rtx_CONST (Pmode, sym); + + /* Unless we can use the bras(l) insn, force the + routine address into a register. */ + if (!TARGET_SMALL_EXEC && !TARGET_64BIT) + { + rtx target = gen_reg_rtx (Pmode); + emit_move_insn (target, sym); + sym = target; + } + + sym = gen_rtx_MEM (QImode, sym); + + /* Emit insn. */ + insn = emit_call_insn ( + gen_call_value_tls_exp (operands[0], sym, const0_rtx, + gen_rtx_REG (Pmode, RETURN_REGNUM), + operands[1])); + + /* The calling convention of __tls_get_offset uses the + GOT register implicitly. */ + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), operands[0]); + CONST_OR_PURE_CALL_P (insn) = 1; + + DONE; +}") + +(define_expand "call_value_tls_exp" + [(parallel [(set (match_operand 0 "" "") + (call (match_operand 1 "" "") + (match_operand 2 "" ""))) + (clobber (match_operand 3 "" "")) + (use (match_operand 4 "" ""))])] + "" + "") + +(define_insn "brasl_tls" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:QI (match_operand:DI 1 "bras_sym_operand" "X")) + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_operand:DI 3 "register_operand" "=r")) + (use (match_operand:DI 4 "" ""))] + "TARGET_64BIT" + "brasl\\t%3,%1%J4" + [(set_attr "op_type" "RIL") + (set_attr "type" "jsr")]) + +(define_insn "bras_tls" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:QI (match_operand:SI 1 "bras_sym_operand" "X")) + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_operand:SI 3 "register_operand" "=r")) + (use (match_operand:SI 4 "" ""))] + "TARGET_SMALL_EXEC" + "bras\\t%3,%1%J4" + [(set_attr "op_type" "RI") + (set_attr "type" "jsr")]) + +(define_insn "basr_tls_64" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:QI (match_operand:DI 1 "register_operand" "a")) + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_operand:DI 3 "register_operand" "=r")) + (use (match_operand:DI 4 "" ""))] + "TARGET_64BIT" + "basr\\t%3,%1%J4" + [(set_attr "op_type" "RR") + (set_attr "type" "jsr")]) + +(define_insn "basr_tls_31" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:QI (match_operand:SI 1 "register_operand" "a")) + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_operand:SI 3 "register_operand" "=r")) + (use (match_operand:SI 4 "" ""))] + "!TARGET_64BIT" + "basr\\t%3,%1%J4" + [(set_attr "op_type" "RR") + (set_attr "type" "jsr") + (set_attr "atype" "agen")]) + +(define_insn "bas_tls_64" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:QI (match_operand:QI 1 "address_operand" "p")) + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_operand:DI 3 "register_operand" "=r")) + (use (match_operand:DI 4 "" ""))] + "TARGET_64BIT" + "bas\\t%3,%a1%J4" + [(set_attr "op_type" "RX") + (set_attr "type" "jsr") + (set_attr "atype" "agen")]) + +(define_insn "bas_tls_31" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:QI (match_operand:QI 1 "address_operand" "p")) + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_operand:SI 3 "register_operand" "=r")) + (use (match_operand:SI 4 "" ""))] + "!TARGET_64BIT" + "bas\\t%3,%a1%J4" + [(set_attr "op_type" "RX") + (set_attr "type" "jsr") + (set_attr "atype" "agen")]) + ;; ;;- Miscellaneous instructions. ;; diff --git a/gcc/configure b/gcc/configure index f9ffb5455bd..060b1359061 100755 --- a/gcc/configure +++ b/gcc/configure @@ -7942,6 +7942,41 @@ foo: data8 25 tls_first_major=2 tls_first_minor=13 ;; + s390-*-*) + conftest_s=' + .section ".tdata","awT",@progbits +foo: .long 25 + .text + .long foo@TLSGD + .long foo@TLSLDM + .long foo@DTPOFF + .long foo@NTPOFF + .long foo@GOTNTPOFF + .long foo@INDNTPOFF + l %r1,foo@GOTNTPOFF(%r12) + l %r1,0(%r1):tls_load:foo + bas %r14,0(%r1,%r13):tls_gdcall:foo + bas %r14,0(%r1,%r13):tls_ldcall:foo' + tls_first_major=2 + tls_first_minor=14 + ;; + s390x-*-*) + conftest_s=' + .section ".tdata","awT",@progbits +foo: .long 25 + .text + .quad foo@TLSGD + .quad foo@TLSLDM + .quad foo@DTPOFF + .quad foo@NTPOFF + .quad foo@GOTNTPOFF + lg %r1,foo@GOTNTPOFF(%r12) + larl %r1,foo@INDNTPOFF + brasl %r14,__tls_get_offset@PLT:tls_gdcall:foo + brasl %r14,__tls_get_offset@PLT:tls_ldcall:foo' + tls_first_major=2 + tls_first_minor=14 + ;; esac if test -z "$tls_first_major"; then : @@ -7972,7 +8007,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:7976: checking assembler supports explicit relocations" >&5 +echo "configure:8011: 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 @@ -8022,7 +8057,7 @@ EOF ;; sparc*-*-*) echo $ac_n "checking assembler .register pseudo-op support""... $ac_c" 1>&6 -echo "configure:8026: checking assembler .register pseudo-op support" >&5 +echo "configure:8061: 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 @@ -8050,7 +8085,7 @@ EOF fi echo $ac_n "checking assembler supports -relax""... $ac_c" 1>&6 -echo "configure:8054: checking assembler supports -relax" >&5 +echo "configure:8089: 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 @@ -8078,7 +8113,7 @@ EOF fi echo $ac_n "checking assembler and linker support unaligned pc related relocs""... $ac_c" 1>&6 -echo "configure:8082: checking assembler and linker support unaligned pc related relocs" >&5 +echo "configure:8117: 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 @@ -8105,7 +8140,7 @@ EOF fi echo $ac_n "checking assembler and linker support unaligned pc related relocs against hidden symbols""... $ac_c" 1>&6 -echo "configure:8109: checking assembler and linker support unaligned pc related relocs against hidden symbols" >&5 +echo "configure:8144: 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 @@ -8145,7 +8180,7 @@ EOF fi echo $ac_n "checking for assembler offsetable %lo() support""... $ac_c" 1>&6 -echo "configure:8149: checking for assembler offsetable %lo() support" >&5 +echo "configure:8184: 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 @@ -8184,7 +8219,7 @@ EOF i[34567]86-*-* | x86_64-*-*) echo $ac_n "checking assembler instructions""... $ac_c" 1>&6 -echo "configure:8188: checking assembler instructions" >&5 +echo "configure:8223: 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 @@ -8211,7 +8246,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:8215: checking assembler GOTOFF in data directives" >&5 +echo "configure:8250: 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 @@ -8241,7 +8276,7 @@ EOF esac echo $ac_n "checking assembler dwarf2 debug_line support""... $ac_c" 1>&6 -echo "configure:8245: checking assembler dwarf2 debug_line support" >&5 +echo "configure:8280: 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 @@ -8298,7 +8333,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:8302: checking assembler --gdwarf2 support" >&5 +echo "configure:8337: 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 @@ -8327,7 +8362,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:8331: checking assembler --gstabs support" >&5 +echo "configure:8366: 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 @@ -8355,7 +8390,7 @@ fi echo "$ac_t""$gcc_cv_as_gstabs_flag" 1>&6 echo $ac_n "checking linker read-only and read-write section mixing""... $ac_c" 1>&6 -echo "configure:8359: checking linker read-only and read-write section mixing" >&5 +echo "configure:8394: checking linker read-only and read-write section mixing" >&5 gcc_cv_ld_ro_rw_mix=unknown 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 10 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then @@ -8393,7 +8428,7 @@ fi echo "$ac_t""$gcc_cv_ld_ro_rw_mix" 1>&6 echo $ac_n "checking linker PT_GNU_EH_FRAME support""... $ac_c" 1>&6 -echo "configure:8397: checking linker PT_GNU_EH_FRAME support" >&5 +echo "configure:8432: 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 @@ -8417,7 +8452,7 @@ echo "$ac_t""$gcc_cv_ld_eh_frame_hdr" 1>&6 case "$target" in mips*-*-*) echo $ac_n "checking whether libgloss uses STARTUP directives consistently""... $ac_c" 1>&6 -echo "configure:8421: checking whether libgloss uses STARTUP directives consistently" >&5 +echo "configure:8456: checking whether libgloss uses STARTUP directives consistently" >&5 gcc_cv_mips_libgloss_startup=no gcc_cv_libgloss_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/libgloss if test "x$exec_prefix" = xNONE; then @@ -8621,7 +8656,7 @@ fi echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 -echo "configure:8625: checking whether to enable maintainer-specific portions of Makefiles" >&5 +echo "configure:8660: 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 980d7420d53..4ec16ea3dcd 100644 --- a/gcc/configure.in +++ b/gcc/configure.in @@ -1944,6 +1944,41 @@ foo: data8 25 tls_first_major=2 tls_first_minor=13 ;; + s390-*-*) + conftest_s=' + .section ".tdata","awT",@progbits +foo: .long 25 + .text + .long foo@TLSGD + .long foo@TLSLDM + .long foo@DTPOFF + .long foo@NTPOFF + .long foo@GOTNTPOFF + .long foo@INDNTPOFF + l %r1,foo@GOTNTPOFF(%r12) + l %r1,0(%r1):tls_load:foo + bas %r14,0(%r1,%r13):tls_gdcall:foo + bas %r14,0(%r1,%r13):tls_ldcall:foo' + tls_first_major=2 + tls_first_minor=14 + ;; + s390x-*-*) + conftest_s=' + .section ".tdata","awT",@progbits +foo: .long 25 + .text + .quad foo@TLSGD + .quad foo@TLSLDM + .quad foo@DTPOFF + .quad foo@NTPOFF + .quad foo@GOTNTPOFF + lg %r1,foo@GOTNTPOFF(%r12) + larl %r1,foo@INDNTPOFF + brasl %r14,__tls_get_offset@PLT:tls_gdcall:foo + brasl %r14,__tls_get_offset@PLT:tls_ldcall:foo' + tls_first_major=2 + tls_first_minor=14 + ;; esac if test -z "$tls_first_major"; then :