comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:3e629dc19168
1 /*
2
3 Package: dyncall
4 Library: dyncallback
5 File: dyncallback/dyncall_callback_ppc32_apple.s
6 Description: Callback Thunk - PowerPC 32-bit System V ABI
7 License:
8
9 Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
10 Tassilo Philipp <tphilipp@potion-studios.com>
11
12 Permission to use, copy, modify, and distribute this software for any
13 purpose with or without fee is hereby granted, provided that the above
14 copyright notice and this permission notice appear in all copies.
15
16 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
17 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
19 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
22 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
24 */
25
26 .machine ppc
27 .text
28 .align 2
29
30 /* Callback Thunk Entry code for PowerPC 32-bit Darwin/Apple Mac OS X. */
31
32
33 /* Stack Frame Layout:
34
35 204 DCValue ( )
36 56 DCArgs (32+104+4+8 = 148)
37 24 Parameter area ( 4*8 = 32 )
38 0 Linkage area ( 24 )
39
40
41 */
42
43 /* Constants. */
44 INT_REGS = 8
45 FLOAT_REGS = 13
46 SIZEOF_INT = 4
47 SIZEOF_DOUBLE = 8
48
49
50 /* Linkage area. */
51 LINK_SP = 0
52 LINK_CR = 4
53 LINK_LR = 8
54 LINK_OFFSET = 0
55 LINK_SIZE = 24
56 /* Parameter area. */
57 PAR_OFFSET = LINK_SIZE
58 PAR_SIZE = 32
59 /* local struct DCArgs */
60 ARGS_OFFSET = (PAR_OFFSET+PAR_SIZE)
61 ARGS_SIZE = (SIZEOF_INT*INT_REGS)+(SIZEOF_DOUBLE*FLOAT_REGS) /* = 136 */
62 /* local struct DCValue */
63 RESULT_OFFSET = (ARGS_OFFSET+ARGS_SIZE)
64 RESULT_SIZE = 16
65 /* additional locals (reg 30/31) */
66 LOCALS_OFFSET = (RESULT_OFFSET+RESULT_SIZE)
67 LOCALS_SIZE = 2*SIZEOF_INT
68 /* total */
69 FRAME_SIZE = ( (LOCALS_OFFSET+LOCALS_SIZE)+15 & (-16) )
70
71 /* struct DCCallback */
72 DCB_THUNK = 0
73 DCB_HANDLER = 24
74 DCB_STACKCLEAN = 28
75 DCB_USERDATA = 32
76
77 /* struct DCArgs */
78 DCA_IARRAY = 0
79 DCA_FARRAY = SIZEOF_INT*INT_REGS
80 DCA_SP = DCA_FARRAY + SIZEOF_DOUBLE*FLOAT_REGS
81 DCA_ICOUNT = DCA_SP + 4
82 DCA_FCOUNT = DCA_ICOUNT + 4
83
84 /* struct DCValue */
85 DCV_INT = 0
86 DCV_FLOAT = 0
87 DCV_DOUBLE = 0
88 DCV_LONG_HI32 = 0
89 DCV_LONG_LO32 = 4
90 DCV_SIZE = 8
91
92 iregfile = ARGS_OFFSET+DCA_IARRAY
93 fregfile = ARGS_OFFSET+DCA_FARRAY
94 save_sp = ARGS_OFFSET+DCA_SP
95 icount = ARGS_OFFSET+DCA_ICOUNT
96 fcount = ARGS_OFFSET+DCA_FCOUNT
97 .globl _dcCallbackThunkEntry
98
99 /*
100 Thunk entry:
101 R2 = DCCallback*
102 */
103 _dcCallbackThunkEntry:
104
105 mflr r0
106 stw r0, 8(r1) /* store return address */
107 /* stmw r30, -8(r1) */ /* store preserved registers (r30/r31) */
108 addi r12, r1, PAR_OFFSET /* temporary r12 = parameter area on callers stack frame */
109 stwu r1, -FRAME_SIZE(r1) /* save callers stack pointer and make new stack frame. */
110 stw r3, iregfile+0*4(r1) /* spill 8 integer parameter registers */
111 stw r4, iregfile+1*4(r1)
112 stw r5, iregfile+2*4(r1)
113 stw r6, iregfile+3*4(r1)
114 stw r7, iregfile+4*4(r1)
115 stw r8, iregfile+5*4(r1)
116 stw r9, iregfile+6*4(r1)
117 stw r10,iregfile+7*4(r1)
118 stfd f1, fregfile+ 0*8(r1) /* spill 13 float parameter registers */
119 stfd f2, fregfile+ 1*8(r1)
120 stfd f3, fregfile+ 2*8(r1)
121 stfd f4, fregfile+ 3*8(r1)
122 stfd f5, fregfile+ 4*8(r1)
123 stfd f6, fregfile+ 5*8(r1)
124 stfd f7, fregfile+ 6*8(r1)
125 stfd f8, fregfile+ 7*8(r1)
126 stfd f9, fregfile+ 8*8(r1)
127 stfd f10,fregfile+ 9*8(r1)
128 stfd f11,fregfile+10*8(r1)
129 stfd f12,fregfile+11*8(r1)
130 stfd f13,fregfile+12*8(r1)
131 /* initialize struct DCCallback */
132 stw r12,save_sp(r1) /* init stack pointer */
133 xor r0, r0, r0 /* init register counters */
134 stw r0, icount(r1)
135 stw r0, fcount(r1)
136 /* invoke callback handler */
137 mr r3, r2 /* arg 1: DCCallback* pcb */
138 addi r4, r1, ARGS_OFFSET /* arg 2: DCArgs* args */
139 addi r5, r1, RESULT_OFFSET /* arg 3: DCValue* result */
140 lwz r6, DCB_USERDATA(r2) /* arg 4: void* userdata */
141
142 /* branch-and-link to DCCallback.handler */
143 lwz r12, DCB_HANDLER(r2)
144 mtctr r12
145 bctrl
146 addi r0, r1, RESULT_OFFSET /* r0 = DCValue* */
147 /* switch on base result type */
148 cmpi cr0, r3, 'B
149 beq .i32
150 cmpi cr0, r3, 'i
151 beq .i32
152 cmpi cr0, r3, 'l
153 beq .i64
154 cmpi cr0, r3, 'f
155 beq .f32
156 cmpi cr0, r3, 'd
157 beq .f64
158 cmpi cr0, r3, 'p
159 beq .i32
160 .void: /* ignore result (void call) */
161 b .end
162 .i32: /* result is integer <= 32-bit result */
163 lwz r3, RESULT_OFFSET + DCV_INT(r1)
164 b .end
165 .f32: /* result is C float result */
166 lfs f1, RESULT_OFFSET + DCV_FLOAT(r1)
167 b .end
168 .f64:
169 lfd f1, RESULT_OFFSET + DCV_FLOAT(r1)
170 b .end
171 .i64: /* result is C double result */
172 lwz r3, RESULT_OFFSET + DCV_LONG_HI32(r1)
173 lwz r4, RESULT_OFFSET + DCV_LONG_LO32(r1)
174 b .end
175 .end:
176 lwz r1, 0(r1) /* restore stack pointer */
177 /* lmw r30, -8(r1) */ /* restore preserved registers */
178 lwz r0, 8(r1) /* load link register with return address */
179 mtlr r0
180 blr /* branch back to link register */
181