Hi Adhemerval, A few comments on the assembly code:
+# This function is called with non-standard calling convention: on entry +# x10 is the requested stack pointer, x11 is previous stack pointer (if +# functions has stacked arguments which needs to be restored), and x12 is +# the caller link register on function entry (which will be restored by +# morestack when returning to caller). The split-stack prologue is in +# the form: +# +# function: +# mrs x9, tpidr_el0 +# ldur x9, [x9, #-8] +# mov x10, <required stack allocation> +# movk x10, #0x0, lsl #16 +# sub x10, sp, x10 +# mov x11, sp # if function has stacked arguments +# mov x12, x30 This should go... +# cmp x9, x10 +# bcc .LX +# main_fn_entry: +# [function body] +# LX: ...here: mov x12, x30 +# bl __morestack +# b main_fn_entry Note using a bl here rather than a branch means you'll kill the return stack. +# 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, x12, [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, [x29, 16] + stp x2, x3, [x29, 32] + add x10, x10, BACKOFF + stp x4, x5, [x29, 48] + stp x6, x7, [x29, 64] + stp x8, x30, [x29, 80] + str x10, [x29, 96] Probably best to use NEWSTACK_SAVE here for clarity. + # 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] Is the label for unwinding exactly at the right place? + # 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 + ldr x30, [x29, 8] + # Indicate __morestack was called. + cmp x12, 0 No idea what this is for but the ldr/cmp are completely redundant. + blr x12 + + stp x0, x1, [x29, 16] + stp x2, x3, [x29, 32] + stp x4, x5, [x29, 48] + stp x6, x7, [x29, 64] These 3 STPs are dead. + 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] These 3 LDPs are dead. + ldp x29, x30, [x29] + + .cfi_remember_state + .cfi_restore 30 + .cfi_restore 29 + .cfi_def_cfa 31, 0 + + ret