Mercurial > pub > dyncall > dyncall
comparison dyncallback/dyncall_callback_ppc64.S @ 0:3e629dc19168
initial from svn dyncall-1745
author | Daniel Adler |
---|---|
date | Thu, 19 Mar 2015 22:24:28 +0100 |
parents | |
children | 7ca57dbefed4 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3e629dc19168 |
---|---|
1 /* | |
2 | |
3 Package: dyncall | |
4 Library: dyncallback | |
5 File: dyncallback/dyncall_callback_ppc64.S | |
6 Description: Callback Thunk - Implementation for PowerPC 64-bit | |
7 License: | |
8 | |
9 Copyright (c) 2014-2015 Masanori Mitsugi <mitsugi@linux.vnet.ibm.com> | |
10 | |
11 Permission to use, copy, modify, and distribute this software for any | |
12 purpose with or without fee is hereby granted, provided that the above | |
13 copyright notice and this permission notice appear in all copies. | |
14 | |
15 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
16 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
17 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
18 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
22 | |
23 */ | |
24 | |
25 #include "../portasm/portasm-ppc.S" | |
26 | |
27 /* Callback Thunk Entry code for PowerPC 64-bit. */ | |
28 | |
29 /* Stack Frame Layout: | |
30 | |
31 296 DCValue ( 8 ) | |
32 112 DCArgs ( 64+104+8+4+4 = 184 ) | |
33 48 Parameter area ( 8*8 = 64 ) | |
34 0 Linkage area ( 48 ) | |
35 | |
36 | |
37 */ | |
38 | |
39 /* Constants. */ | |
40 INT_REGS = 8 | |
41 FLOAT_REGS = 13 | |
42 SIZEOF_GPR = 8 | |
43 SIZEOF_FPR = 8 | |
44 | |
45 /* Linkage area. */ | |
46 LINK_SP = 0 | |
47 LINK_CR = 8 | |
48 LINK_LR = 16 | |
49 LINK_OFFSET = 0 | |
50 #if DC__ABI_PPC64_ELF_V == 2 | |
51 LINK_TOC = 24 | |
52 LINK_SIZE = 32 | |
53 #else | |
54 LINK_TOC = 40 | |
55 LINK_SIZE = 48 | |
56 #endif | |
57 /* Parameter area. */ | |
58 PAR_OFFSET = LINK_SIZE | |
59 #if DC__ABI_PPC64_ELF_V == 2 | |
60 PAR_SIZE = 0 | |
61 #else | |
62 PAR_SIZE = 64 | |
63 #endif | |
64 /* local struct DCArgs */ | |
65 ARGS_OFFSET = (PAR_OFFSET+PAR_SIZE) | |
66 ARGS_SIZE = (SIZEOF_GPR*INT_REGS)+(SIZEOF_FPR*FLOAT_REGS) + 8 + 4 * 4 | |
67 /* local struct DCValue */ | |
68 RESULT_OFFSET = (ARGS_OFFSET+ARGS_SIZE) | |
69 RESULT_SIZE = 8 | |
70 /* additional locals (reg 30/31) */ | |
71 LOCALS_OFFSET = (RESULT_OFFSET+RESULT_SIZE) | |
72 LOCALS_SIZE = 2*SIZEOF_GPR | |
73 /* total */ | |
74 FRAME_SIZE = ( (LOCALS_OFFSET+LOCALS_SIZE)+15 & (-16) ) | |
75 | |
76 /* struct DCCallback */ | |
77 #if DC__ABI_PPC64_ELF_V == 2 | |
78 DCB_THUNK = 0 | |
79 DCB_HANDLER = 48 | |
80 DCB_STACKCLEAN = 56 | |
81 DCB_USERDATA = 64 | |
82 #else | |
83 DCB_THUNK = 0 | |
84 DCB_HANDLER = 64 | |
85 DCB_STACKCLEAN = 72 | |
86 DCB_USERDATA = 80 | |
87 #endif | |
88 | |
89 /* struct DCArgs */ | |
90 DCA_IARRAY = 0 | |
91 DCA_FARRAY = SIZEOF_GPR*INT_REGS | |
92 DCA_SP = DCA_FARRAY + SIZEOF_FPR*FLOAT_REGS | |
93 DCA_ICOUNT = DCA_SP + 8 | |
94 DCA_FCOUNT = DCA_ICOUNT + 4 | |
95 | |
96 /* struct DCValue */ | |
97 DCV_INT = 0 | |
98 DCV_FLOAT = 0 | |
99 DCV_SIZE = 8 | |
100 | |
101 iregfile = ARGS_OFFSET+DCA_IARRAY | |
102 fregfile = ARGS_OFFSET+DCA_FARRAY | |
103 save_sp = ARGS_OFFSET+DCA_SP | |
104 icount = ARGS_OFFSET+DCA_ICOUNT | |
105 fcount = ARGS_OFFSET+DCA_FCOUNT | |
106 | |
107 /* | |
108 Thunk entry: | |
109 R2 = DCCallback* | |
110 */ | |
111 .text | |
112 .global dcCallbackThunkEntry | |
113 .type dcCallbackThunkEntry, @function | |
114 #if DC__ABI_PPC64_ELF_V != 2 | |
115 .section .opd, "aw" | |
116 .align 3 | |
117 #endif | |
118 | |
119 dcCallbackThunkEntry: | |
120 #if DC__ABI_PPC64_ELF_V != 2 | |
121 .quad .dcCallbackThunkEntry, .TOC.@tocbase, 0 | |
122 .previous | |
123 .global .dcCallbackThunkEntry | |
124 | |
125 .dcCallbackThunkEntry: | |
126 #endif | |
127 mflr r0 | |
128 std r0, 16(r1) /* store return address */ | |
129 std r31, -8(r1) /* store preserved registers (r31) */ | |
130 addi r12, r1, PAR_OFFSET /* temporary r12 = parameter area on callers stack frame */ | |
131 stdu r1, -FRAME_SIZE(r1) /* save callers stack pointer and make new stack frame. */ | |
132 | |
133 std r3, iregfile+0*8(r1) /* spill 8 integer parameter registers */ | |
134 std r4, iregfile+1*8(r1) | |
135 std r5, iregfile+2*8(r1) | |
136 std r6, iregfile+3*8(r1) | |
137 std r7, iregfile+4*8(r1) | |
138 std r8, iregfile+5*8(r1) | |
139 std r9, iregfile+6*8(r1) | |
140 std r10,iregfile+7*8(r1) | |
141 stfd f1, fregfile+ 0*8(r1) /* spill 13 float parameter registers */ | |
142 stfd f2, fregfile+ 1*8(r1) | |
143 stfd f3, fregfile+ 2*8(r1) | |
144 stfd f4, fregfile+ 3*8(r1) | |
145 stfd f5, fregfile+ 4*8(r1) | |
146 stfd f6, fregfile+ 5*8(r1) | |
147 stfd f7, fregfile+ 6*8(r1) | |
148 stfd f8, fregfile+ 7*8(r1) | |
149 stfd f9, fregfile+ 8*8(r1) | |
150 stfd f10,fregfile+ 9*8(r1) | |
151 stfd f11,fregfile+10*8(r1) | |
152 stfd f12,fregfile+11*8(r1) | |
153 stfd f13,fregfile+12*8(r1) | |
154 /* initialize struct DCCallback */ | |
155 std r12,save_sp(r1) /* init stack pointer */ | |
156 xor r0, r0, r0 /* init register counters */ | |
157 std r0, icount(r1) | |
158 std r0, fcount(r1) | |
159 std r0, RESULT_OFFSET(r1) | |
160 /* invoke callback handler */ | |
161 mr r3, r11 /* arg 1: DCCallback* pcb */ | |
162 addi r4, r1, ARGS_OFFSET /* arg 2: DCArgs* args */ | |
163 addi r5, r1, RESULT_OFFSET /* arg 3: DCValue* result */ | |
164 ld r6, DCB_USERDATA(r11) /* arg 4: void* userdata */ | |
165 | |
166 /* branch-and-link to DCCallback.handler */ | |
167 ld r12, DCB_HANDLER(r11) | |
168 std r2, LINK_TOC(r1) | |
169 #if DC__ABI_PPC64_ELF_V != 2 | |
170 ld r2, 8(r12) | |
171 ld r0, 0(r12) | |
172 mtctr r0 | |
173 #else | |
174 mtctr r12 | |
175 #endif | |
176 bctrl | |
177 | |
178 addi r0, r1, RESULT_OFFSET /* r0 = DCValue* */ | |
179 /* switch on base result type */ | |
180 cmpi cr0, r3, 'B | |
181 beq .i64 | |
182 cmpi cr0, r3, 'i | |
183 beq .i64 | |
184 cmpi cr0, r3, 'c | |
185 beq .i64 | |
186 cmpi cr0, r3, 's | |
187 beq .i64 | |
188 cmpi cr0, r3, 'l | |
189 beq .i64 | |
190 cmpi cr0, r3, 'f | |
191 beq .f32 | |
192 cmpi cr0, r3, 'd | |
193 beq .f64 | |
194 cmpi cr0, r3, 'p | |
195 beq .i64 | |
196 .void: /* ignore result (void call) */ | |
197 b .end | |
198 .i64: /* result is 64-bit long long result */ | |
199 ld r3, RESULT_OFFSET + DCV_INT(r1) | |
200 b .end | |
201 .f32: /* result is C float result */ | |
202 lfs f1, RESULT_OFFSET + DCV_FLOAT(r1) | |
203 b .end | |
204 .f64: /* result is C double result */ | |
205 lfd f1, RESULT_OFFSET + DCV_FLOAT(r1) | |
206 b .end | |
207 .end: | |
208 | |
209 ld r2, LINK_TOC(r1) | |
210 ld r1, 0(r1) /* restore stack pointer */ | |
211 ld r31, -8(r1) /* restore preserved registers */ | |
212 ld r0, 16(r1) /* load link register with return address */ | |
213 mtlr r0 | |
214 blr /* branch back to link register */ | |
215 |