2 * Copyright (c) 2013 Miodrag Vallat. <miod@openbsd.org>
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * ``Software''), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 * vax Foreign Function Interface
27 * This file attempts to provide all the FFI entry points which can reliably
28 * be implemented in C.
32 #include <ffi_common.h>
37 #define CIF_FLAGS_CHAR 1 /* for struct only */
38 #define CIF_FLAGS_SHORT 2 /* for struct only */
39 #define CIF_FLAGS_INT 4
40 #define CIF_FLAGS_DINT 8
43 * Foreign Function Interface API
46 void ffi_call_elfbsd (extended_cif
*, unsigned, unsigned, void *,
48 void *ffi_prep_args (extended_cif
*ecif
, void *stack
);
51 ffi_prep_args (extended_cif
*ecif
, void *stack
)
57 void *struct_value_ptr
;
61 if (ecif
->cif
->rtype
->type
== FFI_TYPE_STRUCT
63 struct_value_ptr
= ecif
->rvalue
;
65 struct_value_ptr
= NULL
;
67 p_argv
= ecif
->avalue
;
69 for (i
= ecif
->cif
->nargs
, p_arg
= ecif
->cif
->arg_types
;
78 switch ((*p_arg
)->type
)
81 *(signed int *) argp
= (signed int) *(SINT8
*) *p_argv
;
85 *(unsigned int *) argp
= (unsigned int) *(UINT8
*) *p_argv
;
89 *(signed int *) argp
= (signed int) *(SINT16
*) *p_argv
;
93 *(unsigned int *) argp
= (unsigned int) *(UINT16
*) *p_argv
;
97 memcpy (argp
, *p_argv
, z
);
107 memcpy (argp
, *p_argv
, z
);
109 /* Align if necessary. */
110 if ((sizeof(int) - 1) & z
)
111 z
= ALIGN(z
, sizeof(int));
118 return struct_value_ptr
;
122 ffi_prep_cif_machdep (ffi_cif
*cif
)
124 /* Set the return type flag */
125 switch (cif
->rtype
->type
)
131 case FFI_TYPE_STRUCT
:
132 if (cif
->rtype
->elements
[0]->type
== FFI_TYPE_STRUCT
&&
133 cif
->rtype
->elements
[1])
139 if (cif
->rtype
->size
== sizeof (char))
140 cif
->flags
= CIF_FLAGS_CHAR
;
141 else if (cif
->rtype
->size
== sizeof (short))
142 cif
->flags
= CIF_FLAGS_SHORT
;
143 else if (cif
->rtype
->size
== sizeof (int))
144 cif
->flags
= CIF_FLAGS_INT
;
145 else if (cif
->rtype
->size
== 2 * sizeof (int))
146 cif
->flags
= CIF_FLAGS_DINT
;
152 if (cif
->rtype
->size
<= sizeof (int))
153 cif
->flags
= CIF_FLAGS_INT
;
155 cif
->flags
= CIF_FLAGS_DINT
;
163 ffi_call (ffi_cif
*cif
, void (*fn
) (), void *rvalue
, void **avalue
)
168 ecif
.avalue
= avalue
;
170 /* If the return value is a struct and we don't have a return value
171 address then we need to make one. */
174 && cif
->rtype
->type
== FFI_TYPE_STRUCT
176 ecif
.rvalue
= alloca (cif
->rtype
->size
);
178 ecif
.rvalue
= rvalue
;
183 ffi_call_elfbsd (&ecif
, cif
->bytes
, cif
->flags
, ecif
.rvalue
, fn
);
196 void ffi_closure_elfbsd (void);
197 void ffi_closure_struct_elfbsd (void);
198 unsigned int ffi_closure_elfbsd_inner (ffi_closure
*, void *, char *);
201 ffi_prep_closure_elfbsd (ffi_cif
*cif
, void **avalue
, char *stackp
)
209 for (i
= cif
->nargs
, p_arg
= cif
->arg_types
; i
!= 0; i
--, p_arg
++)
216 /* Align if necessary */
217 if ((sizeof (int) - 1) & z
)
218 z
= ALIGN(z
, sizeof (int));
226 ffi_closure_elfbsd_inner (ffi_closure
*closure
, void *resp
, char *stack
)
232 arg_area
= (void **) alloca (cif
->nargs
* sizeof (void *));
234 ffi_prep_closure_elfbsd (cif
, arg_area
, stack
);
236 (closure
->fun
) (cif
, resp
, arg_area
, closure
->user_data
);
242 ffi_prep_closure_loc (ffi_closure
*closure
, ffi_cif
*cif
,
243 void (*fun
)(ffi_cif
*, void *, void **, void *),
244 void *user_data
, void *codeloc
)
246 char *tramp
= (char *) codeloc
;
249 FFI_ASSERT (cif
->abi
== FFI_ELFBSD
);
252 *(unsigned short *)(tramp
+ 0) = 0x0000;
253 /* movl #closure, r0 */
256 *(unsigned int *)(tramp
+ 4) = (unsigned int) closure
;
259 if (cif
->rtype
->type
== FFI_TYPE_STRUCT
261 fn
= &ffi_closure_struct_elfbsd
;
263 fn
= &ffi_closure_elfbsd
;
268 *(unsigned int *)(tramp
+ 11) = (unsigned int)fn
+ 2 -
269 (unsigned int)tramp
- 9 - 6;
272 closure
->user_data
= user_data
;