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