0
|
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
|