@@ -107,6 +107,21 @@ aarch64_handle_option (struct gcc_options *opts,
}
}
+/* -fsplit-stack uses a TCB field available on glibc-2.25. GLIBC also
+ exports symbol, __tcb_private_ss, to signal it has the field available
+ on TCB allocation. This aims to prevent binaries linked against newer
+ GLIBC to run on non-supported ones. */
+
+static bool
+aarch64_supports_split_stack (bool report ATTRIBUTE_UNUSED,
+ struct gcc_options *opts ATTRIBUTE_UNUSED)
+{
+ return true;
+}
+
+#undef TARGET_SUPPORTS_SPLIT_STACK
+#define TARGET_SUPPORTS_SPLIT_STACK aarch64_supports_split_stack
+
struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
/* An ISA extension in the co-processor and main instruction set space. */
@@ -340,4 +355,3 @@ aarch64_rewrite_mcpu (int argc, const char **argv)
}
#undef AARCH64_CPU_NAME_LENGTH
-
@@ -80,8 +80,6 @@
} \
while (0)
-#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
-
/* Uninitialized common symbols in non-PIE executables, even with
strong definitions in dependent shared libraries, will resolve
to COPY relocated symbol in the executable. See PR65780. */
@@ -383,6 +383,8 @@ void aarch64_err_no_fpadvsimd (machine_mode, const char *);
void aarch64_expand_epilogue (bool);
void aarch64_expand_mov_immediate (rtx, rtx);
void aarch64_expand_prologue (void);
+void aarch64_expand_split_stack_prologue (void);
+void aarch64_split_stack_space_check (rtx, rtx);
void aarch64_expand_vector_init (rtx, rtx);
void aarch64_init_cumulative_args (CUMULATIVE_ARGS *, const_tree, rtx,
const_tree, unsigned);
@@ -913,7 +913,12 @@ aarch64_gen_far_branch (rtx * operands, int pos_label, const char * dest,
snprintf (buffer, sizeof (buffer), "%s%s", branch_format, label_ptr);
output_asm_insn (buffer, operands);
- snprintf (buffer, sizeof (buffer), "b\t%%l%d\n%s:", pos_label, label_ptr);
+ if (GET_CODE (operands[pos_label]) == LABEL_REF)
+ snprintf (buffer, sizeof (buffer), "b\t%%l%d\n%s:", pos_label,
+ label_ptr);
+ else
+ snprintf (buffer, sizeof (buffer), "b\t%%%d\n%s:", pos_label,
+ label_ptr);
operands[pos_label] = dest_label;
output_asm_insn (buffer, operands);
return "";
@@ -10139,7 +10144,7 @@ aarch64_expand_builtin_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
/* Emit code to initialize STACK, which points to the next varargs stack
argument. CUM->AAPCS_STACK_SIZE gives the number of stack words used
by named arguments. STACK is 8-byte aligned. */
- t = make_tree (TREE_TYPE (stack), virtual_incoming_args_rtx);
+ t = make_tree (TREE_TYPE (stack), crtl->args.internal_arg_pointer);
if (cum->aapcs_stack_size > 0)
t = fold_build_pointer_plus_hwi (t, cum->aapcs_stack_size * UNITS_PER_WORD);
t = build2 (MODIFY_EXPR, TREE_TYPE (stack), stack, t);
@@ -14682,6 +14687,159 @@ aarch64_excess_precision (enum excess_precision_type type)
return FLT_EVAL_METHOD_UNPREDICTABLE;
}
+/* -fsplit-stack support. */
+
+/* A SYMBOL_REF for __morestack. */
+static GTY(()) rtx morestack_ref;
+
+/* Load split-stack area from thread pointer position. The split-stack is
+ allocate just before thread pointer. */
+
+static rtx
+aarch64_load_split_stack_value (bool use_hard_reg)
+{
+ /* Offset from thread pointer to split-stack area. */
+ const int psso = -8;
+
+ rtx ssvalue = use_hard_reg
+ ? gen_rtx_REG (Pmode, R9_REGNUM) : gen_reg_rtx (Pmode);
+ ssvalue = aarch64_load_tp (ssvalue);
+ rtx mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, ssvalue, psso));
+ emit_move_insn (ssvalue, mem);
+ return ssvalue;
+}
+
+/* Emit -fsplit-stack prologue, which goes before the regular function
+ prologue. */
+
+void
+aarch64_expand_split_stack_prologue (void)
+{
+ rtx ssvalue, reg10, reg11, reg12, cc, cmp, jump;
+ HOST_WIDE_INT allocate;
+ rtx_code_label *ok_label = NULL;
+
+ gcc_assert (flag_split_stack && reload_completed);
+
+ /* It limits total maximum stack allocation on 4G so its value can be
+ materialized using two instructions at most (movn/movk). It might be
+ used by the linker to add some extra space for split calling non split
+ stack functions. */
+ allocate = cfun->machine->frame.frame_size;
+ if (allocate > ((int64_t)1 << 32))
+ {
+ sorry ("Stack frame larger than 4G is not supported for -fsplit-stack");
+ return;
+ }
+
+ if (morestack_ref == NULL_RTX)
+ {
+ morestack_ref = gen_rtx_SYMBOL_REF (Pmode, "__morestack");
+ SYMBOL_REF_FLAGS (morestack_ref) |= (SYMBOL_FLAG_LOCAL
+ | SYMBOL_FLAG_FUNCTION);
+ }
+
+ ssvalue = aarch64_load_split_stack_value (true);
+
+ /* Always emit two insns to calculate the requested stack, so the linker
+ can edit them when adjusting size for calling non-split-stack code. */
+ reg10 = gen_rtx_REG (Pmode, R10_REGNUM);
+ emit_insn (gen_rtx_SET (reg10, GEN_INT (allocate & 0xffff)));
+ emit_insn (gen_insv_immdi (reg10, GEN_INT (16),
+ GEN_INT ((allocate & 0xffff0000) >> 16)));
+ emit_insn (gen_sub3_insn (reg10, stack_pointer_rtx, reg10));
+
+ ok_label = gen_label_rtx ();
+
+ /* If function uses stacked arguments save the old stack value so morestack
+ can return it. */
+ reg11 = gen_rtx_REG (Pmode, R11_REGNUM);
+ if (crtl->args.size
+ || cfun->machine->frame.saved_varargs_size)
+ emit_move_insn (reg11, stack_pointer_rtx);
+
+ /* x12 holds the continuation address used to return to function. */
+ reg12 = gen_rtx_REG (Pmode, R12_REGNUM);
+ aarch64_expand_mov_immediate (reg12, gen_rtx_LABEL_REF (VOIDmode, ok_label));
+
+ /* Jump to __morestack call if current ss guard is not suffice. */
+ cc = aarch64_gen_compare_reg (GE, ssvalue, reg10);
+ cmp = gen_rtx_fmt_ee (GE, VOIDmode, cc, const0_rtx);
+ jump = gen_split_stack_cond_call (morestack_ref, cmp, ok_label, reg12);
+
+ aarch64_emit_unlikely_jump (jump);
+ JUMP_LABEL (jump) = ok_label;
+ LABEL_NUSES (ok_label)++;
+
+ /* __morestack will call us here. */
+ emit_label (ok_label);
+}
+
+/* Implement TARGET_ASM_FILE_END. */
+
+static void
+aarch64_file_end (void)
+{
+ file_end_indicate_exec_stack ();
+
+ if (flag_split_stack)
+ file_end_indicate_split_stack ();
+}
+
+/* Return the internal arg pointer used for function incoming arguments. */
+
+static rtx
+aarch64_internal_arg_pointer (void)
+{
+ if (flag_split_stack
+ && (lookup_attribute ("no_split_stack", DECL_ATTRIBUTES (cfun->decl))
+ == NULL))
+ {
+ if (cfun->machine->frame.split_stack_arg_pointer == NULL_RTX)
+ {
+ rtx pat;
+
+ cfun->machine->frame.split_stack_arg_pointer = gen_reg_rtx (Pmode);
+ REG_POINTER (cfun->machine->frame.split_stack_arg_pointer) = 1;
+
+ /* Put the pseudo initialization right after the note at the
+ beginning of the function. */
+ pat = gen_rtx_SET (cfun->machine->frame.split_stack_arg_pointer,
+ gen_rtx_REG (Pmode, R11_REGNUM));
+ push_topmost_sequence ();
+ emit_insn_after (pat, get_insns ());
+ pop_topmost_sequence ();
+ }
+ return plus_constant (Pmode, cfun->machine->frame.split_stack_arg_pointer,
+ FIRST_PARM_OFFSET (current_function_decl));
+ }
+ return virtual_incoming_args_rtx;
+}
+
+/* Emit -fsplit-stack dynamic stack allocation space check. */
+
+void
+aarch64_split_stack_space_check (rtx size, rtx label)
+{
+ rtx ssvalue, cc, cmp, jump, temp;
+ rtx requested = gen_reg_rtx (Pmode);
+
+ /* Load __private_ss from TCB. */
+ ssvalue = aarch64_load_split_stack_value (false);
+
+ temp = gen_reg_rtx (Pmode);
+
+ /* And compare it with frame pointer plus required stack. */
+ size = force_reg (Pmode, size);
+ emit_move_insn (requested, gen_rtx_MINUS (Pmode, stack_pointer_rtx, size));
+
+ /* Jump to label call if current ss guard is not suffice. */
+ cc = aarch64_gen_compare_reg (LT, temp, ssvalue);
+ cmp = gen_rtx_fmt_ee (GEU, VOIDmode, cc, const0_rtx);
+ jump = emit_jump_insn (gen_condjump (cmp, cc, label));
+ JUMP_LABEL (jump) = label;
+}
+
/* Target-specific selftests. */
#if CHECKING_P
@@ -14754,6 +14912,9 @@ aarch64_run_selftests (void)
#undef TARGET_ASM_FILE_START
#define TARGET_ASM_FILE_START aarch64_start_file
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END aarch64_file_end
+
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK aarch64_output_mi_thunk
@@ -14839,6 +15000,9 @@ aarch64_run_selftests (void)
#undef TARGET_FRAME_POINTER_REQUIRED
#define TARGET_FRAME_POINTER_REQUIRED aarch64_frame_pointer_required
+#undef TARGET_INTERNAL_ARG_POINTER
+#define TARGET_INTERNAL_ARG_POINTER aarch64_internal_arg_pointer
+
#undef TARGET_GIMPLE_FOLD_BUILTIN
#define TARGET_GIMPLE_FOLD_BUILTIN aarch64_gimple_fold_builtin
@@ -594,6 +594,9 @@ struct GTY (()) aarch64_frame
unsigned wb_candidate2;
bool laid_out;
+
+ /* Alternative internal arg pointer for -fsplit-stack. */
+ rtx split_stack_arg_pointer;
};
typedef struct GTY (()) machine_function
@@ -135,6 +135,7 @@
UNSPEC_VSTRUCTDUMMY
UNSPEC_SP_SET
UNSPEC_SP_TEST
+ UNSPEC_STACK_CHECK
UNSPEC_RSQRT
UNSPEC_RSQRTE
UNSPEC_RSQRTS
@@ -150,6 +151,7 @@
UNSPECV_SET_FPSR ; Represent assign of FPSR content.
UNSPECV_BLOCKAGE ; Represent a blockage
UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
+ UNSPECV_SPLIT_STACK_CALL ; Represent a morestack call
]
)
@@ -5572,3 +5574,58 @@
;; ldp/stp peephole patterns
(include "aarch64-ldpstp.md")
+
+;; Handle -fsplit-stack
+(define_expand "split_stack_prologue"
+ [(const_int 0)]
+ ""
+{
+ aarch64_expand_split_stack_prologue ();
+ DONE;
+})
+
+;; If there are operand 0 bytes available on the stack, jump to
+;; operand 1.
+(define_expand "split_stack_space_check"
+ [(set (match_dup 2) (compare:CC (match_dup 3) (match_dup 2)))
+ (set (pc) (if_then_else
+ (geu (match_dup 4) (const_int 0))
+ (label_ref (match_operand 1))
+ (pc)))]
+ ""
+{
+ aarch64_split_stack_space_check (operands[0], operands[1]);
+ DONE;
+})
+
+;; A __morestack call using branch
+
+(define_expand "split_stack_cond_call"
+ [(match_operand 0 "aarch64_call_insn_operand" "")
+ (match_operand 1 "" "")
+ (match_operand 2 "" "")
+ (match_operand 3 "" "")]
+ ""
+{
+ emit_jump_insn (gen_split_stack_cond_call_di (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+})
+
+
+(define_insn "split_stack_cond_call_<mode>"
+ [(set (pc)
+ (if_then_else
+ (match_operand 1 "aarch64_comparison_operator" "")
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (reg:P 1) (unspec_volatile:P [(match_operand:P 0 "aarch64_call_insn_operand" "")
+ (reg:P 1)]
+ UNSPECV_SPLIT_STACK_CALL))
+ (use (match_operand:P 3 "register_operand" ""))]
+ ""
+ {
+ return aarch64_gen_far_branch (operands, 0, "Lbcond", "b%M1\\t");
+ }
+ [(set_attr "type" "branch")]
+)
@@ -347,6 +347,7 @@ aarch64*-*-linux*)
md_unwind_header=aarch64/linux-unwind.h
tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+ tmake_file="${tmake_file} t-stack aarch64/t-stack-aarch64"
;;
alpha*-*-linux*)
tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee t-crtfm alpha/t-linux"
new file mode 100644
@@ -0,0 +1,88 @@
+/* AArch64 support for -fsplit-stack.
+ * Copyright (C) 2016 Free Software Foundation, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Under Section 7 of GPL version 3, you are granted additional
+ * permissions described in the GCC Runtime Library Exception, version
+ * 3.1, as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License and
+ * a copy of the GCC Runtime Library Exception along with this program;
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef inhibit_libc
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include "generic-morestack.h"
+
+#define INITIAL_STACK_SIZE 0x4000
+#define BACKOFF 0x1000
+
+void __generic_morestack_set_initial_sp (void *sp, size_t len);
+void *__morestack_get_guard (void);
+void __morestack_set_guard (void *);
+void *__morestack_make_guard (void *stack, size_t size);
+void __morestack_load_mmap (void);
+
+/* We declare is as weak so it fails either at stack linking or
+ at runtime if the GLIBC does not have the required TCB field. */
+extern void __tcb_private_ss (void) __attribute__ ((weak));
+
+/* split-stack area position from thread pointer. */
+#define SPLITSTACK_PTR_TP (-8)
+
+/* Initialize the stack guard when the program starts or when a new
+ thread. This is called from a constructor using ctors section. */
+void
+__stack_split_initialize (void)
+{
+ __tcb_private_ss ();
+
+ register uintptr_t* sp __asm__ ("sp");
+ uintptr_t *ss = ((char *)__builtin_thread_pointer () + SPLITSTACK_PTR_TP);
+ *ss = sp - INITIAL_STACK_SIZE;
+ __generic_morestack_set_initial_sp (sp, INITIAL_STACK_SIZE);
+}
+
+/* Return current __private_ss. */
+void *
+__morestack_get_guard (void)
+{
+ uintptr_t *ss = ((char *)__builtin_thread_pointer () + SPLITSTACK_PTR_TP);
+ return *ss;
+}
+
+/* Set __private_ss to ptr. */
+void
+__morestack_set_guard (void *ptr)
+{
+ uintptr_t *ss = ((char *)__builtin_thread_pointer () + SPLITSTACK_PTR_TP);
+ *ss = (uintptr_t) ptr;
+}
+
+/* Return the stack guard value for given stack. */
+void *
+__morestack_make_guard (void *stack, size_t size)
+{
+ return (void*)((uintptr_t)stack - size + BACKOFF);
+}
+
+/* Make __stack_split_initialize a high priority constructor. */
+static void (*const ctors [])
+ __attribute__ ((used, section (".ctors.65535"), aligned (sizeof (void *))))
+ = { __stack_split_initialize, __morestack_load_mmap };
+
+#endif /* !defined (inhibit_libc) */
new file mode 100644
@@ -0,0 +1,254 @@
+# AArch64 support for -fsplit-stack.
+# Copyright (C) 2016 Free Software Foundation, Inc.
+
+# This file is part of GCC.
+
+# GCC is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 3, or (at your option) any later
+# version.
+
+# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+/* Define an entry point visible from C. */
+#define ENTRY(name) \
+ .globl name; \
+ .type name,%function; \
+ .align 4; \
+ name##:
+
+#define END(name) \
+ .size name,.-name
+
+/* __morestack frame size. */
+#define MORESTACK_FRAMESIZE 112
+/* Offset from __morestack frame where the new stack size is saved and
+ passed to __generic_morestack. */
+#define NEWSTACK_SAVE 96
+
+#define BACKOFF 0x1000
+# Large excess allocated when calling non-split-stack code.
+#define NON_SPLIT_STACK 0x100000
+
+/* split-stack area position from thread pointer. */
+#define SPLITSTACK_PTR_TP -8
+
+ .text
+ENTRY(__morestack_non_split)
+ .cfi_startproc
+# We use a cleanup to restore the tcbhead_t.__private_ss if
+# an exception is thrown through this code.
+ add x10, x10, NON_SPLIT_STACK
+ .cfi_endproc
+END(__morestack_non_split)
+# Fall through into __morestack
+
+# This function is called with non-standard calling conventions, on entry
+# x10 is the requested stack pointer. The split-stack prologue is in the
+# form:
+#
+# function:
+# mrs x9, tpidr_el0
+# sub x10, sp, N & 0xfff000
+# sub x10, x10, N & 0xfff
+# ldr x9, [x9, 16]
+# adrp x12, main_fn_entry
+# add x12, x12, :lo12:main_fn_entry
+# [mov x11, sp] # If function has stacked arguments
+# cmp x9, x10
+# b.lt main_fn_entry
+# b __morestack
+# main_fn_entry: [x11 is argument pointer]
+# [prolog]
+#
+# The normal function prologue follows here, with a small addition at the
+# end to set up the argument pointer if required (the prolog):
+#
+# [...] # default function prologue
+# b.lt function:
+# function:
+#
+#
+# The N bit is also restored to indicate that the function is called
+# (so the prologue addition can set up the argument pointer correctly).
+
+ENTRY(__morestack)
+.LFB1:
+ .cfi_startproc
+
+#ifdef __PIC__
+ .cfi_personality 0x9b,DW.ref.__gcc_personality_v0
+ .cfi_lsda 0x1b,.LLSDA1
+#else
+ .cfi_personality 0x3,__gcc_personality_v0
+ .cfi_lsda 0x3,.LLSDA1
+#endif
+
+ # Calculate requested stack size.
+ sub x10, sp, x10
+ # Save parameters
+ stp x29, x30, [sp, -MORESTACK_FRAMESIZE]!
+ .cfi_def_cfa_offset MORESTACK_FRAMESIZE
+ .cfi_offset 29, -MORESTACK_FRAMESIZE
+ .cfi_offset 30, -MORESTACK_FRAMESIZE+8
+ add x29, sp, 0
+ .cfi_def_cfa_register 29
+ # Adjust the requested stack size for the frame pointer save.
+ stp x0, x1, [sp, 16]
+ stp x2, x3, [sp, 32]
+ add x10, x10, BACKOFF
+ stp x4, x5, [sp, 48]
+ stp x6, x7, [sp, 64]
+ stp x8, x12, [sp, 80]
+ str x10, [sp, 96]
+
+ # void __morestack_block_signals (void)
+ bl __morestack_block_signals
+
+ # void *__generic_morestack (size_t *pframe_size,
+ # void *old_stack,
+ # size_t param_size)
+ # pframe_size: is the size of the required stack frame (the function
+ # amount of space remaining on the allocated stack).
+ # old_stack: points at the parameters the old stack
+ # param_size: size in bytes of parameters to copy to the new stack.
+ add x0, x29, NEWSTACK_SAVE
+ add x1, x29, MORESTACK_FRAMESIZE
+ mov x2, 0
+ bl __generic_morestack
+
+ # Start using new stack
+ mov sp, x0
+
+ # Set __private_ss stack guard for the new stack.
+ ldr x9, [x29, NEWSTACK_SAVE]
+ add x0, x0, BACKOFF
+ sub x0, x0, x9
+.LEHB0:
+ mrs x1, tpidr_el0
+ str x0, [x1, SPLITSTACK_PTR_TP]
+
+ # void __morestack_unblock_signals (void)
+ bl __morestack_unblock_signals
+
+ # Set up for a call to the target function.
+ ldp x0, x1, [x29, 16]
+ ldp x2, x3, [x29, 32]
+ ldp x4, x5, [x29, 48]
+ ldp x6, x7, [x29, 64]
+ ldp x8, x12, [x29, 80]
+ add x11, x29, MORESTACK_FRAMESIZE
+ # Indicate __morestack was called.
+ cmp x12, 0
+ blr x12
+
+ stp x0, x1, [x29, 16]
+ stp x2, x3, [x29, 32]
+ stp x4, x5, [x29, 48]
+ stp x6, x7, [x29, 64]
+
+ bl __morestack_block_signals
+
+ # void *__generic_releasestack (size_t *pavailable)
+ add x0, x29, NEWSTACK_SAVE
+ bl __generic_releasestack
+
+ # Reset __private_ss stack guard to value for old stack
+ ldr x9, [x29, NEWSTACK_SAVE]
+ add x0, x0, BACKOFF
+ sub x0, x0, x9
+
+ # Update TCB split stack field
+.LEHE0:
+ mrs x1, tpidr_el0
+ str x0, [x1, SPLITSTACK_PTR_TP]
+
+ bl __morestack_unblock_signals
+
+ # Use old stack again.
+ add sp, x29, MORESTACK_FRAMESIZE
+
+ ldp x0, x1, [x29, 16]
+ ldp x2, x3, [x29, 32]
+ ldp x4, x5, [x29, 48]
+ ldp x6, x7, [x29, 64]
+ ldp x29, x30, [x29]
+
+ .cfi_remember_state
+ .cfi_restore 30
+ .cfi_restore 29
+ .cfi_def_cfa 31, 0
+
+ ret
+
+# This is the cleanup code called by the stack unwinder when
+# unwinding through code between .LEHB0 and .LEHE0 above.
+cleanup:
+ .cfi_restore_state
+ # Reuse the new stack allocation to save/restore the
+ # exception header
+ str x0, [x29, NEWSTACK_SAVE]
+ # size_t __generic_findstack (void *stack)
+ add x0, x29, MORESTACK_FRAMESIZE
+ bl __generic_findstack
+ sub x0, x29, x0
+ add x0, x0, BACKOFF
+ # Restore tcbhead_t.__private_ss
+ mrs x1, tpidr_el0
+ str x0, [x1, SPLITSTACK_PTR_TP]
+ ldr x0, [x29, NEWSTACK_SAVE]
+ b _Unwind_Resume
+ .cfi_endproc
+END(__morestack)
+
+ .section .gcc_except_table,"a",@progbits
+ .align 4
+.LLSDA1:
+ # @LPStart format (omit)
+ .byte 0xff
+ # @TType format (omit)
+ .byte 0xff
+ # Call-site format (uleb128)
+ .byte 0x1
+ # Call-site table length
+ .uleb128 .LLSDACSE1-.LLSDACSB1
+.LLSDACSB1:
+ # region 0 start
+ .uleb128 .LEHB0-.LFB1
+ # length
+ .uleb128 .LEHE0-.LEHB0
+ # landing pad
+ .uleb128 cleanup-.LFB1
+ # no action (ie a cleanup)
+ .uleb128 0
+.LLSDACSE1:
+
+
+ .global __gcc_personality_v0
+#ifdef __PIC__
+ # Build a position independent reference to the personality function.
+ .hidden DW.ref.__gcc_personality_v0
+ .weak DW.ref.__gcc_personality_v0
+ .section .data.DW.ref.__gcc_personality_v0,"awG",@progbits,DW.ref.__gcc_personality_v0,comdat
+ .type DW.ref.__gcc_personality_v0, @object
+ .align 3
+DW.ref.__gcc_personality_v0:
+ .size DW.ref.__gcc_personality_v0, 8
+ .quad __gcc_personality_v0
+#endif
+
+ .section .note.GNU-stack,"",@progbits
+ .section .note.GNU-split-stack,"",@progbits
+ .section .note.GNU-no-split-stack,"",@progbits
new file mode 100644
@@ -0,0 +1,3 @@
+# Makefile fragment to support -fsplit-stack for aarch64.
+LIB2ADD_ST += $(srcdir)/config/aarch64/morestack.S \
+ $(srcdir)/config/aarch64/morestack-c.c
@@ -943,6 +943,7 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len,
nsp -= 2 * 160;
#elif defined __s390__
nsp -= 2 * 96;
+#elif defined __aarch64__
#else
#error "unrecognized target"
#endif