@@ -111,6 +111,8 @@ 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_call_template (rtx *, unsigned int, const char *);
+extern const char *rs6000_sibcall_template (rtx *, unsigned int, const char *);
extern enum rtx_code rs6000_reverse_condition (machine_mode,
enum rtx_code);
extern rtx rs6000_emit_eqne (machine_mode, rtx, rtx, rtx);
@@ -228,7 +230,7 @@ extern void (*rs6000_target_modify_macros_ptr) (bool, HOST_WIDE_INT,
extern void rs6000_d_target_versions (void);
#if TARGET_MACHO
-char *output_call (rtx_insn *, rtx *, int, int);
+char *macho_call_template (rtx_insn *, rtx *, int, int);
#endif
#ifdef NO_DOLLAR_IN_LABEL
@@ -21372,6 +21372,50 @@ rs6000_assemble_integer (rtx x, unsigned int size, int aligned_p)
return default_assemble_integer (x, size, aligned_p);
}
+/* Return a template string for assembly to emit when making an
+ external call. FUNOP is the call mem argument operand number,
+ ARG is either NULL or a @TLSGD or @TLSLD __tls_get_addr argument
+ specifier. */
+
+static const char *
+rs6000_call_template_1 (rtx *operands ATTRIBUTE_UNUSED, unsigned int funop,
+ bool sibcall, const char *arg)
+{
+ /* -Wformat-overflow workaround, without which gcc thinks that %u
+ might produce 10 digits. */
+ gcc_assert (funop <= MAX_RECOG_OPERANDS);
+
+ /* The magic 32768 offset here corresponds to the offset of
+ r30 in .got2, as given by LCTOC1. See sysv4.h:toc_section. */
+ char z[11];
+ sprintf (z, "%%z%u%s", funop,
+ (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT && flag_pic == 2
+ ? "+32768" : ""));
+
+ static char str[32]; /* 4 spare */
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ sprintf (str, "b%s %s%s%s", sibcall ? "" : "l", z, arg,
+ sibcall ? "" : "\n\tnop");
+ else if (DEFAULT_ABI == ABI_V4)
+ sprintf (str, "b%s %s%s%s", sibcall ? "" : "l", z, arg,
+ flag_pic ? "@plt" : "");
+ else
+ gcc_unreachable ();
+ return str;
+}
+
+const char *
+rs6000_call_template (rtx *operands, unsigned int funop, const char *arg)
+{
+ return rs6000_call_template_1 (operands, funop, false, arg);
+}
+
+const char *
+rs6000_sibcall_template (rtx *operands, unsigned int funop, const char *arg)
+{
+ return rs6000_call_template_1 (operands, funop, true, arg);
+}
+
#if defined (HAVE_GAS_HIDDEN) && !TARGET_MACHO
/* Emit an assembler directive to set symbol visibility for DECL to
VISIBILITY_TYPE. */
@@ -32810,8 +32854,8 @@ get_prev_label (tree function_name)
CALL_DEST is the routine we are calling. */
char *
-output_call (rtx_insn *insn, rtx *operands, int dest_operand_number,
- int cookie_operand_number)
+macho_call_template (rtx_insn *insn, rtx *operands, int dest_operand_number,
+ int cookie_operand_number)
{
static char buf[256];
if (darwin_emit_branch_islands
@@ -9453,10 +9453,11 @@ (define_insn_and_split "tls_gd_aix<TLSmode:tls_abi_suffix>"
"HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
{
if (TARGET_CMODEL != CMODEL_SMALL)
- return "addis %0,%1,%2@got@tlsgd@ha\;addi %0,%0,%2@got@tlsgd@l\;"
- "bl %z3\;nop";
+ output_asm_insn ("addis %0,%1,%2@got@tlsgd@ha\;"
+ "addi %0,%0,%2@got@tlsgd@l", operands);
else
- return "addi %0,%1,%2@got@tlsgd\;bl %z3\;nop";
+ output_asm_insn ("addi %0,%1,%2@got@tlsgd", operands);
+ return rs6000_call_template (operands, 3, "");
}
"&& TARGET_TLS_MARKERS"
[(set (match_dup 0)
@@ -9485,15 +9486,8 @@ (define_insn_and_split "tls_gd_sysv<TLSmode:tls_sysv_suffix>"
(clobber (reg:SI LR_REGNO))]
"HAVE_AS_TLS && DEFAULT_ABI == ABI_V4"
{
- if (flag_pic)
- {
- if (TARGET_SECURE_PLT && flag_pic == 2)
- return "addi %0,%1,%2@got@tlsgd\;bl %z3+32768@plt";
- else
- return "addi %0,%1,%2@got@tlsgd\;bl %z3@plt";
- }
- else
- return "addi %0,%1,%2@got@tlsgd\;bl %z3";
+ output_asm_insn ("addi %0,%1,%2@got@tlsgd", operands);
+ return rs6000_call_template (operands, 3, "");
}
"&& TARGET_TLS_MARKERS"
[(set (match_dup 0)
@@ -9558,7 +9552,9 @@ (define_insn "*tls_gd_call_aix<TLSmode:tls_abi_suffix>"
(clobber (reg:SI LR_REGNO))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS
&& (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
- "bl %z1(%3@tlsgd)\;nop"
+{
+ return rs6000_call_template (operands, 1, "(%3@tlsgd)");
+}
[(set_attr "type" "branch")
(set_attr "length" "8")])
@@ -9571,13 +9567,7 @@ (define_insn "*tls_gd_call_sysv<TLSmode:tls_abi_suffix>"
(clobber (reg:SI LR_REGNO))]
"HAVE_AS_TLS && DEFAULT_ABI == ABI_V4 && TARGET_TLS_MARKERS"
{
- if (flag_pic)
- {
- if (TARGET_SECURE_PLT && flag_pic == 2)
- return "bl %z1+32768(%3@tlsgd)@plt";
- return "bl %z1(%3@tlsgd)@plt";
- }
- return "bl %z1(%3@tlsgd)";
+ return rs6000_call_template (operands, 1, "(%3@tlsgd)");
}
[(set_attr "type" "branch")])
@@ -9591,10 +9581,11 @@ (define_insn_and_split "tls_ld_aix<TLSmode:tls_abi_suffix>"
"HAVE_AS_TLS && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
{
if (TARGET_CMODEL != CMODEL_SMALL)
- return "addis %0,%1,%&@got@tlsld@ha\;addi %0,%0,%&@got@tlsld@l\;"
- "bl %z2\;nop";
+ output_asm_insn ("addis %0,%1,%&@got@tlsld@ha\;"
+ "addi %0,%0,%&@got@tlsld@l", operands);
else
- return "addi %0,%1,%&@got@tlsld\;bl %z2\;nop";
+ output_asm_insn ("addi %0,%1,%&@got@tlsld", operands);
+ return rs6000_call_template (operands, 2, "");
}
"&& TARGET_TLS_MARKERS"
[(set (match_dup 0)
@@ -9621,15 +9612,8 @@ (define_insn_and_split "tls_ld_sysv<TLSmode:tls_sysv_suffix>"
(clobber (reg:SI LR_REGNO))]
"HAVE_AS_TLS && DEFAULT_ABI == ABI_V4"
{
- if (flag_pic)
- {
- if (TARGET_SECURE_PLT && flag_pic == 2)
- return "addi %0,%1,%&@got@tlsld\;bl %z2+32768@plt";
- else
- return "addi %0,%1,%&@got@tlsld\;bl %z2@plt";
- }
- else
- return "addi %0,%1,%&@got@tlsld\;bl %z2";
+ output_asm_insn ("addi %0,%1,%&@got@tlsld", operands);
+ return rs6000_call_template (operands, 2, "");
}
"&& TARGET_TLS_MARKERS"
[(set (match_dup 0)
@@ -9690,7 +9674,9 @@ (define_insn "*tls_ld_call_aix<TLSmode:tls_abi_suffix>"
(clobber (reg:SI LR_REGNO))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS
&& (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)"
- "bl %z1(%&@tlsld)\;nop"
+{
+ return rs6000_call_template (operands, 1, "(%&@tlsld)");
+}
[(set_attr "type" "branch")
(set_attr "length" "8")])
@@ -9702,13 +9688,7 @@ (define_insn "*tls_ld_call_sysv<TLSmode:tls_abi_suffix>"
(clobber (reg:SI LR_REGNO))]
"HAVE_AS_TLS && DEFAULT_ABI == ABI_V4 && TARGET_TLS_MARKERS"
{
- if (flag_pic)
- {
- if (TARGET_SECURE_PLT && flag_pic == 2)
- return "bl %z1+32768(%&@tlsld)@plt";
- return "bl %z1(%&@tlsld)@plt";
- }
- return "bl %z1(%&@tlsld)";
+ return rs6000_call_template (operands, 1, "(%&@tlsld)");
}
[(set_attr "type" "branch")])
@@ -10594,15 +10574,9 @@ (define_insn_and_split "*call_nonlocal_sysv<mode>"
output_asm_insn ("creqv 6,6,6", operands);
#if TARGET_MACHO
- return output_call(insn, operands, 0, 2);
+ return macho_call_template (insn, operands, 0, 2);
#else
- if (DEFAULT_ABI == ABI_V4 && flag_pic)
- {
- gcc_assert (!TARGET_SECURE_PLT);
- return "bl %z0@plt";
- }
- else
- return "bl %z0";
+ return rs6000_call_template (operands, 0, "");
#endif
}
"DEFAULT_ABI == ABI_V4
@@ -10635,13 +10609,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);
- if (flag_pic == 2)
- /* The magic 32768 offset here and in the other sysv call insns
- corresponds to the offset of r30 in .got2, as given by LCTOC1.
- See sysv4.h:toc_section. */
- return "bl %z0+32768@plt";
- else
- return "bl %z0@plt";
+ return rs6000_call_template (operands, 0, "");
}
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
@@ -10697,15 +10665,9 @@ (define_insn_and_split "*call_value_nonlocal_sysv<mode>"
output_asm_insn ("creqv 6,6,6", operands);
#if TARGET_MACHO
- return output_call(insn, operands, 1, 3);
+ return macho_call_template (insn, operands, 1, 3);
#else
- if (DEFAULT_ABI == ABI_V4 && flag_pic)
- {
- gcc_assert (!TARGET_SECURE_PLT);
- return "bl %z1@plt";
- }
- else
- return "bl %z1";
+ return rs6000_call_template (operands, 1, "");
#endif
}
"DEFAULT_ABI == ABI_V4
@@ -10740,10 +10702,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);
- if (flag_pic == 2)
- return "bl %z1+32768@plt";
- else
- return "bl %z1@plt";
+ return rs6000_call_template (operands, 1, "");
}
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
@@ -10776,7 +10735,9 @@ (define_insn "*call_nonlocal_aix<mode>"
(match_operand 1 "" "g"))
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
- "bl %z0\;nop"
+{
+ return rs6000_call_template (operands, 0, "");
+}
[(set_attr "type" "branch")
(set_attr "length" "8")])
@@ -10786,7 +10747,9 @@ (define_insn "*call_value_nonlocal_aix<mode>"
(match_operand 2 "" "g")))
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
- "bl %z1\;nop"
+{
+ return rs6000_call_template (operands, 1, "");
+}
[(set_attr "type" "branch")
(set_attr "length" "8")])
@@ -11063,13 +11026,8 @@ (define_insn "*sibcall_nonlocal_sysv<mode>"
/* Can use CR0 since it is volatile across sibcalls. */
return "crset 2\;beq%T0-\;b $";
}
- else if (DEFAULT_ABI == ABI_V4 && flag_pic)
- {
- gcc_assert (!TARGET_SECURE_PLT);
- return "b %z0@plt";
- }
else
- return "b %z0";
+ return rs6000_sibcall_template (operands, 0, "");
}
[(set_attr "type" "branch")
(set_attr_alternative "length"
@@ -11108,13 +11066,8 @@ (define_insn "*sibcall_value_nonlocal_sysv<mode>"
/* Can use CR0 since it is volatile across sibcalls. */
return "crset 2\;beq%T1-\;b $";
}
- else if (DEFAULT_ABI == ABI_V4 && flag_pic)
- {
- gcc_assert (!TARGET_SECURE_PLT);
- return "b %z1@plt";
- }
else
- return "b %z1";
+ return rs6000_sibcall_template (operands, 1, "");
}
[(set_attr "type" "branch")
(set_attr_alternative "length"
@@ -11136,9 +11089,12 @@ (define_insn "*sibcall_aix<mode>"
(match_operand 1 "" "g,g"))
(simple_return)]
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
- "@
- b %z0
- b%T0"
+{
+ if (which_alternative == 0)
+ return rs6000_sibcall_template (operands, 0, "");
+ else
+ return "b%T0";
+}
[(set_attr "type" "branch")])
(define_insn "*sibcall_value_aix<mode>"
@@ -11147,9 +11103,12 @@ (define_insn "*sibcall_value_aix<mode>"
(match_operand 2 "" "g,g")))
(simple_return)]
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
- "@
- b %z1
- b%T1"
+{
+ if (which_alternative == 0)
+ return rs6000_sibcall_template (operands, 1, "");
+ else
+ return "b%T1";
+}
[(set_attr "type" "branch")])
(define_expand "sibcall_epilogue"