1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2011, 2013 Anthony Green
3 Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
5 SPARC Foreign Function Interface
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 ``Software''), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26 ----------------------------------------------------------------------- */
29 #include <ffi_common.h>
33 /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
34 all further uses in this file will refer to the 128-bit type. */
35 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
36 # if FFI_TYPE_LONGDOUBLE != 4
37 # error FFI_TYPE_LONGDOUBLE out of date
40 # undef FFI_TYPE_LONGDOUBLE
41 # define FFI_TYPE_LONGDOUBLE 4
46 /* Flatten the contents of a structure to the parts that are passed in
47 floating point registers. The return is a bit mask wherein bit N
48 set means bytes [4*n, 4*n+3] are passed in %fN.
50 We encode both the (running) size (maximum 32) and mask (maxumum 255)
51 into one integer. The size is placed in the low byte, so that align
52 and addition work correctly. The mask is placed in the second byte. */
55 ffi_struct_float_mask (ffi_type
*outer_type
, int size_mask
)
60 if (outer_type
->type
== FFI_TYPE_COMPLEX
)
62 int m
= 0, tt
= outer_type
->elements
[0]->type
;
63 size_t z
= outer_type
->size
;
65 if (tt
== FFI_TYPE_FLOAT
66 || tt
== FFI_TYPE_DOUBLE
67 || tt
== FFI_TYPE_LONGDOUBLE
)
68 m
= (1 << (z
/ 4)) - 1;
71 FFI_ASSERT (outer_type
->type
== FFI_TYPE_STRUCT
);
73 for (elts
= outer_type
->elements
; (t
= *elts
) != NULL
; elts
++)
78 size_mask
= ALIGN(size_mask
, t
->alignment
);
82 size_mask
= ffi_struct_float_mask (t
, size_mask
);
84 case FFI_TYPE_COMPLEX
:
85 tt
= t
->elements
[0]->type
;
86 if (tt
!= FFI_TYPE_FLOAT
87 && tt
!= FFI_TYPE_DOUBLE
88 && tt
!= FFI_TYPE_LONGDOUBLE
)
93 case FFI_TYPE_LONGDOUBLE
:
94 m
= (1 << (z
/ 4)) - 1; /* compute mask for type */
95 o
= (size_mask
>> 2) & 0x3f; /* extract word offset */
96 size_mask
|= m
<< (o
+ 8); /* insert mask into place */
102 size_mask
= ALIGN(size_mask
, outer_type
->alignment
);
103 FFI_ASSERT ((size_mask
& 0xff) == outer_type
->size
);
108 /* Merge floating point data into integer data. If the structure is
109 entirely floating point, simply return a pointer to the fp data. */
112 ffi_struct_float_merge (int size_mask
, void *vi
, void *vf
)
114 int size
= size_mask
& 0xff;
115 int mask
= size_mask
>> 8;
120 else if (mask
== (1 << n
) - 1)
124 unsigned int *wi
= vi
, *wf
= vf
;
127 for (i
= 0; i
< n
; ++i
)
135 /* Similar, but place the data into VD in the end. */
138 ffi_struct_float_copy (int size_mask
, void *vd
, void *vi
, void *vf
)
140 int size
= size_mask
& 0xff;
141 int mask
= size_mask
>> 8;
146 else if (mask
== (1 << n
) - 1)
150 unsigned int *wd
= vd
, *wi
= vi
, *wf
= vf
;
153 for (i
= 0; i
< n
; ++i
)
154 wd
[i
] = ((mask
>> i
) & 1 ? wf
: wi
)[i
];
157 memcpy (vd
, vi
, size
);
160 /* Perform machine dependent cif processing */
163 ffi_prep_cif_machdep_core(ffi_cif
*cif
)
165 ffi_type
*rtype
= cif
->rtype
;
166 int rtt
= rtype
->type
;
170 /* Set the return type flag */
174 flags
= SPARC_RET_VOID
;
177 flags
= SPARC_RET_F_1
;
179 case FFI_TYPE_DOUBLE
:
180 flags
= SPARC_RET_F_2
;
182 case FFI_TYPE_LONGDOUBLE
:
183 flags
= SPARC_RET_F_4
;
186 case FFI_TYPE_COMPLEX
:
187 case FFI_TYPE_STRUCT
:
188 if (rtype
->size
> 32)
190 flags
= SPARC_RET_VOID
| SPARC_FLAG_RET_IN_MEM
;
195 int size_mask
= ffi_struct_float_mask (rtype
, 0);
196 int word_size
= (size_mask
>> 2) & 0x3f;
197 int all_mask
= (1 << word_size
) - 1;
198 int fp_mask
= size_mask
>> 8;
200 flags
= (size_mask
<< SPARC_SIZEMASK_SHIFT
) | SPARC_RET_STRUCT
;
202 /* For special cases of all-int or all-fp, we can return
203 the value directly without popping through a struct copy. */
206 if (rtype
->alignment
>= 8)
208 if (rtype
->size
== 8)
209 flags
= SPARC_RET_INT64
;
210 else if (rtype
->size
== 16)
211 flags
= SPARC_RET_INT128
;
214 else if (fp_mask
== all_mask
)
217 case 1: flags
= SPARC_RET_F_1
; break;
218 case 2: flags
= SPARC_RET_F_2
; break;
219 case 3: flags
= SP_V9_RET_F_3
; break;
220 case 4: flags
= SPARC_RET_F_4
; break;
221 /* 5 word structures skipped; handled via RET_STRUCT. */
222 case 6: flags
= SPARC_RET_F_6
; break;
223 /* 7 word structures skipped; handled via RET_STRUCT. */
224 case 8: flags
= SPARC_RET_F_8
; break;
230 flags
= SPARC_RET_SINT8
;
233 flags
= SPARC_RET_UINT8
;
235 case FFI_TYPE_SINT16
:
236 flags
= SPARC_RET_SINT16
;
238 case FFI_TYPE_UINT16
:
239 flags
= SPARC_RET_UINT16
;
242 case FFI_TYPE_SINT32
:
243 flags
= SP_V9_RET_SINT32
;
245 case FFI_TYPE_UINT32
:
246 flags
= SPARC_RET_UINT32
;
248 case FFI_TYPE_SINT64
:
249 case FFI_TYPE_UINT64
:
250 case FFI_TYPE_POINTER
:
251 flags
= SPARC_RET_INT64
;
259 for (i
= 0, n
= cif
->nargs
; i
< n
; ++i
)
261 ffi_type
*ty
= cif
->arg_types
[i
];
263 size_t a
= ty
->alignment
;
267 case FFI_TYPE_COMPLEX
:
268 case FFI_TYPE_STRUCT
:
269 /* Large structs passed by reference. */
275 /* Small structs may be passed in integer or fp regs or both. */
278 if ((ffi_struct_float_mask (ty
, 0) & 0xff00) == 0)
282 case FFI_TYPE_DOUBLE
:
283 case FFI_TYPE_LONGDOUBLE
:
284 flags
|= SPARC_FLAG_FP_ARGS
;
287 bytes
= ALIGN(bytes
, a
);
288 bytes
+= ALIGN(z
, 8);
291 /* Sparc call frames require that space is allocated for 6 args,
292 even if they aren't used. Make that space if necessary. */
296 /* The stack must be 2 word aligned, so round bytes up appropriately. */
297 bytes
= ALIGN(bytes
, 16);
299 /* Include the call frame to prep_args. */
307 ffi_status FFI_HIDDEN
308 ffi_prep_cif_machdep(ffi_cif
*cif
)
310 cif
->nfixedargs
= cif
->nargs
;
311 return ffi_prep_cif_machdep_core(cif
);
314 ffi_status FFI_HIDDEN
315 ffi_prep_cif_machdep_var(ffi_cif
*cif
, unsigned nfixedargs
, unsigned ntotalargs
)
317 cif
->nfixedargs
= nfixedargs
;
318 return ffi_prep_cif_machdep_core(cif
);
321 extern void ffi_call_v9(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
,
322 void **avalue
, size_t bytes
, void *closure
) FFI_HIDDEN
;
324 /* ffi_prep_args is called by the assembly routine once stack space
325 has been allocated for the function's arguments */
328 ffi_prep_args_v9(ffi_cif
*cif
, unsigned long *argp
, void *rvalue
, void **avalue
)
331 int flags
= cif
->flags
;
336 if (flags
& SPARC_FLAG_RET_IN_MEM
)
338 /* Since we pass the pointer to the callee, we need a value.
339 We allowed for this space in ffi_call, before ffi_call_v8
340 alloca'd the space. */
341 rvalue
= (char *)argp
+ cif
->bytes
;
345 /* Otherwise, we can ignore the return value. */
346 flags
= SPARC_RET_VOID
;
351 /* Purify will probably complain in our assembly routine,
352 unless we zero out this memory. */
353 memset(argp
, 0, 6*8);
356 if (flags
& SPARC_FLAG_RET_IN_MEM
)
357 *argp
++ = (unsigned long)rvalue
;
359 p_arg
= cif
->arg_types
;
360 for (i
= 0, nargs
= cif
->nargs
; i
< nargs
; i
++)
362 ffi_type
*ty
= p_arg
[i
];
369 *argp
++ = *(SINT8
*)a
;
372 *argp
++ = *(UINT8
*)a
;
374 case FFI_TYPE_SINT16
:
375 *argp
++ = *(SINT16
*)a
;
377 case FFI_TYPE_UINT16
:
378 *argp
++ = *(UINT16
*)a
;
381 case FFI_TYPE_SINT32
:
382 *argp
++ = *(SINT32
*)a
;
384 case FFI_TYPE_UINT32
:
386 *argp
++ = *(UINT32
*)a
;
388 case FFI_TYPE_SINT64
:
389 case FFI_TYPE_UINT64
:
390 case FFI_TYPE_POINTER
:
391 case FFI_TYPE_DOUBLE
:
392 *argp
++ = *(UINT64
*)a
;
395 case FFI_TYPE_LONGDOUBLE
:
396 case FFI_TYPE_COMPLEX
:
397 case FFI_TYPE_STRUCT
:
401 /* For structures larger than 16 bytes we pass reference. */
402 *argp
++ = (unsigned long)a
;
405 if (((unsigned long)argp
& 15) && ty
->alignment
> 8)
408 argp
+= ALIGN(z
, 8) / 8;
420 ffi_call_int(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
,
421 void **avalue
, void *closure
)
423 size_t bytes
= cif
->bytes
;
425 FFI_ASSERT (cif
->abi
== FFI_V9
);
427 if (rvalue
== NULL
&& (cif
->flags
& SPARC_FLAG_RET_IN_MEM
))
428 bytes
+= ALIGN (cif
->rtype
->size
, 16);
430 ffi_call_v9(cif
, fn
, rvalue
, avalue
, -bytes
, closure
);
434 ffi_call(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
)
436 ffi_call_int(cif
, fn
, rvalue
, avalue
, NULL
);
440 ffi_call_go(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
,
441 void **avalue
, void *closure
)
443 ffi_call_int(cif
, fn
, rvalue
, avalue
, closure
);
448 ffi_flush_icache (void *p
)
450 asm volatile ("flush %0; flush %0+8" : : "r" (p
) : "memory");
453 extern void ffi_flush_icache (void *) FFI_HIDDEN
;
456 extern void ffi_closure_v9(void) FFI_HIDDEN
;
457 extern void ffi_go_closure_v9(void) FFI_HIDDEN
;
460 ffi_prep_closure_loc (ffi_closure
* closure
,
462 void (*fun
)(ffi_cif
*, void*, void**, void*),
466 unsigned int *tramp
= (unsigned int *) &closure
->tramp
[0];
469 if (cif
->abi
!= FFI_V9
)
472 /* Trampoline address is equal to the closure address. We take advantage
473 of that to reduce the trampoline size by 8 bytes. */
474 fn
= (unsigned long) ffi_closure_v9
;
475 tramp
[0] = 0x83414000; /* rd %pc, %g1 */
476 tramp
[1] = 0xca586010; /* ldx [%g1+16], %g5 */
477 tramp
[2] = 0x81c14000; /* jmp %g5 */
478 tramp
[3] = 0x01000000; /* nop */
479 *((unsigned long *) &tramp
[4]) = fn
;
483 closure
->user_data
= user_data
;
485 ffi_flush_icache (closure
);
491 ffi_prep_go_closure (ffi_go_closure
* closure
, ffi_cif
* cif
,
492 void (*fun
)(ffi_cif
*, void*, void**, void*))
494 if (cif
->abi
!= FFI_V9
)
497 closure
->tramp
= ffi_go_closure_v9
;
505 ffi_closure_sparc_inner_v9(ffi_cif
*cif
,
506 void (*fun
)(ffi_cif
*, void*, void**, void*),
507 void *user_data
, void *rvalue
,
508 unsigned long *gpr
, unsigned long *fpr
)
510 ffi_type
**arg_types
;
512 int i
, argn
, argx
, nargs
, flags
, nfixedargs
;
514 arg_types
= cif
->arg_types
;
517 nfixedargs
= cif
->nfixedargs
;
519 avalue
= alloca(nargs
* sizeof(void *));
521 /* Copy the caller's structure return address so that the closure
522 returns the data directly to the caller. */
523 if (flags
& SPARC_FLAG_RET_IN_MEM
)
525 rvalue
= (void *) gpr
[0];
526 /* Skip the structure return address. */
532 /* Grab the addresses of the arguments from the stack frame. */
533 for (i
= 0; i
< nargs
; i
++, argn
= argx
)
535 int named
= i
< nfixedargs
;
536 ffi_type
*ty
= arg_types
[i
];
537 void *a
= &gpr
[argn
];
543 case FFI_TYPE_COMPLEX
:
544 case FFI_TYPE_STRUCT
:
550 argx
= argn
+ ALIGN (z
, 8) / 8;
551 if (named
&& argn
< 16)
553 int size_mask
= ffi_struct_float_mask (ty
, 0);
554 int argn_mask
= (0xffff00 >> argn
) & 0xff00;
556 /* Eliminate fp registers off the end. */
557 size_mask
= (size_mask
& 0xff) | (size_mask
& argn_mask
);
558 a
= ffi_struct_float_merge (size_mask
, gpr
+argn
, fpr
+argn
);
563 case FFI_TYPE_LONGDOUBLE
:
564 argn
= ALIGN (argn
, 2);
565 a
= (named
&& argn
< 16 ? fpr
: gpr
) + argn
;
568 case FFI_TYPE_DOUBLE
:
569 if (named
&& argn
< 16)
573 if (named
&& argn
< 16)
578 case FFI_TYPE_UINT64
:
579 case FFI_TYPE_SINT64
:
580 case FFI_TYPE_POINTER
:
583 case FFI_TYPE_UINT32
:
584 case FFI_TYPE_SINT32
:
587 case FFI_TYPE_UINT16
:
588 case FFI_TYPE_SINT16
:
602 /* Invoke the closure. */
603 fun (cif
, rvalue
, avalue
, user_data
);
605 /* Tell ffi_closure_sparc how to perform return type promotions. */