xref: /aosp_15_r20/external/libffi/src/bfin/ffi.c (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
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