1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 1998 Geoffrey Keating
4 PowerPC Foreign Function Interface
6 Darwin ABI support (c) 2001 John Hornkvist
7 AIX ABI support (c) 2002 Free Software Foundation, Inc.
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:
17 The above copyright notice and this permission notice shall be included
18 in all copies or substantial portions of the Software.
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 ----------------------------------------------------------------------- */
29 #include <ffi_common.h>
33 extern void ffi_closure_ASM(void);
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),
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)
47 /* About the DARWIN ABI. */
49 NUM_GPR_ARG_REGISTERS = 8,
50 NUM_FPR_ARG_REGISTERS = 13
52 enum { ASM_NEEDS_REGISTERS = 4 };
54 /* ffi_prep_args is called by the assembly routine once stack space
55 has been allocated for the function's arguments.
57 The stack layout we want looks like this:
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
74 |--------------------------------------------| | stack pointer here
75 | Current backchain pointer 4 |-/ during
76 |--------------------------------------------| <<< ffi_call_DARWIN
81 void ffi_prep_args(extended_cif *ecif, unsigned *const stack)
84 const unsigned flags = ecif->cif->flags;
86 /* 'stacktop' points at the previous backchain pointer. */
87 unsigned *const stacktop = stack + (ecif->cif->bytes / sizeof(unsigned));
89 /* 'fpr_base' points at the space for fpr1, and grows upwards as
90 we use FPR registers. */
91 double *fpr_base = (double*) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS;
95 /* 'next_arg' grows up as we put parameters in it. */
96 unsigned *next_arg = stack + 6; // 6 reserved posistions.
98 int i = ecif->cif->nargs;
100 void **p_argv = ecif->avalue;
102 ffi_type** ptr = ecif->cif->arg_types;
104 unsigned size_al = 0;
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);
111 /* Deal with return values that are actually pass-by-reference. */
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;
117 /* Now for the arguments. */
120 i--, ptr++, p_argv++)
122 switch ((*ptr)->type)
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. */
128 double_tmp = *(float *)*p_argv;
129 if (fparg_count >= NUM_FPR_ARG_REGISTERS)
130 *(double *)next_arg = double_tmp;
132 *fpr_base++ = double_tmp;
135 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
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;
142 *fpr_base++ = double_tmp;
145 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
148 case FFI_TYPE_UINT64:
149 case FFI_TYPE_SINT64:
150 *(long long *)next_arg = *(long long *)*p_argv;
154 gprvalue = *(unsigned char *)*p_argv;
157 gprvalue = *(signed char *)*p_argv;
159 case FFI_TYPE_UINT16:
160 gprvalue = *(unsigned short *)*p_argv;
162 case FFI_TYPE_SINT16:
163 gprvalue = *(signed short *)*p_argv;
166 case FFI_TYPE_STRUCT:
168 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
169 case FFI_TYPE_LONGDOUBLE:
171 dest_cpy = (char *) next_arg;
173 /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
174 SI 4 bytes) are aligned as if they were those modes.
175 Structures with 3 byte in size are padded upwards. */
176 size_al = (*ptr)->size;
177 /* If the first member of the struct is a double, then align
178 the struct to double-word.
179 Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
180 if ((*ptr)->elements[0]->type == 3)
181 size_al = ALIGN((*ptr)->size, 8);
182 if (size_al < 3 && ecif->cif->abi == FFI_DARWIN)
183 dest_cpy += 4 - size_al;
185 memcpy((char *)dest_cpy, (char *)*p_argv, size_al);
186 next_arg += (size_al + 3) / 4;
190 case FFI_TYPE_UINT32:
191 case FFI_TYPE_SINT32:
192 case FFI_TYPE_POINTER:
193 gprvalue = *(unsigned *)*p_argv;
195 *next_arg++ = gprvalue;
202 /* Check that we didn't overrun the stack... */
203 //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
204 //FFI_ASSERT((unsigned *)fpr_base
205 // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
206 //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
209 /* Perform machine dependent cif processing */
210 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
212 /* All this is for the DARWIN ABI. */
216 int fparg_count = 0, intarg_count = 0;
218 unsigned size_al = 0;
220 /* All the machine-independent calculation of cif->bytes will be wrong.
221 Redo the calculation for DARWIN. */
223 /* Space for the frame pointer, callee's LR, CR, etc, and for
224 the asm's temp regs. */
226 bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long);
228 /* Return value handling. The rules are as follows:
229 - 32-bit (or less) integer values are returned in gpr3;
230 - Structures of size <= 4 bytes also returned in gpr3;
231 - 64-bit integer values and structures between 5 and 8 bytes are returned
233 - Single/double FP values are returned in fpr1;
234 - Long double FP (if not equivalent to double) values are returned in
236 - Larger structures values are allocated space and a pointer is passed
237 as the first argument. */
238 switch (cif->rtype->type)
240 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
241 case FFI_TYPE_LONGDOUBLE:
244 case FFI_TYPE_DOUBLE:
245 flags |= FLAG_RETURNS_64BITS;
248 flags |= FLAG_RETURNS_FP;
251 case FFI_TYPE_UINT64:
252 case FFI_TYPE_SINT64:
253 flags |= FLAG_RETURNS_64BITS;
256 case FFI_TYPE_STRUCT:
257 flags |= FLAG_RETVAL_REFERENCE;
258 flags |= FLAG_RETURNS_NOTHING;
262 flags |= FLAG_RETURNS_NOTHING;
266 /* Returns 32-bit integer, or similar. Nothing to do here. */
270 /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
271 first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
272 goes on the stack. Structures and long doubles (if not equivalent
273 to double) are passed as a pointer to a copy of the structure.
274 Stuff on the stack needs to keep proper alignment. */
275 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
277 switch ((*ptr)->type)
280 case FFI_TYPE_DOUBLE:
282 /* If this FP arg is going on the stack, it must be
284 if (fparg_count > NUM_FPR_ARG_REGISTERS
285 && intarg_count%2 != 0)
289 case FFI_TYPE_UINT64:
290 case FFI_TYPE_SINT64:
291 /* 'long long' arguments are passed as two words, but
292 either both words must fit in registers or both go
293 on the stack. If they go on the stack, they must
294 be 8-byte-aligned. */
295 if (intarg_count == NUM_GPR_ARG_REGISTERS-1
296 || (intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0))
301 case FFI_TYPE_STRUCT:
302 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
303 case FFI_TYPE_LONGDOUBLE:
305 size_al = (*ptr)->size;
306 /* If the first member of the struct is a double, then align
307 the struct to double-word.
308 Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
309 if ((*ptr)->elements[0]->type == 3)
310 size_al = ALIGN((*ptr)->size, 8);
311 intarg_count += (size_al + 3) / 4;
315 /* Everything else is passed as a 4-byte word in a GPR, either
316 the object itself or a pointer to it. */
322 if (fparg_count != 0)
323 flags |= FLAG_FP_ARGUMENTS;
325 /* Space for the FPR registers, if needed. */
326 if (fparg_count != 0)
327 bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
330 if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
331 bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
333 bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
335 /* The stack space allocated needs to be a multiple of 16 bytes. */
336 bytes = (bytes + 15) & ~0xF;
346 extern void ffi_call_AIX(/*@out@*/ extended_cif *,
348 /*@out@*/ unsigned *,
351 extern void ffi_call_DARWIN(/*@out@*/ extended_cif *,
353 /*@out@*/ unsigned *,
359 void ffi_call(/*@dependent@*/ ffi_cif *cif,
361 /*@out@*/ void *rvalue,
362 /*@dependent@*/ void **avalue)
367 ecif.avalue = avalue;
369 /* If the return value is a struct and we don't have a return */
370 /* value address then we need to make one */
372 if ((rvalue == NULL) &&
373 (cif->rtype->type == FFI_TYPE_STRUCT))
376 ecif.rvalue = alloca(cif->rtype->size);
380 ecif.rvalue = rvalue;
386 ffi_call_AIX(&ecif, -cif->bytes,
387 cif->flags, ecif.rvalue, fn, ffi_prep_args);
392 ffi_call_DARWIN(&ecif, -cif->bytes,
393 cif->flags, ecif.rvalue, fn, ffi_prep_args);
402 static void flush_icache(char *);
403 static void flush_range(char *, int);
405 /* The layout of a function descriptor. A C function pointer really */
406 /* points to one of these. */
408 typedef struct aix_fd_struct {
413 /* here I'd like to add the stack frame layout we use in darwin_closure.S
416 * SP previous -> +---------------------------------------+ <--- child frame
417 | back chain to caller 4 |
418 +---------------------------------------+ 4
420 +---------------------------------------+ 8
422 +---------------------------------------+ 12
423 | reserved for compilers 4 |
424 +---------------------------------------+ 16
425 | reserved for binders 4 |
426 +---------------------------------------+ 20
427 | saved TOC pointer 4 |
428 +---------------------------------------+ 24
429 | always reserved 8*4=32 (previous GPRs)|
430 | according to the linkage convention |
432 +---------------------------------------+ 56
433 | our FPR area 13*8=104 |
437 +---------------------------------------+ 160
439 +---------------------------------------+ 168
440 | alignement to the next multiple of 16 |
441 SP current --> +---------------------------------------+ 176 <- parent frame
442 | back chain to caller 4 |
443 +---------------------------------------+ 180
445 +---------------------------------------+ 184
447 +---------------------------------------+ 188
448 | reserved for compilers 4 |
449 +---------------------------------------+ 192
450 | reserved for binders 4 |
451 +---------------------------------------+ 196
452 | saved TOC pointer 4 |
453 +---------------------------------------+ 200
454 | always reserved 8*4=32 we store our |
459 +---------------------------------------+ 232
461 +---------------------------------------+ xxx
463 +---------------------------------------+ xxx
467 ffi_prep_closure (ffi_closure* closure,
469 void (*fun)(ffi_cif*, void*, void**, void*),
473 struct ffi_aix_trampoline_struct *tramp_aix;
480 FFI_ASSERT (cif->abi == FFI_DARWIN);
482 tramp = (unsigned int *) &closure->tramp[0];
483 tramp[0] = 0x7c0802a6; /* mflr r0 */
484 tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */
485 tramp[4] = 0x7d6802a6; /* mflr r11 */
486 tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */
487 tramp[6] = 0x7c0803a6; /* mtlr r0 */
488 tramp[7] = 0x7d8903a6; /* mtctr r12 */
489 tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */
490 tramp[9] = 0x4e800420; /* bctr */
491 tramp[2] = (unsigned long) ffi_closure_ASM; /* function */
492 tramp[3] = (unsigned long) closure; /* context */
496 closure->user_data = user_data;
498 /* Flush the icache. Only necessary on Darwin. */
499 flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE);
505 tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp);
506 fd = (aix_fd *)(void *)ffi_closure_ASM;
508 FFI_ASSERT (cif->abi == FFI_AIX);
510 tramp_aix->code_pointer = fd->code_pointer;
511 tramp_aix->toc = fd->toc;
512 tramp_aix->static_chain = closure;
515 closure->user_data = user_data;
526 flush_icache(char *addr)
535 : : "r"(addr) : "memory");
540 flush_range(char * addr1, int size)
542 #define MIN_LINE_SIZE 32
544 for (i = 0; i < size; i += MIN_LINE_SIZE)
545 flush_icache(addr1+i);
546 flush_icache(addr1+size-1);
555 int ffi_closure_helper_DARWIN (ffi_closure*, void*,
556 unsigned long*, ffi_dblfl*);
558 /* Basically the trampoline invokes ffi_closure_ASM, and on
559 * entry, r11 holds the address of the closure.
560 * After storing the registers that could possibly contain
561 * parameters to be passed into the stack frame and setting
562 * up space for a return value, ffi_closure_ASM invokes the
563 * following helper function to do most of the work
566 int ffi_closure_helper_DARWIN (ffi_closure* closure, void * rvalue,
567 unsigned long * pgr, ffi_dblfl * pfr)
569 /* rvalue is the pointer to space for return value in closure assembly
570 pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
571 pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */
575 ffi_type ** arg_types;
577 long nf; /* number of floating registers already used */
578 long ng; /* number of general registers already used */
584 avalue = alloca(cif->nargs * sizeof(void *));
589 /* Copy the caller's structure return value address so that the closure
590 returns the data directly to the caller. */
591 if (cif->rtype->type == FFI_TYPE_STRUCT)
593 rvalue = (void *) *pgr;
600 arg_types = cif->arg_types;
602 /* Grab the addresses of the arguments from the stack frame. */
605 switch (arg_types[i]->type)
609 avalue[i] = (char *) pgr + 3;
614 case FFI_TYPE_SINT16:
615 case FFI_TYPE_UINT16:
616 avalue[i] = (char *) pgr + 2;
621 case FFI_TYPE_SINT32:
622 case FFI_TYPE_UINT32:
623 case FFI_TYPE_POINTER:
629 case FFI_TYPE_STRUCT:
630 /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
631 SI 4 bytes) are aligned as if they were those modes. */
632 size_al = arg_types[i]->size;
633 /* If the first member of the struct is a double, then align
634 the struct to double-word.
635 Type 3 is defined in include/ffi.h. #define FFI_TYPE_DOUBLE 3. */
636 if (arg_types[i]->elements[0]->type == 3)
637 size_al = ALIGN(arg_types[i]->size, 8);
638 if (size_al < 3 && cif->abi == FFI_DARWIN)
639 avalue[i] = (void*) pgr + 4 - size_al;
641 avalue[i] = (void*) pgr;
642 ng += (size_al + 3) / 4;
643 pgr += (size_al + 3) / 4;
646 case FFI_TYPE_SINT64:
647 case FFI_TYPE_UINT64:
648 /* Long long ints are passed in two gpr's. */
655 /* a float value consumes a GPR
657 * here are 13 64bit floating point registers.
659 if (nf < NUM_FPR_ARG_REGISTERS)
662 pfr->f = (float)temp;
675 case FFI_TYPE_DOUBLE:
676 /* a double value consumes two GPRs
678 * There are 13 64bit floating point registers.
680 if (nf < NUM_FPR_ARG_REGISTERS)
700 (closure->fun) (cif, rvalue, avalue, closure->user_data);
702 /* Tell ffi_closure_ASM to perform return type promotions. */
703 return cif->rtype->type;