summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rts/StgCRun.c137
-rw-r--r--rts/StgCRunAsm.S134
2 files changed, 85 insertions, 186 deletions
diff --git a/rts/StgCRun.c b/rts/StgCRun.c
index 316d90cd18..2d1cc16b28 100644
--- a/rts/StgCRun.c
+++ b/rts/StgCRun.c
@@ -725,17 +725,36 @@ StgRunIsImplementedInAssembler(void)
-------------------------------------------------------------------------- */
#if defined(powerpc64_HOST_ARCH)
-
+/* 64-bit PowerPC ELF ABI 1.9
+ *
+ * Stack frame organization (see Figure 3-17, ELF ABI 1.9, p 14)
+ *
+ * +-> Back Chain (points to the prevoius stack frame)
+ * | Floating point register save area (f14-f31)
+ * | General register save area (r14-r31)
+ * | ... unused save areas (size 0)
+ * | Local variable space
+ * | Parameter save area
+ * | ... stack header (TOC, link editor, compiler, LR, CR)
+ * +-- Back chain <---- SP (r1)
+ *
+ * We save all callee-saves general purpose registers (r14-r31, _savegpr1_14)
+ * and all callee-saves floating point registers (f14-31, _savefpr14) and
+ * the return address of the caller (LR), which is saved in the caller's
+ * stack frame as required by the ABI. We only modify the CR0 and CR1 fields
+ * of the condition register and those are caller-saves, so we don't save CR.
+ *
+ * StgReturn restores all saved registers from their respective locations
+ * on the stack before returning to the caller.
+ *
+ * There is no need to save the TOC register (r2) because we will return
+ * through StgReturn and the calling convention requires that we load
+ * the TOC pointer from the function descriptor upon a call to StgReturn.
+ * That TOC pointer is the same as the TOC pointer in StgRun.
+ */
static void GNUC3_ATTRIBUTE(used)
StgRunIsImplementedInAssembler(void)
{
- // r0 volatile
- // r1 stack pointer
- // r2 toc - needs to be saved
- // r3-r10 argument passing, volatile
- // r11, r12 very volatile (not saved across cross-module calls)
- // r13 thread local state (never modified, don't need to save)
- // r14-r31 callee-save
__asm__ volatile (
".section \".opd\",\"aw\"\n"
".align 3\n"
@@ -743,108 +762,32 @@ StgRunIsImplementedInAssembler(void)
".hidden StgRun\n"
"StgRun:\n"
"\t.quad\t.StgRun,.TOC.@tocbase,0\n"
- "\t.size StgRun,24\n"
+ "\t.size StgRun,.-StgRun\n"
".globl StgReturn\n"
"StgReturn:\n"
"\t.quad\t.StgReturn,.TOC.@tocbase,0\n"
- "\t.size StgReturn,24\n"
+ "\t.size StgReturn,.-StgReturn\n"
".previous\n"
- ".globl .StgRun\n"
- ".type .StgRun,@function\n"
+ ".type StgRun,@function\n"
".StgRun:\n"
"\tmflr 0\n"
- "\tmr 5, 1\n"
- "\tstd 0, 16(1)\n"
+ "\taddi 12,1,-(8*18)\n"
+ "\tbl _savegpr1_14\n"
+ "\tbl _savefpr_14\n"
"\tstdu 1, -%0(1)\n"
- "\tstd 2, -296(5)\n"
- "\tstd 14, -288(5)\n"
- "\tstd 15, -280(5)\n"
- "\tstd 16, -272(5)\n"
- "\tstd 17, -264(5)\n"
- "\tstd 18, -256(5)\n"
- "\tstd 19, -248(5)\n"
- "\tstd 20, -240(5)\n"
- "\tstd 21, -232(5)\n"
- "\tstd 22, -224(5)\n"
- "\tstd 23, -216(5)\n"
- "\tstd 24, -208(5)\n"
- "\tstd 25, -200(5)\n"
- "\tstd 26, -192(5)\n"
- "\tstd 27, -184(5)\n"
- "\tstd 28, -176(5)\n"
- "\tstd 29, -168(5)\n"
- "\tstd 30, -160(5)\n"
- "\tstd 31, -152(5)\n"
- "\tstfd 14, -144(5)\n"
- "\tstfd 15, -136(5)\n"
- "\tstfd 16, -128(5)\n"
- "\tstfd 17, -120(5)\n"
- "\tstfd 18, -112(5)\n"
- "\tstfd 19, -104(5)\n"
- "\tstfd 20, -96(5)\n"
- "\tstfd 21, -88(5)\n"
- "\tstfd 22, -80(5)\n"
- "\tstfd 23, -72(5)\n"
- "\tstfd 24, -64(5)\n"
- "\tstfd 25, -56(5)\n"
- "\tstfd 26, -48(5)\n"
- "\tstfd 27, -40(5)\n"
- "\tstfd 28, -32(5)\n"
- "\tstfd 29, -24(5)\n"
- "\tstfd 30, -16(5)\n"
- "\tstfd 31, -8(5)\n"
"\tmr 27, 4\n" // BaseReg == r27
- "\tld 2, 8(3)\n"
"\tld 3, 0(3)\n"
+ "\tld 2, 8(3)\n"
"\tmtctr 3\n"
"\tbctr\n"
- ".globl .StgReturn\n"
- ".type .StgReturn,@function\n"
+ ".type StgReturn,@function\n"
".StgReturn:\n"
"\tmr 3,14\n"
- "\tla 5, %0(1)\n" // load address == addi r5, r1, %0
- "\tld 2, -296(5)\n"
- "\tld 14, -288(5)\n"
- "\tld 15, -280(5)\n"
- "\tld 16, -272(5)\n"
- "\tld 17, -264(5)\n"
- "\tld 18, -256(5)\n"
- "\tld 19, -248(5)\n"
- "\tld 20, -240(5)\n"
- "\tld 21, -232(5)\n"
- "\tld 22, -224(5)\n"
- "\tld 23, -216(5)\n"
- "\tld 24, -208(5)\n"
- "\tld 25, -200(5)\n"
- "\tld 26, -192(5)\n"
- "\tld 27, -184(5)\n"
- "\tld 28, -176(5)\n"
- "\tld 29, -168(5)\n"
- "\tld 30, -160(5)\n"
- "\tld 31, -152(5)\n"
- "\tlfd 14, -144(5)\n"
- "\tlfd 15, -136(5)\n"
- "\tlfd 16, -128(5)\n"
- "\tlfd 17, -120(5)\n"
- "\tlfd 18, -112(5)\n"
- "\tlfd 19, -104(5)\n"
- "\tlfd 20, -96(5)\n"
- "\tlfd 21, -88(5)\n"
- "\tlfd 22, -80(5)\n"
- "\tlfd 23, -72(5)\n"
- "\tlfd 24, -64(5)\n"
- "\tlfd 25, -56(5)\n"
- "\tlfd 26, -48(5)\n"
- "\tlfd 27, -40(5)\n"
- "\tlfd 28, -32(5)\n"
- "\tlfd 29, -24(5)\n"
- "\tlfd 30, -16(5)\n"
- "\tlfd 31, -8(5)\n"
- "\tmr 1, 5\n"
- "\tld 0, 16(1)\n"
- "\tmtlr 0\n"
- "\tblr\n"
- : : "i"(RESERVED_C_STACK_BYTES+304 /*stack frame size*/));
+ "\tla 1, %0(1)\n" // load address == addi r1, r1, %0
+ "\taddi 12,1,-(8*18)\n"
+ "\tbl _restgpr1_14\n"
+ "\tb _restfpr_14\n"
+ : : "i"((RESERVED_C_STACK_BYTES+288+15) & ~15 /*stack frame size*/));
}
#endif
diff --git a/rts/StgCRunAsm.S b/rts/StgCRunAsm.S
index b332be2010..60f1bf9a13 100644
--- a/rts/StgCRunAsm.S
+++ b/rts/StgCRunAsm.S
@@ -7,109 +7,65 @@
#if defined(powerpc64le_HOST_ARCH)
# if defined(linux_HOST_OS)
-# define STACK_FRAME_SIZE RESERVED_C_STACK_BYTES+304
+/* 64-bit PowerPC ELF V2 ABI Revision 1.4
+ *
+ * Stack frame organization (see Figure 2.18, ELF V2 ABI Revision 1.4, p 31)
+ *
+ * +-> Back Chain (points to the prevoius stack frame)
+ * | Floating point register save area (f14-f31)
+ * | General register save area (r14-r31)
+ * | ... unused (optional) save areas (size 0)
+ * | Local variable space
+ * | Parameter save area (8 doublewords)
+ * | ... stack header (TOC, LR, CR)
+ * +-- Back chain <---- SP (r1)
+ *
+ * We save all callee-saves general purpose registers (r14-r31, _savegpr1_14)
+ * and all callee-saves floating point registers (f14-31, _savefpr14) and
+ * the return address of the caller (LR), which is saved in the caller's
+ * stack frame as required by the ABI. We only modify the CR0 and CR1 fields
+ * of the condition register and those are caller-saves, so we don't save CR.
+ *
+ * StgReturn restores all saved registers from their respective locations
+ * on the stack before returning to the caller.
+ *
+ * There is no need to save the TOC register (r2) because we will return
+ * through StgReturn. All calls to StgReturn will be to the global entry
+ * point and we compute the TOC from the entry address of StgReturn, which
+ * is required to be in r12 by the ABI.
+ */
+# define STACK_FRAME_SIZE (RESERVED_C_STACK_BYTES+288+15) & ~15
.file "StgCRun.c"
.abiversion 2
.section ".toc","aw"
.section ".text"
.align 2
-.globl StgRun
-.hidden StgRun
-.type StgRun,@function
+ .globl StgRun
+ .hidden StgRun
+ .type StgRun,@function
StgRun:
-.localentry StgRun,.-StgRun
+ .localentry StgRun,.-StgRun
mflr 0
- mr 5, 1
- std 0, 16(1)
+ addi 12,1,-(8*18)
+ bl _savegpr1_14
+ bl _savefpr_14
stdu 1, -(STACK_FRAME_SIZE)(1)
- std 2, -296(5)
- std 14, -288(5)
- std 15, -280(5)
- std 16, -272(5)
- std 17, -264(5)
- std 18, -256(5)
- std 19, -248(5)
- std 20, -240(5)
- std 21, -232(5)
- std 22, -224(5)
- std 23, -216(5)
- std 24, -208(5)
- std 25, -200(5)
- std 26, -192(5)
- std 27, -184(5)
- std 28, -176(5)
- std 29, -168(5)
- std 30, -160(5)
- std 31, -152(5)
- stfd 14, -144(5)
- stfd 15, -136(5)
- stfd 16, -128(5)
- stfd 17, -120(5)
- stfd 18, -112(5)
- stfd 19, -104(5)
- stfd 20, -96(5)
- stfd 21, -88(5)
- stfd 22, -80(5)
- stfd 23, -72(5)
- stfd 24, -64(5)
- stfd 25, -56(5)
- stfd 26, -48(5)
- stfd 27, -40(5)
- stfd 28, -32(5)
- stfd 29, -24(5)
- stfd 30, -16(5)
- stfd 31, -8(5)
mr 27, 4
mtctr 3
mr 12, 3
bctr
-.globl StgReturn
-.type StgReturn,@function
+
+ .globl StgReturn
+ .type StgReturn,@function
StgReturn:
-.localentry StgReturn,.-StgReturn
+ addis 2,12,.TOC.-StgReturn@ha
+ addi 2,2,.TOC.-StgReturn@l
+ .localentry StgReturn,.-StgReturn
mr 3,14
- la 5, STACK_FRAME_SIZE(1)
- ld 2, -296(5)
- ld 14, -288(5)
- ld 15, -280(5)
- ld 16, -272(5)
- ld 17, -264(5)
- ld 18, -256(5)
- ld 19, -248(5)
- ld 20, -240(5)
- ld 21, -232(5)
- ld 22, -224(5)
- ld 23, -216(5)
- ld 24, -208(5)
- ld 25, -200(5)
- ld 26, -192(5)
- ld 27, -184(5)
- ld 28, -176(5)
- ld 29, -168(5)
- ld 30, -160(5)
- ld 31, -152(5)
- lfd 14, -144(5)
- lfd 15, -136(5)
- lfd 16, -128(5)
- lfd 17, -120(5)
- lfd 18, -112(5)
- lfd 19, -104(5)
- lfd 20, -96(5)
- lfd 21, -88(5)
- lfd 22, -80(5)
- lfd 23, -72(5)
- lfd 24, -64(5)
- lfd 25, -56(5)
- lfd 26, -48(5)
- lfd 27, -40(5)
- lfd 28, -32(5)
- lfd 29, -24(5)
- lfd 30, -16(5)
- lfd 31, -8(5)
- mr 1, 5
- ld 0, 16(1)
- mtlr 0
- blr
+ la 1, STACK_FRAME_SIZE(1)
+ addi 12,1,-(8*18)
+ bl _restgpr1_14
+ b _restfpr_14
.section .note.GNU-stack,"",@progbits
# else // linux_HOST_OS