• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 2011, 2013 Anthony Green
3            Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
4 
5    SPARC Foreign Function Interface
6 
7    Permission is hereby granted, free of charge, to any person obtaining
8    a copy of this software and associated documentation files (the
9    ``Software''), to deal in the Software without restriction, including
10    without limitation the rights to use, copy, modify, merge, publish,
11    distribute, sublicense, and/or sell copies of the Software, and to
12    permit persons to whom the Software is furnished to do so, subject to
13    the following conditions:
14 
15    The above copyright notice and this permission notice shall be included
16    in all copies or substantial portions of the Software.
17 
18    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25    DEALINGS IN THE SOFTWARE.
26    ----------------------------------------------------------------------- */
27 
28 #include <ffi.h>
29 #include <ffi_common.h>
30 #include <stdlib.h>
31 #include "internal.h"
32 
33 /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
34    all further uses in this file will refer to the 128-bit type.  */
35 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
36 # if FFI_TYPE_LONGDOUBLE != 4
37 #  error FFI_TYPE_LONGDOUBLE out of date
38 # endif
39 #else
40 # undef FFI_TYPE_LONGDOUBLE
41 # define FFI_TYPE_LONGDOUBLE 4
42 #endif
43 
44 #ifdef SPARC64
45 
46 /* Flatten the contents of a structure to the parts that are passed in
47    floating point registers.  The return is a bit mask wherein bit N
48    set means bytes [4*n, 4*n+3] are passed in %fN.
49 
50    We encode both the (running) size (maximum 32) and mask (maxumum 255)
51    into one integer.  The size is placed in the low byte, so that align
52    and addition work correctly.  The mask is placed in the second byte.  */
53 
54 static int
ffi_struct_float_mask(ffi_type * outer_type,int size_mask)55 ffi_struct_float_mask (ffi_type *outer_type, int size_mask)
56 {
57   ffi_type **elts;
58   ffi_type *t;
59 
60   if (outer_type->type == FFI_TYPE_COMPLEX)
61     {
62       int m = 0, tt = outer_type->elements[0]->type;
63       size_t z = outer_type->size;
64 
65       if (tt == FFI_TYPE_FLOAT
66 	  || tt == FFI_TYPE_DOUBLE
67 	  || tt == FFI_TYPE_LONGDOUBLE)
68         m = (1 << (z / 4)) - 1;
69       return (m << 8) | z;
70     }
71   FFI_ASSERT (outer_type->type == FFI_TYPE_STRUCT);
72 
73   for (elts = outer_type->elements; (t = *elts) != NULL; elts++)
74     {
75       size_t z = t->size;
76       int o, m, tt;
77 
78       size_mask = FFI_ALIGN(size_mask, t->alignment);
79       switch (t->type)
80 	{
81 	case FFI_TYPE_STRUCT:
82 	  size_mask = ffi_struct_float_mask (t, size_mask);
83 	  continue;
84 	case FFI_TYPE_COMPLEX:
85 	  tt = t->elements[0]->type;
86 	  if (tt != FFI_TYPE_FLOAT
87 	      && tt != FFI_TYPE_DOUBLE
88 	      && tt != FFI_TYPE_LONGDOUBLE)
89 	    break;
90 	  /* FALLTHRU */
91 	case FFI_TYPE_FLOAT:
92 	case FFI_TYPE_DOUBLE:
93 	case FFI_TYPE_LONGDOUBLE:
94 	  m = (1 << (z / 4)) - 1;	/* compute mask for type */
95 	  o = (size_mask >> 2) & 0x3f;	/* extract word offset */
96 	  size_mask |= m << (o + 8);	/* insert mask into place */
97 	  break;
98 	}
99       size_mask += z;
100     }
101 
102   size_mask = FFI_ALIGN(size_mask, outer_type->alignment);
103   FFI_ASSERT ((size_mask & 0xff) == outer_type->size);
104 
105   return size_mask;
106 }
107 
108 /* Merge floating point data into integer data.  If the structure is
109    entirely floating point, simply return a pointer to the fp data.  */
110 
111 static void *
ffi_struct_float_merge(int size_mask,void * vi,void * vf)112 ffi_struct_float_merge (int size_mask, void *vi, void *vf)
113 {
114   int size = size_mask & 0xff;
115   int mask = size_mask >> 8;
116   int n = size >> 2;
117 
118   if (mask == 0)
119     return vi;
120   else if (mask == (1 << n) - 1)
121     return vf;
122   else
123     {
124       unsigned int *wi = vi, *wf = vf;
125       int i;
126 
127       for (i = 0; i < n; ++i)
128 	if ((mask >> i) & 1)
129 	  wi[i] = wf[i];
130 
131       return vi;
132     }
133 }
134 
135 /* Similar, but place the data into VD in the end.  */
136 
137 void FFI_HIDDEN
ffi_struct_float_copy(int size_mask,void * vd,void * vi,void * vf)138 ffi_struct_float_copy (int size_mask, void *vd, void *vi, void *vf)
139 {
140   int size = size_mask & 0xff;
141   int mask = size_mask >> 8;
142   int n = size >> 2;
143 
144   if (mask == 0)
145     ;
146   else if (mask == (1 << n) - 1)
147     vi = vf;
148   else
149     {
150       unsigned int *wd = vd, *wi = vi, *wf = vf;
151       int i;
152 
153       for (i = 0; i < n; ++i)
154 	wd[i] = ((mask >> i) & 1 ? wf : wi)[i];
155       return;
156     }
157   memcpy (vd, vi, size);
158 }
159 
160 /* Perform machine dependent cif processing */
161 
162 static ffi_status
ffi_prep_cif_machdep_core(ffi_cif * cif)163 ffi_prep_cif_machdep_core(ffi_cif *cif)
164 {
165   ffi_type *rtype = cif->rtype;
166   int rtt = rtype->type;
167   size_t bytes = 0;
168   int i, n, flags;
169 
170   /* Set the return type flag */
171   switch (rtt)
172     {
173     case FFI_TYPE_VOID:
174       flags = SPARC_RET_VOID;
175       break;
176     case FFI_TYPE_FLOAT:
177       flags = SPARC_RET_F_1;
178       break;
179     case FFI_TYPE_DOUBLE:
180       flags = SPARC_RET_F_2;
181       break;
182     case FFI_TYPE_LONGDOUBLE:
183       flags = SPARC_RET_F_4;
184       break;
185 
186     case FFI_TYPE_COMPLEX:
187     case FFI_TYPE_STRUCT:
188       if (rtype->size > 32)
189 	{
190 	  flags = SPARC_RET_VOID | SPARC_FLAG_RET_IN_MEM;
191 	  bytes = 8;
192 	}
193       else
194 	{
195 	  int size_mask = ffi_struct_float_mask (rtype, 0);
196 	  int word_size = (size_mask >> 2) & 0x3f;
197 	  int all_mask = (1 << word_size) - 1;
198 	  int fp_mask = size_mask >> 8;
199 
200 	  flags = (size_mask << SPARC_SIZEMASK_SHIFT) | SPARC_RET_STRUCT;
201 
202 	  /* For special cases of all-int or all-fp, we can return
203 	     the value directly without popping through a struct copy.  */
204 	  if (fp_mask == 0)
205 	    {
206 	      if (rtype->alignment >= 8)
207 		{
208 		  if (rtype->size == 8)
209 		    flags = SPARC_RET_INT64;
210 		  else if (rtype->size == 16)
211 		    flags = SPARC_RET_INT128;
212 		}
213 	    }
214 	  else if (fp_mask == all_mask)
215 	    switch (word_size)
216 	      {
217 	      case 1: flags = SPARC_RET_F_1; break;
218 	      case 2: flags = SPARC_RET_F_2; break;
219 	      case 3: flags = SP_V9_RET_F_3; break;
220 	      case 4: flags = SPARC_RET_F_4; break;
221 	      /* 5 word structures skipped; handled via RET_STRUCT.  */
222 	      case 6: flags = SPARC_RET_F_6; break;
223 	      /* 7 word structures skipped; handled via RET_STRUCT.  */
224 	      case 8: flags = SPARC_RET_F_8; break;
225 	      }
226 	}
227       break;
228 
229     case FFI_TYPE_SINT8:
230       flags = SPARC_RET_SINT8;
231       break;
232     case FFI_TYPE_UINT8:
233       flags = SPARC_RET_UINT8;
234       break;
235     case FFI_TYPE_SINT16:
236       flags = SPARC_RET_SINT16;
237       break;
238     case FFI_TYPE_UINT16:
239       flags = SPARC_RET_UINT16;
240       break;
241     case FFI_TYPE_INT:
242     case FFI_TYPE_SINT32:
243       flags = SP_V9_RET_SINT32;
244       break;
245     case FFI_TYPE_UINT32:
246       flags = SPARC_RET_UINT32;
247       break;
248     case FFI_TYPE_SINT64:
249     case FFI_TYPE_UINT64:
250     case FFI_TYPE_POINTER:
251       flags = SPARC_RET_INT64;
252       break;
253 
254     default:
255       abort();
256     }
257 
258   bytes = 0;
259   for (i = 0, n = cif->nargs; i < n; ++i)
260     {
261       ffi_type *ty = cif->arg_types[i];
262       size_t z = ty->size;
263       size_t a = ty->alignment;
264 
265       switch (ty->type)
266 	{
267 	case FFI_TYPE_COMPLEX:
268 	case FFI_TYPE_STRUCT:
269 	  /* Large structs passed by reference.  */
270 	  if (z > 16)
271 	    {
272 	      a = z = 8;
273 	      break;
274 	    }
275 	  /* Small structs may be passed in integer or fp regs or both.  */
276 	  if (bytes >= 16*8)
277 	    break;
278 	  if ((ffi_struct_float_mask (ty, 0) & 0xff00) == 0)
279 	    break;
280 	  /* FALLTHRU */
281 	case FFI_TYPE_FLOAT:
282 	case FFI_TYPE_DOUBLE:
283 	case FFI_TYPE_LONGDOUBLE:
284 	  flags |= SPARC_FLAG_FP_ARGS;
285 	  break;
286 	}
287       bytes = FFI_ALIGN(bytes, a);
288       bytes += FFI_ALIGN(z, 8);
289     }
290 
291   /* Sparc call frames require that space is allocated for 6 args,
292      even if they aren't used. Make that space if necessary. */
293   if (bytes < 6 * 8)
294     bytes = 6 * 8;
295 
296   /* The stack must be 2 word aligned, so round bytes up appropriately. */
297   bytes = FFI_ALIGN(bytes, 16);
298 
299   /* Include the call frame to prep_args.  */
300   bytes += 8*16 + 8*8;
301 
302   cif->bytes = bytes;
303   cif->flags = flags;
304   return FFI_OK;
305 }
306 
307 ffi_status FFI_HIDDEN
ffi_prep_cif_machdep(ffi_cif * cif)308 ffi_prep_cif_machdep(ffi_cif *cif)
309 {
310   cif->nfixedargs = cif->nargs;
311   return ffi_prep_cif_machdep_core(cif);
312 }
313 
314 ffi_status FFI_HIDDEN
ffi_prep_cif_machdep_var(ffi_cif * cif,unsigned nfixedargs,unsigned ntotalargs)315 ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned nfixedargs, unsigned ntotalargs)
316 {
317   cif->nfixedargs = nfixedargs;
318   return ffi_prep_cif_machdep_core(cif);
319 }
320 
321 extern void ffi_call_v9(ffi_cif *cif, void (*fn)(void), void *rvalue,
322 			void **avalue, size_t bytes, void *closure) FFI_HIDDEN;
323 
324 /* ffi_prep_args is called by the assembly routine once stack space
325    has been allocated for the function's arguments */
326 
327 int FFI_HIDDEN
ffi_prep_args_v9(ffi_cif * cif,unsigned long * argp,void * rvalue,void ** avalue)328 ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
329 {
330   ffi_type **p_arg;
331   int flags = cif->flags;
332   int i, nargs;
333 
334   if (rvalue == NULL)
335     {
336       if (flags & SPARC_FLAG_RET_IN_MEM)
337 	{
338 	  /* Since we pass the pointer to the callee, we need a value.
339 	     We allowed for this space in ffi_call, before ffi_call_v8
340 	     alloca'd the space.  */
341 	  rvalue = (char *)argp + cif->bytes;
342 	}
343       else
344 	{
345 	  /* Otherwise, we can ignore the return value.  */
346 	  flags = SPARC_RET_VOID;
347 	}
348     }
349 
350 #ifdef USING_PURIFY
351   /* Purify will probably complain in our assembly routine,
352      unless we zero out this memory. */
353   memset(argp, 0, 6*8);
354 #endif
355 
356   if (flags & SPARC_FLAG_RET_IN_MEM)
357     *argp++ = (unsigned long)rvalue;
358 
359   p_arg = cif->arg_types;
360   for (i = 0, nargs = cif->nargs; i < nargs; i++)
361     {
362       ffi_type *ty = p_arg[i];
363       void *a = avalue[i];
364       size_t z;
365 
366       switch (ty->type)
367 	{
368 	case FFI_TYPE_SINT8:
369 	  *argp++ = *(SINT8 *)a;
370 	  break;
371 	case FFI_TYPE_UINT8:
372 	  *argp++ = *(UINT8 *)a;
373 	  break;
374 	case FFI_TYPE_SINT16:
375 	  *argp++ = *(SINT16 *)a;
376 	  break;
377 	case FFI_TYPE_UINT16:
378 	  *argp++ = *(UINT16 *)a;
379 	  break;
380 	case FFI_TYPE_INT:
381 	case FFI_TYPE_SINT32:
382 	  *argp++ = *(SINT32 *)a;
383 	  break;
384 	case FFI_TYPE_UINT32:
385 	case FFI_TYPE_FLOAT:
386 	  *argp++ = *(UINT32 *)a;
387 	  break;
388 	case FFI_TYPE_SINT64:
389 	case FFI_TYPE_UINT64:
390 	case FFI_TYPE_POINTER:
391 	case FFI_TYPE_DOUBLE:
392 	  *argp++ = *(UINT64 *)a;
393 	  break;
394 
395 	case FFI_TYPE_LONGDOUBLE:
396 	case FFI_TYPE_COMPLEX:
397 	case FFI_TYPE_STRUCT:
398 	  z = ty->size;
399 	  if (z > 16)
400 	    {
401 	      /* For structures larger than 16 bytes we pass reference.  */
402 	      *argp++ = (unsigned long)a;
403 	      break;
404 	    }
405 	  if (((unsigned long)argp & 15) && ty->alignment > 8)
406 	    argp++;
407 	  memcpy(argp, a, z);
408 	  argp += FFI_ALIGN(z, 8) / 8;
409 	  break;
410 
411 	default:
412 	  abort();
413 	}
414     }
415 
416   return flags;
417 }
418 
419 static void
ffi_call_int(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)420 ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue,
421 	     void **avalue, void *closure)
422 {
423   size_t bytes = cif->bytes;
424 
425   FFI_ASSERT (cif->abi == FFI_V9);
426 
427   if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM))
428     bytes += FFI_ALIGN (cif->rtype->size, 16);
429 
430   ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure);
431 }
432 
433 void
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)434 ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
435 {
436   ffi_call_int(cif, fn, rvalue, avalue, NULL);
437 }
438 
439 void
ffi_call_go(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)440 ffi_call_go(ffi_cif *cif, void (*fn)(void), void *rvalue,
441 	    void **avalue, void *closure)
442 {
443   ffi_call_int(cif, fn, rvalue, avalue, closure);
444 }
445 
446 #ifdef __GNUC__
447 static inline void
ffi_flush_icache(void * p)448 ffi_flush_icache (void *p)
449 {
450   asm volatile ("flush	%0; flush %0+8" : : "r" (p) : "memory");
451 }
452 #else
453 extern void ffi_flush_icache (void *) FFI_HIDDEN;
454 #endif
455 
456 extern void ffi_closure_v9(void) FFI_HIDDEN;
457 extern void ffi_go_closure_v9(void) FFI_HIDDEN;
458 
459 ffi_status
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)460 ffi_prep_closure_loc (ffi_closure* closure,
461 		      ffi_cif* cif,
462 		      void (*fun)(ffi_cif*, void*, void**, void*),
463 		      void *user_data,
464 		      void *codeloc)
465 {
466   unsigned int *tramp = (unsigned int *) &closure->tramp[0];
467   unsigned long fn;
468 
469   if (cif->abi != FFI_V9)
470     return FFI_BAD_ABI;
471 
472   /* Trampoline address is equal to the closure address.  We take advantage
473      of that to reduce the trampoline size by 8 bytes. */
474   fn = (unsigned long) ffi_closure_v9;
475   tramp[0] = 0x83414000;	/* rd	%pc, %g1	*/
476   tramp[1] = 0xca586010;	/* ldx	[%g1+16], %g5	*/
477   tramp[2] = 0x81c14000;	/* jmp	%g5		*/
478   tramp[3] = 0x01000000;	/* nop			*/
479   *((unsigned long *) &tramp[4]) = fn;
480 
481   closure->cif = cif;
482   closure->fun = fun;
483   closure->user_data = user_data;
484 
485   ffi_flush_icache (closure);
486 
487   return FFI_OK;
488 }
489 
490 ffi_status
ffi_prep_go_closure(ffi_go_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *))491 ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
492 		     void (*fun)(ffi_cif*, void*, void**, void*))
493 {
494   if (cif->abi != FFI_V9)
495     return FFI_BAD_ABI;
496 
497   closure->tramp = ffi_go_closure_v9;
498   closure->cif = cif;
499   closure->fun = fun;
500 
501   return FFI_OK;
502 }
503 
504 int FFI_HIDDEN
ffi_closure_sparc_inner_v9(ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * rvalue,unsigned long * gpr,unsigned long * fpr)505 ffi_closure_sparc_inner_v9(ffi_cif *cif,
506 			   void (*fun)(ffi_cif*, void*, void**, void*),
507 			   void *user_data, void *rvalue,
508 			   unsigned long *gpr, unsigned long *fpr)
509 {
510   ffi_type **arg_types;
511   void **avalue;
512   int i, argn, argx, nargs, flags, nfixedargs;
513 
514   arg_types = cif->arg_types;
515   nargs = cif->nargs;
516   flags = cif->flags;
517   nfixedargs = cif->nfixedargs;
518 
519   avalue = alloca(nargs * sizeof(void *));
520 
521   /* Copy the caller's structure return address so that the closure
522      returns the data directly to the caller.  */
523   if (flags & SPARC_FLAG_RET_IN_MEM)
524     {
525       rvalue = (void *) gpr[0];
526       /* Skip the structure return address.  */
527       argn = 1;
528     }
529   else
530     argn = 0;
531 
532   /* Grab the addresses of the arguments from the stack frame.  */
533   for (i = 0; i < nargs; i++, argn = argx)
534     {
535       int named = i < nfixedargs;
536       ffi_type *ty = arg_types[i];
537       void *a = &gpr[argn];
538       size_t z;
539 
540       argx = argn + 1;
541       switch (ty->type)
542 	{
543 	case FFI_TYPE_COMPLEX:
544 	case FFI_TYPE_STRUCT:
545 	  z = ty->size;
546 	  if (z > 16)
547 	    a = *(void **)a;
548 	  else
549 	    {
550 	      argx = argn + FFI_ALIGN (z, 8) / 8;
551 	      if (named && argn < 16)
552 		{
553 		  int size_mask = ffi_struct_float_mask (ty, 0);
554 		  int argn_mask = (0xffff00 >> argn) & 0xff00;
555 
556 		  /* Eliminate fp registers off the end.  */
557 		  size_mask = (size_mask & 0xff) | (size_mask & argn_mask);
558 		  a = ffi_struct_float_merge (size_mask, gpr+argn, fpr+argn);
559 		}
560 	    }
561 	  break;
562 
563 	case FFI_TYPE_LONGDOUBLE:
564 	  argn = FFI_ALIGN (argn, 2);
565 	  a = (named && argn < 16 ? fpr : gpr) + argn;
566 	  argx = argn + 2;
567 	  break;
568 	case FFI_TYPE_DOUBLE:
569 	  if (named && argn < 16)
570 	    a = fpr + argn;
571 	  break;
572 	case FFI_TYPE_FLOAT:
573 	  if (named && argn < 16)
574 	    a = fpr + argn;
575 	  a += 4;
576 	  break;
577 
578 	case FFI_TYPE_UINT64:
579 	case FFI_TYPE_SINT64:
580 	case FFI_TYPE_POINTER:
581 	  break;
582 	case FFI_TYPE_INT:
583 	case FFI_TYPE_UINT32:
584 	case FFI_TYPE_SINT32:
585 	  a += 4;
586 	  break;
587         case FFI_TYPE_UINT16:
588         case FFI_TYPE_SINT16:
589 	  a += 6;
590 	  break;
591         case FFI_TYPE_UINT8:
592         case FFI_TYPE_SINT8:
593 	  a += 7;
594 	  break;
595 
596 	default:
597 	  abort();
598 	}
599       avalue[i] = a;
600     }
601 
602   /* Invoke the closure.  */
603   fun (cif, rvalue, avalue, user_data);
604 
605   /* Tell ffi_closure_sparc how to perform return type promotions.  */
606   return flags;
607 }
608 #endif /* SPARC64 */
609