1/* -----------------------------------------------------------------------
2   ffi.c - Copyright (c) 2002-2008, 2012 Kaz Kojima
3           Copyright (c) 2008 Red Hat, Inc.
4
5   SuperH 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
31#include <stdlib.h>
32
33#define NGREGARG 4
34#if defined(__SH4__)
35#define NFREGARG 8
36#endif
37
38#if defined(__HITACHI__)
39#define STRUCT_VALUE_ADDRESS_WITH_ARG 1
40#else
41#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
42#endif
43
44/* If the structure has essentially an unique element, return its type.  */
45static int
46simple_type (ffi_type *arg)
47{
48  if (arg->type != FFI_TYPE_STRUCT)
49    return arg->type;
50  else if (arg->elements[1])
51    return FFI_TYPE_STRUCT;
52
53  return simple_type (arg->elements[0]);
54}
55
56static int
57return_type (ffi_type *arg)
58{
59  unsigned short type;
60
61  if (arg->type != FFI_TYPE_STRUCT)
62    return arg->type;
63
64  type = simple_type (arg->elements[0]);
65  if (! arg->elements[1])
66    {
67      switch (type)
68	{
69	case FFI_TYPE_SINT8:
70	case FFI_TYPE_UINT8:
71	case FFI_TYPE_SINT16:
72	case FFI_TYPE_UINT16:
73	case FFI_TYPE_SINT32:
74	case FFI_TYPE_UINT32:
75	  return FFI_TYPE_INT;
76
77	default:
78	  return type;
79	}
80    }
81
82  /* gcc uses r0/r1 pair for some kind of structures.  */
83  if (arg->size <= 2 * sizeof (int))
84    {
85      int i = 0;
86      ffi_type *e;
87
88      while ((e = arg->elements[i++]))
89	{
90	  type = simple_type (e);
91	  switch (type)
92	    {
93	    case FFI_TYPE_SINT32:
94	    case FFI_TYPE_UINT32:
95	    case FFI_TYPE_INT:
96	    case FFI_TYPE_FLOAT:
97	      return FFI_TYPE_UINT64;
98
99	    default:
100	      break;
101	    }
102	}
103    }
104
105  return FFI_TYPE_STRUCT;
106}
107
108/* ffi_prep_args is called by the assembly routine once stack space
109   has been allocated for the function's arguments */
110
111void ffi_prep_args(char *stack, extended_cif *ecif)
112{
113  register unsigned int i;
114  register int tmp;
115  register unsigned int avn;
116  register void **p_argv;
117  register char *argp;
118  register ffi_type **p_arg;
119  int greg, ireg;
120#if defined(__SH4__)
121  int freg = 0;
122#endif
123
124  tmp = 0;
125  argp = stack;
126
127  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
128    {
129      *(void **) argp = ecif->rvalue;
130      argp += 4;
131      ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
132    }
133  else
134    ireg = 0;
135
136  /* Set arguments for registers.  */
137  greg = ireg;
138  avn = ecif->cif->nargs;
139  p_argv = ecif->avalue;
140
141  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
142    {
143      size_t z;
144
145      z = (*p_arg)->size;
146      if (z < sizeof(int))
147	{
148	  if (greg++ >= NGREGARG)
149	    continue;
150
151	  z = sizeof(int);
152	  switch ((*p_arg)->type)
153	    {
154	    case FFI_TYPE_SINT8:
155	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
156	      break;
157
158	    case FFI_TYPE_UINT8:
159	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
160	      break;
161
162	    case FFI_TYPE_SINT16:
163	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
164	      break;
165
166	    case FFI_TYPE_UINT16:
167	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
168	      break;
169
170	    case FFI_TYPE_STRUCT:
171	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
172	      break;
173
174	    default:
175	      FFI_ASSERT(0);
176	    }
177	  argp += z;
178	}
179      else if (z == sizeof(int))
180	{
181#if defined(__SH4__)
182	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
183	    {
184	      if (freg++ >= NFREGARG)
185		continue;
186	    }
187	  else
188#endif
189	    {
190	      if (greg++ >= NGREGARG)
191		continue;
192	    }
193	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
194	  argp += z;
195	}
196#if defined(__SH4__)
197      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
198	{
199	  if (freg + 1 >= NFREGARG)
200	    continue;
201	  freg = (freg + 1) & ~1;
202	  freg += 2;
203	  memcpy (argp, *p_argv, z);
204	  argp += z;
205	}
206#endif
207      else
208	{
209	  int n = (z + sizeof (int) - 1) / sizeof (int);
210#if defined(__SH4__)
211	  if (greg + n - 1 >= NGREGARG)
212	    continue;
213#else
214	  if (greg >= NGREGARG)
215	    continue;
216#endif
217	  greg += n;
218	  memcpy (argp, *p_argv, z);
219	  argp += n * sizeof (int);
220	}
221    }
222
223  /* Set arguments on stack.  */
224  greg = ireg;
225#if defined(__SH4__)
226  freg = 0;
227#endif
228  p_argv = ecif->avalue;
229
230  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
231    {
232      size_t z;
233
234      z = (*p_arg)->size;
235      if (z < sizeof(int))
236	{
237	  if (greg++ < NGREGARG)
238	    continue;
239
240	  z = sizeof(int);
241	  switch ((*p_arg)->type)
242	    {
243	    case FFI_TYPE_SINT8:
244	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
245	      break;
246
247	    case FFI_TYPE_UINT8:
248	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
249	      break;
250
251	    case FFI_TYPE_SINT16:
252	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
253	      break;
254
255	    case FFI_TYPE_UINT16:
256	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
257	      break;
258
259	    case FFI_TYPE_STRUCT:
260	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
261	      break;
262
263	    default:
264	      FFI_ASSERT(0);
265	    }
266	  argp += z;
267	}
268      else if (z == sizeof(int))
269	{
270#if defined(__SH4__)
271	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
272	    {
273	      if (freg++ < NFREGARG)
274		continue;
275	    }
276	  else
277#endif
278	    {
279	      if (greg++ < NGREGARG)
280		continue;
281	    }
282	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
283	  argp += z;
284	}
285#if defined(__SH4__)
286      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
287	{
288	  if (freg + 1 < NFREGARG)
289	    {
290	      freg = (freg + 1) & ~1;
291	      freg += 2;
292	      continue;
293	    }
294	  memcpy (argp, *p_argv, z);
295	  argp += z;
296	}
297#endif
298      else
299	{
300	  int n = (z + sizeof (int) - 1) / sizeof (int);
301	  if (greg + n - 1 < NGREGARG)
302	    {
303	      greg += n;
304	      continue;
305	    }
306#if (! defined(__SH4__))
307	  else if (greg < NGREGARG)
308	    {
309	      greg = NGREGARG;
310	      continue;
311	    }
312#endif
313	  memcpy (argp, *p_argv, z);
314	  argp += n * sizeof (int);
315	}
316    }
317
318  return;
319}
320
321/* Perform machine dependent cif processing */
322ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
323{
324  int i, j;
325  int size, type;
326  int n, m;
327  int greg;
328#if defined(__SH4__)
329  int freg = 0;
330#endif
331
332  cif->flags = 0;
333
334  greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
335	  STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
336
337#if defined(__SH4__)
338  for (i = j = 0; i < cif->nargs && j < 12; i++)
339    {
340      type = (cif->arg_types)[i]->type;
341      switch (type)
342	{
343	case FFI_TYPE_FLOAT:
344	  if (freg >= NFREGARG)
345	    continue;
346	  freg++;
347	  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
348	  j++;
349	  break;
350
351	case FFI_TYPE_DOUBLE:
352	  if ((freg + 1) >= NFREGARG)
353	    continue;
354	  freg = (freg + 1) & ~1;
355	  freg += 2;
356	  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
357	  j++;
358	  break;
359
360	default:
361	  size = (cif->arg_types)[i]->size;
362	  n = (size + sizeof (int) - 1) / sizeof (int);
363	  if (greg + n - 1 >= NGREGARG)
364		continue;
365	  greg += n;
366	  for (m = 0; m < n; m++)
367	    cif->flags += FFI_TYPE_INT << (2 * j++);
368	  break;
369	}
370    }
371#else
372  for (i = j = 0; i < cif->nargs && j < 4; i++)
373    {
374      size = (cif->arg_types)[i]->size;
375      n = (size + sizeof (int) - 1) / sizeof (int);
376      if (greg >= NGREGARG)
377	continue;
378      else if (greg + n - 1 >= NGREGARG)
379	n = NGREGARG - greg;
380      greg += n;
381      for (m = 0; m < n; m++)
382        cif->flags += FFI_TYPE_INT << (2 * j++);
383    }
384#endif
385
386  /* Set the return type flag */
387  switch (cif->rtype->type)
388    {
389    case FFI_TYPE_STRUCT:
390      cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
391      break;
392
393    case FFI_TYPE_VOID:
394    case FFI_TYPE_FLOAT:
395    case FFI_TYPE_DOUBLE:
396    case FFI_TYPE_SINT64:
397    case FFI_TYPE_UINT64:
398      cif->flags += (unsigned) cif->rtype->type << 24;
399      break;
400
401    default:
402      cif->flags += FFI_TYPE_INT << 24;
403      break;
404    }
405
406  return FFI_OK;
407}
408
409extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
410			  unsigned, unsigned, unsigned *, void (*fn)(void));
411
412void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
413{
414  extended_cif ecif;
415  UINT64 trvalue;
416
417  ecif.cif = cif;
418  ecif.avalue = avalue;
419
420  /* If the return value is a struct and we don't have a return	*/
421  /* value address then we need to make one		        */
422
423  if (cif->rtype->type == FFI_TYPE_STRUCT
424      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
425    ecif.rvalue = &trvalue;
426  else if ((rvalue == NULL) &&
427      (cif->rtype->type == FFI_TYPE_STRUCT))
428    {
429      ecif.rvalue = alloca(cif->rtype->size);
430    }
431  else
432    ecif.rvalue = rvalue;
433
434  switch (cif->abi)
435    {
436    case FFI_SYSV:
437      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
438		    fn);
439      break;
440    default:
441      FFI_ASSERT(0);
442      break;
443    }
444
445  if (rvalue
446      && cif->rtype->type == FFI_TYPE_STRUCT
447      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
448    memcpy (rvalue, &trvalue, cif->rtype->size);
449}
450
451extern void ffi_closure_SYSV (void);
452#if defined(__SH4__)
453extern void __ic_invalidate (void *line);
454#endif
455
456ffi_status
457ffi_prep_closure_loc (ffi_closure* closure,
458		      ffi_cif* cif,
459		      void (*fun)(ffi_cif*, void*, void**, void*),
460		      void *user_data,
461		      void *codeloc)
462{
463  unsigned int *tramp;
464  unsigned int insn;
465
466  if (cif->abi != FFI_SYSV)
467    return FFI_BAD_ABI;
468
469  tramp = (unsigned int *) &closure->tramp[0];
470  /* Set T bit if the function returns a struct pointed with R2.  */
471  insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
472	  ? 0x0018 /* sett */
473	  : 0x0008 /* clrt */);
474
475#ifdef __LITTLE_ENDIAN__
476  tramp[0] = 0xd301d102;
477  tramp[1] = 0x0000412b | (insn << 16);
478#else
479  tramp[0] = 0xd102d301;
480  tramp[1] = 0x412b0000 | insn;
481#endif
482  *(void **) &tramp[2] = (void *)codeloc;          /* ctx */
483  *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
484
485  closure->cif = cif;
486  closure->fun = fun;
487  closure->user_data = user_data;
488
489#if defined(__SH4__)
490  /* Flush the icache.  */
491  __ic_invalidate(codeloc);
492#endif
493
494  return FFI_OK;
495}
496
497/* Basically the trampoline invokes ffi_closure_SYSV, and on
498 * entry, r3 holds the address of the closure.
499 * After storing the registers that could possibly contain
500 * parameters to be passed into the stack frame and setting
501 * up space for a return value, ffi_closure_SYSV invokes the
502 * following helper function to do most of the work.
503 */
504
505#ifdef __LITTLE_ENDIAN__
506#define OFS_INT8	0
507#define OFS_INT16	0
508#else
509#define OFS_INT8	3
510#define OFS_INT16	2
511#endif
512
513int
514ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
515			 unsigned long *pgr, unsigned long *pfr,
516			 unsigned long *pst)
517{
518  void **avalue;
519  ffi_type **p_arg;
520  int i, avn;
521  int ireg, greg = 0;
522#if defined(__SH4__)
523  int freg = 0;
524#endif
525  ffi_cif *cif;
526
527  cif = closure->cif;
528  avalue = alloca(cif->nargs * sizeof(void *));
529
530  /* Copy the caller's structure return value address so that the closure
531     returns the data directly to the caller.  */
532  if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
533    {
534      rvalue = (void *) *pgr++;
535      ireg = 1;
536    }
537  else
538    ireg = 0;
539
540  cif = closure->cif;
541  greg = ireg;
542  avn = cif->nargs;
543
544  /* Grab the addresses of the arguments from the stack frame.  */
545  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
546    {
547      size_t z;
548
549      z = (*p_arg)->size;
550      if (z < sizeof(int))
551	{
552	  if (greg++ >= NGREGARG)
553	    continue;
554
555	  z = sizeof(int);
556	  switch ((*p_arg)->type)
557	    {
558	    case FFI_TYPE_SINT8:
559	    case FFI_TYPE_UINT8:
560	      avalue[i] = (((char *)pgr) + OFS_INT8);
561	      break;
562
563	    case FFI_TYPE_SINT16:
564	    case FFI_TYPE_UINT16:
565	      avalue[i] = (((char *)pgr) + OFS_INT16);
566	      break;
567
568	    case FFI_TYPE_STRUCT:
569	      avalue[i] = pgr;
570	      break;
571
572	    default:
573	      FFI_ASSERT(0);
574	    }
575	  pgr++;
576	}
577      else if (z == sizeof(int))
578	{
579#if defined(__SH4__)
580	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
581	    {
582	      if (freg++ >= NFREGARG)
583		continue;
584	      avalue[i] = pfr;
585	      pfr++;
586	    }
587	  else
588#endif
589	    {
590	      if (greg++ >= NGREGARG)
591		continue;
592	      avalue[i] = pgr;
593	      pgr++;
594	    }
595	}
596#if defined(__SH4__)
597      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
598	{
599	  if (freg + 1 >= NFREGARG)
600	    continue;
601	  if (freg & 1)
602	    pfr++;
603	  freg = (freg + 1) & ~1;
604	  freg += 2;
605	  avalue[i] = pfr;
606	  pfr += 2;
607	}
608#endif
609      else
610	{
611	  int n = (z + sizeof (int) - 1) / sizeof (int);
612#if defined(__SH4__)
613	  if (greg + n - 1 >= NGREGARG)
614	    continue;
615#else
616	  if (greg >= NGREGARG)
617	    continue;
618#endif
619	  greg += n;
620	  avalue[i] = pgr;
621	  pgr += n;
622	}
623    }
624
625  greg = ireg;
626#if defined(__SH4__)
627  freg = 0;
628#endif
629
630  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
631    {
632      size_t z;
633
634      z = (*p_arg)->size;
635      if (z < sizeof(int))
636	{
637	  if (greg++ < NGREGARG)
638	    continue;
639
640	  z = sizeof(int);
641	  switch ((*p_arg)->type)
642	    {
643	    case FFI_TYPE_SINT8:
644	    case FFI_TYPE_UINT8:
645	      avalue[i] = (((char *)pst) + OFS_INT8);
646	      break;
647
648	    case FFI_TYPE_SINT16:
649	    case FFI_TYPE_UINT16:
650	      avalue[i] = (((char *)pst) + OFS_INT16);
651	      break;
652
653	    case FFI_TYPE_STRUCT:
654	      avalue[i] = pst;
655	      break;
656
657	    default:
658	      FFI_ASSERT(0);
659	    }
660	  pst++;
661	}
662      else if (z == sizeof(int))
663	{
664#if defined(__SH4__)
665	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
666	    {
667	      if (freg++ < NFREGARG)
668		continue;
669	    }
670	  else
671#endif
672	    {
673	      if (greg++ < NGREGARG)
674		continue;
675	    }
676	  avalue[i] = pst;
677	  pst++;
678	}
679#if defined(__SH4__)
680      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
681	{
682	  if (freg + 1 < NFREGARG)
683	    {
684	      freg = (freg + 1) & ~1;
685	      freg += 2;
686	      continue;
687	    }
688	  avalue[i] = pst;
689	  pst += 2;
690	}
691#endif
692      else
693	{
694	  int n = (z + sizeof (int) - 1) / sizeof (int);
695	  if (greg + n - 1 < NGREGARG)
696	    {
697	      greg += n;
698	      continue;
699	    }
700#if (! defined(__SH4__))
701	  else if (greg < NGREGARG)
702	    {
703	      greg += n;
704	      pst += greg - NGREGARG;
705	      continue;
706	    }
707#endif
708	  avalue[i] = pst;
709	  pst += n;
710	}
711    }
712
713  (closure->fun) (cif, rvalue, avalue, closure->user_data);
714
715  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
716  return return_type (cif->rtype);
717}
718