diff options
-rw-r--r-- | rts/StgCRun.c | 137 | ||||
-rw-r--r-- | rts/StgCRunAsm.S | 134 |
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 |