Mercurial > pub > dyncall > dyncall
diff dyncall/dyncall_call_ppc32.S @ 0:3e629dc19168
initial from svn dyncall-1745
author | Daniel Adler |
---|---|
date | Thu, 19 Mar 2015 22:24:28 +0100 |
parents | |
children | f5577f6bf97a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dyncall/dyncall_call_ppc32.S Thu Mar 19 22:24:28 2015 +0100 @@ -0,0 +1,291 @@ +/* + + Package: dyncall + Library: dyncall + File: dyncall/dyncall_call_ppc32.S + Description: Call Kernel for PowerPC 32-bit Architecture + License: + + Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>, + Tassilo Philipp <tphilipp@potion-studios.com> + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + + + +#include "../portasm/portasm-ppc.S" + +/* + Call Kernel Implementations for PowerPC. + Supported Calling Conventions: sysv, darwin, syscall + +*/ + + .machine ppc + .text + +/* ============================================================================ + DynCall Call Kernels for PPC32 Architecture + ------------------------------------------------------------------------- + C Interface: + struct DCRegData { int i[8]; double d[13]; }; + dcCall_ppc32_XXX(DCpointer target, struct DCRegData* pRegData, DCsize stacksize, DCptr stackdata); + + Where XXX is one of the following Calling Conventions: + darwin, sysv + + ChangeLog: + 2015-01-15: Added support for system calls. + 2011-04-03: Using portasm. + 2009-01-09: Added Support for System V ABI. + 2007-11-28: Initial Support for Darwin. + +*/ + +/*--------------------------------------------------------------------------- + + Call Kernel for ppc32 Darwin + + Input: + r3 : target address ptr + r4 : register data ptr (8 x GPR 32 bytes, 13 x FPR 64 bytes) + r5 : stack data size + r6 : stack data ptr + + Details: + - Stack frames are always aligned on 16 byte + - The GPR3 .. GPR10 are loaded + - The FPR1 .. FPR13 are loaded + - No support for Vector Parameters so far. + - Parameter Area (min. 32 Bytes) + - Linkage Area (24 Bytes) +*/ + + .align 2 +GLOBAL_C(dcCall_ppc32_darwin) +ENTRY_C(dcCall_ppc32_darwin) + + + mflr r0 /* r0 = return address */ + stw r0,8(r1) /* store return address in caller link-area */ + + /* compute aligned stack-size */ + + /* add link area and align to 16 byte border */ + + addi r0,r5,24+15 /* r0 = stacksize + link area */ + + rlwinm r0,r0,0,0,27 /* r0 = r0 and -15 */ + /* r0 = r0 and -15 */ + neg r2,r0 /* r2 = -stacksize */ + + stwux r1,r1,r2 /* r1 = r1 - stacksize */ + + /* copy stack data */ + + subi r6,r6,4 /* r6 = 4 bytes before source stack ptr */ + addi r7,r1,20 /* r7 = 4 bytes before target stack parameter-block */ + + srwi r5,r5,2 /* r5 = size in words */ + + cmpi cr0,r5,0 /* if stacksize != 0 .. */ + beq cr0,.osx_done + + mtctr r5 /* copy loop */ + +.osx_next: + lwzu r0, 4(r6) + stwu r0, 4(r7) + bdnz .osx_next + +.osx_done: + + mr r12, r3 /* r12 = target function */ + mtctr r12 /* control register = target function */ + mr r2, r4 /* r2 = reg data */ + + /* load 8 integer registers */ + + lwz r3 , 0(r2) + lwz r4 , 4(r2) + lwz r5 , 8(r2) + lwz r6 ,12(r2) + lwz r7 ,16(r2) + lwz r8 ,20(r2) + lwz r9 ,24(r2) + lwz r10,28(r2) + + /* load 13 float registers */ + + lfd f1 ,32(r2) + lfd f2 ,40(r2) + lfd f3 ,48(r2) + lfd f4 ,56(r2) + lfd f5 ,64(r2) + lfd f6 ,72(r2) + lfd f7 ,80(r2) + lfd f8 ,88(r2) + lfd f9 ,96(r2) + lfd f10,104(r2) + lfd f11,112(r2) + lfd f12,120(r2) + lfd f13,128(r2) + + /* branch */ + + bctrl + + /* epilog */ + + lwz r1, 0(r1) /* restore stack */ + lwz r0, 8(r1) /* r0 = return address */ + mtlr r0 /* setup link register */ + blr /* return */ + +/* ---------------------------------------------------------------------------- + + Call Kernel for ppc32 System + + Input: + r3 : target address ptr + r4 : register data ptr (8 x GPR 32 bytes, 8 x FPR 64 bytes) + r5 : stack data size + r6 : stack data ptr + + Details: + - Stack frames are always aligned on 16 byte + - Reserve GPR2 (System register) + - The GPR3 .. GPR10 are loaded + - The FPR1 .. FPR8 are loaded + - No support for Vector Parameters so far. + + Frame structure: + + on entry, parent frame layout: + + offset + 4: LR save word (Callee stores LR in parent frame) + 0: parent stack frame (back-chain) + + after frame initialization: + + stack size = ( (8+15) + stacksize ) & -(16) + + ... locals and register spills + 8: parameter list area + 4: LR save word (Callee stores LR in parent frame) + 0: parent stack frame (back-chain) +*/ + + .align 2 +GLOBAL_C(dcCall_ppc32_sysv) +ENTRY_C(dcCall_ppc32_sysv) + mflr r0 /* r0 = return address */ + stw r0,4(r1) /* store r0 to link-area */ + + /* compute aligned stack-size */ + + /* add link area (+8) and align to 16 byte (+15) */ + + /* r0 = stacksize + frame parameter(back-chain link, this callee's call return address) */ + addi r0,r5,8+15 /* r0 = r5 + 8 + 15 */ + rlwinm r0,r0,0,0,27 /* r0 = r0 and -15 */ + neg r0,r0 /* r0 = -r0 */ + stwux r1,r1,r0 /* store r1 and decrement */ + + /* copy stack data */ + + subi r6,r6,4 /* r6 = 4 bytes before source stack ptr */ + + /* 4 bytes before target stack parameter-block */ + addi r7,r1,4 /* r7 = r1 + 8 offset - 4 displacement */ + + srwi r5,r5,2 /* r5 = size in words */ + + cmpi cr0,r5,0 /* if stacksize != 0 .. */ + beq cr0,.sysv_done + + mtctr r5 /* copy loop */ + +.sysv_next: + lwzu r0, 4(r6) + stwu r0, 4(r7) + bdnz .sysv_next + +.sysv_done: + + /* this call support using ctr branch register */ + + mr r12, r3 /* r12 = target function */ + mtctr r12 /* control register = r12 */ + mr r11, r4 /* r11 = reg data */ + + /* load 8 integer registers */ + + lwz r3 , 0(r11) + lwz r4 , 4(r11) + lwz r5 , 8(r11) + lwz r6 ,12(r11) + lwz r7 ,16(r11) + lwz r8 ,20(r11) + lwz r9 ,24(r11) + lwz r10,28(r11) + + /* load 8 float registers */ + + lfd f1 ,32(r11) + lfd f2 ,40(r11) + lfd f3 ,48(r11) + lfd f4 ,56(r11) + lfd f5 ,64(r11) + lfd f6 ,72(r11) + lfd f7 ,80(r11) + lfd f8 ,88(r11) + + creqv 6,6,6 /* used for ellipsis calls */ + + bctrl /* branch with this call support */ + + /* epilog */ + + lwz r1, 0(r1) /* restore stack */ + lwz r0, 4(r1) /* r0 = return address */ + mtlr r0 /* setup link register */ + blr /* return */ + + + .align 2 + +GLOBAL_C(dcCall_ppc32_syscall) +ENTRY_C(dcCall_ppc32_syscall) + mflr r0 /* r0 = return address */ + stw r0,4(r1) /* store r0 to link-area */ + li r0, -8 + stwux r1,r1,r0 /* store r1 and decrement */ + + mr r0, r3 /* r0 = syscall number ( passed as 'target function' ) */ + mr r11, r4 /* r11 = reg data */ + lwz r3 , 0(r11) + lwz r4 , 4(r11) + lwz r5 , 8(r11) + lwz r6 ,12(r11) + lwz r7 ,16(r11) + sc + + lwz r1, 0(r1) /* restore stack */ + lwz r0, 4(r1) /* r0 = return address */ + mtlr r0 /* setup link register */ + blr +