Mercurial > pub > dyncall > dyncall
diff dyncallback/dyncall_callback_ppc32_apple.s @ 0:3e629dc19168
initial from svn dyncall-1745
author | Daniel Adler |
---|---|
date | Thu, 19 Mar 2015 22:24:28 +0100 |
parents | |
children | df556fd8ea37 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dyncallback/dyncall_callback_ppc32_apple.s Thu Mar 19 22:24:28 2015 +0100 @@ -0,0 +1,181 @@ +/* + + Package: dyncall + Library: dyncallback + File: dyncallback/dyncall_callback_ppc32_apple.s + Description: Callback Thunk - PowerPC 32-bit System V ABI + 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. + +*/ + + .machine ppc + .text + .align 2 + +/* Callback Thunk Entry code for PowerPC 32-bit Darwin/Apple Mac OS X. */ + + +/* Stack Frame Layout: + + 204 DCValue ( ) + 56 DCArgs (32+104+4+8 = 148) + 24 Parameter area ( 4*8 = 32 ) + 0 Linkage area ( 24 ) + + +*/ + +/* Constants. */ +INT_REGS = 8 +FLOAT_REGS = 13 +SIZEOF_INT = 4 +SIZEOF_DOUBLE = 8 + + +/* Linkage area. */ +LINK_SP = 0 +LINK_CR = 4 +LINK_LR = 8 +LINK_OFFSET = 0 +LINK_SIZE = 24 +/* Parameter area. */ +PAR_OFFSET = LINK_SIZE +PAR_SIZE = 32 +/* local struct DCArgs */ +ARGS_OFFSET = (PAR_OFFSET+PAR_SIZE) +ARGS_SIZE = (SIZEOF_INT*INT_REGS)+(SIZEOF_DOUBLE*FLOAT_REGS) /* = 136 */ +/* local struct DCValue */ +RESULT_OFFSET = (ARGS_OFFSET+ARGS_SIZE) +RESULT_SIZE = 16 +/* additional locals (reg 30/31) */ +LOCALS_OFFSET = (RESULT_OFFSET+RESULT_SIZE) +LOCALS_SIZE = 2*SIZEOF_INT +/* total */ +FRAME_SIZE = ( (LOCALS_OFFSET+LOCALS_SIZE)+15 & (-16) ) + +/* struct DCCallback */ +DCB_THUNK = 0 +DCB_HANDLER = 24 +DCB_STACKCLEAN = 28 +DCB_USERDATA = 32 + +/* struct DCArgs */ +DCA_IARRAY = 0 +DCA_FARRAY = SIZEOF_INT*INT_REGS +DCA_SP = DCA_FARRAY + SIZEOF_DOUBLE*FLOAT_REGS +DCA_ICOUNT = DCA_SP + 4 +DCA_FCOUNT = DCA_ICOUNT + 4 + +/* struct DCValue */ +DCV_INT = 0 +DCV_FLOAT = 0 +DCV_DOUBLE = 0 +DCV_LONG_HI32 = 0 +DCV_LONG_LO32 = 4 +DCV_SIZE = 8 + +iregfile = ARGS_OFFSET+DCA_IARRAY +fregfile = ARGS_OFFSET+DCA_FARRAY +save_sp = ARGS_OFFSET+DCA_SP +icount = ARGS_OFFSET+DCA_ICOUNT +fcount = ARGS_OFFSET+DCA_FCOUNT + .globl _dcCallbackThunkEntry + + /* + Thunk entry: + R2 = DCCallback* + */ +_dcCallbackThunkEntry: + + mflr r0 + stw r0, 8(r1) /* store return address */ + /* stmw r30, -8(r1) */ /* store preserved registers (r30/r31) */ + addi r12, r1, PAR_OFFSET /* temporary r12 = parameter area on callers stack frame */ + stwu r1, -FRAME_SIZE(r1) /* save callers stack pointer and make new stack frame. */ + stw r3, iregfile+0*4(r1) /* spill 8 integer parameter registers */ + stw r4, iregfile+1*4(r1) + stw r5, iregfile+2*4(r1) + stw r6, iregfile+3*4(r1) + stw r7, iregfile+4*4(r1) + stw r8, iregfile+5*4(r1) + stw r9, iregfile+6*4(r1) + stw r10,iregfile+7*4(r1) + stfd f1, fregfile+ 0*8(r1) /* spill 13 float parameter registers */ + stfd f2, fregfile+ 1*8(r1) + stfd f3, fregfile+ 2*8(r1) + stfd f4, fregfile+ 3*8(r1) + stfd f5, fregfile+ 4*8(r1) + stfd f6, fregfile+ 5*8(r1) + stfd f7, fregfile+ 6*8(r1) + stfd f8, fregfile+ 7*8(r1) + stfd f9, fregfile+ 8*8(r1) + stfd f10,fregfile+ 9*8(r1) + stfd f11,fregfile+10*8(r1) + stfd f12,fregfile+11*8(r1) + stfd f13,fregfile+12*8(r1) + /* initialize struct DCCallback */ + stw r12,save_sp(r1) /* init stack pointer */ + xor r0, r0, r0 /* init register counters */ + stw r0, icount(r1) + stw r0, fcount(r1) + /* invoke callback handler */ + mr r3, r2 /* arg 1: DCCallback* pcb */ + addi r4, r1, ARGS_OFFSET /* arg 2: DCArgs* args */ + addi r5, r1, RESULT_OFFSET /* arg 3: DCValue* result */ + lwz r6, DCB_USERDATA(r2) /* arg 4: void* userdata */ + + /* branch-and-link to DCCallback.handler */ + lwz r12, DCB_HANDLER(r2) + mtctr r12 + bctrl + addi r0, r1, RESULT_OFFSET /* r0 = DCValue* */ + /* switch on base result type */ + cmpi cr0, r3, 'B + beq .i32 + cmpi cr0, r3, 'i + beq .i32 + cmpi cr0, r3, 'l + beq .i64 + cmpi cr0, r3, 'f + beq .f32 + cmpi cr0, r3, 'd + beq .f64 + cmpi cr0, r3, 'p + beq .i32 +.void: /* ignore result (void call) */ + b .end +.i32: /* result is integer <= 32-bit result */ + lwz r3, RESULT_OFFSET + DCV_INT(r1) + b .end +.f32: /* result is C float result */ + lfs f1, RESULT_OFFSET + DCV_FLOAT(r1) + b .end +.f64: + lfd f1, RESULT_OFFSET + DCV_FLOAT(r1) + b .end +.i64: /* result is C double result */ + lwz r3, RESULT_OFFSET + DCV_LONG_HI32(r1) + lwz r4, RESULT_OFFSET + DCV_LONG_LO32(r1) + b .end +.end: + lwz r1, 0(r1) /* restore stack pointer */ + /* lmw r30, -8(r1) */ /* restore preserved registers */ + lwz r0, 8(r1) /* load link register with return address */ + mtlr r0 + blr /* branch back to link register */ +