summaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2011-12-20 22:34:30 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2011-12-20 22:34:30 +0000
commit0d84f1645ee9ac09db43378156f779109ed076db (patch)
treebbef8556fa5a1916624b2d5a114a335e949690c6 /libgcc
parent4ccf368d026f1965bf7b9abc1656f47f9b1f2243 (diff)
downloadgcc-0d84f1645ee9ac09db43378156f779109ed076db.tar.gz
* config/i386/morestack.S (__morestack_non_split): If there is
enough stack space already, don't split. Ask for more stack space than we required. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182555 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/ChangeLog6
-rw-r--r--libgcc/config/i386/morestack.S104
2 files changed, 108 insertions, 2 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 3f957673680..f5d02dd79fd 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,9 @@
+2011-12-20 Ian Lance Taylor <iant@google.com>
+
+ * config/i386/morestack.S (__morestack_non_split): If there is
+ enough stack space already, don't split. Ask for more stack space
+ than we required.
+
2011-12-20 Sergio Durigan Junior <sergiodj@redhat.com>
* unwind-arm-common.inc: Include `tconfig.h', `tsystem.h' and
diff --git a/libgcc/config/i386/morestack.S b/libgcc/config/i386/morestack.S
index 0667590bcf0..8e0eb2009bc 100644
--- a/libgcc/config/i386/morestack.S
+++ b/libgcc/config/i386/morestack.S
@@ -96,13 +96,113 @@
#endif
__morestack_non_split:
+ .cfi_startproc
#ifndef __x86_64__
- addl $0x4000,4(%esp)
+
+ # See below for an extended explanation of the CFI instructions.
+ .cfi_offset 8, 8 # New PC stored at CFA + 8
+ .cfi_escape 0x15, 4, 0x7d # DW_CFA_val_offset_sf, %esp, 12/-4
+ # i.e., next %esp is CFA + 12
+
+ pushl %eax # Save %eax in case it is a parameter.
+
+ .cfi_def_cfa %esp,8 # Account for pushed register.
+
+ movl %esp,%eax # Current stack,
+ subl 8(%esp),%eax # less required stack frame size,
+ subl $0x4000,%eax # less space for non-split code.
+ cmpl %gs:0x30,%eax # See if we have enough space.
+ jb 2f # Get more space if we need it.
+
+ # Here the stack is
+ # %esp + 20: stack pointer after two returns
+ # %esp + 16: return address of morestack caller's caller
+ # %esp + 12: size of parameters
+ # %esp + 8: new stack frame size
+ # %esp + 4: return address of this function
+ # %esp: saved %eax
+ #
+ # Since we aren't doing a full split stack, we don't need to
+ # do anything when our caller returns. So we return to our
+ # caller rather than calling it, and let it return as usual.
+ # To make that work we adjust the return address.
+
+ # This breaks call/return address prediction for the call to
+ # this function. I can't figure out a way to make it work
+ # short of copying the parameters down the stack, which will
+ # probably take more clock cycles than we will lose breaking
+ # call/return address prediction. We will only break
+ # prediction for this call, not for our caller.
+
+ movl 4(%esp),%eax # Increment the return address
+ cmpb $0xc3,(%eax) # to skip the ret instruction;
+ je 1f # see above.
+ addl $2,%eax
+1: inc %eax
+ movl %eax,4(%esp) # Update return address.
+
+ popl %eax # Restore %eax and stack.
+
+ .cfi_def_cfa %esp,4 # Account for popped register.
+
+ ret $8 # Return to caller, popping args.
+
+2:
+ .cfi_def_cfa %esp,8 # Back to where we were.
+
+ popl %eax # Restore %eax and stack.
+
+ .cfi_def_cfa %esp,4 # Account for popped register.
+
+ addl $0x5000+BACKOFF,4(%esp) # Increment space we request.
+
+ # Fall through into morestack.
+
#else
- addq $0x4000,%r10
+
+ # See below for an extended explanation of the CFI instructions.
+ .cfi_offset 16, 0
+ .cfi_escape 0x15, 7, 0x7f # DW_CFA_val_offset_sf, %esp, 8/-8
+
+ pushq %rax # Save %rax in case caller is using
+ # it to preserve original %r10.
+ .cfi_def_cfa %rsp,16 # Adjust for pushed register.
+
+ movq %rsp,%rax # Current stack,
+ subq %r10,%rax # less required stack frame size,
+ subq $0x4000,%rax # less space for non-split code.
+
+#ifdef __LP64__
+ cmpq %fs:0x70,%rax # See if we have enough space.
+#else
+ cmpl %fs:0x40,%eax
#endif
+ jb 2f # Get more space if we need it.
+
+ # This breaks call/return prediction, as described above.
+ incq 8(%rsp) # Increment the return address.
+
+ popq %rax # Restore register.
+
+ .cfi_def_cfa %rsp,8 # Adjust for popped register.
+ ret # Return to caller.
+
+2:
+ .cfi_def_cfa %rsp,16 # Back to where we were.
+
+ popq %rax # Restore register.
+
+ .cfi_def_cfa %rsp,8 # Adjust for popped register.
+
+ addq $0x5000+BACKOFF,%r10 # Increment space we request.
+
+ # Fall throug into morestack.
+
+#endif
+
+ .cfi_endproc
#ifdef __ELF__
.size __morestack_non_split, . - __morestack_non_split
#endif