xref: /aosp_15_r20/external/libffi/src/m32r/ffi.c (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan    ffi.c - Copyright (c) 2004  Renesas Technology
3*1fd5a2e1SPrashanth Swaminathan            Copyright (c) 2008  Red Hat, Inc.
4*1fd5a2e1SPrashanth Swaminathan 
5*1fd5a2e1SPrashanth Swaminathan    M32R 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, EXPRESS
19*1fd5a2e1SPrashanth Swaminathan    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*1fd5a2e1SPrashanth Swaminathan    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21*1fd5a2e1SPrashanth Swaminathan    IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
22*1fd5a2e1SPrashanth Swaminathan    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23*1fd5a2e1SPrashanth Swaminathan    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24*1fd5a2e1SPrashanth Swaminathan    OTHER DEALINGS IN THE SOFTWARE.
25*1fd5a2e1SPrashanth Swaminathan    ----------------------------------------------------------------------- */
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 
32*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args is called by the assembly routine once stack
33*1fd5a2e1SPrashanth Swaminathan    space has been allocated for the function's arguments.  */
34*1fd5a2e1SPrashanth Swaminathan 
ffi_prep_args(char * stack,extended_cif * ecif)35*1fd5a2e1SPrashanth Swaminathan void ffi_prep_args(char *stack, extended_cif *ecif)
36*1fd5a2e1SPrashanth Swaminathan {
37*1fd5a2e1SPrashanth Swaminathan   unsigned int i;
38*1fd5a2e1SPrashanth Swaminathan   int tmp;
39*1fd5a2e1SPrashanth Swaminathan   unsigned int avn;
40*1fd5a2e1SPrashanth Swaminathan   void **p_argv;
41*1fd5a2e1SPrashanth Swaminathan   char *argp;
42*1fd5a2e1SPrashanth Swaminathan   ffi_type **p_arg;
43*1fd5a2e1SPrashanth Swaminathan 
44*1fd5a2e1SPrashanth Swaminathan   tmp = 0;
45*1fd5a2e1SPrashanth Swaminathan   argp = stack;
46*1fd5a2e1SPrashanth Swaminathan 
47*1fd5a2e1SPrashanth Swaminathan   if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8)
48*1fd5a2e1SPrashanth Swaminathan     {
49*1fd5a2e1SPrashanth Swaminathan       *(void **) argp = ecif->rvalue;
50*1fd5a2e1SPrashanth Swaminathan       argp += 4;
51*1fd5a2e1SPrashanth Swaminathan     }
52*1fd5a2e1SPrashanth Swaminathan 
53*1fd5a2e1SPrashanth Swaminathan   avn = ecif->cif->nargs;
54*1fd5a2e1SPrashanth Swaminathan   p_argv = ecif->avalue;
55*1fd5a2e1SPrashanth Swaminathan 
56*1fd5a2e1SPrashanth Swaminathan   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
57*1fd5a2e1SPrashanth Swaminathan        (i != 0) && (avn != 0);
58*1fd5a2e1SPrashanth Swaminathan        i--, p_arg++)
59*1fd5a2e1SPrashanth Swaminathan     {
60*1fd5a2e1SPrashanth Swaminathan       size_t z;
61*1fd5a2e1SPrashanth Swaminathan 
62*1fd5a2e1SPrashanth Swaminathan       /* Align if necessary.  */
63*1fd5a2e1SPrashanth Swaminathan       if (((*p_arg)->alignment - 1) & (unsigned) argp)
64*1fd5a2e1SPrashanth Swaminathan 	argp = (char *) FFI_ALIGN (argp, (*p_arg)->alignment);
65*1fd5a2e1SPrashanth Swaminathan 
66*1fd5a2e1SPrashanth Swaminathan       if (avn != 0)
67*1fd5a2e1SPrashanth Swaminathan 	{
68*1fd5a2e1SPrashanth Swaminathan 	  avn--;
69*1fd5a2e1SPrashanth Swaminathan 	  z = (*p_arg)->size;
70*1fd5a2e1SPrashanth Swaminathan 	  if (z < sizeof (int))
71*1fd5a2e1SPrashanth Swaminathan 	    {
72*1fd5a2e1SPrashanth Swaminathan 	      z = sizeof (int);
73*1fd5a2e1SPrashanth Swaminathan 
74*1fd5a2e1SPrashanth Swaminathan 	      switch ((*p_arg)->type)
75*1fd5a2e1SPrashanth Swaminathan 		{
76*1fd5a2e1SPrashanth Swaminathan 		case FFI_TYPE_SINT8:
77*1fd5a2e1SPrashanth Swaminathan 		  *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
78*1fd5a2e1SPrashanth Swaminathan 		  break;
79*1fd5a2e1SPrashanth Swaminathan 
80*1fd5a2e1SPrashanth Swaminathan 		case FFI_TYPE_UINT8:
81*1fd5a2e1SPrashanth Swaminathan 		  *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
82*1fd5a2e1SPrashanth Swaminathan 		  break;
83*1fd5a2e1SPrashanth Swaminathan 
84*1fd5a2e1SPrashanth Swaminathan 		case FFI_TYPE_SINT16:
85*1fd5a2e1SPrashanth Swaminathan 		  *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
86*1fd5a2e1SPrashanth Swaminathan 		  break;
87*1fd5a2e1SPrashanth Swaminathan 
88*1fd5a2e1SPrashanth Swaminathan 		case FFI_TYPE_UINT16:
89*1fd5a2e1SPrashanth Swaminathan 		  *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
90*1fd5a2e1SPrashanth Swaminathan 		  break;
91*1fd5a2e1SPrashanth Swaminathan 
92*1fd5a2e1SPrashanth Swaminathan 		case FFI_TYPE_STRUCT:
93*1fd5a2e1SPrashanth Swaminathan 	  	  z = (*p_arg)->size;
94*1fd5a2e1SPrashanth Swaminathan 	  	  if ((*p_arg)->alignment != 1)
95*1fd5a2e1SPrashanth Swaminathan 		    memcpy (argp, *p_argv, z);
96*1fd5a2e1SPrashanth Swaminathan 		  else
97*1fd5a2e1SPrashanth Swaminathan 		    memcpy (argp + 4 - z, *p_argv, z);
98*1fd5a2e1SPrashanth Swaminathan 	  	  z = sizeof (int);
99*1fd5a2e1SPrashanth Swaminathan 		  break;
100*1fd5a2e1SPrashanth Swaminathan 
101*1fd5a2e1SPrashanth Swaminathan 		default:
102*1fd5a2e1SPrashanth Swaminathan 		  FFI_ASSERT(0);
103*1fd5a2e1SPrashanth Swaminathan 		}
104*1fd5a2e1SPrashanth Swaminathan 	    }
105*1fd5a2e1SPrashanth Swaminathan 	  else if (z == sizeof (int))
106*1fd5a2e1SPrashanth Swaminathan 	    {
107*1fd5a2e1SPrashanth Swaminathan 	       *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
108*1fd5a2e1SPrashanth Swaminathan 	    }
109*1fd5a2e1SPrashanth Swaminathan 	  else
110*1fd5a2e1SPrashanth Swaminathan 	    {
111*1fd5a2e1SPrashanth Swaminathan 	      if ((*p_arg)->type == FFI_TYPE_STRUCT)
112*1fd5a2e1SPrashanth Swaminathan 	        {
113*1fd5a2e1SPrashanth Swaminathan 		  if (z > 8)
114*1fd5a2e1SPrashanth Swaminathan 		    {
115*1fd5a2e1SPrashanth Swaminathan 		      *(unsigned int *) argp = (unsigned int)(void *)(* p_argv);
116*1fd5a2e1SPrashanth Swaminathan 		      z = sizeof(void *);
117*1fd5a2e1SPrashanth Swaminathan 		    }
118*1fd5a2e1SPrashanth Swaminathan 		  else
119*1fd5a2e1SPrashanth Swaminathan 		    {
120*1fd5a2e1SPrashanth Swaminathan 	              memcpy(argp, *p_argv, z);
121*1fd5a2e1SPrashanth Swaminathan 		      z = 8;
122*1fd5a2e1SPrashanth Swaminathan 		    }
123*1fd5a2e1SPrashanth Swaminathan 	        }
124*1fd5a2e1SPrashanth Swaminathan 	      else
125*1fd5a2e1SPrashanth Swaminathan 	        {
126*1fd5a2e1SPrashanth Swaminathan 		  /* Double or long long 64bit.  */
127*1fd5a2e1SPrashanth Swaminathan 	          memcpy (argp, *p_argv, z);
128*1fd5a2e1SPrashanth Swaminathan 	        }
129*1fd5a2e1SPrashanth Swaminathan 	    }
130*1fd5a2e1SPrashanth Swaminathan 	  p_argv++;
131*1fd5a2e1SPrashanth Swaminathan 	  argp += z;
132*1fd5a2e1SPrashanth Swaminathan 	}
133*1fd5a2e1SPrashanth Swaminathan     }
134*1fd5a2e1SPrashanth Swaminathan 
135*1fd5a2e1SPrashanth Swaminathan   return;
136*1fd5a2e1SPrashanth Swaminathan }
137*1fd5a2e1SPrashanth Swaminathan 
138*1fd5a2e1SPrashanth Swaminathan /* Perform machine dependent cif processing.  */
139*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_cif_machdep(ffi_cif * cif)140*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_machdep(ffi_cif *cif)
141*1fd5a2e1SPrashanth Swaminathan {
142*1fd5a2e1SPrashanth Swaminathan   /* Set the return type flag.  */
143*1fd5a2e1SPrashanth Swaminathan   switch (cif->rtype->type)
144*1fd5a2e1SPrashanth Swaminathan     {
145*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_VOID:
146*1fd5a2e1SPrashanth Swaminathan       cif->flags = (unsigned) cif->rtype->type;
147*1fd5a2e1SPrashanth Swaminathan       break;
148*1fd5a2e1SPrashanth Swaminathan 
149*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_STRUCT:
150*1fd5a2e1SPrashanth Swaminathan       if (cif->rtype->size <= 4)
151*1fd5a2e1SPrashanth Swaminathan 	cif->flags = FFI_TYPE_INT;
152*1fd5a2e1SPrashanth Swaminathan 
153*1fd5a2e1SPrashanth Swaminathan       else if (cif->rtype->size <= 8)
154*1fd5a2e1SPrashanth Swaminathan 	cif->flags = FFI_TYPE_DOUBLE;
155*1fd5a2e1SPrashanth Swaminathan 
156*1fd5a2e1SPrashanth Swaminathan       else
157*1fd5a2e1SPrashanth Swaminathan 	cif->flags = (unsigned) cif->rtype->type;
158*1fd5a2e1SPrashanth Swaminathan       break;
159*1fd5a2e1SPrashanth Swaminathan 
160*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_SINT64:
161*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_UINT64:
162*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_DOUBLE:
163*1fd5a2e1SPrashanth Swaminathan       cif->flags = FFI_TYPE_DOUBLE;
164*1fd5a2e1SPrashanth Swaminathan       break;
165*1fd5a2e1SPrashanth Swaminathan 
166*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_FLOAT:
167*1fd5a2e1SPrashanth Swaminathan     default:
168*1fd5a2e1SPrashanth Swaminathan       cif->flags = FFI_TYPE_INT;
169*1fd5a2e1SPrashanth Swaminathan       break;
170*1fd5a2e1SPrashanth Swaminathan     }
171*1fd5a2e1SPrashanth Swaminathan 
172*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
173*1fd5a2e1SPrashanth Swaminathan }
174*1fd5a2e1SPrashanth Swaminathan 
175*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
176*1fd5a2e1SPrashanth Swaminathan 			  unsigned, unsigned, unsigned *, void (*fn)(void));
177*1fd5a2e1SPrashanth Swaminathan 
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)178*1fd5a2e1SPrashanth Swaminathan void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
179*1fd5a2e1SPrashanth Swaminathan {
180*1fd5a2e1SPrashanth Swaminathan   extended_cif ecif;
181*1fd5a2e1SPrashanth Swaminathan 
182*1fd5a2e1SPrashanth Swaminathan   ecif.cif = cif;
183*1fd5a2e1SPrashanth Swaminathan   ecif.avalue = avalue;
184*1fd5a2e1SPrashanth Swaminathan 
185*1fd5a2e1SPrashanth Swaminathan   /* If the return value is a struct and we don't have
186*1fd5a2e1SPrashanth Swaminathan      a return value address then we need to make one.  */
187*1fd5a2e1SPrashanth Swaminathan   if ((rvalue == NULL) &&
188*1fd5a2e1SPrashanth Swaminathan       (cif->rtype->type == FFI_TYPE_STRUCT))
189*1fd5a2e1SPrashanth Swaminathan     {
190*1fd5a2e1SPrashanth Swaminathan       ecif.rvalue = alloca (cif->rtype->size);
191*1fd5a2e1SPrashanth Swaminathan     }
192*1fd5a2e1SPrashanth Swaminathan   else
193*1fd5a2e1SPrashanth Swaminathan     ecif.rvalue = rvalue;
194*1fd5a2e1SPrashanth Swaminathan 
195*1fd5a2e1SPrashanth Swaminathan   switch (cif->abi)
196*1fd5a2e1SPrashanth Swaminathan     {
197*1fd5a2e1SPrashanth Swaminathan     case FFI_SYSV:
198*1fd5a2e1SPrashanth Swaminathan       ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
199*1fd5a2e1SPrashanth Swaminathan 		    cif->flags, ecif.rvalue, fn);
200*1fd5a2e1SPrashanth Swaminathan       if (cif->rtype->type == FFI_TYPE_STRUCT)
201*1fd5a2e1SPrashanth Swaminathan 	{
202*1fd5a2e1SPrashanth Swaminathan 	  int size = cif->rtype->size;
203*1fd5a2e1SPrashanth Swaminathan 	  int align = cif->rtype->alignment;
204*1fd5a2e1SPrashanth Swaminathan 
205*1fd5a2e1SPrashanth Swaminathan 	  if (size < 4)
206*1fd5a2e1SPrashanth Swaminathan 	    {
207*1fd5a2e1SPrashanth Swaminathan 	      if (align == 1)
208*1fd5a2e1SPrashanth Swaminathan 	        *(unsigned long *)(ecif.rvalue) <<= (4 - size) * 8;
209*1fd5a2e1SPrashanth Swaminathan 	    }
210*1fd5a2e1SPrashanth Swaminathan 	  else if (4 < size && size < 8)
211*1fd5a2e1SPrashanth Swaminathan 	    {
212*1fd5a2e1SPrashanth Swaminathan 	      if (align == 1)
213*1fd5a2e1SPrashanth Swaminathan 		{
214*1fd5a2e1SPrashanth Swaminathan 		  memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
215*1fd5a2e1SPrashanth Swaminathan 		}
216*1fd5a2e1SPrashanth Swaminathan 	      else if (align == 2)
217*1fd5a2e1SPrashanth Swaminathan 		{
218*1fd5a2e1SPrashanth Swaminathan 		  if (size & 1)
219*1fd5a2e1SPrashanth Swaminathan 		    size += 1;
220*1fd5a2e1SPrashanth Swaminathan 
221*1fd5a2e1SPrashanth Swaminathan 		  if (size != 8)
222*1fd5a2e1SPrashanth Swaminathan 		    memcpy (ecif.rvalue, ecif.rvalue + 8-size, size);
223*1fd5a2e1SPrashanth Swaminathan 		}
224*1fd5a2e1SPrashanth Swaminathan 	    }
225*1fd5a2e1SPrashanth Swaminathan 	}
226*1fd5a2e1SPrashanth Swaminathan       break;
227*1fd5a2e1SPrashanth Swaminathan 
228*1fd5a2e1SPrashanth Swaminathan     default:
229*1fd5a2e1SPrashanth Swaminathan       FFI_ASSERT(0);
230*1fd5a2e1SPrashanth Swaminathan       break;
231*1fd5a2e1SPrashanth Swaminathan     }
232*1fd5a2e1SPrashanth Swaminathan }
233