1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan ffi.c - Copyright (c) 2012 Alexandre K. I. de Mendonca <[email protected]>,
3*1fd5a2e1SPrashanth Swaminathan Paulo Pizarro <[email protected]>
4*1fd5a2e1SPrashanth Swaminathan
5*1fd5a2e1SPrashanth Swaminathan Blackfin Foreign Function Interface
6*1fd5a2e1SPrashanth Swaminathan
7*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining
8*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the
9*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including
10*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish,
11*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to
12*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to
13*1fd5a2e1SPrashanth Swaminathan the following conditions:
14*1fd5a2e1SPrashanth Swaminathan
15*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be included
16*1fd5a2e1SPrashanth Swaminathan in all copies or substantial portions of the Software.
17*1fd5a2e1SPrashanth Swaminathan
18*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19*1fd5a2e1SPrashanth Swaminathan EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21*1fd5a2e1SPrashanth Swaminathan NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22*1fd5a2e1SPrashanth Swaminathan HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23*1fd5a2e1SPrashanth Swaminathan WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24*1fd5a2e1SPrashanth Swaminathan OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25*1fd5a2e1SPrashanth Swaminathan DEALINGS IN THE SOFTWARE.
26*1fd5a2e1SPrashanth Swaminathan ----------------------------------------------------------------------- */
27*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
28*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
29*1fd5a2e1SPrashanth Swaminathan
30*1fd5a2e1SPrashanth Swaminathan #include <stdlib.h>
31*1fd5a2e1SPrashanth Swaminathan #include <stdio.h>
32*1fd5a2e1SPrashanth Swaminathan
33*1fd5a2e1SPrashanth Swaminathan /* Maximum number of GPRs available for argument passing. */
34*1fd5a2e1SPrashanth Swaminathan #define MAX_GPRARGS 3
35*1fd5a2e1SPrashanth Swaminathan
36*1fd5a2e1SPrashanth Swaminathan /*
37*1fd5a2e1SPrashanth Swaminathan * Return types
38*1fd5a2e1SPrashanth Swaminathan */
39*1fd5a2e1SPrashanth Swaminathan #define FFIBFIN_RET_VOID 0
40*1fd5a2e1SPrashanth Swaminathan #define FFIBFIN_RET_BYTE 1
41*1fd5a2e1SPrashanth Swaminathan #define FFIBFIN_RET_HALFWORD 2
42*1fd5a2e1SPrashanth Swaminathan #define FFIBFIN_RET_INT64 3
43*1fd5a2e1SPrashanth Swaminathan #define FFIBFIN_RET_INT32 4
44*1fd5a2e1SPrashanth Swaminathan
45*1fd5a2e1SPrashanth Swaminathan /*====================================================================*/
46*1fd5a2e1SPrashanth Swaminathan /* PROTOTYPE *
47*1fd5a2e1SPrashanth Swaminathan /*====================================================================*/
48*1fd5a2e1SPrashanth Swaminathan void ffi_prep_args(unsigned char *, extended_cif *);
49*1fd5a2e1SPrashanth Swaminathan
50*1fd5a2e1SPrashanth Swaminathan /*====================================================================*/
51*1fd5a2e1SPrashanth Swaminathan /* Externals */
52*1fd5a2e1SPrashanth Swaminathan /* (Assembly) */
53*1fd5a2e1SPrashanth Swaminathan /*====================================================================*/
54*1fd5a2e1SPrashanth Swaminathan
55*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_SYSV(unsigned, extended_cif *, void(*)(unsigned char *, extended_cif *), unsigned, void *, void(*fn)(void));
56*1fd5a2e1SPrashanth Swaminathan
57*1fd5a2e1SPrashanth Swaminathan /*====================================================================*/
58*1fd5a2e1SPrashanth Swaminathan /* Implementation */
59*1fd5a2e1SPrashanth Swaminathan /* */
60*1fd5a2e1SPrashanth Swaminathan /*====================================================================*/
61*1fd5a2e1SPrashanth Swaminathan
62*1fd5a2e1SPrashanth Swaminathan
63*1fd5a2e1SPrashanth Swaminathan /*
64*1fd5a2e1SPrashanth Swaminathan * This function calculates the return type (size) based on type.
65*1fd5a2e1SPrashanth Swaminathan */
66*1fd5a2e1SPrashanth Swaminathan
ffi_prep_cif_machdep(ffi_cif * cif)67*1fd5a2e1SPrashanth Swaminathan ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
68*1fd5a2e1SPrashanth Swaminathan {
69*1fd5a2e1SPrashanth Swaminathan /* --------------------------------------*
70*1fd5a2e1SPrashanth Swaminathan * Return handling *
71*1fd5a2e1SPrashanth Swaminathan * --------------------------------------*/
72*1fd5a2e1SPrashanth Swaminathan switch (cif->rtype->type) {
73*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_VOID:
74*1fd5a2e1SPrashanth Swaminathan cif->flags = FFIBFIN_RET_VOID;
75*1fd5a2e1SPrashanth Swaminathan break;
76*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
77*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
78*1fd5a2e1SPrashanth Swaminathan cif->flags = FFIBFIN_RET_HALFWORD;
79*1fd5a2e1SPrashanth Swaminathan break;
80*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
81*1fd5a2e1SPrashanth Swaminathan cif->flags = FFIBFIN_RET_BYTE;
82*1fd5a2e1SPrashanth Swaminathan break;
83*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_INT:
84*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
85*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
86*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
87*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
88*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
89*1fd5a2e1SPrashanth Swaminathan cif->flags = FFIBFIN_RET_INT32;
90*1fd5a2e1SPrashanth Swaminathan break;
91*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
92*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
93*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
94*1fd5a2e1SPrashanth Swaminathan cif->flags = FFIBFIN_RET_INT64;
95*1fd5a2e1SPrashanth Swaminathan break;
96*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
97*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->size <= 4){
98*1fd5a2e1SPrashanth Swaminathan cif->flags = FFIBFIN_RET_INT32;
99*1fd5a2e1SPrashanth Swaminathan }else if (cif->rtype->size == 8){
100*1fd5a2e1SPrashanth Swaminathan cif->flags = FFIBFIN_RET_INT64;
101*1fd5a2e1SPrashanth Swaminathan }else{
102*1fd5a2e1SPrashanth Swaminathan //it will return via a hidden pointer in P0
103*1fd5a2e1SPrashanth Swaminathan cif->flags = FFIBFIN_RET_VOID;
104*1fd5a2e1SPrashanth Swaminathan }
105*1fd5a2e1SPrashanth Swaminathan break;
106*1fd5a2e1SPrashanth Swaminathan default:
107*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(0);
108*1fd5a2e1SPrashanth Swaminathan break;
109*1fd5a2e1SPrashanth Swaminathan }
110*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
111*1fd5a2e1SPrashanth Swaminathan }
112*1fd5a2e1SPrashanth Swaminathan
113*1fd5a2e1SPrashanth Swaminathan /*
114*1fd5a2e1SPrashanth Swaminathan * This will prepare the arguments and will call the assembly routine
115*1fd5a2e1SPrashanth Swaminathan * cif = the call interface
116*1fd5a2e1SPrashanth Swaminathan * fn = the function to be called
117*1fd5a2e1SPrashanth Swaminathan * rvalue = the return value
118*1fd5a2e1SPrashanth Swaminathan * avalue = the arguments
119*1fd5a2e1SPrashanth Swaminathan */
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)120*1fd5a2e1SPrashanth Swaminathan void ffi_call(ffi_cif *cif, void(*fn)(void), void *rvalue, void **avalue)
121*1fd5a2e1SPrashanth Swaminathan {
122*1fd5a2e1SPrashanth Swaminathan int ret_type = cif->flags;
123*1fd5a2e1SPrashanth Swaminathan extended_cif ecif;
124*1fd5a2e1SPrashanth Swaminathan ecif.cif = cif;
125*1fd5a2e1SPrashanth Swaminathan ecif.avalue = avalue;
126*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = rvalue;
127*1fd5a2e1SPrashanth Swaminathan
128*1fd5a2e1SPrashanth Swaminathan switch (cif->abi) {
129*1fd5a2e1SPrashanth Swaminathan case FFI_SYSV:
130*1fd5a2e1SPrashanth Swaminathan ffi_call_SYSV(cif->bytes, &ecif, ffi_prep_args, ret_type, ecif.rvalue, fn);
131*1fd5a2e1SPrashanth Swaminathan break;
132*1fd5a2e1SPrashanth Swaminathan default:
133*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(0);
134*1fd5a2e1SPrashanth Swaminathan break;
135*1fd5a2e1SPrashanth Swaminathan }
136*1fd5a2e1SPrashanth Swaminathan }
137*1fd5a2e1SPrashanth Swaminathan
138*1fd5a2e1SPrashanth Swaminathan
139*1fd5a2e1SPrashanth Swaminathan /*
140*1fd5a2e1SPrashanth Swaminathan * This function prepares the parameters (copies them from the ecif to the stack)
141*1fd5a2e1SPrashanth Swaminathan * to call the function (ffi_prep_args is called by the assembly routine in file
142*1fd5a2e1SPrashanth Swaminathan * sysv.S, which also calls the actual function)
143*1fd5a2e1SPrashanth Swaminathan */
ffi_prep_args(unsigned char * stack,extended_cif * ecif)144*1fd5a2e1SPrashanth Swaminathan void ffi_prep_args(unsigned char *stack, extended_cif *ecif)
145*1fd5a2e1SPrashanth Swaminathan {
146*1fd5a2e1SPrashanth Swaminathan register unsigned int i = 0;
147*1fd5a2e1SPrashanth Swaminathan void **p_argv;
148*1fd5a2e1SPrashanth Swaminathan unsigned char *argp;
149*1fd5a2e1SPrashanth Swaminathan ffi_type **p_arg;
150*1fd5a2e1SPrashanth Swaminathan argp = stack;
151*1fd5a2e1SPrashanth Swaminathan p_argv = ecif->avalue;
152*1fd5a2e1SPrashanth Swaminathan for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
153*1fd5a2e1SPrashanth Swaminathan (i != 0);
154*1fd5a2e1SPrashanth Swaminathan i--, p_arg++) {
155*1fd5a2e1SPrashanth Swaminathan size_t z;
156*1fd5a2e1SPrashanth Swaminathan z = (*p_arg)->size;
157*1fd5a2e1SPrashanth Swaminathan if (z < sizeof(int)) {
158*1fd5a2e1SPrashanth Swaminathan z = sizeof(int);
159*1fd5a2e1SPrashanth Swaminathan switch ((*p_arg)->type) {
160*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8: {
161*1fd5a2e1SPrashanth Swaminathan signed char v = *(SINT8 *)(* p_argv);
162*1fd5a2e1SPrashanth Swaminathan signed int t = v;
163*1fd5a2e1SPrashanth Swaminathan *(signed int *) argp = t;
164*1fd5a2e1SPrashanth Swaminathan }
165*1fd5a2e1SPrashanth Swaminathan break;
166*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8: {
167*1fd5a2e1SPrashanth Swaminathan unsigned char v = *(UINT8 *)(* p_argv);
168*1fd5a2e1SPrashanth Swaminathan unsigned int t = v;
169*1fd5a2e1SPrashanth Swaminathan *(unsigned int *) argp = t;
170*1fd5a2e1SPrashanth Swaminathan }
171*1fd5a2e1SPrashanth Swaminathan break;
172*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
173*1fd5a2e1SPrashanth Swaminathan *(signed int *) argp = (signed int) * (SINT16 *)(* p_argv);
174*1fd5a2e1SPrashanth Swaminathan break;
175*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
176*1fd5a2e1SPrashanth Swaminathan *(unsigned int *) argp = (unsigned int) * (UINT16 *)(* p_argv);
177*1fd5a2e1SPrashanth Swaminathan break;
178*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
179*1fd5a2e1SPrashanth Swaminathan memcpy(argp, *p_argv, (*p_arg)->size);
180*1fd5a2e1SPrashanth Swaminathan break;
181*1fd5a2e1SPrashanth Swaminathan default:
182*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(0);
183*1fd5a2e1SPrashanth Swaminathan break;
184*1fd5a2e1SPrashanth Swaminathan }
185*1fd5a2e1SPrashanth Swaminathan } else if (z == sizeof(int)) {
186*1fd5a2e1SPrashanth Swaminathan *(unsigned int *) argp = (unsigned int) * (UINT32 *)(* p_argv);
187*1fd5a2e1SPrashanth Swaminathan } else {
188*1fd5a2e1SPrashanth Swaminathan memcpy(argp, *p_argv, z);
189*1fd5a2e1SPrashanth Swaminathan }
190*1fd5a2e1SPrashanth Swaminathan p_argv++;
191*1fd5a2e1SPrashanth Swaminathan argp += z;
192*1fd5a2e1SPrashanth Swaminathan }
193*1fd5a2e1SPrashanth Swaminathan }
194*1fd5a2e1SPrashanth Swaminathan
195*1fd5a2e1SPrashanth Swaminathan
196*1fd5a2e1SPrashanth Swaminathan
197