rs6000.c (rs6000_call_indirect_aix): Rename to ...
2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> * config/rs6000/rs6000.c (rs6000_call_indirect_aix): Rename to ... (rs6000_call_aix): ... this. Handle both direct and indirect calls. Create call insn directly instead of via various gen_... routines. Mention special registers used by the call in CALL_INSN_FUNCTION_USAGE. (rs6000_sibcall_aix): New function. * config/rs6000/rs6000.md (TOC_SAVE_OFFSET_32BIT): Remove. (TOC_SAVE_OFFSET_64BIT): Likewise. (AIX_FUNC_DESC_TOC_32BIT): Likewise. (AIX_FUNC_DESC_TOC_64BIT): Likewise. (AIX_FUNC_DESC_SC_32BIT): Likewise. (AIX_FUNC_DESC_SC_64BIT): Likewise. ("call" expander): Call rs6000_call_aix. ("call_value" expander): Likewise. ("call_indirect_aix<ptrsize>"): Replace this pattern ... ("call_indirect_aix<ptrsize>_nor11"): ... and this pattern ... ("*call_indirect_aix<mode>"): ... by this insn pattern. ("call_value_indirect_aix<ptrsize>"): Replace this pattern ... ("call_value_indirect_aix<ptrsize>_nor11"): ... and this pattern ... ("*call_value_indirect_aix<mode>"): ... by this insn pattern. ("*call_nonlocal_aix32", "*call_nonlocal_aix64"): Replace by ... ("*call_nonlocal_aix<mode>"): ... this pattern. ("*call_value_nonlocal_aix32", "*call_value_nonlocal_aix64"): Replace ("*call_value_nonlocal_aix<mode>"): ... by this pattern. ("*call_local_aix<mode>"): New insn pattern. ("*call_value_local_aix<mode>"): Likewise. ("sibcall" expander): Call rs6000_sibcall_aix. ("sibcall_value" expander): Likewise. Move earlier in file. ("*sibcall_nonlocal_aix<mode>"): Replace by ... ("*sibcall_aix<mode>"): ... this pattern. ("*sibcall_value_nonlocal_aix<mode>"): Replace by ... ("*sibcall_value_aix<mode>"): ... this pattern. * config/rs6000/rs6000-protos.h (rs6000_call_indirect_aix): Remove. (rs6000_call_aix): Add prototype. (rs6000_sibcall_aix): Likewise. From-SVN: r204803
This commit is contained in:
parent
4f883df12f
commit
f90f960ca8
4 changed files with 295 additions and 300 deletions
|
@ -1,3 +1,40 @@
|
|||
2013-11-14 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
|
||||
|
||||
* config/rs6000/rs6000.c (rs6000_call_indirect_aix): Rename to ...
|
||||
(rs6000_call_aix): ... this. Handle both direct and indirect calls.
|
||||
Create call insn directly instead of via various gen_... routines.
|
||||
Mention special registers used by the call in CALL_INSN_FUNCTION_USAGE.
|
||||
(rs6000_sibcall_aix): New function.
|
||||
* config/rs6000/rs6000.md (TOC_SAVE_OFFSET_32BIT): Remove.
|
||||
(TOC_SAVE_OFFSET_64BIT): Likewise.
|
||||
(AIX_FUNC_DESC_TOC_32BIT): Likewise.
|
||||
(AIX_FUNC_DESC_TOC_64BIT): Likewise.
|
||||
(AIX_FUNC_DESC_SC_32BIT): Likewise.
|
||||
(AIX_FUNC_DESC_SC_64BIT): Likewise.
|
||||
("call" expander): Call rs6000_call_aix.
|
||||
("call_value" expander): Likewise.
|
||||
("call_indirect_aix<ptrsize>"): Replace this pattern ...
|
||||
("call_indirect_aix<ptrsize>_nor11"): ... and this pattern ...
|
||||
("*call_indirect_aix<mode>"): ... by this insn pattern.
|
||||
("call_value_indirect_aix<ptrsize>"): Replace this pattern ...
|
||||
("call_value_indirect_aix<ptrsize>_nor11"): ... and this pattern ...
|
||||
("*call_value_indirect_aix<mode>"): ... by this insn pattern.
|
||||
("*call_nonlocal_aix32", "*call_nonlocal_aix64"): Replace by ...
|
||||
("*call_nonlocal_aix<mode>"): ... this pattern.
|
||||
("*call_value_nonlocal_aix32", "*call_value_nonlocal_aix64"): Replace
|
||||
("*call_value_nonlocal_aix<mode>"): ... by this pattern.
|
||||
("*call_local_aix<mode>"): New insn pattern.
|
||||
("*call_value_local_aix<mode>"): Likewise.
|
||||
("sibcall" expander): Call rs6000_sibcall_aix.
|
||||
("sibcall_value" expander): Likewise. Move earlier in file.
|
||||
("*sibcall_nonlocal_aix<mode>"): Replace by ...
|
||||
("*sibcall_aix<mode>"): ... this pattern.
|
||||
("*sibcall_value_nonlocal_aix<mode>"): Replace by ...
|
||||
("*sibcall_value_aix<mode>"): ... this pattern.
|
||||
* config/rs6000/rs6000-protos.h (rs6000_call_indirect_aix): Remove.
|
||||
(rs6000_call_aix): Add prototype.
|
||||
(rs6000_sibcall_aix): Likewise.
|
||||
|
||||
2013-11-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR sanitizer/59122
|
||||
|
|
|
@ -182,7 +182,8 @@ extern unsigned int rs6000_dbx_register_number (unsigned int);
|
|||
extern void rs6000_emit_epilogue (int);
|
||||
extern void rs6000_emit_eh_reg_restore (rtx, rtx);
|
||||
extern const char * output_isel (rtx *);
|
||||
extern void rs6000_call_indirect_aix (rtx, rtx, rtx);
|
||||
extern void rs6000_call_aix (rtx, rtx, rtx, rtx);
|
||||
extern void rs6000_sibcall_aix (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);
|
||||
|
|
|
@ -30604,118 +30604,138 @@ rs6000_legitimate_constant_p (enum machine_mode mode, rtx x)
|
|||
}
|
||||
|
||||
|
||||
/* A function pointer under AIX is a pointer to a data area whose first word
|
||||
contains the actual address of the function, whose second word contains a
|
||||
pointer to its TOC, and whose third word contains a value to place in the
|
||||
static chain register (r11). Note that if we load the static chain, our
|
||||
"trampoline" need not have any executable code. */
|
||||
|
||||
/* Expand code to perform a call under the AIX ABI. */
|
||||
|
||||
void
|
||||
rs6000_call_indirect_aix (rtx value, rtx func_desc, rtx flag)
|
||||
rs6000_call_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
|
||||
{
|
||||
rtx toc_reg = gen_rtx_REG (Pmode, TOC_REGNUM);
|
||||
rtx toc_load = NULL_RTX;
|
||||
rtx toc_restore = NULL_RTX;
|
||||
rtx func_addr;
|
||||
rtx toc_reg;
|
||||
rtx sc_reg;
|
||||
rtx stack_ptr;
|
||||
rtx stack_toc_offset;
|
||||
rtx stack_toc_mem;
|
||||
rtx func_toc_offset;
|
||||
rtx func_toc_mem;
|
||||
rtx func_sc_offset;
|
||||
rtx func_sc_mem;
|
||||
rtx abi_reg = NULL_RTX;
|
||||
rtx call[4];
|
||||
int n_call;
|
||||
rtx insn;
|
||||
rtx (*call_func) (rtx, rtx, rtx, rtx);
|
||||
rtx (*call_value_func) (rtx, rtx, rtx, rtx, rtx);
|
||||
|
||||
stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
|
||||
toc_reg = gen_rtx_REG (Pmode, TOC_REGNUM);
|
||||
/* Handle longcall attributes. */
|
||||
if (INTVAL (cookie) & CALL_LONG)
|
||||
func_desc = rs6000_longcall_ref (func_desc);
|
||||
|
||||
/* Load up address of the actual function. */
|
||||
func_desc = force_reg (Pmode, func_desc);
|
||||
func_addr = gen_reg_rtx (Pmode);
|
||||
emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func_desc));
|
||||
|
||||
if (TARGET_32BIT)
|
||||
/* Handle indirect calls. */
|
||||
if (GET_CODE (func_desc) != SYMBOL_REF
|
||||
|| !SYMBOL_REF_FUNCTION_P (func_desc))
|
||||
{
|
||||
/* 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 (5 * GET_MODE_SIZE (Pmode));
|
||||
rtx stack_toc_mem = gen_frame_mem (Pmode,
|
||||
gen_rtx_PLUS (Pmode, stack_ptr,
|
||||
stack_toc_offset));
|
||||
toc_restore = gen_rtx_SET (VOIDmode, toc_reg, stack_toc_mem);
|
||||
|
||||
stack_toc_offset = GEN_INT (TOC_SAVE_OFFSET_32BIT);
|
||||
func_toc_offset = GEN_INT (AIX_FUNC_DESC_TOC_32BIT);
|
||||
func_sc_offset = GEN_INT (AIX_FUNC_DESC_SC_32BIT);
|
||||
if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
|
||||
{
|
||||
call_func = gen_call_indirect_aix32bit;
|
||||
call_value_func = gen_call_value_indirect_aix32bit;
|
||||
}
|
||||
/* Can we optimize saving the TOC in the prologue or
|
||||
do we need to do it at every call? */
|
||||
if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca)
|
||||
cfun->machine->save_toc_in_prologue = true;
|
||||
else
|
||||
{
|
||||
call_func = gen_call_indirect_aix32bit_nor11;
|
||||
call_value_func = gen_call_value_indirect_aix32bit_nor11;
|
||||
MEM_VOLATILE_P (stack_toc_mem) = 1;
|
||||
emit_move_insn (stack_toc_mem, toc_reg);
|
||||
}
|
||||
|
||||
/* A function pointer under AIX is a pointer to a data area whose
|
||||
first word contains the actual address of the function, whose
|
||||
second word contains a pointer to its TOC, and whose third word
|
||||
contains a value to place in the static chain register (r11).
|
||||
Note that if we load the static chain, our "trampoline" need
|
||||
not have any executable code. */
|
||||
|
||||
/* Load up address of the actual function. */
|
||||
func_desc = force_reg (Pmode, func_desc);
|
||||
func_addr = gen_reg_rtx (Pmode);
|
||||
emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func_desc));
|
||||
|
||||
/* Prepare to load the TOC of the called function. Note that the
|
||||
TOC load must happen immediately before the actual call so
|
||||
that unwinding the TOC registers works correctly. See the
|
||||
comment in frob_update_context. */
|
||||
rtx func_toc_offset = GEN_INT (GET_MODE_SIZE (Pmode));
|
||||
rtx func_toc_mem = gen_rtx_MEM (Pmode,
|
||||
gen_rtx_PLUS (Pmode, func_desc,
|
||||
func_toc_offset));
|
||||
toc_load = gen_rtx_USE (VOIDmode, func_toc_mem);
|
||||
|
||||
/* If we have a static chain, load it up. */
|
||||
if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
|
||||
{
|
||||
rtx sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
|
||||
rtx func_sc_offset = GEN_INT (2 * GET_MODE_SIZE (Pmode));
|
||||
rtx func_sc_mem = gen_rtx_MEM (Pmode,
|
||||
gen_rtx_PLUS (Pmode, func_desc,
|
||||
func_sc_offset));
|
||||
emit_move_insn (sc_reg, func_sc_mem);
|
||||
abi_reg = sc_reg;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stack_toc_offset = GEN_INT (TOC_SAVE_OFFSET_64BIT);
|
||||
func_toc_offset = GEN_INT (AIX_FUNC_DESC_TOC_64BIT);
|
||||
func_sc_offset = GEN_INT (AIX_FUNC_DESC_SC_64BIT);
|
||||
if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
|
||||
{
|
||||
call_func = gen_call_indirect_aix64bit;
|
||||
call_value_func = gen_call_value_indirect_aix64bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
call_func = gen_call_indirect_aix64bit_nor11;
|
||||
call_value_func = gen_call_value_indirect_aix64bit_nor11;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reserved spot to store the TOC. */
|
||||
stack_toc_mem = gen_frame_mem (Pmode,
|
||||
gen_rtx_PLUS (Pmode,
|
||||
stack_ptr,
|
||||
stack_toc_offset));
|
||||
|
||||
gcc_assert (cfun);
|
||||
gcc_assert (cfun->machine);
|
||||
|
||||
/* Can we optimize saving the TOC in the prologue or do we need to do it at
|
||||
every call? */
|
||||
if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca)
|
||||
cfun->machine->save_toc_in_prologue = true;
|
||||
|
||||
else
|
||||
{
|
||||
MEM_VOLATILE_P (stack_toc_mem) = 1;
|
||||
emit_move_insn (stack_toc_mem, toc_reg);
|
||||
}
|
||||
|
||||
/* Calculate the address to load the TOC of the called function. We don't
|
||||
actually load this until the split after reload. */
|
||||
func_toc_mem = gen_rtx_MEM (Pmode,
|
||||
gen_rtx_PLUS (Pmode,
|
||||
func_desc,
|
||||
func_toc_offset));
|
||||
|
||||
/* If we have a static chain, load it up. */
|
||||
if (TARGET_POINTERS_TO_NESTED_FUNCTIONS)
|
||||
{
|
||||
func_sc_mem = gen_rtx_MEM (Pmode,
|
||||
gen_rtx_PLUS (Pmode,
|
||||
func_desc,
|
||||
func_sc_offset));
|
||||
|
||||
sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
|
||||
emit_move_insn (sc_reg, func_sc_mem);
|
||||
/* Direct calls use the TOC: for local calls, the callee will
|
||||
assume the TOC register is set; for non-local calls, the
|
||||
PLT stub needs the TOC register. */
|
||||
abi_reg = toc_reg;
|
||||
func_addr = func_desc;
|
||||
}
|
||||
|
||||
/* Create the call. */
|
||||
if (value)
|
||||
insn = call_value_func (value, func_addr, flag, func_toc_mem,
|
||||
stack_toc_mem);
|
||||
else
|
||||
insn = call_func (func_addr, flag, func_toc_mem, stack_toc_mem);
|
||||
call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_addr), flag);
|
||||
if (value != NULL_RTX)
|
||||
call[0] = gen_rtx_SET (VOIDmode, value, call[0]);
|
||||
n_call = 1;
|
||||
|
||||
emit_call_insn (insn);
|
||||
if (toc_load)
|
||||
call[n_call++] = toc_load;
|
||||
if (toc_restore)
|
||||
call[n_call++] = toc_restore;
|
||||
|
||||
call[n_call++] = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
|
||||
|
||||
insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (n_call, call));
|
||||
insn = emit_call_insn (insn);
|
||||
|
||||
/* Mention all registers defined by the ABI to hold information
|
||||
as uses in CALL_INSN_FUNCTION_USAGE. */
|
||||
if (abi_reg)
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), abi_reg);
|
||||
}
|
||||
|
||||
/* Expand code to perform a sibling call under the AIX ABI. */
|
||||
|
||||
void
|
||||
rs6000_sibcall_aix (rtx value, rtx func_desc, rtx flag, rtx cookie)
|
||||
{
|
||||
rtx call[2];
|
||||
rtx insn;
|
||||
|
||||
gcc_assert (INTVAL (cookie) == 0);
|
||||
|
||||
/* Create the call. */
|
||||
call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_desc), flag);
|
||||
if (value != NULL_RTX)
|
||||
call[0] = gen_rtx_SET (VOIDmode, value, call[0]);
|
||||
|
||||
call[1] = simple_return_rtx;
|
||||
|
||||
insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (2, call));
|
||||
insn = emit_call_insn (insn);
|
||||
|
||||
/* Note use of the TOC register. */
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, TOC_REGNUM));
|
||||
/* We need to also mark a use of the link register since the function we
|
||||
sibling-call to will use it to return to our caller. */
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, LR_REGNO));
|
||||
}
|
||||
|
||||
/* Return whether we need to always update the saved TOC pointer when we update
|
||||
|
|
|
@ -56,18 +56,6 @@
|
|||
(TFHAR_REGNO 114)
|
||||
(TFIAR_REGNO 115)
|
||||
(TEXASR_REGNO 116)
|
||||
|
||||
; ABI defined stack offsets for storing the TOC pointer with AIX calls.
|
||||
(TOC_SAVE_OFFSET_32BIT 20)
|
||||
(TOC_SAVE_OFFSET_64BIT 40)
|
||||
|
||||
; Function TOC offset in the AIX function descriptor.
|
||||
(AIX_FUNC_DESC_TOC_32BIT 4)
|
||||
(AIX_FUNC_DESC_TOC_64BIT 8)
|
||||
|
||||
; Static chain offset in the AIX function descriptor.
|
||||
(AIX_FUNC_DESC_SC_32BIT 8)
|
||||
(AIX_FUNC_DESC_SC_64BIT 16)
|
||||
])
|
||||
|
||||
;;
|
||||
|
@ -12093,8 +12081,13 @@
|
|||
|
||||
operands[0] = XEXP (operands[0], 0);
|
||||
|
||||
if (DEFAULT_ABI == ABI_AIX)
|
||||
{
|
||||
rs6000_call_aix (NULL_RTX, operands[0], operands[1], operands[2]);
|
||||
DONE;
|
||||
}
|
||||
|
||||
if (GET_CODE (operands[0]) != SYMBOL_REF
|
||||
|| (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[0]))
|
||||
|| (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0))
|
||||
{
|
||||
if (INTVAL (operands[2]) & CALL_LONG)
|
||||
|
@ -12107,12 +12100,6 @@
|
|||
operands[0] = force_reg (Pmode, operands[0]);
|
||||
break;
|
||||
|
||||
case ABI_AIX:
|
||||
/* AIX function pointers are really pointers to a three word
|
||||
area. */
|
||||
rs6000_call_indirect_aix (NULL_RTX, operands[0], operands[1]);
|
||||
DONE;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -12138,8 +12125,13 @@
|
|||
|
||||
operands[1] = XEXP (operands[1], 0);
|
||||
|
||||
if (DEFAULT_ABI == ABI_AIX)
|
||||
{
|
||||
rs6000_call_aix (operands[0], operands[1], operands[2], operands[3]);
|
||||
DONE;
|
||||
}
|
||||
|
||||
if (GET_CODE (operands[1]) != SYMBOL_REF
|
||||
|| (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[1]))
|
||||
|| (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0))
|
||||
{
|
||||
if (INTVAL (operands[3]) & CALL_LONG)
|
||||
|
@ -12152,12 +12144,6 @@
|
|||
operands[1] = force_reg (Pmode, operands[1]);
|
||||
break;
|
||||
|
||||
case ABI_AIX:
|
||||
/* AIX function pointers are really pointers to a three word
|
||||
area. */
|
||||
rs6000_call_indirect_aix (operands[0], operands[1], operands[2]);
|
||||
DONE;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -12249,135 +12235,6 @@
|
|||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4,8")])
|
||||
|
||||
;; Call to indirect functions with the AIX abi using a 3 word descriptor.
|
||||
;; Operand0 is the addresss of the function to call
|
||||
;; Operand1 is the flag for System V.4 for unprototyped or FP registers
|
||||
;; Operand2 is the location in the function descriptor to load r2 from
|
||||
;; Operand3 is the stack location to hold the current TOC pointer
|
||||
|
||||
(define_insn "call_indirect_aix<ptrsize>"
|
||||
[(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
|
||||
(match_operand 1 "" "g,g"))
|
||||
(use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
|
||||
(set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
|
||||
(use (reg:P STATIC_CHAIN_REGNUM))
|
||||
(clobber (reg:P LR_REGNO))]
|
||||
"DEFAULT_ABI == ABI_AIX && TARGET_POINTERS_TO_NESTED_FUNCTIONS"
|
||||
"<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3"
|
||||
[(set_attr "type" "jmpreg")
|
||||
(set_attr "length" "12")])
|
||||
|
||||
;; Like call_indirect_aix<ptrsize>, but no use of the static chain
|
||||
;; Operand0 is the addresss of the function to call
|
||||
;; Operand1 is the flag for System V.4 for unprototyped or FP registers
|
||||
;; Operand2 is the location in the function descriptor to load r2 from
|
||||
;; Operand3 is the stack location to hold the current TOC pointer
|
||||
|
||||
(define_insn "call_indirect_aix<ptrsize>_nor11"
|
||||
[(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
|
||||
(match_operand 1 "" "g,g"))
|
||||
(use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
|
||||
(set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
|
||||
(clobber (reg:P LR_REGNO))]
|
||||
"DEFAULT_ABI == ABI_AIX && !TARGET_POINTERS_TO_NESTED_FUNCTIONS"
|
||||
"<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3"
|
||||
[(set_attr "type" "jmpreg")
|
||||
(set_attr "length" "12")])
|
||||
|
||||
;; Operand0 is the return result of the function
|
||||
;; Operand1 is the addresss of the function to call
|
||||
;; Operand2 is the flag for System V.4 for unprototyped or FP registers
|
||||
;; Operand3 is the location in the function descriptor to load r2 from
|
||||
;; Operand4 is the stack location to hold the current TOC pointer
|
||||
|
||||
(define_insn "call_value_indirect_aix<ptrsize>"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
|
||||
(match_operand 2 "" "g,g")))
|
||||
(use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
|
||||
(set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>"))
|
||||
(use (reg:P STATIC_CHAIN_REGNUM))
|
||||
(clobber (reg:P LR_REGNO))]
|
||||
"DEFAULT_ABI == ABI_AIX && TARGET_POINTERS_TO_NESTED_FUNCTIONS"
|
||||
"<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4"
|
||||
[(set_attr "type" "jmpreg")
|
||||
(set_attr "length" "12")])
|
||||
|
||||
;; Like call_value_indirect_aix<ptrsize>, but no use of the static chain
|
||||
;; Operand0 is the return result of the function
|
||||
;; Operand1 is the addresss of the function to call
|
||||
;; Operand2 is the flag for System V.4 for unprototyped or FP registers
|
||||
;; Operand3 is the location in the function descriptor to load r2 from
|
||||
;; Operand4 is the stack location to hold the current TOC pointer
|
||||
|
||||
(define_insn "call_value_indirect_aix<ptrsize>_nor11"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
|
||||
(match_operand 2 "" "g,g")))
|
||||
(use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
|
||||
(set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>"))
|
||||
(clobber (reg:P LR_REGNO))]
|
||||
"DEFAULT_ABI == ABI_AIX && !TARGET_POINTERS_TO_NESTED_FUNCTIONS"
|
||||
"<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4"
|
||||
[(set_attr "type" "jmpreg")
|
||||
(set_attr "length" "12")])
|
||||
|
||||
;; Call to function which may be in another module. Restore the TOC
|
||||
;; pointer (r2) after the call unless this is System V.
|
||||
;; Operand2 is nonzero if we are using the V.4 calling sequence and
|
||||
;; either the function was not prototyped, or it was prototyped as a
|
||||
;; variable argument function. It is > 0 if FP registers were passed
|
||||
;; and < 0 if they were not.
|
||||
|
||||
(define_insn "*call_nonlocal_aix32"
|
||||
[(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s"))
|
||||
(match_operand 1 "" "g"))
|
||||
(use (match_operand:SI 2 "immediate_operand" "O"))
|
||||
(clobber (reg:SI LR_REGNO))]
|
||||
"TARGET_32BIT
|
||||
&& DEFAULT_ABI == ABI_AIX
|
||||
&& (INTVAL (operands[2]) & CALL_LONG) == 0"
|
||||
"bl %z0\;nop"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
(define_insn "*call_nonlocal_aix64"
|
||||
[(call (mem:SI (match_operand:DI 0 "symbol_ref_operand" "s"))
|
||||
(match_operand 1 "" "g"))
|
||||
(use (match_operand:SI 2 "immediate_operand" "O"))
|
||||
(clobber (reg:SI LR_REGNO))]
|
||||
"TARGET_64BIT
|
||||
&& DEFAULT_ABI == ABI_AIX
|
||||
&& (INTVAL (operands[2]) & CALL_LONG) == 0"
|
||||
"bl %z0\;nop"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
(define_insn "*call_value_nonlocal_aix32"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s"))
|
||||
(match_operand 2 "" "g")))
|
||||
(use (match_operand:SI 3 "immediate_operand" "O"))
|
||||
(clobber (reg:SI LR_REGNO))]
|
||||
"TARGET_32BIT
|
||||
&& DEFAULT_ABI == ABI_AIX
|
||||
&& (INTVAL (operands[3]) & CALL_LONG) == 0"
|
||||
"bl %z1\;nop"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
(define_insn "*call_value_nonlocal_aix64"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:DI 1 "symbol_ref_operand" "s"))
|
||||
(match_operand 2 "" "g")))
|
||||
(use (match_operand:SI 3 "immediate_operand" "O"))
|
||||
(clobber (reg:SI LR_REGNO))]
|
||||
"TARGET_64BIT
|
||||
&& DEFAULT_ABI == ABI_AIX
|
||||
&& (INTVAL (operands[3]) & CALL_LONG) == 0"
|
||||
"bl %z1\;nop"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
;; A function pointer under System V is just a normal pointer
|
||||
;; operands[0] is the function pointer
|
||||
|
@ -12560,6 +12417,79 @@
|
|||
[(set_attr "type" "branch,branch")
|
||||
(set_attr "length" "4,8")])
|
||||
|
||||
|
||||
;; Call to AIX abi function in the same module.
|
||||
|
||||
(define_insn "*call_local_aix<mode>"
|
||||
[(call (mem:SI (match_operand:P 0 "current_file_function_operand" "s"))
|
||||
(match_operand 1 "" "g"))
|
||||
(clobber (reg:P LR_REGNO))]
|
||||
"DEFAULT_ABI == ABI_AIX"
|
||||
"bl %z0"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*call_value_local_aix<mode>"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:P 1 "current_file_function_operand" "s"))
|
||||
(match_operand 2 "" "g")))
|
||||
(clobber (reg:P LR_REGNO))]
|
||||
"DEFAULT_ABI == ABI_AIX"
|
||||
"bl %z1"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4")])
|
||||
|
||||
;; Call to AIX abi function which may be in another module.
|
||||
;; Restore the TOC pointer (r2) after the call.
|
||||
|
||||
(define_insn "*call_nonlocal_aix<mode>"
|
||||
[(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s"))
|
||||
(match_operand 1 "" "g"))
|
||||
(clobber (reg:P LR_REGNO))]
|
||||
"DEFAULT_ABI == ABI_AIX"
|
||||
"bl %z0\;nop"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
(define_insn "*call_value_nonlocal_aix<mode>"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s"))
|
||||
(match_operand 2 "" "g")))
|
||||
(clobber (reg:P LR_REGNO))]
|
||||
"DEFAULT_ABI == ABI_AIX"
|
||||
"bl %z1\;nop"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
;; Call to indirect functions with the AIX abi using a 3 word descriptor.
|
||||
;; Operand0 is the addresss of the function to call
|
||||
;; Operand2 is the location in the function descriptor to load r2 from
|
||||
;; Operand3 is the stack location to hold the current TOC pointer
|
||||
|
||||
(define_insn "*call_indirect_aix<mode>"
|
||||
[(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
|
||||
(match_operand 1 "" "g,g"))
|
||||
(use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>"))
|
||||
(set (reg:P TOC_REGNUM) (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
|
||||
(clobber (reg:P LR_REGNO))]
|
||||
"DEFAULT_ABI == ABI_AIX"
|
||||
"<ptrload> 2,%2\;b%T0l\;<ptrload> 2,%3"
|
||||
[(set_attr "type" "jmpreg")
|
||||
(set_attr "length" "12")])
|
||||
|
||||
(define_insn "*call_value_indirect_aix<mode>"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
|
||||
(match_operand 2 "" "g,g")))
|
||||
(use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>"))
|
||||
(set (reg:P TOC_REGNUM) (match_operand:P 4 "memory_operand" "<ptrm>,<ptrm>"))
|
||||
(clobber (reg:P LR_REGNO))]
|
||||
"DEFAULT_ABI == ABI_AIX"
|
||||
"<ptrload> 2,%3\;b%T1l\;<ptrload> 2,%4"
|
||||
[(set_attr "type" "jmpreg")
|
||||
(set_attr "length" "12")])
|
||||
|
||||
|
||||
;; Call subroutine returning any type.
|
||||
(define_expand "untyped_call"
|
||||
[(parallel [(call (match_operand 0 "" "")
|
||||
|
@ -12607,6 +12537,39 @@
|
|||
gcc_assert (GET_CODE (operands[1]) == CONST_INT);
|
||||
|
||||
operands[0] = XEXP (operands[0], 0);
|
||||
|
||||
if (DEFAULT_ABI == ABI_AIX)
|
||||
{
|
||||
rs6000_sibcall_aix (NULL_RTX, operands[0], operands[1], operands[2]);
|
||||
DONE;
|
||||
}
|
||||
}")
|
||||
|
||||
(define_expand "sibcall_value"
|
||||
[(parallel [(set (match_operand 0 "register_operand" "")
|
||||
(call (mem:SI (match_operand 1 "address_operand" ""))
|
||||
(match_operand 2 "" "")))
|
||||
(use (match_operand 3 "" ""))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(simple_return)])]
|
||||
""
|
||||
"
|
||||
{
|
||||
#if TARGET_MACHO
|
||||
if (MACHOPIC_INDIRECT)
|
||||
operands[1] = machopic_indirect_call_target (operands[1]);
|
||||
#endif
|
||||
|
||||
gcc_assert (GET_CODE (operands[1]) == MEM);
|
||||
gcc_assert (GET_CODE (operands[2]) == CONST_INT);
|
||||
|
||||
operands[1] = XEXP (operands[1], 0);
|
||||
|
||||
if (DEFAULT_ABI == ABI_AIX)
|
||||
{
|
||||
rs6000_sibcall_aix (operands[0], operands[1], operands[2], operands[3]);
|
||||
DONE;
|
||||
}
|
||||
}")
|
||||
|
||||
;; this and similar patterns must be marked as using LR, otherwise
|
||||
|
@ -12674,7 +12637,6 @@
|
|||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4,8")])
|
||||
|
||||
|
||||
(define_insn "*sibcall_value_local64"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
|
||||
|
@ -12696,35 +12658,6 @@
|
|||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4,8")])
|
||||
|
||||
(define_insn "*sibcall_nonlocal_aix<mode>"
|
||||
[(call (mem:SI (match_operand:P 0 "call_operand" "s,c"))
|
||||
(match_operand 1 "" "g,g"))
|
||||
(use (match_operand:SI 2 "immediate_operand" "O,O"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(simple_return)]
|
||||
"DEFAULT_ABI == ABI_AIX
|
||||
&& (INTVAL (operands[2]) & CALL_LONG) == 0"
|
||||
"@
|
||||
b %z0
|
||||
b%T0"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*sibcall_value_nonlocal_aix<mode>"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:P 1 "call_operand" "s,c"))
|
||||
(match_operand 2 "" "g,g")))
|
||||
(use (match_operand:SI 3 "immediate_operand" "O,O"))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(simple_return)]
|
||||
"DEFAULT_ABI == ABI_AIX
|
||||
&& (INTVAL (operands[3]) & CALL_LONG) == 0"
|
||||
"@
|
||||
b %z1
|
||||
b%T1"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*sibcall_nonlocal_sysv<mode>"
|
||||
[(call (mem:SI (match_operand:P 0 "call_operand" "s,s,c,c"))
|
||||
(match_operand 1 "" ""))
|
||||
|
@ -12755,27 +12688,6 @@
|
|||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4,8,4,8")])
|
||||
|
||||
(define_expand "sibcall_value"
|
||||
[(parallel [(set (match_operand 0 "register_operand" "")
|
||||
(call (mem:SI (match_operand 1 "address_operand" ""))
|
||||
(match_operand 2 "" "")))
|
||||
(use (match_operand 3 "" ""))
|
||||
(use (reg:SI LR_REGNO))
|
||||
(simple_return)])]
|
||||
""
|
||||
"
|
||||
{
|
||||
#if TARGET_MACHO
|
||||
if (MACHOPIC_INDIRECT)
|
||||
operands[1] = machopic_indirect_call_target (operands[1]);
|
||||
#endif
|
||||
|
||||
gcc_assert (GET_CODE (operands[1]) == MEM);
|
||||
gcc_assert (GET_CODE (operands[2]) == CONST_INT);
|
||||
|
||||
operands[1] = XEXP (operands[1], 0);
|
||||
}")
|
||||
|
||||
(define_insn "*sibcall_value_nonlocal_sysv<mode>"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:P 1 "call_operand" "s,s,c,c"))
|
||||
|
@ -12807,6 +12719,31 @@
|
|||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4,8,4,8")])
|
||||
|
||||
;; AIX ABI sibling call patterns.
|
||||
|
||||
(define_insn "*sibcall_aix<mode>"
|
||||
[(call (mem:SI (match_operand:P 0 "call_operand" "s,c"))
|
||||
(match_operand 1 "" "g,g"))
|
||||
(simple_return)]
|
||||
"DEFAULT_ABI == ABI_AIX"
|
||||
"@
|
||||
b %z0
|
||||
b%T0"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*sibcall_value_aix<mode>"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:P 1 "call_operand" "s,c"))
|
||||
(match_operand 2 "" "g,g")))
|
||||
(simple_return)]
|
||||
"DEFAULT_ABI == ABI_AIX"
|
||||
"@
|
||||
b %z1
|
||||
b%T1"
|
||||
[(set_attr "type" "branch")
|
||||
(set_attr "length" "4")])
|
||||
|
||||
(define_expand "sibcall_epilogue"
|
||||
[(use (const_int 0))]
|
||||
""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue