1 | /* -----------------------------------------------------------------------
|
---|
2 | ffi.c - Copyright (c) 1998 Geoffrey Keating
|
---|
3 |
|
---|
4 | PowerPC Foreign Function Interface
|
---|
5 |
|
---|
6 | Darwin ABI support (c) 2001 John Hornkvist
|
---|
7 | AIX ABI support (c) 2002 Free Software Foundation, Inc.
|
---|
8 |
|
---|
9 | Permission is hereby granted, free of charge, to any person obtaining
|
---|
10 | a copy of this software and associated documentation files (the
|
---|
11 | ``Software''), to deal in the Software without restriction, including
|
---|
12 | without limitation the rights to use, copy, modify, merge, publish,
|
---|
13 | distribute, sublicense, and/or sell copies of the Software, and to
|
---|
14 | permit persons to whom the Software is furnished to do so, subject to
|
---|
15 | the following conditions:
|
---|
16 |
|
---|
17 | The above copyright notice and this permission notice shall be included
|
---|
18 | in all copies or substantial portions of the Software.
|
---|
19 |
|
---|
20 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
---|
21 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
---|
22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
---|
23 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
---|
24 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
---|
25 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
---|
26 | OTHER DEALINGS IN THE SOFTWARE.
|
---|
27 | ----------------------------------------------------------------------- */
|
---|
28 | #include <ffi.h>
|
---|
29 | #include <ffi_common.h>
|
---|
30 |
|
---|
31 | #include <stdlib.h>
|
---|
32 |
|
---|
33 | extern void ffi_closure_ASM(void);
|
---|
34 |
|
---|
35 | enum {
|
---|
36 | /* The assembly depends on these exact flags. */
|
---|
37 | FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
|
---|
38 | FLAG_RETURNS_FP = 1 << (31-29),
|
---|
39 | FLAG_RETURNS_64BITS = 1 << (31-28),
|
---|
40 |
|
---|
41 | FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
|
---|
42 | FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
|
---|
43 | FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
|
---|
44 | FLAG_RETVAL_REFERENCE = 1 << (31- 4)
|
---|
45 | };
|
---|
46 |
|
---|
47 | /* About the DARWIN ABI. */
|
---|
48 | enum {
|
---|
49 | NUM_GPR_ARG_REGISTERS = 8,
|
---|
50 | NUM_FPR_ARG_REGISTERS = 13
|
---|
51 | };
|
---|
52 | enum { ASM_NEEDS_REGISTERS = 4 };
|
---|
53 |
|
---|
54 | /* ffi_prep_args is called by the assembly routine once stack space
|
---|
55 | has been allocated for the function's arguments.
|
---|
56 |
|
---|
57 | The stack layout we want looks like this:
|
---|
58 |
|
---|
59 | | Return address from ffi_call_DARWIN | higher addresses
|
---|
60 | |--------------------------------------------|
|
---|
61 | | Previous backchain pointer 4 | stack pointer here
|
---|
62 | |--------------------------------------------|<+ <<< on entry to
|
---|
63 | | Saved r28-r31 4*4 | | ffi_call_DARWIN
|
---|
64 | |--------------------------------------------| |
|
---|
65 | | Parameters (at least 8*4=32) | |
|
---|
66 | |--------------------------------------------| |
|
---|
67 | | Space for GPR2 4 | |
|
---|
68 | |--------------------------------------------| | stack |
|
---|
69 | | Reserved 2*4 | | grows |
|
---|
70 | |--------------------------------------------| | down V
|
---|
71 | | Space for callee's LR 4 | |
|
---|
72 | |--------------------------------------------| | lower addresses
|
---|
73 | | Saved CR 4 | |
|
---|
74 | |--------------------------------------------| | stack pointer here
|
---|
75 | | Current backchain pointer 4 |-/ during
|
---|
76 | |--------------------------------------------| <<< ffi_call_DARWIN
|
---|
77 |
|
---|
78 | */
|
---|
79 |
|
---|
80 | /*@-exportheader@*/
|
---|
81 | void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
|
---|
82 | /*@=exportheader@*/
|
---|
83 | {
|
---|
84 | const unsigned bytes = ecif->cif->bytes;
|
---|
85 | const unsigned flags = ecif->cif->flags;
|
---|
86 |
|
---|
87 | /* 'stacktop' points at the previous backchain pointer. */
|
---|
88 | unsigned *const stacktop = stack + (ecif->cif->bytes / sizeof(unsigned));
|
---|
89 |
|
---|
90 | /* 'fpr_base' points at the space for fpr1, and grows upwards as
|
---|
91 | we use FPR registers. */
|
---|
92 | double *fpr_base = (double*) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS;
|
---|
93 | int fparg_count = 0;
|
---|
94 |
|
---|
95 |
|
---|
96 | /* 'next_arg' grows up as we put parameters in it. */
|
---|
97 | unsigned *next_arg = stack + 6; // 6 reserved posistions.
|
---|
98 |
|
---|
99 | int i=ecif->cif->nargs;
|
---|
100 | double double_tmp;
|
---|
101 | float float_tmp;
|
---|
102 | void **p_argv = ecif->avalue;
|
---|
103 | unsigned gprvalue;
|
---|
104 | ffi_type** ptr = ecif->cif->arg_types;
|
---|
105 |
|
---|
106 | /* Check that everything starts aligned properly. */
|
---|
107 | FFI_ASSERT(((unsigned)(char *)stack & 0xF) == 0);
|
---|
108 | FFI_ASSERT(((unsigned)(char *)stacktop & 0xF) == 0);
|
---|
109 | FFI_ASSERT((bytes & 0xF) == 0);
|
---|
110 |
|
---|
111 | /* Deal with return values that are actually pass-by-reference. */
|
---|
112 | // Rule:
|
---|
113 | // Return values are referenced by r3, so r4 is the first parameter.
|
---|
114 | if (flags & FLAG_RETVAL_REFERENCE)
|
---|
115 | *next_arg++ = (unsigned)(char *)ecif->rvalue;
|
---|
116 |
|
---|
117 | /* Now for the arguments. */
|
---|
118 | for (;
|
---|
119 | i > 0;
|
---|
120 | i--, ptr++, p_argv++)
|
---|
121 | {
|
---|
122 | switch ((*ptr)->type)
|
---|
123 | {
|
---|
124 | /* If a floating-point parameter appears before all of the general-
|
---|
125 | purpose registers are filled, the corresponding GPRs that match
|
---|
126 | the size of the floating-point parameter are skipped. */
|
---|
127 | case FFI_TYPE_FLOAT:
|
---|
128 | double_tmp = *(float *)*p_argv;
|
---|
129 | if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
---|
130 | *(double *)next_arg = double_tmp;
|
---|
131 | else
|
---|
132 | *fpr_base++ = double_tmp;
|
---|
133 | next_arg++;
|
---|
134 | fparg_count++;
|
---|
135 | FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
---|
136 | break;
|
---|
137 | case FFI_TYPE_DOUBLE:
|
---|
138 | double_tmp = *(double *)*p_argv;
|
---|
139 | if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
---|
140 | *(double *)next_arg = double_tmp;
|
---|
141 | else
|
---|
142 | *fpr_base++ = double_tmp;
|
---|
143 | next_arg += 2;
|
---|
144 | fparg_count++;
|
---|
145 | FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
---|
146 | break;
|
---|
147 |
|
---|
148 | case FFI_TYPE_UINT64:
|
---|
149 | case FFI_TYPE_SINT64:
|
---|
150 | *(long long *)next_arg = *(long long *)*p_argv;
|
---|
151 | next_arg+=2;
|
---|
152 | break;
|
---|
153 | case FFI_TYPE_UINT8:
|
---|
154 | gprvalue = *(unsigned char *)*p_argv;
|
---|
155 | goto putgpr;
|
---|
156 | case FFI_TYPE_SINT8:
|
---|
157 | gprvalue = *(signed char *)*p_argv;
|
---|
158 | goto putgpr;
|
---|
159 | case FFI_TYPE_UINT16:
|
---|
160 | gprvalue = *(unsigned short *)*p_argv;
|
---|
161 | goto putgpr;
|
---|
162 | case FFI_TYPE_SINT16:
|
---|
163 | gprvalue = *(signed short *)*p_argv;
|
---|
164 | goto putgpr;
|
---|
165 |
|
---|
166 | case FFI_TYPE_STRUCT:
|
---|
167 |
|
---|
168 | #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
---|
169 | case FFI_TYPE_LONGDOUBLE:
|
---|
170 | #endif
|
---|
171 |
|
---|
172 | memcpy((char*)next_arg, (char *)*p_argv, (*ptr)->size);
|
---|
173 | next_arg+=(((((*ptr)->size) + 3) & ~0x3)/4);
|
---|
174 | break;
|
---|
175 |
|
---|
176 | case FFI_TYPE_INT:
|
---|
177 | case FFI_TYPE_UINT32:
|
---|
178 | case FFI_TYPE_SINT32:
|
---|
179 | case FFI_TYPE_POINTER:
|
---|
180 | gprvalue = *(unsigned *)*p_argv;
|
---|
181 | putgpr:
|
---|
182 | *next_arg++ = gprvalue;
|
---|
183 | break;
|
---|
184 | default:
|
---|
185 | break;
|
---|
186 | }
|
---|
187 | }
|
---|
188 |
|
---|
189 | /* Check that we didn't overrun the stack... */
|
---|
190 | //FFI_ASSERT(copy_space >= (char *)next_arg);
|
---|
191 | //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
|
---|
192 | //FFI_ASSERT((unsigned *)fpr_base
|
---|
193 | // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
|
---|
194 | //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
|
---|
195 | }
|
---|
196 |
|
---|
197 | /* Perform machine dependent cif processing */
|
---|
198 | ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
---|
199 | {
|
---|
200 | /* All this is for the DARWIN ABI. */
|
---|
201 | int i;
|
---|
202 | ffi_type **ptr;
|
---|
203 | unsigned bytes;
|
---|
204 | int fparg_count = 0, intarg_count = 0;
|
---|
205 | unsigned flags = 0;
|
---|
206 | unsigned struct_copy_size = 0;
|
---|
207 |
|
---|
208 | /* All the machine-independent calculation of cif->bytes will be wrong.
|
---|
209 | Redo the calculation for DARWIN. */
|
---|
210 |
|
---|
211 | /* Space for the frame pointer, callee's LR, CR, etc, and for
|
---|
212 | the asm's temp regs. */
|
---|
213 |
|
---|
214 | bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long);
|
---|
215 |
|
---|
216 | /* Return value handling. The rules are as follows:
|
---|
217 | - 32-bit (or less) integer values are returned in gpr3;
|
---|
218 | - Structures of size <= 4 bytes also returned in gpr3;
|
---|
219 | - 64-bit integer values and structures between 5 and 8 bytes are returned
|
---|
220 | in gpr3 and gpr4;
|
---|
221 | - Single/double FP values are returned in fpr1;
|
---|
222 | - Long double FP (if not equivalent to double) values are returned in
|
---|
223 | fpr1 and fpr2;
|
---|
224 | - Larger structures values are allocated space and a pointer is passed
|
---|
225 | as the first argument. */
|
---|
226 | switch (cif->rtype->type)
|
---|
227 | {
|
---|
228 | #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
---|
229 | case FFI_TYPE_LONGDOUBLE:
|
---|
230 | #endif
|
---|
231 | /* Fall through. */
|
---|
232 | case FFI_TYPE_DOUBLE:
|
---|
233 | flags |= FLAG_RETURNS_64BITS;
|
---|
234 | /* Fall through. */
|
---|
235 | case FFI_TYPE_FLOAT:
|
---|
236 | flags |= FLAG_RETURNS_FP;
|
---|
237 | break;
|
---|
238 |
|
---|
239 | case FFI_TYPE_UINT64:
|
---|
240 | case FFI_TYPE_SINT64:
|
---|
241 | flags |= FLAG_RETURNS_64BITS;
|
---|
242 | break;
|
---|
243 |
|
---|
244 | case FFI_TYPE_STRUCT:
|
---|
245 | flags |= FLAG_RETVAL_REFERENCE;
|
---|
246 | flags |= FLAG_RETURNS_NOTHING;
|
---|
247 | intarg_count++;
|
---|
248 | break;
|
---|
249 | case FFI_TYPE_VOID:
|
---|
250 | flags |= FLAG_RETURNS_NOTHING;
|
---|
251 | break;
|
---|
252 |
|
---|
253 | default:
|
---|
254 | /* Returns 32-bit integer, or similar. Nothing to do here. */
|
---|
255 | break;
|
---|
256 | }
|
---|
257 |
|
---|
258 | /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
|
---|
259 | first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
|
---|
260 | goes on the stack. Structures and long doubles (if not equivalent
|
---|
261 | to double) are passed as a pointer to a copy of the structure.
|
---|
262 | Stuff on the stack needs to keep proper alignment. */
|
---|
263 | for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
---|
264 | {
|
---|
265 | switch ((*ptr)->type)
|
---|
266 | {
|
---|
267 | case FFI_TYPE_FLOAT:
|
---|
268 | case FFI_TYPE_DOUBLE:
|
---|
269 | fparg_count++;
|
---|
270 | /* If this FP arg is going on the stack, it must be
|
---|
271 | 8-byte-aligned. */
|
---|
272 | if (fparg_count > NUM_FPR_ARG_REGISTERS
|
---|
273 | && intarg_count%2 != 0)
|
---|
274 | intarg_count++;
|
---|
275 | break;
|
---|
276 |
|
---|
277 | case FFI_TYPE_UINT64:
|
---|
278 | case FFI_TYPE_SINT64:
|
---|
279 | /* 'long long' arguments are passed as two words, but
|
---|
280 | either both words must fit in registers or both go
|
---|
281 | on the stack. If they go on the stack, they must
|
---|
282 | be 8-byte-aligned. */
|
---|
283 | if (intarg_count == NUM_GPR_ARG_REGISTERS-1
|
---|
284 | || intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0)
|
---|
285 | intarg_count++;
|
---|
286 | intarg_count += 2;
|
---|
287 | break;
|
---|
288 |
|
---|
289 | case FFI_TYPE_STRUCT:
|
---|
290 | #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
---|
291 | case FFI_TYPE_LONGDOUBLE:
|
---|
292 | #endif
|
---|
293 | intarg_count+=(((*ptr)->size + 3) & ~0x3)/4;
|
---|
294 | break;
|
---|
295 |
|
---|
296 | default:
|
---|
297 | /* Everything else is passed as a 4-byte word in a GPR, either
|
---|
298 | the object itself or a pointer to it. */
|
---|
299 | intarg_count++;
|
---|
300 | break;
|
---|
301 | }
|
---|
302 | }
|
---|
303 |
|
---|
304 | if (fparg_count != 0)
|
---|
305 | flags |= FLAG_FP_ARGUMENTS;
|
---|
306 | if (struct_copy_size != 0)
|
---|
307 | flags |= FLAG_ARG_NEEDS_COPY;
|
---|
308 |
|
---|
309 | /* Space for the FPR registers, if needed. */
|
---|
310 | if (fparg_count != 0)
|
---|
311 | bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
|
---|
312 |
|
---|
313 | /* Stack space. */
|
---|
314 | if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
|
---|
315 | bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
|
---|
316 | else
|
---|
317 | bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
|
---|
318 |
|
---|
319 | /* The stack space allocated needs to be a multiple of 16 bytes. */
|
---|
320 | bytes = (bytes + 15) & ~0xF;
|
---|
321 |
|
---|
322 | cif->flags = flags;
|
---|
323 | cif->bytes = bytes;
|
---|
324 |
|
---|
325 | return FFI_OK;
|
---|
326 | }
|
---|
327 |
|
---|
328 | /*@-declundef@*/
|
---|
329 | /*@-exportheader@*/
|
---|
330 | extern void ffi_call_AIX(/*@out@*/ extended_cif *,
|
---|
331 | unsigned, unsigned,
|
---|
332 | /*@out@*/ unsigned *,
|
---|
333 | void (*fn)(),
|
---|
334 | void (*fn2)());
|
---|
335 | extern void ffi_call_DARWIN(/*@out@*/ extended_cif *,
|
---|
336 | unsigned, unsigned,
|
---|
337 | /*@out@*/ unsigned *,
|
---|
338 | void (*fn)(),
|
---|
339 | void (*fn2)());
|
---|
340 | /*@=declundef@*/
|
---|
341 | /*@=exportheader@*/
|
---|
342 |
|
---|
343 | void ffi_call(/*@dependent@*/ ffi_cif *cif,
|
---|
344 | void (*fn)(),
|
---|
345 | /*@out@*/ void *rvalue,
|
---|
346 | /*@dependent@*/ void **avalue)
|
---|
347 | {
|
---|
348 | extended_cif ecif;
|
---|
349 |
|
---|
350 | ecif.cif = cif;
|
---|
351 | ecif.avalue = avalue;
|
---|
352 |
|
---|
353 | /* If the return value is a struct and we don't have a return */
|
---|
354 | /* value address then we need to make one */
|
---|
355 |
|
---|
356 | if ((rvalue == NULL) &&
|
---|
357 | (cif->rtype->type == FFI_TYPE_STRUCT))
|
---|
358 | {
|
---|
359 | /*@-sysunrecog@*/
|
---|
360 | ecif.rvalue = alloca(cif->rtype->size);
|
---|
361 | /*@=sysunrecog@*/
|
---|
362 | }
|
---|
363 | else
|
---|
364 | ecif.rvalue = rvalue;
|
---|
365 |
|
---|
366 | switch (cif->abi)
|
---|
367 | {
|
---|
368 | case FFI_AIX:
|
---|
369 | /*@-usedef@*/
|
---|
370 | ffi_call_AIX(&ecif, -cif->bytes,
|
---|
371 | cif->flags, ecif.rvalue, fn, ffi_prep_args);
|
---|
372 | /*@=usedef@*/
|
---|
373 | break;
|
---|
374 | case FFI_DARWIN:
|
---|
375 | /*@-usedef@*/
|
---|
376 | ffi_call_DARWIN(&ecif, -cif->bytes,
|
---|
377 | cif->flags, ecif.rvalue, fn, ffi_prep_args);
|
---|
378 | /*@=usedef@*/
|
---|
379 | break;
|
---|
380 | default:
|
---|
381 | FFI_ASSERT(0);
|
---|
382 | break;
|
---|
383 | }
|
---|
384 | }
|
---|
385 |
|
---|
386 | static void flush_icache(char *);
|
---|
387 | static void flush_range(char *, int);
|
---|
388 |
|
---|
389 | /* The layout of a function descriptor. A C function pointer really */
|
---|
390 | /* points to one of these. */
|
---|
391 |
|
---|
392 | typedef struct aix_fd_struct {
|
---|
393 | void *code_pointer;
|
---|
394 | void *toc;
|
---|
395 | } aix_fd;
|
---|
396 |
|
---|
397 | /* here I'd like to add the stack frame layout we use in darwin_closure.S
|
---|
398 | * and aix_clsoure.S
|
---|
399 | *
|
---|
400 | /* SP previous -> +---------------------------------------+ <--- child frame
|
---|
401 | | back chain to caller 4 |
|
---|
402 | +---------------------------------------+ 4
|
---|
403 | | saved CR 4 |
|
---|
404 | +---------------------------------------+ 8
|
---|
405 | | saved LR 4 |
|
---|
406 | +---------------------------------------+ 12
|
---|
407 | | reserved for compilers 4 |
|
---|
408 | +---------------------------------------+ 16
|
---|
409 | | reserved for binders 4 |
|
---|
410 | +---------------------------------------+ 20
|
---|
411 | | saved TOC pointer 4 |
|
---|
412 | +---------------------------------------+ 24
|
---|
413 | | always reserved 8*4=32 (previous GPRs)|
|
---|
414 | | according to the linkage convention |
|
---|
415 | | from AIX |
|
---|
416 | +---------------------------------------+ 56
|
---|
417 | | our FPR area 13*8=104 |
|
---|
418 | | f1 |
|
---|
419 | | . |
|
---|
420 | | f13 |
|
---|
421 | +---------------------------------------+ 160
|
---|
422 | | result area 8 |
|
---|
423 | +---------------------------------------+ 168
|
---|
424 | | alignement to the next multiple of 16 |
|
---|
425 | SP current --> +---------------------------------------+ 176 <- parent frame
|
---|
426 | | back chain to caller 4 |
|
---|
427 | +---------------------------------------+ 180
|
---|
428 | | saved CR 4 |
|
---|
429 | +---------------------------------------+ 184
|
---|
430 | | saved LR 4 |
|
---|
431 | +---------------------------------------+ 188
|
---|
432 | | reserved for compilers 4 |
|
---|
433 | +---------------------------------------+ 192
|
---|
434 | | reserved for binders 4 |
|
---|
435 | +---------------------------------------+ 196
|
---|
436 | | saved TOC pointer 4 |
|
---|
437 | +---------------------------------------+ 200
|
---|
438 | | always reserved 8*4=32 we store our |
|
---|
439 | | GPRs here |
|
---|
440 | | r3 |
|
---|
441 | | . |
|
---|
442 | | r10 |
|
---|
443 | +---------------------------------------+ 232
|
---|
444 | | PST area, overflow part |
|
---|
445 | +---------------------------------------+ xxx
|
---|
446 | | ???? |
|
---|
447 | +---------------------------------------+ xxx
|
---|
448 |
|
---|
449 | */
|
---|
450 | ffi_status
|
---|
451 | ffi_prep_closure (ffi_closure* closure,
|
---|
452 | ffi_cif* cif,
|
---|
453 | void (*fun)(ffi_cif*, void*, void**, void*),
|
---|
454 | void *user_data)
|
---|
455 | {
|
---|
456 | unsigned int *tramp;
|
---|
457 | struct ffi_aix_trampoline_struct *tramp_aix;
|
---|
458 | aix_fd *fd;
|
---|
459 |
|
---|
460 | switch (cif->abi)
|
---|
461 | {
|
---|
462 | case FFI_DARWIN:
|
---|
463 |
|
---|
464 | FFI_ASSERT (cif->abi == FFI_DARWIN);
|
---|
465 |
|
---|
466 | tramp = (unsigned int *) &closure->tramp[0];
|
---|
467 | tramp[0] = 0x7c0802a6; /* mflr r0 */
|
---|
468 | tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
|
---|
469 | tramp[4] = 0x7d6802a6; /* mflr r11 */
|
---|
470 | tramp[5] = 0x818b0000; /* lwz r12,0(r11) /* function address */
|
---|
471 | tramp[6] = 0x7c0803a6; /* mtlr r0 */
|
---|
472 | tramp[7] = 0x7d8903a6; /* mtctr r12 */
|
---|
473 | tramp[8] = 0x816b0004; /* lwz r11,4(r11) /* static chain */
|
---|
474 | tramp[9] = 0x4e800420; /* bctr */
|
---|
475 | *(void **) &tramp[2] = (void *)ffi_closure_ASM; /* function */
|
---|
476 | *(void **) &tramp[3] = (void *)closure; /* context */
|
---|
477 |
|
---|
478 | closure->cif = cif;
|
---|
479 | closure->fun = fun;
|
---|
480 | closure->user_data = user_data;
|
---|
481 |
|
---|
482 | /* Flush the icache. Only necessary on Darwin */
|
---|
483 | flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
|
---|
484 |
|
---|
485 | break;
|
---|
486 |
|
---|
487 | case FFI_AIX:
|
---|
488 |
|
---|
489 | tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp);
|
---|
490 | fd = (aix_fd *)(void *)ffi_closure_ASM;
|
---|
491 |
|
---|
492 | FFI_ASSERT (cif->abi == FFI_AIX);
|
---|
493 |
|
---|
494 | tramp_aix->code_pointer = fd->code_pointer;
|
---|
495 | tramp_aix->toc = fd->toc;
|
---|
496 | tramp_aix->static_chain = closure;
|
---|
497 | closure->cif = cif;
|
---|
498 | closure->fun = fun;
|
---|
499 | closure->user_data = user_data;
|
---|
500 |
|
---|
501 | default:
|
---|
502 |
|
---|
503 | FFI_ASSERT(0);
|
---|
504 | break;
|
---|
505 | }
|
---|
506 | return FFI_OK;
|
---|
507 | }
|
---|
508 |
|
---|
509 | static void
|
---|
510 | flush_icache(char *addr)
|
---|
511 | {
|
---|
512 | #ifndef _AIX
|
---|
513 | __asm__ volatile (
|
---|
514 | "dcbf 0,%0;"
|
---|
515 | "sync;"
|
---|
516 | "icbi 0,%0;"
|
---|
517 | "sync;"
|
---|
518 | "isync;"
|
---|
519 | : : "r"(addr) : "memory");
|
---|
520 | #endif
|
---|
521 | }
|
---|
522 |
|
---|
523 | static void
|
---|
524 | flush_range(char * addr1, int size)
|
---|
525 | {
|
---|
526 | #define MIN_LINE_SIZE 32
|
---|
527 | int i;
|
---|
528 | for (i = 0; i < size; i += MIN_LINE_SIZE)
|
---|
529 | flush_icache(addr1+i);
|
---|
530 | flush_icache(addr1+size-1);
|
---|
531 | }
|
---|
532 |
|
---|
533 | int ffi_closure_helper_DARWIN (ffi_closure*, void*, unsigned long*,
|
---|
534 | unsigned long*, unsigned long*);
|
---|
535 |
|
---|
536 | /* Basically the trampoline invokes ffi_closure_ASM, and on
|
---|
537 | * entry, r11 holds the address of the closure.
|
---|
538 | * After storing the registers that could possibly contain
|
---|
539 | * parameters to be passed into the stack frame and setting
|
---|
540 | * up space for a return value, ffi_closure_ASM invokes the
|
---|
541 | * following helper function to do most of the work
|
---|
542 | */
|
---|
543 |
|
---|
544 | int
|
---|
545 | ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
|
---|
546 | unsigned long * pgr, unsigned long * pfr,
|
---|
547 | unsigned long * pst)
|
---|
548 | {
|
---|
549 | /* rvalue is the pointer to space for return value in closure assembly */
|
---|
550 | /* pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM */
|
---|
551 | /* pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM */
|
---|
552 | /* pst is the pointer to outgoing parameter stack in original caller */
|
---|
553 |
|
---|
554 | void ** avalue;
|
---|
555 | ffi_type ** arg_types;
|
---|
556 | long i, avn;
|
---|
557 | long nf; /* number of floating registers already used */
|
---|
558 | long ng; /* number of general registers already used */
|
---|
559 | ffi_cif * cif;
|
---|
560 | double temp;
|
---|
561 |
|
---|
562 | cif = closure->cif;
|
---|
563 | avalue = alloca(cif->nargs * sizeof(void *));
|
---|
564 |
|
---|
565 | nf = 0;
|
---|
566 | ng = 0;
|
---|
567 |
|
---|
568 | /* Copy the caller's structure return value address so that the closure
|
---|
569 | returns the data directly to the caller. */
|
---|
570 | if (cif->rtype->type == FFI_TYPE_STRUCT)
|
---|
571 | {
|
---|
572 | rvalue = (void *)pgr;
|
---|
573 | ng++;
|
---|
574 | pgr++;
|
---|
575 | }
|
---|
576 |
|
---|
577 | i = 0;
|
---|
578 | avn = cif->nargs;
|
---|
579 | arg_types = cif->arg_types;
|
---|
580 |
|
---|
581 | /* Grab the addresses of the arguments from the stack frame. */
|
---|
582 | while (i < avn)
|
---|
583 | {
|
---|
584 | switch (arg_types[i]->type)
|
---|
585 | {
|
---|
586 | case FFI_TYPE_SINT8:
|
---|
587 | case FFI_TYPE_UINT8:
|
---|
588 | /* there are 8 gpr registers used to pass values */
|
---|
589 | if (ng < 8) {
|
---|
590 | avalue[i] = (((char *)pgr)+3);
|
---|
591 | ng++;
|
---|
592 | pgr++;
|
---|
593 | } else {
|
---|
594 | avalue[i] = (((char *)pst)+3);
|
---|
595 | pst++;
|
---|
596 | }
|
---|
597 | break;
|
---|
598 |
|
---|
599 | case FFI_TYPE_SINT16:
|
---|
600 | case FFI_TYPE_UINT16:
|
---|
601 | /* there are 8 gpr registers used to pass values */
|
---|
602 | if (ng < 8) {
|
---|
603 | avalue[i] = (((char *)pgr)+2);
|
---|
604 | ng++;
|
---|
605 | pgr++;
|
---|
606 | } else {
|
---|
607 | avalue[i] = (((char *)pst)+2);
|
---|
608 | pst++;
|
---|
609 | }
|
---|
610 | break;
|
---|
611 |
|
---|
612 | case FFI_TYPE_SINT32:
|
---|
613 | case FFI_TYPE_UINT32:
|
---|
614 | case FFI_TYPE_POINTER:
|
---|
615 | case FFI_TYPE_STRUCT:
|
---|
616 | /* there are 8 gpr registers used to pass values */
|
---|
617 | if (ng < 8) {
|
---|
618 | avalue[i] = pgr;
|
---|
619 | ng++;
|
---|
620 | pgr++;
|
---|
621 | } else {
|
---|
622 | avalue[i] = pst;
|
---|
623 | pst++;
|
---|
624 | }
|
---|
625 | break;
|
---|
626 |
|
---|
627 | case FFI_TYPE_SINT64:
|
---|
628 | case FFI_TYPE_UINT64:
|
---|
629 | /* long long ints are passed in two gpr's if available or in
|
---|
630 | * the pst, one place is a bit odd, when a long long passes
|
---|
631 | * the boundary between gpr and pst area we have to increment
|
---|
632 | * the pst by one.
|
---|
633 | */
|
---|
634 | if (ng < 7) {
|
---|
635 | avalue[i] = pgr;
|
---|
636 | ng+=2;
|
---|
637 | pgr+=2;
|
---|
638 | } else if (ng == 7) {
|
---|
639 | avalue[i] = pgr;
|
---|
640 | ng++;
|
---|
641 | pgr++;
|
---|
642 | pst++;
|
---|
643 | } else {
|
---|
644 | avalue[i] = pst;
|
---|
645 | pst+=2;
|
---|
646 | }
|
---|
647 | break;
|
---|
648 |
|
---|
649 | case FFI_TYPE_FLOAT:
|
---|
650 | /* a float value consumes a GPR
|
---|
651 | *
|
---|
652 | * there are 13 64bit floating point registers
|
---|
653 | */
|
---|
654 |
|
---|
655 | if ((ng > 7) && (nf < 13)) {
|
---|
656 | pst++;
|
---|
657 | }
|
---|
658 | if (nf < 13) {
|
---|
659 | temp = *(double*)pfr;
|
---|
660 | *(float*)pfr = (float)temp;
|
---|
661 | avalue[i] = pfr;
|
---|
662 | nf++;
|
---|
663 | pfr+=2;
|
---|
664 | ng++;
|
---|
665 | pgr++;
|
---|
666 |
|
---|
667 | } else {
|
---|
668 | avalue[i] = pst;
|
---|
669 | nf++;
|
---|
670 | pst++;
|
---|
671 | }
|
---|
672 | break;
|
---|
673 |
|
---|
674 | case FFI_TYPE_DOUBLE:
|
---|
675 | /* a double value consumes two GPRs
|
---|
676 | *
|
---|
677 | * there are 13 64bit floating point registers
|
---|
678 | */
|
---|
679 |
|
---|
680 | if ((ng == 7) && (nf < 13)) {
|
---|
681 | pst++; /* if only one gpr is left the double steals it */
|
---|
682 | } else if ((ng > 7) && (nf < 13)) {
|
---|
683 | pst+=2; /* a double consumes two GPRs in Darwin/AIX */
|
---|
684 | }
|
---|
685 | if (nf < 13) {
|
---|
686 | avalue[i] = pfr;
|
---|
687 | nf++;
|
---|
688 | pfr+=2;
|
---|
689 | ng+=2;
|
---|
690 | pgr+=2;
|
---|
691 |
|
---|
692 | } else {
|
---|
693 | avalue[i] = pst;
|
---|
694 | nf++;
|
---|
695 | pst+=2;
|
---|
696 | }
|
---|
697 | break;
|
---|
698 |
|
---|
699 | default:
|
---|
700 | FFI_ASSERT(0);
|
---|
701 |
|
---|
702 | }
|
---|
703 |
|
---|
704 | i++;
|
---|
705 | }
|
---|
706 |
|
---|
707 | (closure->fun) (cif, rvalue, avalue, closure->user_data);
|
---|
708 |
|
---|
709 | /* Tell ffi_closure_ASM to perform return type promotions. */
|
---|
710 | return cif->rtype->type;
|
---|
711 |
|
---|
712 | }
|
---|