[RS6000] Use standard call patterns for __tls_get_addr calls
The current code handling __tls_get_addr calls for powerpc*-linux generates a call then overwrites the call insn with a special tls_{gd,ld}_{aix,sysv} pattern. It's done that way to support !TARGET_TLS_MARKERS, where the arg setup insns need to be emitted immediately before the branch and link. When TARGET_TLS_MARKERS, the arg setup insns are split from the actual call, but we then have a non-standard call pattern that needs to be carried through to output. This patch changes that scheme, to instead use the standard call patterns for __tls_get_addr calls, except for the now rare !TARGET_TLS_MARKERS case. Doing it this way should be better for maintenance as the !TARGET_TLS_MARKERS code can eventually disappear. It also makes it possible to support longcalls (and in following patches, inline plt calls) for __tls_get_addr without introducing yet more special call patterns. __tls_get_addr calls do however need to be different to standard calls, because when TARGET_TLS_MARKERS the calls are decorated with an argument specifier, eg. "bl __tls_get_addr(thread_var@tlsgd)" that causes a reloc to be emitted by the assembler tying the call to its arg setup insns. I chose to smuggle the arg in the currently unused stack size rtl. I've also introduced rs6000_call_sysv to generate rtl for sysv calls, as rs6000_call_aix does for aix and elfv2 calls. This allows rs6000_longcall_ref to be local to rs6000.c since the calls in the expanders never did anything for darwin. * config/rs6000/predicates.md (unspec_tls): New. * config/rs6000/rs6000-protos.h (rs6000_call_template), (rs6000_sibcall_template): Update prototype. (rs6000_longcall_ref): Delete. (rs6000_call_sysv): Declare. * config/rs6000/rs6000.c (edit_tls_call_insn): New function. (global_tlsarg): New variable. (rs6000_legitimize_tls_address): Rewrite __tls_get_addr call handling. (print_operand): Extract UNSPEC_TLSGD address operand. (rs6000_call_template, rs6000_sibcall_template): Remove arg parameter, extract from second call operand instead. (rs6000_longcall_ref): Make static, localize vars. (rs6000_call_aix): Rename parameter to reflect new usage. Take tlsarg from global_tlsarg. Don't create unused rtl or nop insns. (rs6000_sibcall_aix): Rename parameter to reflect new usage. Take tlsarg from global_tlsarg. (rs6000_call_sysv): New function. * config/rs6000/rs6000.md: Adjust rs6000_call_template and rs6000_sibcall_template throughout. (tls_gd_aix, tls_gd_sysv, tls_gd_call_aix, tls_gd_call_sysv): Delete. (tls_ld_aix, tls_ld_sysv, tls_ld_call_aix, tls_ld_call_sysv): Delete. (tls_gdld_nomark): New insn. (tls_gd): Swap operand order. Simplify mode selection. (tls_gd_high, tls_gd_low): Swap operand order. (tls_ld): Remove const_int 0 vector element from UNSPEC_TLSLD. Simplify mode selection. (tls_ld_high, tls_ld_low): Similarly adjust UNSPEC_TLSLD. (call, call_value): Don't assert for second call operand. Use rs6000_call_sysv. From-SVN: r266604
This commit is contained in:
parent
7a24893b2e
commit
ece3bca2bd
|
@ -1,3 +1,36 @@
|
|||
2018-11-29 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* config/rs6000/predicates.md (unspec_tls): New.
|
||||
* config/rs6000/rs6000-protos.h (rs6000_call_template),
|
||||
(rs6000_sibcall_template): Update prototype.
|
||||
(rs6000_longcall_ref): Delete.
|
||||
(rs6000_call_sysv): Declare.
|
||||
* config/rs6000/rs6000.c (edit_tls_call_insn): New function.
|
||||
(global_tlsarg): New variable.
|
||||
(rs6000_legitimize_tls_address): Rewrite __tls_get_addr call
|
||||
handling.
|
||||
(print_operand): Extract UNSPEC_TLSGD address operand.
|
||||
(rs6000_call_template, rs6000_sibcall_template): Remove arg
|
||||
parameter, extract from second call operand instead.
|
||||
(rs6000_longcall_ref): Make static, localize vars.
|
||||
(rs6000_call_aix): Rename parameter to reflect new usage. Take
|
||||
tlsarg from global_tlsarg. Don't create unused rtl or nop insns.
|
||||
(rs6000_sibcall_aix): Rename parameter to reflect new usage. Take
|
||||
tlsarg from global_tlsarg.
|
||||
(rs6000_call_sysv): New function.
|
||||
* config/rs6000/rs6000.md: Adjust rs6000_call_template and
|
||||
rs6000_sibcall_template throughout.
|
||||
(tls_gd_aix, tls_gd_sysv, tls_gd_call_aix, tls_gd_call_sysv): Delete.
|
||||
(tls_ld_aix, tls_ld_sysv, tls_ld_call_aix, tls_ld_call_sysv): Delete.
|
||||
(tls_gdld_nomark): New insn.
|
||||
(tls_gd): Swap operand order. Simplify mode selection.
|
||||
(tls_gd_high, tls_gd_low): Swap operand order.
|
||||
(tls_ld): Remove const_int 0 vector element from UNSPEC_TLSLD.
|
||||
Simplify mode selection.
|
||||
(tls_ld_high, tls_ld_low): Similarly adjust UNSPEC_TLSLD.
|
||||
(call, call_value): Don't assert for second call operand.
|
||||
Use rs6000_call_sysv.
|
||||
|
||||
2018-11-29 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* config/rs6000/darwin.md (call_indirect_nonlocal_darwin64),
|
||||
|
|
|
@ -997,6 +997,13 @@
|
|||
(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"
|
||||
|
|
|
@ -105,8 +105,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 const char *rs6000_call_template (rtx *, unsigned int);
|
||||
extern const char *rs6000_sibcall_template (rtx *, unsigned int);
|
||||
extern const char *rs6000_indirect_call_template (rtx *, unsigned int);
|
||||
extern const char *rs6000_indirect_sibcall_template (rtx *, unsigned int);
|
||||
extern enum rtx_code rs6000_reverse_condition (machine_mode,
|
||||
|
@ -130,7 +130,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);
|
||||
|
@ -198,6 +197,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);
|
||||
|
|
|
@ -8566,6 +8566,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. */
|
||||
|
||||
|
@ -8618,7 +8655,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
|
||||
|
@ -8658,52 +8695,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)
|
||||
{
|
||||
|
@ -21170,19 +21197,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 '&':
|
||||
|
@ -21368,18 +21395,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. FUNOP is the call mem argument operand number,
|
||||
ARG is either NULL or a @TLSGD or @TLSLD __tls_get_addr argument
|
||||
specifier. */
|
||||
external call. FUNOP is the call mem argument operand number. */
|
||||
|
||||
static const char *
|
||||
rs6000_call_template_1 (rtx *operands ATTRIBUTE_UNUSED, unsigned int funop,
|
||||
bool sibcall, const char *arg)
|
||||
rs6000_call_template_1 (rtx *operands, unsigned int funop, bool sibcall)
|
||||
{
|
||||
/* -Wformat-overflow workaround, without which gcc thinks that %u
|
||||
might produce 10 digits. */
|
||||
gcc_assert (funop <= MAX_RECOG_OPERANDS);
|
||||
|
||||
char arg[12];
|
||||
arg[0] = 0;
|
||||
if (TARGET_TLS_MARKERS && GET_CODE (operands[funop + 1]) == UNSPEC)
|
||||
{
|
||||
if (XINT (operands[funop + 1], 1) == UNSPEC_TLSGD)
|
||||
sprintf (arg, "(%%%u@tlsgd)", funop + 1);
|
||||
else if (XINT (operands[funop + 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[11];
|
||||
|
@ -21387,7 +21423,7 @@ rs6000_call_template_1 (rtx *operands ATTRIBUTE_UNUSED, unsigned int funop,
|
|||
(DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT && flag_pic == 2
|
||||
? "+32768" : ""));
|
||||
|
||||
static char str[32]; /* 4 spare */
|
||||
static char str[32]; /* 2 spare */
|
||||
if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
|
||||
sprintf (str, "b%s %s%s%s", sibcall ? "" : "l", z, arg,
|
||||
sibcall ? "" : "\n\tnop");
|
||||
|
@ -21400,15 +21436,15 @@ rs6000_call_template_1 (rtx *operands ATTRIBUTE_UNUSED, unsigned int funop,
|
|||
}
|
||||
|
||||
const char *
|
||||
rs6000_call_template (rtx *operands, unsigned int funop, const char *arg)
|
||||
rs6000_call_template (rtx *operands, unsigned int funop)
|
||||
{
|
||||
return rs6000_call_template_1 (operands, funop, false, arg);
|
||||
return rs6000_call_template_1 (operands, funop, false);
|
||||
}
|
||||
|
||||
const char *
|
||||
rs6000_sibcall_template (rtx *operands, unsigned int funop, const char *arg)
|
||||
rs6000_sibcall_template (rtx *operands, unsigned int funop)
|
||||
{
|
||||
return rs6000_call_template_1 (operands, funop, true, arg);
|
||||
return rs6000_call_template_1 (operands, funop, true);
|
||||
}
|
||||
|
||||
/* As above, for indirect calls. */
|
||||
|
@ -32498,23 +32534,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));
|
||||
}
|
||||
|
||||
|
@ -37485,7 +37518,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);
|
||||
|
@ -37498,6 +37531,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);
|
||||
|
@ -37508,11 +37544,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);
|
||||
|
@ -37524,6 +37556,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);
|
||||
}
|
||||
|
@ -37533,7 +37569,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
|
||||
|
@ -37588,7 +37625,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;
|
||||
|
@ -37612,15 +37649,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]);
|
||||
|
||||
|
@ -37633,6 +37673,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. */
|
||||
|
||||
|
|
|
@ -9422,74 +9422,51 @@
|
|||
|
||||
;; TLS support.
|
||||
|
||||
(define_insn_and_split "tls_gd_aix<bits>"
|
||||
[(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_nomark<bits>"
|
||||
[(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_DARWIN"
|
||||
{
|
||||
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_call_template (operands, 3, "");
|
||||
{
|
||||
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_call_template (operands, 1);
|
||||
}
|
||||
"&& 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<mode>"
|
||||
[(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"
|
||||
{
|
||||
output_asm_insn ("addi %0,%1,%2@got@tlsgd", operands);
|
||||
return rs6000_call_template (operands, 3, "");
|
||||
}
|
||||
"&& 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")])
|
||||
(cond [(match_test "TARGET_CMODEL != CMODEL_SMALL")
|
||||
(const_int 16)
|
||||
(match_test "DEFAULT_ABI != ABI_V4")
|
||||
(const_int 12)]
|
||||
(const_int 8)))])
|
||||
|
||||
(define_insn_and_split "*tls_gd<bits>"
|
||||
[(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
|
||||
|
@ -9498,7 +9475,7 @@
|
|||
(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"))
|
||||
|
@ -9508,105 +9485,21 @@
|
|||
(define_insn "*tls_gd_high<bits>"
|
||||
[(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<bits>"
|
||||
[(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<bits>"
|
||||
[(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_call_template (operands, 1, "(%3@tlsgd)");
|
||||
}
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
(define_insn "*tls_gd_call_sysv<bits>"
|
||||
[(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_call_template (operands, 1, "(%3@tlsgd)");
|
||||
}
|
||||
[(set_attr "type" "branch")])
|
||||
|
||||
(define_insn_and_split "tls_ld_aix<bits>"
|
||||
[(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_call_template (operands, 2, "");
|
||||
}
|
||||
"&& 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<mode>"
|
||||
[(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_call_template (operands, 2, "");
|
||||
}
|
||||
"&& 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<bits>"
|
||||
[(set (match_operand:P 0 "gpc_reg_operand" "=b")
|
||||
(unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")]
|
||||
|
@ -9616,12 +9509,12 @@
|
|||
"&& 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"))
|
||||
|
@ -9631,8 +9524,7 @@
|
|||
(define_insn "*tls_ld_high<bits>"
|
||||
[(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")
|
||||
|
@ -9640,38 +9532,11 @@
|
|||
(define_insn "*tls_ld_low<bits>"
|
||||
[(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<bits>"
|
||||
[(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_call_template (operands, 1, "(%&@tlsld)");
|
||||
}
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
(define_insn "*tls_ld_call_sysv<bits>"
|
||||
[(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_call_template (operands, 1, "(%&@tlsld)");
|
||||
}
|
||||
[(set_attr "type" "branch")])
|
||||
|
||||
(define_insn "tls_dtprel_<bits>"
|
||||
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
|
||||
(unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")
|
||||
|
@ -10345,7 +10210,6 @@
|
|||
#endif
|
||||
|
||||
gcc_assert (GET_CODE (operands[0]) == MEM);
|
||||
gcc_assert (GET_CODE (operands[1]) == CONST_INT);
|
||||
|
||||
operands[0] = XEXP (operands[0], 0);
|
||||
|
||||
|
@ -10355,23 +10219,14 @@
|
|||
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"
|
||||
|
@ -10388,7 +10243,6 @@
|
|||
#endif
|
||||
|
||||
gcc_assert (GET_CODE (operands[1]) == MEM);
|
||||
gcc_assert (GET_CODE (operands[2]) == CONST_INT);
|
||||
|
||||
operands[1] = XEXP (operands[1], 0);
|
||||
|
||||
|
@ -10398,23 +10252,14 @@
|
|||
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.
|
||||
|
@ -10501,7 +10346,7 @@
|
|||
|
||||
;; 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
|
||||
|
||||
|
@ -10552,7 +10397,7 @@
|
|||
#if TARGET_MACHO
|
||||
return macho_call_template (insn, operands, 0, 2);
|
||||
#else
|
||||
return rs6000_call_template (operands, 0, "");
|
||||
return rs6000_call_template (operands, 0);
|
||||
#endif
|
||||
}
|
||||
"DEFAULT_ABI == ABI_V4
|
||||
|
@ -10585,7 +10430,7 @@
|
|||
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
|
||||
output_asm_insn ("creqv 6,6,6", operands);
|
||||
|
||||
return rs6000_call_template (operands, 0, "");
|
||||
return rs6000_call_template (operands, 0);
|
||||
}
|
||||
[(set_attr "type" "branch,branch")
|
||||
(set_attr "length" "4,8")])
|
||||
|
@ -10639,7 +10484,7 @@
|
|||
#if TARGET_MACHO
|
||||
return macho_call_template (insn, operands, 1, 3);
|
||||
#else
|
||||
return rs6000_call_template (operands, 1, "");
|
||||
return rs6000_call_template (operands, 1);
|
||||
#endif
|
||||
}
|
||||
"DEFAULT_ABI == ABI_V4
|
||||
|
@ -10674,7 +10519,7 @@
|
|||
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
|
||||
output_asm_insn ("creqv 6,6,6", operands);
|
||||
|
||||
return rs6000_call_template (operands, 1, "");
|
||||
return rs6000_call_template (operands, 1);
|
||||
}
|
||||
[(set_attr "type" "branch,branch")
|
||||
(set_attr "length" "4,8")])
|
||||
|
@ -10708,7 +10553,7 @@
|
|||
(clobber (reg:P LR_REGNO))]
|
||||
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
|
||||
{
|
||||
return rs6000_call_template (operands, 0, "");
|
||||
return rs6000_call_template (operands, 0);
|
||||
}
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "8")])
|
||||
|
@ -10720,7 +10565,7 @@
|
|||
(clobber (reg:P LR_REGNO))]
|
||||
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
|
||||
{
|
||||
return rs6000_call_template (operands, 1, "");
|
||||
return rs6000_call_template (operands, 1);
|
||||
}
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "8")])
|
||||
|
@ -10971,7 +10816,7 @@
|
|||
if (which_alternative >= 2)
|
||||
return rs6000_indirect_sibcall_template (operands, 0);
|
||||
else
|
||||
return rs6000_sibcall_template (operands, 0, "");
|
||||
return rs6000_sibcall_template (operands, 0);
|
||||
}
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr_alternative "length"
|
||||
|
@ -11011,7 +10856,7 @@
|
|||
return "crset 2\;beq%T1-\;b $";
|
||||
}
|
||||
else
|
||||
return rs6000_sibcall_template (operands, 1, "");
|
||||
return rs6000_sibcall_template (operands, 1);
|
||||
}
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr_alternative "length"
|
||||
|
@ -11035,7 +10880,7 @@
|
|||
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
|
||||
{
|
||||
if (which_alternative == 0)
|
||||
return rs6000_sibcall_template (operands, 0, "");
|
||||
return rs6000_sibcall_template (operands, 0);
|
||||
else
|
||||
return "b%T0";
|
||||
}
|
||||
|
@ -11049,7 +10894,7 @@
|
|||
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
|
||||
{
|
||||
if (which_alternative == 0)
|
||||
return rs6000_sibcall_template (operands, 1, "");
|
||||
return rs6000_sibcall_template (operands, 1);
|
||||
else
|
||||
return "b%T1";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue