ffi.c revision 817acef0e6c6b33ade68132b090ea745badbbece
1/* -----------------------------------------------------------------------
2   ffi.c - Copyright (c) 1996, 2003, 2004, 2007, 2008 Red Hat, Inc.
3
4   SPARC 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
33/* ffi_prep_args is called by the assembly routine once stack space
34   has been allocated for the function's arguments */
35
36void ffi_prep_args_v8(char *stack, extended_cif *ecif)
37{
38  int i;
39  void **p_argv;
40  char *argp;
41  ffi_type **p_arg;
42
43  /* Skip 16 words for the window save area */
44  argp = stack + 16*sizeof(int);
45
46  /* This should only really be done when we are returning a structure,
47     however, it's faster just to do it all the time...
48
49  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
50  *(int *) argp = (long)ecif->rvalue;
51
52  /* And 1 word for the  structure return value. */
53  argp += sizeof(int);
54
55#ifdef USING_PURIFY
56  /* Purify will probably complain in our assembly routine, unless we
57     zero out this memory. */
58
59  ((int*)argp)[0] = 0;
60  ((int*)argp)[1] = 0;
61  ((int*)argp)[2] = 0;
62  ((int*)argp)[3] = 0;
63  ((int*)argp)[4] = 0;
64  ((int*)argp)[5] = 0;
65#endif
66
67  p_argv = ecif->avalue;
68
69  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
70    {
71      size_t z;
72
73	  if ((*p_arg)->type == FFI_TYPE_STRUCT
74#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
75	      || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
76#endif
77	      )
78	    {
79	      *(unsigned int *) argp = (unsigned long)(* p_argv);
80	      z = sizeof(int);
81	    }
82	  else
83	    {
84	      z = (*p_arg)->size;
85	      if (z < sizeof(int))
86		{
87		  z = sizeof(int);
88		  switch ((*p_arg)->type)
89		    {
90		    case FFI_TYPE_SINT8:
91		      *(signed int *) argp = *(SINT8 *)(* p_argv);
92		      break;
93
94		    case FFI_TYPE_UINT8:
95		      *(unsigned int *) argp = *(UINT8 *)(* p_argv);
96		      break;
97
98		    case FFI_TYPE_SINT16:
99		      *(signed int *) argp = *(SINT16 *)(* p_argv);
100		      break;
101
102		    case FFI_TYPE_UINT16:
103		      *(unsigned int *) argp = *(UINT16 *)(* p_argv);
104		      break;
105
106		    default:
107		      FFI_ASSERT(0);
108		    }
109		}
110	      else
111		{
112		  memcpy(argp, *p_argv, z);
113		}
114	    }
115	  p_argv++;
116	  argp += z;
117    }
118
119  return;
120}
121
122int ffi_prep_args_v9(char *stack, extended_cif *ecif)
123{
124  int i, ret = 0;
125  int tmp;
126  void **p_argv;
127  char *argp;
128  ffi_type **p_arg;
129
130  tmp = 0;
131
132  /* Skip 16 words for the window save area */
133  argp = stack + 16*sizeof(long long);
134
135#ifdef USING_PURIFY
136  /* Purify will probably complain in our assembly routine, unless we
137     zero out this memory. */
138
139  ((long long*)argp)[0] = 0;
140  ((long long*)argp)[1] = 0;
141  ((long long*)argp)[2] = 0;
142  ((long long*)argp)[3] = 0;
143  ((long long*)argp)[4] = 0;
144  ((long long*)argp)[5] = 0;
145#endif
146
147  p_argv = ecif->avalue;
148
149  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
150      ecif->cif->rtype->size > 32)
151    {
152      *(unsigned long long *) argp = (unsigned long)ecif->rvalue;
153      argp += sizeof(long long);
154      tmp = 1;
155    }
156
157  for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
158       i++, p_arg++)
159    {
160      size_t z;
161
162      z = (*p_arg)->size;
163      switch ((*p_arg)->type)
164	{
165	case FFI_TYPE_STRUCT:
166	  if (z > 16)
167	    {
168	      /* For structures larger than 16 bytes we pass reference.  */
169	      *(unsigned long long *) argp = (unsigned long)* p_argv;
170	      argp += sizeof(long long);
171	      tmp++;
172	      p_argv++;
173	      continue;
174	    }
175	  /* FALLTHROUGH */
176	case FFI_TYPE_FLOAT:
177	case FFI_TYPE_DOUBLE:
178#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
179	case FFI_TYPE_LONGDOUBLE:
180#endif
181	  ret = 1; /* We should promote into FP regs as well as integer.  */
182	  break;
183	}
184      if (z < sizeof(long long))
185	{
186	  switch ((*p_arg)->type)
187	    {
188	    case FFI_TYPE_SINT8:
189	      *(signed long long *) argp = *(SINT8 *)(* p_argv);
190	      break;
191
192	    case FFI_TYPE_UINT8:
193	      *(unsigned long long *) argp = *(UINT8 *)(* p_argv);
194	      break;
195
196	    case FFI_TYPE_SINT16:
197	      *(signed long long *) argp = *(SINT16 *)(* p_argv);
198	      break;
199
200	    case FFI_TYPE_UINT16:
201	      *(unsigned long long *) argp = *(UINT16 *)(* p_argv);
202	      break;
203
204	    case FFI_TYPE_SINT32:
205	      *(signed long long *) argp = *(SINT32 *)(* p_argv);
206	      break;
207
208	    case FFI_TYPE_UINT32:
209	      *(unsigned long long *) argp = *(UINT32 *)(* p_argv);
210	      break;
211
212	    case FFI_TYPE_FLOAT:
213	      *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
214	      break;
215
216	    case FFI_TYPE_STRUCT:
217	      memcpy(argp, *p_argv, z);
218	      break;
219
220	    default:
221	      FFI_ASSERT(0);
222	    }
223	  z = sizeof(long long);
224	  tmp++;
225	}
226      else if (z == sizeof(long long))
227	{
228	  memcpy(argp, *p_argv, z);
229	  z = sizeof(long long);
230	  tmp++;
231	}
232      else
233	{
234	  if ((tmp & 1) && (*p_arg)->alignment > 8)
235	    {
236	      tmp++;
237	      argp += sizeof(long long);
238	    }
239	  memcpy(argp, *p_argv, z);
240	  z = 2 * sizeof(long long);
241	  tmp += 2;
242	}
243      p_argv++;
244      argp += z;
245    }
246
247  return ret;
248}
249
250/* Perform machine dependent cif processing */
251ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
252{
253  int wordsize;
254
255  if (cif->abi != FFI_V9)
256    {
257      wordsize = 4;
258
259      /* If we are returning a struct, this will already have been added.
260	 Otherwise we need to add it because it's always got to be there! */
261
262      if (cif->rtype->type != FFI_TYPE_STRUCT)
263	cif->bytes += wordsize;
264
265      /* sparc call frames require that space is allocated for 6 args,
266	 even if they aren't used. Make that space if necessary. */
267
268      if (cif->bytes < 4*6+4)
269	cif->bytes = 4*6+4;
270    }
271  else
272    {
273      wordsize = 8;
274
275      /* sparc call frames require that space is allocated for 6 args,
276	 even if they aren't used. Make that space if necessary. */
277
278      if (cif->bytes < 8*6)
279	cif->bytes = 8*6;
280    }
281
282  /* Adjust cif->bytes. to include 16 words for the window save area,
283     and maybe the struct/union return pointer area, */
284
285  cif->bytes += 16 * wordsize;
286
287  /* The stack must be 2 word aligned, so round bytes up
288     appropriately. */
289
290  cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
291
292  /* Set the return type flag */
293  switch (cif->rtype->type)
294    {
295    case FFI_TYPE_VOID:
296    case FFI_TYPE_FLOAT:
297    case FFI_TYPE_DOUBLE:
298#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
299    case FFI_TYPE_LONGDOUBLE:
300#endif
301      cif->flags = cif->rtype->type;
302      break;
303
304    case FFI_TYPE_STRUCT:
305      if (cif->abi == FFI_V9 && cif->rtype->size > 32)
306	cif->flags = FFI_TYPE_VOID;
307      else
308	cif->flags = FFI_TYPE_STRUCT;
309      break;
310
311    case FFI_TYPE_SINT8:
312    case FFI_TYPE_UINT8:
313    case FFI_TYPE_SINT16:
314    case FFI_TYPE_UINT16:
315      if (cif->abi == FFI_V9)
316	cif->flags = FFI_TYPE_INT;
317      else
318	cif->flags = cif->rtype->type;
319      break;
320
321    case FFI_TYPE_SINT64:
322    case FFI_TYPE_UINT64:
323      if (cif->abi == FFI_V9)
324	cif->flags = FFI_TYPE_INT;
325      else
326	cif->flags = FFI_TYPE_SINT64;
327      break;
328
329    default:
330      cif->flags = FFI_TYPE_INT;
331      break;
332    }
333  return FFI_OK;
334}
335
336int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
337{
338  ffi_type **ptr = &arg->elements[0];
339
340  while (*ptr != NULL)
341    {
342      if (off & ((*ptr)->alignment - 1))
343	off = ALIGN(off, (*ptr)->alignment);
344
345      switch ((*ptr)->type)
346	{
347	case FFI_TYPE_STRUCT:
348	  off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt);
349	  off = ALIGN(off, FFI_SIZEOF_ARG);
350	  break;
351	case FFI_TYPE_FLOAT:
352	case FFI_TYPE_DOUBLE:
353#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
354	case FFI_TYPE_LONGDOUBLE:
355#endif
356	  memmove(ret + off, flt + off, (*ptr)->size);
357	  off += (*ptr)->size;
358	  break;
359	default:
360	  memmove(ret + off, intg + off, (*ptr)->size);
361	  off += (*ptr)->size;
362	  break;
363	}
364      ptr++;
365    }
366  return off;
367}
368
369
370#ifdef SPARC64
371extern int ffi_call_v9(void *, extended_cif *, unsigned,
372		       unsigned, unsigned *, void (*fn)(void));
373#else
374extern int ffi_call_v8(void *, extended_cif *, unsigned,
375		       unsigned, unsigned *, void (*fn)(void));
376#endif
377
378void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
379{
380  extended_cif ecif;
381  void *rval = rvalue;
382
383  ecif.cif = cif;
384  ecif.avalue = avalue;
385
386  /* If the return value is a struct and we don't have a return	*/
387  /* value address then we need to make one		        */
388
389  ecif.rvalue = rvalue;
390  if (cif->rtype->type == FFI_TYPE_STRUCT)
391    {
392      if (cif->rtype->size <= 32)
393	rval = alloca(64);
394      else
395	{
396	  rval = NULL;
397	  if (rvalue == NULL)
398	    ecif.rvalue = alloca(cif->rtype->size);
399	}
400    }
401
402  switch (cif->abi)
403    {
404    case FFI_V8:
405#ifdef SPARC64
406      /* We don't yet support calling 32bit code from 64bit */
407      FFI_ASSERT(0);
408#else
409      ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
410		  cif->flags, rvalue, fn);
411#endif
412      break;
413    case FFI_V9:
414#ifdef SPARC64
415      ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes,
416		  cif->flags, rval, fn);
417      if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
418	ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
419#else
420      /* And vice versa */
421      FFI_ASSERT(0);
422#endif
423      break;
424    default:
425      FFI_ASSERT(0);
426      break;
427    }
428
429}
430
431
432#ifdef SPARC64
433extern void ffi_closure_v9(void);
434#else
435extern void ffi_closure_v8(void);
436#endif
437
438ffi_status
439ffi_prep_closure_loc (ffi_closure* closure,
440		      ffi_cif* cif,
441		      void (*fun)(ffi_cif*, void*, void**, void*),
442		      void *user_data,
443		      void *codeloc)
444{
445  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
446  unsigned long fn;
447#ifdef SPARC64
448  /* Trampoline address is equal to the closure address.  We take advantage
449     of that to reduce the trampoline size by 8 bytes. */
450  FFI_ASSERT (cif->abi == FFI_V9);
451  fn = (unsigned long) ffi_closure_v9;
452  tramp[0] = 0x83414000;	/* rd	%pc, %g1	*/
453  tramp[1] = 0xca586010;	/* ldx	[%g1+16], %g5	*/
454  tramp[2] = 0x81c14000;	/* jmp	%g5		*/
455  tramp[3] = 0x01000000;	/* nop			*/
456  *((unsigned long *) &tramp[4]) = fn;
457#else
458  unsigned long ctx = (unsigned long) codeloc;
459  FFI_ASSERT (cif->abi == FFI_V8);
460  fn = (unsigned long) ffi_closure_v8;
461  tramp[0] = 0x03000000 | fn >> 10;	/* sethi %hi(fn), %g1	*/
462  tramp[1] = 0x05000000 | ctx >> 10;	/* sethi %hi(ctx), %g2	*/
463  tramp[2] = 0x81c06000 | (fn & 0x3ff);	/* jmp   %g1+%lo(fn)	*/
464  tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or    %g2, %lo(ctx)	*/
465#endif
466
467  closure->cif = cif;
468  closure->fun = fun;
469  closure->user_data = user_data;
470
471  /* Flush the Icache.  FIXME: alignment isn't certain, assume 8 bytes */
472#ifdef SPARC64
473  asm volatile ("flush	%0" : : "r" (closure) : "memory");
474  asm volatile ("flush	%0" : : "r" (((char *) closure) + 8) : "memory");
475#else
476  asm volatile ("iflush	%0" : : "r" (closure) : "memory");
477  asm volatile ("iflush	%0" : : "r" (((char *) closure) + 8) : "memory");
478#endif
479
480  return FFI_OK;
481}
482
483int
484ffi_closure_sparc_inner_v8(ffi_closure *closure,
485  void *rvalue, unsigned long *gpr, unsigned long *scratch)
486{
487  ffi_cif *cif;
488  ffi_type **arg_types;
489  void **avalue;
490  int i, argn;
491
492  cif = closure->cif;
493  arg_types = cif->arg_types;
494  avalue = alloca(cif->nargs * sizeof(void *));
495
496  /* Copy the caller's structure return address so that the closure
497     returns the data directly to the caller.  */
498  if (cif->flags == FFI_TYPE_STRUCT
499#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
500      || cif->flags == FFI_TYPE_LONGDOUBLE
501#endif
502     )
503    rvalue = (void *) gpr[0];
504
505  /* Always skip the structure return address.  */
506  argn = 1;
507
508  /* Grab the addresses of the arguments from the stack frame.  */
509  for (i = 0; i < cif->nargs; i++)
510    {
511      if (arg_types[i]->type == FFI_TYPE_STRUCT
512#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
513	  || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
514#endif
515         )
516	{
517	  /* Straight copy of invisible reference.  */
518	  avalue[i] = (void *)gpr[argn++];
519	}
520      else if ((arg_types[i]->type == FFI_TYPE_DOUBLE
521	       || arg_types[i]->type == FFI_TYPE_SINT64
522	       || arg_types[i]->type == FFI_TYPE_UINT64)
523	       /* gpr is 8-byte aligned.  */
524	       && (argn % 2) != 0)
525	{
526	  /* Align on a 8-byte boundary.  */
527	  scratch[0] = gpr[argn];
528	  scratch[1] = gpr[argn+1];
529	  avalue[i] = scratch;
530	  scratch -= 2;
531	  argn += 2;
532	}
533      else
534	{
535	  /* Always right-justify.  */
536	  argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
537	  avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
538	}
539    }
540
541  /* Invoke the closure.  */
542  (closure->fun) (cif, rvalue, avalue, closure->user_data);
543
544  /* Tell ffi_closure_sparc how to perform return type promotions.  */
545  return cif->rtype->type;
546}
547
548int
549ffi_closure_sparc_inner_v9(ffi_closure *closure,
550  void *rvalue, unsigned long *gpr, double *fpr)
551{
552  ffi_cif *cif;
553  ffi_type **arg_types;
554  void **avalue;
555  int i, argn, fp_slot_max;
556
557  cif = closure->cif;
558  arg_types = cif->arg_types;
559  avalue = alloca(cif->nargs * sizeof(void *));
560
561  /* Copy the caller's structure return address so that the closure
562     returns the data directly to the caller.  */
563  if (cif->flags == FFI_TYPE_VOID
564      && cif->rtype->type == FFI_TYPE_STRUCT)
565    {
566      rvalue = (void *) gpr[0];
567      /* Skip the structure return address.  */
568      argn = 1;
569    }
570  else
571    argn = 0;
572
573  fp_slot_max = 16 - argn;
574
575  /* Grab the addresses of the arguments from the stack frame.  */
576  for (i = 0; i < cif->nargs; i++)
577    {
578      if (arg_types[i]->type == FFI_TYPE_STRUCT)
579	{
580	  if (arg_types[i]->size > 16)
581	    {
582	      /* Straight copy of invisible reference.  */
583	      avalue[i] = (void *)gpr[argn++];
584	    }
585	  else
586	    {
587	      /* Left-justify.  */
588	      ffi_v9_layout_struct(arg_types[i],
589				   0,
590				   (char *) &gpr[argn],
591				   (char *) &gpr[argn],
592				   (char *) &fpr[argn]);
593	      avalue[i] = &gpr[argn];
594	      argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
595	    }
596	}
597      else
598	{
599	  /* Right-justify.  */
600	  argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
601
602	  /* Align on a 16-byte boundary.  */
603#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
604	  if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0)
605	    argn++;
606#endif
607	  if (i < fp_slot_max
608	      && (arg_types[i]->type == FFI_TYPE_FLOAT
609		  || arg_types[i]->type == FFI_TYPE_DOUBLE
610#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
611		  || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
612#endif
613		  ))
614	    avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
615	  else
616	    avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
617	}
618    }
619
620  /* Invoke the closure.  */
621  (closure->fun) (cif, rvalue, avalue, closure->user_data);
622
623  /* Tell ffi_closure_sparc how to perform return type promotions.  */
624  return cif->rtype->type;
625}
626