Mercurial > pub > dyncall > dyncall
comparison dyncall/dyncall_callvm_ppc32.c @ 0:3e629dc19168
initial from svn dyncall-1745
author | Daniel Adler |
---|---|
date | Thu, 19 Mar 2015 22:24:28 +0100 |
parents | |
children | 67961454902b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3e629dc19168 |
---|---|
1 /* | |
2 | |
3 Package: dyncall | |
4 Library: dyncall | |
5 File: dyncall/dyncall_callvm_ppc32.c | |
6 Description: | |
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 | |
27 | |
28 /* | |
29 | |
30 dyncall callvm for ppc32 architectures | |
31 | |
32 SUPPORTED CALLING CONVENTIONS | |
33 ppc32/osx | |
34 ppc32/linux (sysv abi) | |
35 ppc32/syscall | |
36 | |
37 REVISION | |
38 2015/01/15 added syscall (tested on Linux) | |
39 2009/01/09 added System V ABI support | |
40 2007/12/11 initial support for Darwin ABI | |
41 | |
42 */ | |
43 | |
44 #include "dyncall_callvm_ppc32.h" | |
45 #include "dyncall_call_ppc32.h" | |
46 #include "dyncall_alloc.h" | |
47 #include "dyncall_macros.h" | |
48 #include "dyncall_types.h" | |
49 #include "dyncall_utils.h" | |
50 | |
51 /* Support for Mac OS X (Darwin) and Systen V ABI for Power PC 32-bit */ | |
52 | |
53 #if defined(DC__OS_Darwin) | |
54 #define DC__ABI_Darwin | |
55 #elif defined(DC__OS_Linux) || defined(DC__OS_FreeBSD) || defined(DC__OS_OpenBSD) || defined(DC__OS_NetBSD) || defined(DC__OS_DragonFlyBSD) || defined(DC__OS_SunOS) | |
56 #define DC__ABI_SysV | |
57 #else | |
58 #error Unsupported OS for ppc32 architecture. | |
59 #endif | |
60 | |
61 static void dc_callvm_free_ppc32(DCCallVM* in_self) | |
62 { | |
63 dcFreeMem(in_self); | |
64 } | |
65 | |
66 static void dc_callvm_reset_ppc32(DCCallVM* in_self) | |
67 { | |
68 DCCallVM_ppc32* self = (DCCallVM_ppc32*)in_self; | |
69 dcVecReset(&self->mVecHead); | |
70 self->mIntRegs = 0; | |
71 self->mFloatRegs = 0; | |
72 } | |
73 | |
74 /* OS X/Darwin: fillup integer register file AND push on stack (for ellipsis) */ | |
75 | |
76 static void dc_callvm_argInt_ppc32_darwin(DCCallVM* in_self, DCint i) | |
77 { | |
78 DCCallVM_ppc32* self = (DCCallVM_ppc32*)in_self; | |
79 /* fillup integer register file */ | |
80 if (self->mIntRegs < 8) | |
81 self->mRegData.mIntData[self->mIntRegs++] = i; | |
82 /* AND push onto stack */ | |
83 dcVecAppend(&self->mVecHead,&i,sizeof(DCint)); | |
84 } | |
85 | |
86 static void dc_callvm_argInt_ppc32_sysv(DCCallVM* in_self, DCint i) | |
87 { | |
88 DCCallVM_ppc32* self = (DCCallVM_ppc32*)in_self; | |
89 /* fillup integer register file */ | |
90 if (self->mIntRegs < 8) | |
91 self->mRegData.mIntData[self->mIntRegs++] = i; | |
92 /* OR push onto stack */ | |
93 else | |
94 dcVecAppend(&self->mVecHead,&i,sizeof(DCint)); | |
95 } | |
96 | |
97 /** floating-point **/ | |
98 | |
99 /* double*/ | |
100 | |
101 static void dc_callvm_argDouble_ppc32_darwin(DCCallVM* in_self, DCdouble d) | |
102 { | |
103 DCCallVM_ppc32* self = (DCCallVM_ppc32*)in_self; | |
104 if (self->mFloatRegs < 13) { | |
105 self->mRegData.mFloatData[self->mFloatRegs++] = d; | |
106 /* skip two integer register file entries */ | |
107 if (self->mIntRegs < 8) | |
108 self->mRegData.mIntData[self->mIntRegs++] = ( (DCint*) &d )[0]; | |
109 if (self->mIntRegs < 8) | |
110 self->mRegData.mIntData[self->mIntRegs++] = ( (DCint*) &d )[1]; | |
111 } | |
112 /* push on stack */ | |
113 dcVecAppend(&self->mVecHead, &d, sizeof(DCdouble)); | |
114 } | |
115 | |
116 #if 0 | |
117 static void dc_callvm_argDouble_ppc32_sysv(DCCallVM* in_self, DCdouble d) | |
118 { | |
119 DCCallVM_ppc32* self = (DCCallVM_ppc32*)in_self; | |
120 if (self->mFloatRegs < 8) { | |
121 self->mRegData.mFloatData[self->mFloatRegs++] = d; | |
122 /* skip two integer register file entries */ | |
123 if (self->mIntRegs < 8) | |
124 self->mRegData.mIntData[self->mIntRegs++] = ( (DCint*) &d )[0]; | |
125 if (self->mIntRegs < 8) | |
126 self->mRegData.mIntData[self->mIntRegs++] = ( (DCint*) &d )[1]; | |
127 } | |
128 /* push on stack */ | |
129 dcVecAppend(&self->mVecHead, &d, sizeof(DCdouble)); | |
130 } | |
131 #endif | |
132 static void dc_callvm_argDouble_ppc32_sysv(DCCallVM* in_self, DCdouble d) | |
133 { | |
134 DCCallVM_ppc32* self = (DCCallVM_ppc32*)in_self; | |
135 if (self->mFloatRegs < 8) | |
136 self->mRegData.mFloatData[self->mFloatRegs++] = d; | |
137 else /* OR push data on stack */ | |
138 { | |
139 /* align stack to 8 byte boundary */ | |
140 dcVecResize(&self->mVecHead , ( dcVecSize(&self->mVecHead) + 7UL ) & -8UL ); | |
141 /* AND push data */ | |
142 dcVecAppend(&self->mVecHead,(DCpointer) &d,sizeof(DCdouble)); | |
143 } | |
144 } | |
145 | |
146 /* Floating-point */ | |
147 | |
148 | |
149 /* darwin: | |
150 * - skip one integer register file entry (write in - for ellipsis calls) | |
151 * sysv: | |
152 * - | |
153 */ | |
154 | |
155 static void dc_callvm_argFloat_ppc32_darwin(DCCallVM* in_self, DCfloat f) | |
156 { | |
157 DCCallVM_ppc32* self = (DCCallVM_ppc32*)in_self; | |
158 if (self->mFloatRegs < 13) { | |
159 self->mRegData.mFloatData[self->mFloatRegs++] = (DCdouble) (f); | |
160 } | |
161 | |
162 /* AND skip one integer register file entry (write in - for ellipsis calls) */ | |
163 | |
164 if (self->mIntRegs < 8) | |
165 self->mRegData.mIntData[self->mIntRegs++] = *( (DCint*) &f ); | |
166 | |
167 /* AND push on stack */ | |
168 | |
169 dcVecAppend(&self->mVecHead, &f, sizeof(DCfloat)); | |
170 } | |
171 | |
172 static void dc_callvm_argFloat_ppc32_sysv(DCCallVM* in_self, DCfloat f) | |
173 { | |
174 DCCallVM_ppc32* self = (DCCallVM_ppc32*)in_self; | |
175 | |
176 /* Put as float register (casted to double) */ | |
177 | |
178 if (self->mFloatRegs < 8) | |
179 self->mRegData.mFloatData[self->mFloatRegs++] = (DCdouble) (f); | |
180 | |
181 else /* OR put float on stack */ | |
182 dcVecAppend(&self->mVecHead, &f, sizeof(DCfloat)); | |
183 } | |
184 | |
185 /* long long integer */ | |
186 | |
187 static void dc_callvm_argLongLong_ppc32_darwin(DCCallVM* in_self, DClonglong L) | |
188 { | |
189 DCint* p = (DCint*) &L; | |
190 dcArgInt(in_self, p[0]); | |
191 dcArgInt(in_self, p[1]); | |
192 } | |
193 | |
194 static void dc_callvm_argLongLong_ppc32_sysv(DCCallVM* in_self, DClonglong L) | |
195 { | |
196 DCint* p = (DCint*) &L; | |
197 DCCallVM_ppc32* self = (DCCallVM_ppc32*)in_self; | |
198 /* fillup integer register file */ | |
199 if (self->mIntRegs < 7) | |
200 { | |
201 /* next free integer register is even (r0, r2, r3) ? */ | |
202 /* if not, skip one integer */ | |
203 if (self->mIntRegs & 1) self->mIntRegs++; | |
204 | |
205 self->mRegData.mIntData[self->mIntRegs++] = p[0]; | |
206 self->mRegData.mIntData[self->mIntRegs++] = p[1]; | |
207 } | |
208 /* OR push onto stack */ | |
209 else | |
210 { | |
211 /* in case, mIntRegs == 7, set it to 8 */ | |
212 self->mIntRegs = 8; | |
213 /* align stack to 8 byte boundary */ | |
214 dcVecResize(&self->mVecHead , ( dcVecSize(&self->mVecHead) + 7 ) & (-8UL) ); | |
215 /* push data */ | |
216 dcVecAppend(&self->mVecHead,&L,sizeof(DClonglong)); | |
217 } | |
218 } | |
219 | |
220 | |
221 static void dc_callvm_argBool_ppc32(DCCallVM* in_self, DCbool x) | |
222 { | |
223 /* promote to integer */ | |
224 dcArgInt(in_self, (x == 0) ? DC_FALSE : DC_TRUE ); | |
225 } | |
226 | |
227 | |
228 static void dc_callvm_argChar_ppc32(DCCallVM* in_self, DCchar ch) | |
229 { | |
230 /* promote to integer */ | |
231 dcArgInt(in_self, (DCint) ch ); | |
232 } | |
233 | |
234 | |
235 static void dc_callvm_argShort_ppc32(DCCallVM* in_self, DCshort s) | |
236 { | |
237 /* promote to integer */ | |
238 dcArgInt(in_self, (DCint) s ); | |
239 } | |
240 | |
241 | |
242 static void dc_callvm_argLong_ppc32(DCCallVM* in_self, DClong l) | |
243 { | |
244 /* promote to integer */ | |
245 dcArgInt(in_self, (DCint) l ); | |
246 } | |
247 | |
248 static void dc_callvm_argPointer_ppc32(DCCallVM* in_self, DCpointer p) | |
249 { | |
250 /* promote to integer */ | |
251 dcArgInt(in_self, *(DCint*) &p ); | |
252 } | |
253 | |
254 | |
255 void dc_callvm_call_ppc32_darwin(DCCallVM* in_self, DCpointer target) | |
256 { | |
257 DCCallVM_ppc32* self = (DCCallVM_ppc32*)in_self; | |
258 dcCall_ppc32_darwin( | |
259 target, | |
260 &self->mRegData, | |
261 DC_MAX(dcVecSize(&self->mVecHead), 8*4), | |
262 dcVecData(&self->mVecHead) | |
263 ); | |
264 } | |
265 | |
266 void dc_callvm_call_ppc32_sysv(DCCallVM* in_self, DCpointer target) | |
267 { | |
268 DCCallVM_ppc32* self = (DCCallVM_ppc32*) in_self; | |
269 dcCall_ppc32_sysv( target, &self->mRegData, dcVecSize(&self->mVecHead) , dcVecData(&self->mVecHead)); | |
270 } | |
271 | |
272 void dc_callvm_call_ppc32_syscall(DCCallVM* in_self, DCpointer target) | |
273 { | |
274 DCCallVM_ppc32* self = (DCCallVM_ppc32*) in_self; | |
275 dcCall_ppc32_syscall( target, &self->mRegData, dcVecSize(&self->mVecHead) , dcVecData(&self->mVecHead)); | |
276 } | |
277 | |
278 void dc_callvm_mode_ppc32(DCCallVM* in_self, DCint mode); | |
279 | |
280 DCCallVM_vt gVT_ppc32_darwin = | |
281 { | |
282 &dc_callvm_free_ppc32 | |
283 , &dc_callvm_reset_ppc32 | |
284 , &dc_callvm_mode_ppc32 | |
285 , &dc_callvm_argBool_ppc32 | |
286 , &dc_callvm_argChar_ppc32 | |
287 , &dc_callvm_argShort_ppc32 | |
288 , &dc_callvm_argInt_ppc32_darwin | |
289 , &dc_callvm_argLong_ppc32 | |
290 , &dc_callvm_argLongLong_ppc32_darwin | |
291 , &dc_callvm_argFloat_ppc32_darwin | |
292 , &dc_callvm_argDouble_ppc32_darwin | |
293 , &dc_callvm_argPointer_ppc32 | |
294 , NULL /* argStruct */ | |
295 , (DCvoidvmfunc*) &dc_callvm_call_ppc32_darwin | |
296 , (DCboolvmfunc*) &dc_callvm_call_ppc32_darwin | |
297 , (DCcharvmfunc*) &dc_callvm_call_ppc32_darwin | |
298 , (DCshortvmfunc*) &dc_callvm_call_ppc32_darwin | |
299 , (DCintvmfunc*) &dc_callvm_call_ppc32_darwin | |
300 , (DClongvmfunc*) &dc_callvm_call_ppc32_darwin | |
301 , (DClonglongvmfunc*) &dc_callvm_call_ppc32_darwin | |
302 , (DCfloatvmfunc*) &dc_callvm_call_ppc32_darwin | |
303 , (DCdoublevmfunc*) &dc_callvm_call_ppc32_darwin | |
304 , (DCpointervmfunc*) &dc_callvm_call_ppc32_darwin | |
305 , NULL /* callStruct */ | |
306 }; | |
307 | |
308 DCCallVM_vt gVT_ppc32_sysv = | |
309 { | |
310 &dc_callvm_free_ppc32 | |
311 , &dc_callvm_reset_ppc32 | |
312 , &dc_callvm_mode_ppc32 | |
313 , &dc_callvm_argBool_ppc32 | |
314 , &dc_callvm_argChar_ppc32 | |
315 , &dc_callvm_argShort_ppc32 | |
316 , &dc_callvm_argInt_ppc32_sysv | |
317 , &dc_callvm_argLong_ppc32 | |
318 , &dc_callvm_argLongLong_ppc32_sysv | |
319 , &dc_callvm_argFloat_ppc32_sysv | |
320 , &dc_callvm_argDouble_ppc32_sysv | |
321 , &dc_callvm_argPointer_ppc32 | |
322 , NULL /* argStruct */ | |
323 , (DCvoidvmfunc*) &dc_callvm_call_ppc32_sysv | |
324 , (DCboolvmfunc*) &dc_callvm_call_ppc32_sysv | |
325 , (DCcharvmfunc*) &dc_callvm_call_ppc32_sysv | |
326 , (DCshortvmfunc*) &dc_callvm_call_ppc32_sysv | |
327 , (DCintvmfunc*) &dc_callvm_call_ppc32_sysv | |
328 , (DClongvmfunc*) &dc_callvm_call_ppc32_sysv | |
329 , (DClonglongvmfunc*) &dc_callvm_call_ppc32_sysv | |
330 , (DCfloatvmfunc*) &dc_callvm_call_ppc32_sysv | |
331 , (DCdoublevmfunc*) &dc_callvm_call_ppc32_sysv | |
332 , (DCpointervmfunc*) &dc_callvm_call_ppc32_sysv | |
333 , NULL /* callStruct */ | |
334 }; | |
335 | |
336 DCCallVM_vt gVT_ppc32_syscall = | |
337 { | |
338 &dc_callvm_free_ppc32 | |
339 , &dc_callvm_reset_ppc32 | |
340 , &dc_callvm_mode_ppc32 | |
341 , &dc_callvm_argBool_ppc32 | |
342 , &dc_callvm_argChar_ppc32 | |
343 , &dc_callvm_argShort_ppc32 | |
344 , &dc_callvm_argInt_ppc32_sysv | |
345 , &dc_callvm_argLong_ppc32 | |
346 , &dc_callvm_argLongLong_ppc32_sysv | |
347 , &dc_callvm_argFloat_ppc32_sysv | |
348 , &dc_callvm_argDouble_ppc32_sysv | |
349 , &dc_callvm_argPointer_ppc32 | |
350 , NULL /* argStruct */ | |
351 , (DCvoidvmfunc*) &dc_callvm_call_ppc32_syscall | |
352 , (DCboolvmfunc*) &dc_callvm_call_ppc32_syscall | |
353 , (DCcharvmfunc*) &dc_callvm_call_ppc32_syscall | |
354 , (DCshortvmfunc*) &dc_callvm_call_ppc32_syscall | |
355 , (DCintvmfunc*) &dc_callvm_call_ppc32_syscall | |
356 , (DClongvmfunc*) &dc_callvm_call_ppc32_syscall | |
357 , (DClonglongvmfunc*) &dc_callvm_call_ppc32_syscall | |
358 , (DCfloatvmfunc*) &dc_callvm_call_ppc32_syscall | |
359 , (DCdoublevmfunc*) &dc_callvm_call_ppc32_syscall | |
360 , (DCpointervmfunc*) &dc_callvm_call_ppc32_syscall | |
361 , NULL /* callStruct */ | |
362 }; | |
363 | |
364 | |
365 void dc_callvm_mode_ppc32(DCCallVM* in_self, DCint mode) | |
366 { | |
367 DCCallVM_ppc32* self = (DCCallVM_ppc32*) in_self; | |
368 DCCallVM_vt* vt; | |
369 switch(mode) { | |
370 | |
371 case DC_CALL_C_PPC32_OSX: | |
372 | |
373 #if defined(DC__ABI_Darwin) | |
374 case DC_CALL_C_DEFAULT: | |
375 case DC_CALL_C_ELLIPSIS: | |
376 case DC_CALL_C_ELLIPSIS_VARARGS: | |
377 #endif | |
378 | |
379 vt = &gVT_ppc32_darwin; | |
380 break; | |
381 | |
382 case DC_CALL_C_PPC32_SYSV: | |
383 | |
384 #if defined(DC__ABI_SysV) | |
385 case DC_CALL_C_DEFAULT: | |
386 case DC_CALL_C_ELLIPSIS: | |
387 case DC_CALL_C_ELLIPSIS_VARARGS: | |
388 #endif | |
389 | |
390 vt = &gVT_ppc32_sysv; | |
391 break; | |
392 | |
393 case DC_CALL_SYS_DEFAULT: | |
394 case DC_CALL_SYS_PPC32: | |
395 vt = &gVT_ppc32_syscall; | |
396 break; | |
397 | |
398 default: | |
399 self->mInterface.mError = DC_ERROR_UNSUPPORTED_MODE; | |
400 return; | |
401 } | |
402 | |
403 dc_callvm_base_init(&self->mInterface, vt); | |
404 } | |
405 | |
406 DCCallVM* dcNewCallVM(DCsize size) | |
407 { | |
408 DCCallVM_ppc32* self = (DCCallVM_ppc32*)dcAllocMem(sizeof(DCCallVM_ppc32)+size); | |
409 dcVecInit(&self->mVecHead, size); | |
410 self->mIntRegs = 0; | |
411 self->mFloatRegs = 0; | |
412 dc_callvm_mode_ppc32( (DCCallVM*) self, DC_CALL_C_DEFAULT ); | |
413 return (DCCallVM*)self; | |
414 } | |
415 |