#define PARAMS 48
#endif
#define MORESTACK_FRAMESIZE (PARAMS+96)
+#define R2_SAVE -MORESTACK_FRAMESIZE+PARAMS-8
#define PARAMREG_SAVE -MORESTACK_FRAMESIZE+PARAMS+0
#define STATIC_CHAIN_SAVE -MORESTACK_FRAMESIZE+PARAMS+64
#define R29_SAVE -MORESTACK_FRAMESIZE+PARAMS+72
# cr7 must also be preserved.
ENTRY0(__morestack)
+
+#if _CALL_ELF == 2
+# Functions with localentry bits of zero cannot make calls if those
+# calls might change r2. This is true generally, and also true for
+# __morestack with its special calling convention. When __morestack's
+# caller is non-pcrel but libgcc is pcrel, the functions called here
+# might modify r2. r2 must be preserved on exit, and also restored
+# for the call back to our caller.
+ std %r2,R2_SAVE(%r1)
+#endif
+
# Save parameter passing registers, our arguments, lr, r29
# and use r29 as a frame pointer.
std %r3,PARAMREG_SAVE+0(%r1)
std %r12,LINKREG_SAVE(%r1)
std %r3,NEWSTACKSIZE_SAVE(%r1) # new stack size
mr %r29,%r1
+#if _CALL_ELF == 2
+ .cfi_offset %r2,R2_SAVE
+#endif
.cfi_offset %r29,R29_SAVE
.cfi_def_cfa_register %r29
stdu %r1,-MORESTACK_FRAMESIZE(%r1)
+#if _CALL_ELF == 2 && !defined __PCREL__
+# If this isn't a pcrel libgcc then the functions we call here will
+# require r2 to be valid. If __morestack is called from pcrel code r2
+# won't be valid. Set it up.
+ bcl 20,31,1f
+1:
+ mflr %r12
+ addis %r2,%r12,.TOC.-1b@ha
+ addi %r2,%r2,.TOC.-1b@l
+#endif
+
# void __morestack_block_signals (void)
bl JUMP_TARGET(__morestack_block_signals)
# instructions after __morestack's return address.
#
ld %r12,LINKREG_SAVE(%r29)
+#if _CALL_ELF == 2
+ ld %r2,R2_SAVE(%r29)
+#endif
ld %r3,PARAMREG_SAVE+0(%r29) # restore arg regs
ld %r4,PARAMREG_SAVE+8(%r29)
ld %r5,PARAMREG_SAVE+16(%r29)
std %r10,PARAMREG_SAVE+56(%r29)
#endif
+#if _CALL_ELF == 2 && !defined __PCREL__
+# r2 was restored for calling back into our caller. Set it up again.
+ bcl 20,31,1f
+1:
+ mflr %r12
+ addis %r2,%r12,.TOC.-1b@ha
+ addi %r2,%r2,.TOC.-1b@l
+#endif
+
bl JUMP_TARGET(__morestack_block_signals)
# void *__generic_releasestack (size_t *pavailable)
# Restore return value regs, and return.
ld %r0,LINKREG_SAVE(%r29)
mtlr %r0
+#if _CALL_ELF == 2
+ ld %r2,R2_SAVE(%r29)
+#endif
ld %r3,PARAMREG_SAVE+0(%r29)
ld %r4,PARAMREG_SAVE+8(%r29)
ld %r5,PARAMREG_SAVE+16(%r29)