1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (C) 2012, 2013, 2018  Anthony Green
3 
4    Moxie Foreign Function Interface
5 
6    Permission is hereby granted, free of charge, to any person obtaining
7    a copy of this software and associated documentation files (the
8    ``Software''), to deal in the Software without restriction, including
9    without limitation the rights to use, copy, modify, merge, publish,
10    distribute, sublicense, and/or sell copies of the Software, and to
11    permit persons to whom the Software is furnished to do so, subject to
12    the following conditions:
13 
14    The above copyright notice and this permission notice shall be included
15    in all copies or substantial portions of the Software.
16 
17    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24    DEALINGS IN THE SOFTWARE.
25    ----------------------------------------------------------------------- */
26 
27 #include <ffi.h>
28 #include <ffi_common.h>
29 
30 #include <stdlib.h>
31 
32 /* ffi_prep_args is called by the assembly routine once stack space
33    has been allocated for the function's arguments */
34 
ffi_prep_args(char * stack,extended_cif * ecif)35 void *ffi_prep_args(char *stack, extended_cif *ecif)
36 {
37   register unsigned int i;
38   register void **p_argv;
39   register char *argp;
40   register ffi_type **p_arg;
41   register int count = 0;
42 
43   p_argv = ecif->avalue;
44   argp = stack;
45 
46   if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
47     {
48       *(void **) argp = ecif->rvalue;
49       argp += 4;
50     }
51 
52   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
53        (i != 0);
54        i--, p_arg++)
55     {
56       size_t z;
57 
58       z = (*p_arg)->size;
59 
60       if ((*p_arg)->type == FFI_TYPE_STRUCT)
61 	{
62 	  z = sizeof(void*);
63 	  *(void **) argp = *p_argv;
64 	}
65       else if (z < sizeof(int))
66 	{
67 	  z = sizeof(int);
68 	  switch ((*p_arg)->type)
69 	    {
70 	    case FFI_TYPE_SINT8:
71 	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
72 	      break;
73 
74 	    case FFI_TYPE_UINT8:
75 	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
76 	      break;
77 
78 	    case FFI_TYPE_SINT16:
79 	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
80 	      break;
81 
82 	    case FFI_TYPE_UINT16:
83 	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
84 	      break;
85 
86 	    default:
87 	      FFI_ASSERT(0);
88 	    }
89 	}
90       else if (z == sizeof(int))
91 	{
92 	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
93 	}
94       else
95 	{
96 	  memcpy(argp, *p_argv, z);
97 	}
98       p_argv++;
99       argp += z;
100       count += z;
101     }
102 
103   return (stack + ((count > 24) ? 24 : FFI_ALIGN_DOWN(count, 8)));
104 }
105 
106 /* Perform machine dependent cif processing */
ffi_prep_cif_machdep(ffi_cif * cif)107 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
108 {
109   if (cif->rtype->type == FFI_TYPE_STRUCT)
110     cif->flags = -1;
111   else
112     cif->flags = cif->rtype->size;
113 
114   cif->bytes = FFI_ALIGN (cif->bytes, 8);
115 
116   return FFI_OK;
117 }
118 
119 extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
120 			  extended_cif *,
121 			  unsigned, unsigned,
122 			  unsigned *,
123 			  void (*fn)(void));
124 
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)125 void ffi_call(ffi_cif *cif,
126 	      void (*fn)(void),
127 	      void *rvalue,
128 	      void **avalue)
129 {
130   extended_cif ecif;
131 
132   ecif.cif = cif;
133   ecif.avalue = avalue;
134 
135   /* If the return value is a struct and we don't have a return	*/
136   /* value address then we need to make one		        */
137 
138   if ((rvalue == NULL) &&
139       (cif->rtype->type == FFI_TYPE_STRUCT))
140     {
141       ecif.rvalue = alloca(cif->rtype->size);
142     }
143   else
144     ecif.rvalue = rvalue;
145 
146   switch (cif->abi)
147     {
148     case FFI_EABI:
149       ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
150 		    cif->flags, ecif.rvalue, fn);
151       break;
152     default:
153       FFI_ASSERT(0);
154       break;
155     }
156 }
157 
ffi_closure_eabi(unsigned arg1,unsigned arg2,unsigned arg3,unsigned arg4,unsigned arg5,unsigned arg6)158 void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
159 		       unsigned arg4, unsigned arg5, unsigned arg6)
160 {
161   /* This function is called by a trampoline.  The trampoline stows a
162      pointer to the ffi_closure object in $r12.  We must save this
163      pointer in a place that will persist while we do our work.  */
164   register ffi_closure *creg __asm__ ("$r12");
165   ffi_closure *closure = creg;
166 
167   /* Arguments that don't fit in registers are found on the stack
168      at a fixed offset above the current frame pointer.  */
169   register char *frame_pointer __asm__ ("$fp");
170 
171   /* Pointer to a struct return value.  */
172   void *struct_rvalue = (void *) arg1;
173 
174   /* 6 words reserved for register args + 3 words from jsr */
175   char *stack_args = frame_pointer + 9*4;
176 
177   /* Lay the register arguments down in a continuous chunk of memory.  */
178   unsigned register_args[6] =
179     { arg1, arg2, arg3, arg4, arg5, arg6 };
180   char *register_args_ptr = (char *) register_args;
181 
182   ffi_cif *cif = closure->cif;
183   ffi_type **arg_types = cif->arg_types;
184   void **avalue = alloca (cif->nargs * sizeof(void *));
185   char *ptr = (char *) register_args;
186   int i;
187 
188   /* preserve struct type return pointer passing */
189   if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
190     ptr += 4;
191     register_args_ptr = (char *)&register_args[1];
192   }
193 
194   /* Find the address of each argument.  */
195   for (i = 0; i < cif->nargs; i++)
196     {
197       switch (arg_types[i]->type)
198 	{
199 	case FFI_TYPE_SINT8:
200 	case FFI_TYPE_UINT8:
201 	  avalue[i] = ptr + 3;
202 	  break;
203 	case FFI_TYPE_SINT16:
204 	case FFI_TYPE_UINT16:
205 	  avalue[i] = ptr + 2;
206 	  break;
207 	case FFI_TYPE_SINT32:
208 	case FFI_TYPE_UINT32:
209 	case FFI_TYPE_FLOAT:
210 	case FFI_TYPE_POINTER:
211 	  avalue[i] = ptr;
212 	  break;
213 	case FFI_TYPE_STRUCT:
214 	  avalue[i] = *(void**)ptr;
215 	  break;
216 	default:
217 	  /* This is an 8-byte value.  */
218 	  if (ptr == (char *) &register_args[5])
219 	    {
220 	      /* The value is split across two locations */
221 	      unsigned *ip = alloca(8);
222 	      avalue[i] = ip;
223 	      ip[0] = *(unsigned *) ptr;
224 	      ip[1] = *(unsigned *) stack_args;
225 	    }
226 	  else
227 	    {
228 	      avalue[i] = ptr;
229 	    }
230 	  ptr += 4;
231 	  break;
232 	}
233       ptr += 4;
234 
235       /* If we've handled more arguments than fit in registers,
236 	 start looking at the those passed on the stack.  */
237       if (ptr == (char *) &register_args[6])
238 	ptr = stack_args;
239       else if (ptr == (char *) &register_args[7])
240 	ptr = stack_args + 4;
241     }
242 
243   /* Invoke the closure.  */
244   if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT))
245     {
246       (closure->fun) (cif, struct_rvalue, avalue, closure->user_data);
247     }
248   else
249     {
250       /* Allocate space for the return value and call the function.  */
251       long long rvalue;
252       (closure->fun) (cif, &rvalue, avalue, closure->user_data);
253       asm ("mov $r12, %0\n ld.l $r0, ($r12)\n ldo.l $r1, 4($r12)" : : "r" (&rvalue));
254     }
255 }
256 
257 ffi_status
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)258 ffi_prep_closure_loc (ffi_closure* closure,
259 		      ffi_cif* cif,
260 		      void (*fun)(ffi_cif*, void*, void**, void*),
261 		      void *user_data,
262 		      void *codeloc)
263 {
264   unsigned short *tramp = (unsigned short *) &closure->tramp[0];
265   unsigned long fn = (long) ffi_closure_eabi;
266   unsigned long cls = (long) codeloc;
267 
268   if (cif->abi != FFI_EABI)
269     return FFI_BAD_ABI;
270 
271   fn = (unsigned long) ffi_closure_eabi;
272 
273   tramp[0] = 0x01e0; /* ldi.l $r12, .... */
274   tramp[1] = cls >> 16;
275   tramp[2] = cls & 0xffff;
276   tramp[3] = 0x1a00; /* jmpa .... */
277   tramp[4] = fn >> 16;
278   tramp[5] = fn & 0xffff;
279 
280   closure->cif = cif;
281   closure->fun = fun;
282   closure->user_data = user_data;
283 
284   return FFI_OK;
285 }
286