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