@@ -1039,6 +1039,13 @@ (define_predicate "rs6000_tls_symbol_ref"
(and (match_code "symbol_ref")
(match_test "RS6000_SYMBOL_REF_TLS_P (op)")))
+;; Return 1 for the UNSPEC used in TLS call operands
+(define_predicate "unspec_tls"
+ (match_code "unspec")
+{
+ return XINT (op, 1) == UNSPEC_TLSGD || XINT (op, 1) == UNSPEC_TLSLD;
+})
+
;; Return 1 if the operand, used inside a MEM, is a valid first argument
;; to CALL. This is a SYMBOL_REF, a pseudo-register, LR or CTR.
(define_predicate "call_operand"
@@ -111,7 +111,7 @@ extern int ccr_bit (rtx, int);
extern void rs6000_output_function_entry (FILE *, const char *);
extern void print_operand (FILE *, rtx, int);
extern void print_operand_address (FILE *, rtx);
-extern const char *rs6000_output_call (rtx *, unsigned int, bool, const char *);
+extern const char *rs6000_output_call (rtx *, unsigned int, bool);
extern const char *rs6000_output_indirect_call (rtx *, unsigned int, bool);
extern enum rtx_code rs6000_reverse_condition (machine_mode,
enum rtx_code);
@@ -134,7 +134,6 @@ extern void rs6000_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
extern void rs6000_emit_swdiv (rtx, rtx, rtx, bool);
extern void rs6000_emit_swsqrt (rtx, rtx, bool);
extern void output_toc (FILE *, rtx, int, machine_mode);
-extern rtx rs6000_longcall_ref (rtx);
extern void rs6000_fatal_bad_address (rtx);
extern rtx create_TOC_reference (rtx, rtx);
extern void rs6000_split_multireg_move (rtx, rtx);
@@ -202,6 +201,7 @@ extern void rs6000_split_stack_space_check (rtx, rtx);
extern void rs6000_emit_eh_reg_restore (rtx, rtx);
extern void rs6000_call_aix (rtx, rtx, rtx, rtx);
extern void rs6000_sibcall_aix (rtx, rtx, rtx, rtx);
+extern void rs6000_call_sysv (rtx, rtx, rtx, rtx);
extern void rs6000_aix_asm_output_dwarf_table_ref (char *);
extern void get_ppc476_thunk_name (char name[32]);
extern bool rs6000_overloaded_builtin_p (enum rs6000_builtins);
@@ -8583,6 +8583,43 @@ rs6000_legitimize_tls_address_aix (rtx addr, enum tls_model model)
return dest;
}
+/* Mess with a call, to make it look like the tls_gdld insns when
+ !TARGET_TLS_MARKERS. These insns have an extra unspec to
+ differentiate them from standard calls, because they need to emit
+ the arg setup insns as well as the actual call. That keeps the
+ arg setup insns immediately adjacent to the branch and link. */
+
+static void
+edit_tls_call_insn (rtx arg)
+{
+ rtx call_insn = last_call_insn ();
+ if (!TARGET_TLS_MARKERS)
+ {
+ rtx patt = PATTERN (call_insn);
+ gcc_assert (GET_CODE (patt) == PARALLEL);
+ rtvec orig = XVEC (patt, 0);
+ rtvec v = rtvec_alloc (GET_NUM_ELEM (orig) + 1);
+ gcc_assert (GET_NUM_ELEM (orig) > 0);
+ /* The (set (..) (call (mem ..))). */
+ RTVEC_ELT (v, 0) = RTVEC_ELT (orig, 0);
+ /* The extra unspec. */
+ RTVEC_ELT (v, 1) = arg;
+ /* All other assorted call pattern pieces. */
+ for (int i = 1; i < GET_NUM_ELEM (orig); i++)
+ RTVEC_ELT (v, i + 1) = RTVEC_ELT (orig, i);
+ XVEC (patt, 0) = v;
+ }
+ if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT && flag_pic)
+ use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
+ pic_offset_table_rtx);
+}
+
+/* Passes the tls arg value for global dynamic and local dynamic
+ emit_library_call_value in rs6000_legitimize_Tls_address to
+ rs6000_call_aix and rs6000_call_sysv. This is used to emit the
+ marker relocs put on __tls_get_addr calls. */
+static rtx global_tlsarg;
+
/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
this (thread-local) address. */
@@ -8635,7 +8672,7 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
}
else
{
- rtx r3, got, tga, tmp1, tmp2, call_insn;
+ rtx got, tga, tmp1, tmp2;
/* We currently use relocations like @got@tlsgd for tls, which
means the linker will handle allocation of tls entries, placing
@@ -8675,52 +8712,42 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
if (model == TLS_MODEL_GLOBAL_DYNAMIC)
{
+ rtx arg = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, addr, got),
+ UNSPEC_TLSGD);
+ global_tlsarg = arg;
+ rtx argreg = const0_rtx;
+ if (TARGET_TLS_MARKERS)
+ {
+ argreg = gen_rtx_REG (Pmode, 3);
+ emit_insn (gen_rtx_SET (argreg, arg));
+ }
+
tga = rs6000_tls_get_addr ();
emit_library_call_value (tga, dest, LCT_CONST, Pmode,
- const0_rtx, Pmode);
+ argreg, Pmode);
+ global_tlsarg = NULL_RTX;
- r3 = gen_rtx_REG (Pmode, 3);
- if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
- {
- if (TARGET_64BIT)
- insn = gen_tls_gd_aix64 (r3, got, addr, tga, const0_rtx);
- else
- insn = gen_tls_gd_aix32 (r3, got, addr, tga, const0_rtx);
- }
- else if (DEFAULT_ABI == ABI_V4)
- insn = gen_tls_gd_sysvsi (r3, got, addr, tga, const0_rtx);
- else
- gcc_unreachable ();
- call_insn = last_call_insn ();
- PATTERN (call_insn) = insn;
- if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT && flag_pic)
- use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
- pic_offset_table_rtx);
+ edit_tls_call_insn (arg);
}
else if (model == TLS_MODEL_LOCAL_DYNAMIC)
{
+ rtx arg = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got),
+ UNSPEC_TLSLD);
+ global_tlsarg = arg;
+ rtx argreg = const0_rtx;
+ if (TARGET_TLS_MARKERS)
+ {
+ argreg = gen_rtx_REG (Pmode, 3);
+ emit_insn (gen_rtx_SET (argreg, arg));
+ }
+
tga = rs6000_tls_get_addr ();
tmp1 = gen_reg_rtx (Pmode);
emit_library_call_value (tga, tmp1, LCT_CONST, Pmode,
- const0_rtx, Pmode);
+ argreg, Pmode);
+ global_tlsarg = NULL_RTX;
- r3 = gen_rtx_REG (Pmode, 3);
- if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
- {
- if (TARGET_64BIT)
- insn = gen_tls_ld_aix64 (r3, got, tga, const0_rtx);
- else
- insn = gen_tls_ld_aix32 (r3, got, tga, const0_rtx);
- }
- else if (DEFAULT_ABI == ABI_V4)
- insn = gen_tls_ld_sysvsi (r3, got, tga, const0_rtx);
- else
- gcc_unreachable ();
- call_insn = last_call_insn ();
- PATTERN (call_insn) = insn;
- if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT && flag_pic)
- use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
- pic_offset_table_rtx);
+ edit_tls_call_insn (arg);
if (rs6000_tls_size == 16)
{
@@ -21183,19 +21210,19 @@ print_operand (FILE *file, rtx x, int code)
else
output_address (GET_MODE (x), XEXP (x, 0));
}
+ else if (toc_relative_expr_p (x, false,
+ &tocrel_base_oac, &tocrel_offset_oac))
+ /* This hack along with a corresponding hack in
+ rs6000_output_addr_const_extra arranges to output addends
+ where the assembler expects to find them. eg.
+ (plus (unspec [(symbol_ref ("x")) (reg 2)] tocrel) 4)
+ without this hack would be output as "x@toc+4". We
+ want "x+4@toc". */
+ output_addr_const (file, CONST_CAST_RTX (tocrel_base_oac));
+ else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSGD)
+ output_addr_const (file, XVECEXP (x, 0, 0));
else
- {
- if (toc_relative_expr_p (x, false, &tocrel_base_oac, &tocrel_offset_oac))
- /* This hack along with a corresponding hack in
- rs6000_output_addr_const_extra arranges to output addends
- where the assembler expects to find them. eg.
- (plus (unspec [(symbol_ref ("x")) (reg 2)] tocrel) 4)
- without this hack would be output as "x@toc+4". We
- want "x+4@toc". */
- output_addr_const (file, CONST_CAST_RTX (tocrel_base_oac));
- else
- output_addr_const (file, x);
- }
+ output_addr_const (file, x);
return;
case '&':
@@ -21381,17 +21408,27 @@ rs6000_assemble_integer (rtx x, unsigned int size, int aligned_p)
}
/* Return a template string for assembly to emit when making an
- external call. FUN is the %z argument, ARG is either NULL or
- a @TLSGD or @TLSLD __tls_get_addr argument specifier. */
+ external call. FUN is the %z argument. */
const char *
-rs6000_output_call (rtx *operands, unsigned int fun, bool sibcall,
- const char *arg)
+rs6000_output_call (rtx *operands, unsigned int fun, bool sibcall)
{
/* -Wformat-overflow workaround, without which gcc thinks that %u
might produce 10 digits. FUN is 0 or 1 as of 2018-03. */
gcc_assert (fun <= 6);
+ char arg[11];
+ arg[0] = 0;
+ if (GET_CODE (operands[fun + 1]) == UNSPEC)
+ {
+ if (XINT (operands[fun + 1], 1) == UNSPEC_TLSGD)
+ sprintf (arg, "(%%%u@tlsgd)", fun + 1);
+ else if (XINT (operands[fun + 1], 1) == UNSPEC_TLSLD)
+ sprintf (arg, "(%%&@tlsld)");
+ else
+ gcc_unreachable ();
+ }
+
/* The magic 32768 offset here corresponds to the offset of
r30 in .got2, as given by LCTOC1. See sysv4.h:toc_section. */
char z[10];
@@ -32484,23 +32521,20 @@ rs6000_set_default_type_attributes (tree type)
/* Return a reference suitable for calling a function with the
longcall attribute. */
-rtx
+static rtx
rs6000_longcall_ref (rtx call_ref)
{
- const char *call_name;
- tree node;
-
if (GET_CODE (call_ref) != SYMBOL_REF)
return call_ref;
/* System V adds '.' to the internal name, so skip them. */
- call_name = XSTR (call_ref, 0);
+ const char *call_name = XSTR (call_ref, 0);
if (*call_name == '.')
{
while (*call_name == '.')
call_name++;
- node = get_identifier (call_name);
+ tree node = get_identifier (call_name);
call_ref = gen_rtx_SYMBOL_REF (VOIDmode, IDENTIFIER_POINTER (node));
}
@@ -37472,7 +37506,7 @@ chain_already_loaded (rtx_insn *last)
/* Expand code to perform a call under the AIX or ELFv2 ABI. */
void
-rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
+rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
{
const bool direct_call_p
= GET_CODE (func_desc) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (func_desc);
@@ -37485,6 +37519,9 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
int n_call;
rtx insn;
+ if (global_tlsarg)
+ tlsarg = global_tlsarg;
+
/* Handle longcall attributes. */
if (INTVAL (cookie) & CALL_LONG)
func_desc = rs6000_longcall_ref (func_desc);
@@ -37495,11 +37532,7 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
{
/* Save the TOC into its reserved slot before the call,
and prepare to restore it after the call. */
- rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
rtx stack_toc_offset = GEN_INT (RS6000_TOC_SAVE_SLOT);
- rtx stack_toc_mem = gen_frame_mem (Pmode,
- gen_rtx_PLUS (Pmode, stack_ptr,
- stack_toc_offset));
rtx stack_toc_unspec = gen_rtx_UNSPEC (Pmode,
gen_rtvec (1, stack_toc_offset),
UNSPEC_TOCSLOT);
@@ -37511,6 +37544,10 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
cfun->machine->save_toc_in_prologue = true;
else
{
+ rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ rtx stack_toc_mem = gen_frame_mem (Pmode,
+ gen_rtx_PLUS (Pmode, stack_ptr,
+ stack_toc_offset));
MEM_VOLATILE_P (stack_toc_mem) = 1;
emit_move_insn (stack_toc_mem, toc_reg);
}
@@ -37520,7 +37557,8 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
/* A function pointer in the ELFv2 ABI is just a plain address, but
the ABI requires it to be loaded into r12 before the call. */
func_addr = gen_rtx_REG (Pmode, 12);
- emit_move_insn (func_addr, func_desc);
+ if (!rtx_equal_p (func_addr, func_desc))
+ emit_move_insn (func_addr, func_desc);
abi_reg = func_addr;
}
else
@@ -37575,7 +37613,7 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
}
/* Create the call. */
- call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_addr), flag);
+ call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_addr), tlsarg);
if (value != NULL_RTX)
call[0] = gen_rtx_SET (value, call[0]);
n_call = 1;
@@ -37599,15 +37637,18 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
/* Expand code to perform a sibling call under the AIX or ELFv2 ABI. */
void
-rs6000_sibcall_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
+rs6000_sibcall_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
{
rtx call[2];
rtx insn;
gcc_assert (INTVAL (cookie) == 0);
+ if (global_tlsarg)
+ tlsarg = global_tlsarg;
+
/* Create the call. */
- call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_desc), flag);
+ call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_desc), tlsarg);
if (value != NULL_RTX)
call[0] = gen_rtx_SET (value, call[0]);
@@ -37620,6 +37661,42 @@ rs6000_sibcall_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, TOC_REGNUM));
}
+/* Expand code to perform a call under the SYSV4 ABI. */
+
+void
+rs6000_call_sysv (rtx value, rtx func, rtx tlsarg, rtx cookie)
+{
+ rtx func_addr;
+ rtx call[3];
+ rtx insn;
+
+ if (global_tlsarg)
+ tlsarg = global_tlsarg;
+
+ /* Handle longcall attributes. */
+ if (INTVAL (cookie) & CALL_LONG)
+ func = rs6000_longcall_ref (func);
+
+ /* Handle indirect calls. */
+ if (GET_CODE (func) != SYMBOL_REF)
+ func_addr = force_reg (Pmode, func);
+ else
+ func_addr = func;
+
+ /* Create the call. */
+ call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_addr), tlsarg);
+ if (value != NULL_RTX)
+ call[0] = gen_rtx_SET (value, call[0]);
+
+ unsigned int mask = CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS;
+ call[1] = gen_rtx_USE (VOIDmode, GEN_INT (INTVAL (cookie) & mask));
+
+ call[2] = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
+
+ insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (3, call));
+ insn = emit_call_insn (insn);
+}
+
/* Return whether we need to always update the saved TOC pointer when we update
the stack pointer. */
@@ -9439,77 +9439,75 @@ (define_peephole2
;; Mode attributes for different ABIs.
(define_mode_attr tls_abi_suffix [(SI "32") (DI "64")])
-(define_mode_attr tls_sysv_suffix [(SI "si") (DI "di")])
(define_mode_attr tls_insn_suffix [(SI "wz") (DI "d")])
-(define_insn_and_split "tls_gd_aix<P:tls_abi_suffix>"
- [(set (match_operand:P 0 "gpc_reg_operand" "=b")
- (call (mem:SI (match_operand:P 3 "symbol_ref_operand" "s"))
- (match_operand 4)))
- (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")
- (match_operand:P 2 "rs6000_tls_symbol_ref" "")]
- UNSPEC_TLSGD)
- (clobber (reg:SI LR_REGNO))]
- "HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
+(define_insn "*tls_gdld_aix<P:tls_abi_suffix>"
+ [(match_parallel 3 ""
+ [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+ (call (mem:SI (match_operand:P 1))
+ (match_operand:P 2 "unspec_tls")))
+ (match_dup 2)])]
+ "HAVE_AS_TLS && !TARGET_TLS_MARKERS
+ && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
{
- if (TARGET_CMODEL != CMODEL_SMALL)
- output_asm_insn ("addis %0,%1,%2@got@tlsgd@ha\;"
- "addi %0,%0,%2@got@tlsgd@l", operands);
+ rtx op[3];
+ op[0] = operands[0];
+ op[1] = XVECEXP (operands[2], 0, 0);
+ if (XINT (operands[2], 1) == UNSPEC_TLSGD)
+ {
+ op[2] = XVECEXP (operands[2], 0, 1);
+ if (TARGET_CMODEL != CMODEL_SMALL)
+ output_asm_insn ("addis %0,%2,%1@got@tlsgd@ha\;"
+ "addi %0,%0,%1@got@tlsgd@l", op);
+ else
+ output_asm_insn ("addi %0,%2,%1@got@tlsgd", op);
+ }
else
- output_asm_insn ("addi %0,%1,%2@got@tlsgd", operands);
- return rs6000_output_call (operands, 3, false, "");
+ {
+ if (TARGET_CMODEL != CMODEL_SMALL)
+ output_asm_insn ("addis %0,%1,%&@got@tlsld@ha\;"
+ "addi %0,%0,%&@got@tlsld@l", op);
+ else
+ output_asm_insn ("addi %0,%1,%&@got@tlsld", op);
+ }
+ return rs6000_output_call (operands, 1, false);
}
- "&& TARGET_TLS_MARKERS"
- [(set (match_dup 0)
- (unspec:P [(match_dup 1)
- (match_dup 2)]
- UNSPEC_TLSGD))
- (parallel [(set (match_dup 0)
- (call (mem:SI (match_dup 3))
- (match_dup 4)))
- (unspec:P [(match_dup 2)] UNSPEC_TLSGD)
- (clobber (reg:SI LR_REGNO))])]
- ""
[(set_attr "type" "two")
(set (attr "length")
(if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
(const_int 16)
(const_int 12)))])
-(define_insn_and_split "tls_gd_sysv<P:tls_sysv_suffix>"
- [(set (match_operand:P 0 "gpc_reg_operand" "=b")
- (call (mem:SI (match_operand:P 3 "symbol_ref_operand" "s"))
- (match_operand 4)))
- (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")
- (match_operand:P 2 "rs6000_tls_symbol_ref" "")]
- UNSPEC_TLSGD)
- (clobber (reg:SI LR_REGNO))]
- "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4"
+(define_insn "*tls_gdld_sysv<P:tls_abi_suffix>"
+ [(match_parallel 3 ""
+ [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+ (call (mem:SI (match_operand:P 1))
+ (match_operand:P 2 "unspec_tls")))
+ (match_dup 2)])]
+ "HAVE_AS_TLS && !TARGET_TLS_MARKERS && DEFAULT_ABI == ABI_V4"
{
- output_asm_insn ("addi %0,%1,%2@got@tlsgd", operands);
- return rs6000_output_call (operands, 3, false, "");
+ rtx op[3];
+ op[0] = operands[0];
+ op[1] = XVECEXP (operands[2], 0, 0);
+ if (XINT (operands[2], 1) == UNSPEC_TLSGD)
+ {
+ op[2] = XVECEXP (operands[2], 0, 1);
+ output_asm_insn ("addi %0,%2,%1@got@tlsgd", op);
+ }
+ else
+ output_asm_insn ("addi %0,%1,%&@got@tlsld", op);
+ return rs6000_output_call (operands, 1, false);
}
- "&& TARGET_TLS_MARKERS"
- [(set (match_dup 0)
- (unspec:P [(match_dup 1)
- (match_dup 2)]
- UNSPEC_TLSGD))
- (parallel [(set (match_dup 0)
- (call (mem:SI (match_dup 3))
- (match_dup 4)))
- (unspec:P [(match_dup 2)] UNSPEC_TLSGD)
- (clobber (reg:SI LR_REGNO))])]
- ""
[(set_attr "type" "two")
(set_attr "length" "8")])
(define_insn_and_split "*tls_gd<P:tls_abi_suffix>"
[(set (match_operand:P 0 "gpc_reg_operand" "=b")
- (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")
- (match_operand:P 2 "rs6000_tls_symbol_ref" "")]
+ (unspec:P [(match_operand:P 1 "rs6000_tls_symbol_ref" "")
+ (match_operand:P 2 "gpc_reg_operand" "b")]
UNSPEC_TLSGD))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS"
- "addi %0,%1,%2@got@tlsgd"
+ "addi %0,%2,%1@got@tlsgd"
"&& TARGET_CMODEL != CMODEL_SMALL"
[(set (match_dup 3)
(high:P
@@ -9518,7 +9516,7 @@ (define_insn_and_split "*tls_gd<P:tls_abi_suffix>"
(lo_sum:P (match_dup 3)
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_TLSGD)))]
{
- operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
+ operands[3] = gen_reg_rtx (<MODE>mode);
}
[(set (attr "length")
(if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
@@ -9528,105 +9526,21 @@ (define_insn_and_split "*tls_gd<P:tls_abi_suffix>"
(define_insn "*tls_gd_high<P:tls_abi_suffix>"
[(set (match_operand:P 0 "gpc_reg_operand" "=b")
(high:P
- (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")
- (match_operand:P 2 "rs6000_tls_symbol_ref" "")]
+ (unspec:P [(match_operand:P 1 "rs6000_tls_symbol_ref" "")
+ (match_operand:P 2 "gpc_reg_operand" "b")]
UNSPEC_TLSGD)))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
- "addis %0,%1,%2@got@tlsgd@ha")
+ "addis %0,%2,%1@got@tlsgd@ha")
(define_insn "*tls_gd_low<P:tls_abi_suffix>"
[(set (match_operand:P 0 "gpc_reg_operand" "=b")
(lo_sum:P (match_operand:P 1 "gpc_reg_operand" "b")
- (unspec:P [(match_operand:P 3 "gpc_reg_operand" "b")
- (match_operand:P 2 "rs6000_tls_symbol_ref" "")]
+ (unspec:P [(match_operand:P 2 "rs6000_tls_symbol_ref" "")
+ (match_operand:P 3 "gpc_reg_operand" "b")]
UNSPEC_TLSGD)))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
"addi %0,%1,%2@got@tlsgd@l")
-(define_insn "*tls_gd_call_aix<P:tls_abi_suffix>"
- [(set (match_operand:P 0 "gpc_reg_operand" "=b")
- (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s"))
- (match_operand 2)))
- (unspec:P [(match_operand:P 3 "rs6000_tls_symbol_ref" "")]
- UNSPEC_TLSGD)
- (clobber (reg:SI LR_REGNO))]
- "HAVE_AS_TLS && TARGET_TLS_MARKERS
- && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
-{
- return rs6000_output_call (operands, 1, false, "(%3@tlsgd)");
-}
- [(set_attr "type" "branch")
- (set_attr "length" "8")])
-
-(define_insn "*tls_gd_call_sysv<P:tls_abi_suffix>"
- [(set (match_operand:P 0 "gpc_reg_operand" "=b")
- (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s"))
- (match_operand 2)))
- (unspec:P [(match_operand:P 3 "rs6000_tls_symbol_ref" "")]
- UNSPEC_TLSGD)
- (clobber (reg:SI LR_REGNO))]
- "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4 && TARGET_TLS_MARKERS"
-{
- return rs6000_output_call (operands, 1, false, "(%3@tlsgd)");
-}
- [(set_attr "type" "branch")])
-
-(define_insn_and_split "tls_ld_aix<P:tls_abi_suffix>"
- [(set (match_operand:P 0 "gpc_reg_operand" "=b")
- (call (mem:SI (match_operand:P 2 "symbol_ref_operand" "s"))
- (match_operand 3)))
- (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")]
- UNSPEC_TLSLD)
- (clobber (reg:SI LR_REGNO))]
- "HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
-{
- if (TARGET_CMODEL != CMODEL_SMALL)
- output_asm_insn ("addis %0,%1,%&@got@tlsld@ha\;"
- "addi %0,%0,%&@got@tlsld@l", operands);
- else
- output_asm_insn ("addi %0,%1,%&@got@tlsld", operands);
- return rs6000_output_call (operands, 2, false, "");
-}
- "&& TARGET_TLS_MARKERS"
- [(set (match_dup 0)
- (unspec:P [(match_dup 1)]
- UNSPEC_TLSLD))
- (parallel [(set (match_dup 0)
- (call (mem:SI (match_dup 2))
- (match_dup 3)))
- (unspec:P [(const_int 0)] UNSPEC_TLSLD)
- (clobber (reg:SI LR_REGNO))])]
- ""
- [(set_attr "type" "two")
- (set (attr "length")
- (if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
- (const_int 16)
- (const_int 12)))])
-
-(define_insn_and_split "tls_ld_sysv<P:tls_sysv_suffix>"
- [(set (match_operand:P 0 "gpc_reg_operand" "=b")
- (call (mem:SI (match_operand:P 2 "symbol_ref_operand" "s"))
- (match_operand 3)))
- (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")]
- UNSPEC_TLSLD)
- (clobber (reg:SI LR_REGNO))]
- "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4"
-{
- output_asm_insn ("addi %0,%1,%&@got@tlsld", operands);
- return rs6000_output_call (operands, 2, false, "");
-}
- "&& TARGET_TLS_MARKERS"
- [(set (match_dup 0)
- (unspec:P [(match_dup 1)]
- UNSPEC_TLSLD))
- (parallel [(set (match_dup 0)
- (call (mem:SI (match_dup 2))
- (match_dup 3)))
- (unspec:P [(const_int 0)] UNSPEC_TLSLD)
- (clobber (reg:SI LR_REGNO))])]
- ""
- [(set_attr "length" "8")])
-
(define_insn_and_split "*tls_ld<P:tls_abi_suffix>"
[(set (match_operand:P 0 "gpc_reg_operand" "=b")
(unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")]
@@ -9636,12 +9550,12 @@ (define_insn_and_split "*tls_ld<P:tls_abi_suffix>"
"&& TARGET_CMODEL != CMODEL_SMALL"
[(set (match_dup 2)
(high:P
- (unspec:P [(const_int 0) (match_dup 1)] UNSPEC_TLSLD)))
+ (unspec:P [(match_dup 1)] UNSPEC_TLSLD)))
(set (match_dup 0)
(lo_sum:P (match_dup 2)
- (unspec:P [(const_int 0) (match_dup 1)] UNSPEC_TLSLD)))]
+ (unspec:P [(match_dup 1)] UNSPEC_TLSLD)))]
{
- operands[2] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
+ operands[2] = gen_reg_rtx (<MODE>mode);
}
[(set (attr "length")
(if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
@@ -9651,8 +9565,7 @@ (define_insn_and_split "*tls_ld<P:tls_abi_suffix>"
(define_insn "*tls_ld_high<P:tls_abi_suffix>"
[(set (match_operand:P 0 "gpc_reg_operand" "=b")
(high:P
- (unspec:P [(const_int 0)
- (match_operand:P 1 "gpc_reg_operand" "b")]
+ (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")]
UNSPEC_TLSLD)))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
"addis %0,%1,%&@got@tlsld@ha")
@@ -9660,38 +9573,11 @@ (define_insn "*tls_ld_high<P:tls_abi_suffix>"
(define_insn "*tls_ld_low<P:tls_abi_suffix>"
[(set (match_operand:P 0 "gpc_reg_operand" "=b")
(lo_sum:P (match_operand:P 1 "gpc_reg_operand" "b")
- (unspec:P [(const_int 0)
- (match_operand:P 2 "gpc_reg_operand" "b")]
+ (unspec:P [(match_operand:P 2 "gpc_reg_operand" "b")]
UNSPEC_TLSLD)))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
"addi %0,%1,%&@got@tlsld@l")
-(define_insn "*tls_ld_call_aix<P:tls_abi_suffix>"
- [(set (match_operand:P 0 "gpc_reg_operand" "=b")
- (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s"))
- (match_operand 2)))
- (unspec:P [(const_int 0)] UNSPEC_TLSLD)
- (clobber (reg:SI LR_REGNO))]
- "HAVE_AS_TLS && TARGET_TLS_MARKERS
- && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
-{
- return rs6000_output_call (operands, 1, false, "(%&@tlsld)");
-}
- [(set_attr "type" "branch")
- (set_attr "length" "8")])
-
-(define_insn "*tls_ld_call_sysv<P:tls_abi_suffix>"
- [(set (match_operand:P 0 "gpc_reg_operand" "=b")
- (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s"))
- (match_operand 2)))
- (unspec:P [(const_int 0)] UNSPEC_TLSLD)
- (clobber (reg:SI LR_REGNO))]
- "HAVE_AS_TLS && DEFAULT_ABI == ABI_V4 && TARGET_TLS_MARKERS"
-{
- return rs6000_output_call (operands, 1, false, "(%&@tlsld)");
-}
- [(set_attr "type" "branch")])
-
(define_insn "tls_dtprel_<P:tls_abi_suffix>"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")
@@ -10365,7 +10251,6 @@ (define_expand "call"
#endif
gcc_assert (GET_CODE (operands[0]) == MEM);
- gcc_assert (GET_CODE (operands[1]) == CONST_INT);
operands[0] = XEXP (operands[0], 0);
@@ -10375,23 +10260,14 @@ (define_expand "call"
DONE;
}
- if (GET_CODE (operands[0]) != SYMBOL_REF
- || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0))
+ if (DEFAULT_ABI == ABI_V4)
{
- if (INTVAL (operands[2]) & CALL_LONG)
- operands[0] = rs6000_longcall_ref (operands[0]);
-
- switch (DEFAULT_ABI)
- {
- case ABI_V4:
- case ABI_DARWIN:
- operands[0] = force_reg (Pmode, operands[0]);
- break;
-
- default:
- gcc_unreachable ();
- }
+ rs6000_call_sysv (NULL_RTX, operands[0], operands[1], operands[2]);
+ DONE;
}
+
+ if (GET_CODE (operands[0]) != SYMBOL_REF)
+ operands[0] = force_reg (Pmode, operands[0]);
})
(define_expand "call_value"
@@ -10408,7 +10284,6 @@ (define_expand "call_value"
#endif
gcc_assert (GET_CODE (operands[1]) == MEM);
- gcc_assert (GET_CODE (operands[2]) == CONST_INT);
operands[1] = XEXP (operands[1], 0);
@@ -10418,23 +10293,14 @@ (define_expand "call_value"
DONE;
}
- if (GET_CODE (operands[1]) != SYMBOL_REF
- || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0))
+ if (DEFAULT_ABI == ABI_V4)
{
- if (INTVAL (operands[3]) & CALL_LONG)
- operands[1] = rs6000_longcall_ref (operands[1]);
-
- switch (DEFAULT_ABI)
- {
- case ABI_V4:
- case ABI_DARWIN:
- operands[1] = force_reg (Pmode, operands[1]);
- break;
-
- default:
- gcc_unreachable ();
- }
+ rs6000_call_sysv (operands[0], operands[1], operands[2], operands[3]);
+ DONE;
}
+
+ if (GET_CODE (operands[1]) != SYMBOL_REF)
+ operands[1] = force_reg (Pmode, operands[1]);
})
;; Call to function in current module. No TOC pointer reload needed.
@@ -10521,7 +10387,7 @@ (define_insn "*call_value_local64"
;; A function pointer under System V is just a normal pointer
;; operands[0] is the function pointer
-;; operands[1] is the stack size to clean up
+;; operands[1] is the tls call arg
;; operands[2] is the value FUNCTION_ARG returns for the VOID argument
;; which indicates how to set cr1
@@ -10572,7 +10438,7 @@ (define_insn_and_split "*call_nonlocal_sysv<mode>"
#if TARGET_MACHO
return macho_output_call(insn, operands, 0, 2);
#else
- return rs6000_output_call (operands, 0, false, "");
+ return rs6000_output_call (operands, 0, false);
#endif
}
"DEFAULT_ABI == ABI_V4
@@ -10605,7 +10471,7 @@ (define_insn "*call_nonlocal_sysv_secure<mode>"
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn ("creqv 6,6,6", operands);
- return rs6000_output_call (operands, 0, false, "");
+ return rs6000_output_call (operands, 0, false);
}
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
@@ -10659,7 +10525,7 @@ (define_insn_and_split "*call_value_nonlocal_sysv<mode>"
#if TARGET_MACHO
return macho_output_call(insn, operands, 1, 3);
#else
- return rs6000_output_call (operands, 1, false, "");
+ return rs6000_output_call (operands, 1, false);
#endif
}
"DEFAULT_ABI == ABI_V4
@@ -10694,7 +10560,7 @@ (define_insn "*call_value_nonlocal_sysv_secure<mode>"
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn ("creqv 6,6,6", operands);
- return rs6000_output_call (operands, 1, false, "");
+ return rs6000_output_call (operands, 1, false);
}
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
@@ -10728,7 +10594,7 @@ (define_insn "*call_nonlocal_aix<mode>"
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
{
- return rs6000_output_call (operands, 0, false, "");
+ return rs6000_output_call (operands, 0, false);
}
[(set_attr "type" "branch")
(set_attr "length" "8")])
@@ -10740,7 +10606,7 @@ (define_insn "*call_value_nonlocal_aix<mode>"
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
{
- return rs6000_output_call (operands, 1, false, "");
+ return rs6000_output_call (operands, 1, false);
}
[(set_attr "type" "branch")
(set_attr "length" "8")])
@@ -10991,7 +10857,7 @@ (define_insn "*sibcall_nonlocal_sysv<mode>"
if (which_alternative >= 2)
return rs6000_output_indirect_call (operands, 0, true);
else
- return rs6000_output_call (operands, 0, true, "");
+ return rs6000_output_call (operands, 0, true);
}
[(set_attr "type" "branch")
(set_attr_alternative "length"
@@ -11031,7 +10897,7 @@ (define_insn "*sibcall_value_nonlocal_sysv<mode>"
return "crset 2\;beq%T1-\;b $";
}
else
- return rs6000_output_call (operands, 1, true, "");
+ return rs6000_output_call (operands, 1, true);
}
[(set_attr "type" "branch")
(set_attr_alternative "length"
@@ -11055,7 +10921,7 @@ (define_insn "*sibcall_aix<mode>"
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
{
if (which_alternative == 0)
- return rs6000_output_call (operands, 0, true, "");
+ return rs6000_output_call (operands, 0, true);
else
return "b%T0";
}
@@ -11069,7 +10935,7 @@ (define_insn "*sibcall_value_aix<mode>"
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
{
if (which_alternative == 0)
- return rs6000_output_call (operands, 1, true, "");
+ return rs6000_output_call (operands, 1, true);
else
return "b%T1";
}