1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 2000, 2007 Software AG
3            Copyright (c) 2008 Red Hat, Inc
4 
5    S390 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, EXPRESS
19    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
22    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24    OTHER DEALINGS IN THE SOFTWARE.
25    ----------------------------------------------------------------------- */
26 /*====================================================================*/
27 /*                          Includes                                  */
28 /*                          --------                                  */
29 /*====================================================================*/
30 
31 #include <ffi.h>
32 #include <ffi_common.h>
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 
37 /*====================== End of Includes =============================*/
38 
39 /*====================================================================*/
40 /*                           Defines                                  */
41 /*                           -------                                  */
42 /*====================================================================*/
43 
44 /* Maximum number of GPRs available for argument passing.  */
45 #define MAX_GPRARGS 5
46 
47 /* Maximum number of FPRs available for argument passing.  */
48 #ifdef __s390x__
49 #define MAX_FPRARGS 4
50 #else
51 #define MAX_FPRARGS 2
52 #endif
53 
54 /* Round to multiple of 16.  */
55 #define ROUND_SIZE(size) (((size) + 15) & ~15)
56 
57 /* If these values change, sysv.S must be adapted!  */
58 #define FFI390_RET_VOID		0
59 #define FFI390_RET_STRUCT	1
60 #define FFI390_RET_FLOAT	2
61 #define FFI390_RET_DOUBLE	3
62 #define FFI390_RET_INT32	4
63 #define FFI390_RET_INT64	5
64 
65 /*===================== End of Defines ===============================*/
66 
67 /*====================================================================*/
68 /*                          Prototypes                                */
69 /*                          ----------                                */
70 /*====================================================================*/
71 
72 static void ffi_prep_args (unsigned char *, extended_cif *);
73 void
74 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
75 __attribute__ ((visibility ("hidden")))
76 #endif
77 ffi_closure_helper_SYSV (ffi_closure *, unsigned long *,
78 			 unsigned long long *, unsigned long *);
79 
80 /*====================== End of Prototypes ===========================*/
81 
82 /*====================================================================*/
83 /*                          Externals                                 */
84 /*                          ---------                                 */
85 /*====================================================================*/
86 
87 extern void ffi_call_SYSV(unsigned,
88 			  extended_cif *,
89 			  void (*)(unsigned char *, extended_cif *),
90 			  unsigned,
91 			  void *,
92 			  void (*fn)(void));
93 
94 extern void ffi_closure_SYSV(void);
95 
96 /*====================== End of Externals ============================*/
97 
98 /*====================================================================*/
99 /*                                                                    */
100 /* Name     - ffi_check_struct_type.                                  */
101 /*                                                                    */
102 /* Function - Determine if a structure can be passed within a         */
103 /*            general purpose or floating point register.             */
104 /*                                                                    */
105 /*====================================================================*/
106 
107 static int
ffi_check_struct_type(ffi_type * arg)108 ffi_check_struct_type (ffi_type *arg)
109 {
110   size_t size = arg->size;
111 
112   /* If the struct has just one element, look at that element
113      to find out whether to consider the struct as floating point.  */
114   while (arg->type == FFI_TYPE_STRUCT
115          && arg->elements[0] && !arg->elements[1])
116     arg = arg->elements[0];
117 
118   /* Structs of size 1, 2, 4, and 8 are passed in registers,
119      just like the corresponding int/float types.  */
120   switch (size)
121     {
122       case 1:
123         return FFI_TYPE_UINT8;
124 
125       case 2:
126         return FFI_TYPE_UINT16;
127 
128       case 4:
129 	if (arg->type == FFI_TYPE_FLOAT)
130           return FFI_TYPE_FLOAT;
131 	else
132 	  return FFI_TYPE_UINT32;
133 
134       case 8:
135 	if (arg->type == FFI_TYPE_DOUBLE)
136           return FFI_TYPE_DOUBLE;
137 	else
138 	  return FFI_TYPE_UINT64;
139 
140       default:
141 	break;
142     }
143 
144   /* Other structs are passed via a pointer to the data.  */
145   return FFI_TYPE_POINTER;
146 }
147 
148 /*======================== End of Routine ============================*/
149 
150 /*====================================================================*/
151 /*                                                                    */
152 /* Name     - ffi_prep_args.                                          */
153 /*                                                                    */
154 /* Function - Prepare parameters for call to function.                */
155 /*                                                                    */
156 /* ffi_prep_args is called by the assembly routine once stack space   */
157 /* has been allocated for the function's arguments.                   */
158 /*                                                                    */
159 /*====================================================================*/
160 
161 static void
ffi_prep_args(unsigned char * stack,extended_cif * ecif)162 ffi_prep_args (unsigned char *stack, extended_cif *ecif)
163 {
164   /* The stack space will be filled with those areas:
165 
166 	FPR argument register save area     (highest addresses)
167 	GPR argument register save area
168 	temporary struct copies
169 	overflow argument area              (lowest addresses)
170 
171      We set up the following pointers:
172 
173         p_fpr: bottom of the FPR area (growing upwards)
174 	p_gpr: bottom of the GPR area (growing upwards)
175 	p_ov: bottom of the overflow area (growing upwards)
176 	p_struct: top of the struct copy area (growing downwards)
177 
178      All areas are kept aligned to twice the word size.  */
179 
180   int gpr_off = ecif->cif->bytes;
181   int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long));
182 
183   unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off);
184   unsigned long *p_gpr = (unsigned long *)(stack + gpr_off);
185   unsigned char *p_struct = (unsigned char *)p_gpr;
186   unsigned long *p_ov = (unsigned long *)stack;
187 
188   int n_fpr = 0;
189   int n_gpr = 0;
190   int n_ov = 0;
191 
192   ffi_type **ptr;
193   void **p_argv = ecif->avalue;
194   int i;
195 
196   /* If we returning a structure then we set the first parameter register
197      to the address of where we are returning this structure.  */
198 
199   if (ecif->cif->flags == FFI390_RET_STRUCT)
200     p_gpr[n_gpr++] = (unsigned long) ecif->rvalue;
201 
202   /* Now for the arguments.  */
203 
204   for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
205        i > 0;
206        i--, ptr++, p_argv++)
207     {
208       void *arg = *p_argv;
209       int type = (*ptr)->type;
210 
211 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
212       /* 16-byte long double is passed like a struct.  */
213       if (type == FFI_TYPE_LONGDOUBLE)
214 	type = FFI_TYPE_STRUCT;
215 #endif
216 
217       /* Check how a structure type is passed.  */
218       if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
219 	{
220 	  if (type == FFI_TYPE_COMPLEX)
221 	    type = FFI_TYPE_POINTER;
222 	  else
223 	    type = ffi_check_struct_type (*ptr);
224 
225 	  /* If we pass the struct via pointer, copy the data.  */
226 	  if (type == FFI_TYPE_POINTER)
227 	    {
228 	      p_struct -= ROUND_SIZE ((*ptr)->size);
229 	      memcpy (p_struct, (char *)arg, (*ptr)->size);
230 	      arg = &p_struct;
231 	    }
232 	}
233 
234       /* Now handle all primitive int/pointer/float data types.  */
235       switch (type)
236 	{
237 	  case FFI_TYPE_DOUBLE:
238 	    if (n_fpr < MAX_FPRARGS)
239 	      p_fpr[n_fpr++] = *(unsigned long long *) arg;
240 	    else
241 #ifdef __s390x__
242 	      p_ov[n_ov++] = *(unsigned long *) arg;
243 #else
244 	      p_ov[n_ov++] = ((unsigned long *) arg)[0],
245 	      p_ov[n_ov++] = ((unsigned long *) arg)[1];
246 #endif
247 	    break;
248 
249 	  case FFI_TYPE_FLOAT:
250 	    if (n_fpr < MAX_FPRARGS)
251 	      p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32;
252 	    else
253 	      p_ov[n_ov++] = *(unsigned int *) arg;
254 	    break;
255 
256 	  case FFI_TYPE_POINTER:
257 	    if (n_gpr < MAX_GPRARGS)
258 	      p_gpr[n_gpr++] = (unsigned long)*(unsigned char **) arg;
259 	    else
260 	      p_ov[n_ov++] = (unsigned long)*(unsigned char **) arg;
261 	    break;
262 
263 	  case FFI_TYPE_UINT64:
264 	  case FFI_TYPE_SINT64:
265 #ifdef __s390x__
266 	    if (n_gpr < MAX_GPRARGS)
267 	      p_gpr[n_gpr++] = *(unsigned long *) arg;
268 	    else
269 	      p_ov[n_ov++] = *(unsigned long *) arg;
270 #else
271 	    if (n_gpr == MAX_GPRARGS-1)
272 	      n_gpr = MAX_GPRARGS;
273 	    if (n_gpr < MAX_GPRARGS)
274 	      p_gpr[n_gpr++] = ((unsigned long *) arg)[0],
275 	      p_gpr[n_gpr++] = ((unsigned long *) arg)[1];
276 	    else
277 	      p_ov[n_ov++] = ((unsigned long *) arg)[0],
278 	      p_ov[n_ov++] = ((unsigned long *) arg)[1];
279 #endif
280 	    break;
281 
282 	  case FFI_TYPE_UINT32:
283 	    if (n_gpr < MAX_GPRARGS)
284 	      p_gpr[n_gpr++] = *(unsigned int *) arg;
285 	    else
286 	      p_ov[n_ov++] = *(unsigned int *) arg;
287 	    break;
288 
289 	  case FFI_TYPE_INT:
290 	  case FFI_TYPE_SINT32:
291 	    if (n_gpr < MAX_GPRARGS)
292 	      p_gpr[n_gpr++] = *(signed int *) arg;
293 	    else
294 	      p_ov[n_ov++] = *(signed int *) arg;
295 	    break;
296 
297 	  case FFI_TYPE_UINT16:
298 	    if (n_gpr < MAX_GPRARGS)
299 	      p_gpr[n_gpr++] = *(unsigned short *) arg;
300 	    else
301 	      p_ov[n_ov++] = *(unsigned short *) arg;
302 	    break;
303 
304 	  case FFI_TYPE_SINT16:
305 	    if (n_gpr < MAX_GPRARGS)
306 	      p_gpr[n_gpr++] = *(signed short *) arg;
307 	    else
308 	      p_ov[n_ov++] = *(signed short *) arg;
309 	    break;
310 
311 	  case FFI_TYPE_UINT8:
312 	    if (n_gpr < MAX_GPRARGS)
313 	      p_gpr[n_gpr++] = *(unsigned char *) arg;
314 	    else
315 	      p_ov[n_ov++] = *(unsigned char *) arg;
316 	    break;
317 
318 	  case FFI_TYPE_SINT8:
319 	    if (n_gpr < MAX_GPRARGS)
320 	      p_gpr[n_gpr++] = *(signed char *) arg;
321 	    else
322 	      p_ov[n_ov++] = *(signed char *) arg;
323 	    break;
324 
325 	  default:
326 	    FFI_ASSERT (0);
327 	    break;
328         }
329     }
330 }
331 
332 /*======================== End of Routine ============================*/
333 
334 /*====================================================================*/
335 /*                                                                    */
336 /* Name     - ffi_prep_cif_machdep.                                   */
337 /*                                                                    */
338 /* Function - Perform machine dependent CIF processing.               */
339 /*                                                                    */
340 /*====================================================================*/
341 
342 ffi_status
ffi_prep_cif_machdep(ffi_cif * cif)343 ffi_prep_cif_machdep(ffi_cif *cif)
344 {
345   size_t struct_size = 0;
346   int n_gpr = 0;
347   int n_fpr = 0;
348   int n_ov = 0;
349 
350   ffi_type **ptr;
351   int i;
352 
353   /* Determine return value handling.  */
354 
355   switch (cif->rtype->type)
356     {
357       /* Void is easy.  */
358       case FFI_TYPE_VOID:
359 	cif->flags = FFI390_RET_VOID;
360 	break;
361 
362       /* Structures and complex are returned via a hidden pointer.  */
363       case FFI_TYPE_STRUCT:
364       case FFI_TYPE_COMPLEX:
365 	cif->flags = FFI390_RET_STRUCT;
366 	n_gpr++;  /* We need one GPR to pass the pointer.  */
367 	break;
368 
369       /* Floating point values are returned in fpr 0.  */
370       case FFI_TYPE_FLOAT:
371 	cif->flags = FFI390_RET_FLOAT;
372 	break;
373 
374       case FFI_TYPE_DOUBLE:
375 	cif->flags = FFI390_RET_DOUBLE;
376 	break;
377 
378 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
379       case FFI_TYPE_LONGDOUBLE:
380 	cif->flags = FFI390_RET_STRUCT;
381 	n_gpr++;
382 	break;
383 #endif
384       /* Integer values are returned in gpr 2 (and gpr 3
385 	 for 64-bit values on 31-bit machines).  */
386       case FFI_TYPE_UINT64:
387       case FFI_TYPE_SINT64:
388 	cif->flags = FFI390_RET_INT64;
389 	break;
390 
391       case FFI_TYPE_POINTER:
392       case FFI_TYPE_INT:
393       case FFI_TYPE_UINT32:
394       case FFI_TYPE_SINT32:
395       case FFI_TYPE_UINT16:
396       case FFI_TYPE_SINT16:
397       case FFI_TYPE_UINT8:
398       case FFI_TYPE_SINT8:
399 	/* These are to be extended to word size.  */
400 #ifdef __s390x__
401 	cif->flags = FFI390_RET_INT64;
402 #else
403 	cif->flags = FFI390_RET_INT32;
404 #endif
405 	break;
406 
407       default:
408         FFI_ASSERT (0);
409         break;
410     }
411 
412   /* Now for the arguments.  */
413 
414   for (ptr = cif->arg_types, i = cif->nargs;
415        i > 0;
416        i--, ptr++)
417     {
418       int type = (*ptr)->type;
419 
420 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
421       /* 16-byte long double is passed like a struct.  */
422       if (type == FFI_TYPE_LONGDOUBLE)
423 	type = FFI_TYPE_STRUCT;
424 #endif
425 
426       /* Check how a structure type is passed.  */
427       if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
428 	{
429 	  if (type == FFI_TYPE_COMPLEX)
430 	    type = FFI_TYPE_POINTER;
431 	  else
432 	    type = ffi_check_struct_type (*ptr);
433 
434 	  /* If we pass the struct via pointer, we must reserve space
435 	     to copy its data for proper call-by-value semantics.  */
436 	  if (type == FFI_TYPE_POINTER)
437 	    struct_size += ROUND_SIZE ((*ptr)->size);
438 	}
439 
440       /* Now handle all primitive int/float data types.  */
441       switch (type)
442 	{
443 	  /* The first MAX_FPRARGS floating point arguments
444 	     go in FPRs, the rest overflow to the stack.  */
445 
446 	  case FFI_TYPE_DOUBLE:
447 	    if (n_fpr < MAX_FPRARGS)
448 	      n_fpr++;
449 	    else
450 	      n_ov += sizeof (double) / sizeof (long);
451 	    break;
452 
453 	  case FFI_TYPE_FLOAT:
454 	    if (n_fpr < MAX_FPRARGS)
455 	      n_fpr++;
456 	    else
457 	      n_ov++;
458 	    break;
459 
460 	  /* On 31-bit machines, 64-bit integers are passed in GPR pairs,
461 	     if one is still available, or else on the stack.  If only one
462 	     register is free, skip the register (it won't be used for any
463 	     subsequent argument either).  */
464 
465 #ifndef __s390x__
466 	  case FFI_TYPE_UINT64:
467 	  case FFI_TYPE_SINT64:
468 	    if (n_gpr == MAX_GPRARGS-1)
469 	      n_gpr = MAX_GPRARGS;
470 	    if (n_gpr < MAX_GPRARGS)
471 	      n_gpr += 2;
472 	    else
473 	      n_ov += 2;
474 	    break;
475 #endif
476 
477 	  /* Everything else is passed in GPRs (until MAX_GPRARGS
478 	     have been used) or overflows to the stack.  */
479 
480 	  default:
481 	    if (n_gpr < MAX_GPRARGS)
482 	      n_gpr++;
483 	    else
484 	      n_ov++;
485 	    break;
486         }
487     }
488 
489   /* Total stack space as required for overflow arguments
490      and temporary structure copies.  */
491 
492   cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
493 
494   return FFI_OK;
495 }
496 
497 /*======================== End of Routine ============================*/
498 
499 /*====================================================================*/
500 /*                                                                    */
501 /* Name     - ffi_call.                                               */
502 /*                                                                    */
503 /* Function - Call the FFI routine.                                   */
504 /*                                                                    */
505 /*====================================================================*/
506 
507 void
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)508 ffi_call(ffi_cif *cif,
509 	 void (*fn)(void),
510 	 void *rvalue,
511 	 void **avalue)
512 {
513   int ret_type = cif->flags;
514   extended_cif ecif;
515 
516   ecif.cif    = cif;
517   ecif.avalue = avalue;
518   ecif.rvalue = rvalue;
519 
520   /* If we don't have a return value, we need to fake one.  */
521   if (rvalue == NULL)
522     {
523       if (ret_type == FFI390_RET_STRUCT)
524 	ecif.rvalue = alloca (cif->rtype->size);
525       else
526 	ret_type = FFI390_RET_VOID;
527     }
528 
529   switch (cif->abi)
530     {
531       case FFI_SYSV:
532         ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
533 		       ret_type, ecif.rvalue, fn);
534         break;
535 
536       default:
537         FFI_ASSERT (0);
538         break;
539     }
540 }
541 
542 /*======================== End of Routine ============================*/
543 
544 /*====================================================================*/
545 /*                                                                    */
546 /* Name     - ffi_closure_helper_SYSV.                                */
547 /*                                                                    */
548 /* Function - Call a FFI closure target function.                     */
549 /*                                                                    */
550 /*====================================================================*/
551 
552 void
ffi_closure_helper_SYSV(ffi_closure * closure,unsigned long * p_gpr,unsigned long long * p_fpr,unsigned long * p_ov)553 ffi_closure_helper_SYSV (ffi_closure *closure,
554 			 unsigned long *p_gpr,
555 			 unsigned long long *p_fpr,
556 			 unsigned long *p_ov)
557 {
558   unsigned long long ret_buffer;
559 
560   void *rvalue = &ret_buffer;
561   void **avalue;
562   void **p_arg;
563 
564   int n_gpr = 0;
565   int n_fpr = 0;
566   int n_ov = 0;
567 
568   ffi_type **ptr;
569   int i;
570 
571   /* Allocate buffer for argument list pointers.  */
572 
573   p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
574 
575   /* If we returning a structure, pass the structure address
576      directly to the target function.  Otherwise, have the target
577      function store the return value to the GPR save area.  */
578 
579   if (closure->cif->flags == FFI390_RET_STRUCT)
580     rvalue = (void *) p_gpr[n_gpr++];
581 
582   /* Now for the arguments.  */
583 
584   for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
585        i > 0;
586        i--, p_arg++, ptr++)
587     {
588       int deref_struct_pointer = 0;
589       int type = (*ptr)->type;
590 
591 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
592       /* 16-byte long double is passed like a struct.  */
593       if (type == FFI_TYPE_LONGDOUBLE)
594 	type = FFI_TYPE_STRUCT;
595 #endif
596 
597       /* Check how a structure type is passed.  */
598       if (type == FFI_TYPE_STRUCT || type == FFI_TYPE_COMPLEX)
599 	{
600 	  if (type == FFI_TYPE_COMPLEX)
601 	    type = FFI_TYPE_POINTER;
602 	  else
603 	    type = ffi_check_struct_type (*ptr);
604 
605 	  /* If we pass the struct via pointer, remember to
606 	     retrieve the pointer later.  */
607 	  if (type == FFI_TYPE_POINTER)
608 	    deref_struct_pointer = 1;
609 	}
610 
611       /* Pointers are passed like UINTs of the same size.  */
612       if (type == FFI_TYPE_POINTER)
613 #ifdef __s390x__
614 	type = FFI_TYPE_UINT64;
615 #else
616 	type = FFI_TYPE_UINT32;
617 #endif
618 
619       /* Now handle all primitive int/float data types.  */
620       switch (type)
621 	{
622 	  case FFI_TYPE_DOUBLE:
623 	    if (n_fpr < MAX_FPRARGS)
624 	      *p_arg = &p_fpr[n_fpr++];
625 	    else
626 	      *p_arg = &p_ov[n_ov],
627 	      n_ov += sizeof (double) / sizeof (long);
628 	    break;
629 
630 	  case FFI_TYPE_FLOAT:
631 	    if (n_fpr < MAX_FPRARGS)
632 	      *p_arg = &p_fpr[n_fpr++];
633 	    else
634 	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
635 	    break;
636 
637 	  case FFI_TYPE_UINT64:
638 	  case FFI_TYPE_SINT64:
639 #ifdef __s390x__
640 	    if (n_gpr < MAX_GPRARGS)
641 	      *p_arg = &p_gpr[n_gpr++];
642 	    else
643 	      *p_arg = &p_ov[n_ov++];
644 #else
645 	    if (n_gpr == MAX_GPRARGS-1)
646 	      n_gpr = MAX_GPRARGS;
647 	    if (n_gpr < MAX_GPRARGS)
648 	      *p_arg = &p_gpr[n_gpr], n_gpr += 2;
649 	    else
650 	      *p_arg = &p_ov[n_ov], n_ov += 2;
651 #endif
652 	    break;
653 
654 	  case FFI_TYPE_INT:
655 	  case FFI_TYPE_UINT32:
656 	  case FFI_TYPE_SINT32:
657 	    if (n_gpr < MAX_GPRARGS)
658 	      *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4;
659 	    else
660 	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
661 	    break;
662 
663 	  case FFI_TYPE_UINT16:
664 	  case FFI_TYPE_SINT16:
665 	    if (n_gpr < MAX_GPRARGS)
666 	      *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2;
667 	    else
668 	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2;
669 	    break;
670 
671 	  case FFI_TYPE_UINT8:
672 	  case FFI_TYPE_SINT8:
673 	    if (n_gpr < MAX_GPRARGS)
674 	      *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1;
675 	    else
676 	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
677 	    break;
678 
679 	  default:
680 	    FFI_ASSERT (0);
681 	    break;
682         }
683 
684       /* If this is a struct passed via pointer, we need to
685 	 actually retrieve that pointer.  */
686       if (deref_struct_pointer)
687 	*p_arg = *(void **)*p_arg;
688     }
689 
690 
691   /* Call the target function.  */
692   (closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
693 
694   /* Convert the return value.  */
695   switch (closure->cif->rtype->type)
696     {
697       /* Void is easy, and so is struct.  */
698       case FFI_TYPE_VOID:
699       case FFI_TYPE_STRUCT:
700       case FFI_TYPE_COMPLEX:
701 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
702       case FFI_TYPE_LONGDOUBLE:
703 #endif
704 	break;
705 
706       /* Floating point values are returned in fpr 0.  */
707       case FFI_TYPE_FLOAT:
708 	p_fpr[0] = (long long) *(unsigned int *) rvalue << 32;
709 	break;
710 
711       case FFI_TYPE_DOUBLE:
712 	p_fpr[0] = *(unsigned long long *) rvalue;
713 	break;
714 
715       /* Integer values are returned in gpr 2 (and gpr 3
716 	 for 64-bit values on 31-bit machines).  */
717       case FFI_TYPE_UINT64:
718       case FFI_TYPE_SINT64:
719 #ifdef __s390x__
720 	p_gpr[0] = *(unsigned long *) rvalue;
721 #else
722 	p_gpr[0] = ((unsigned long *) rvalue)[0],
723 	p_gpr[1] = ((unsigned long *) rvalue)[1];
724 #endif
725 	break;
726 
727       case FFI_TYPE_POINTER:
728       case FFI_TYPE_UINT32:
729       case FFI_TYPE_UINT16:
730       case FFI_TYPE_UINT8:
731 	p_gpr[0] = *(unsigned long *) rvalue;
732 	break;
733 
734       case FFI_TYPE_INT:
735       case FFI_TYPE_SINT32:
736       case FFI_TYPE_SINT16:
737       case FFI_TYPE_SINT8:
738 	p_gpr[0] = *(signed long *) rvalue;
739 	break;
740 
741       default:
742         FFI_ASSERT (0);
743         break;
744     }
745 }
746 
747 /*======================== End of Routine ============================*/
748 
749 /*====================================================================*/
750 /*                                                                    */
751 /* Name     - ffi_prep_closure_loc.                                   */
752 /*                                                                    */
753 /* Function - Prepare a FFI closure.                                  */
754 /*                                                                    */
755 /*====================================================================*/
756 
757 ffi_status
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)758 ffi_prep_closure_loc (ffi_closure *closure,
759 		      ffi_cif *cif,
760 		      void (*fun) (ffi_cif *, void *, void **, void *),
761 		      void *user_data,
762 		      void *codeloc)
763 {
764   if (cif->abi != FFI_SYSV)
765     return FFI_BAD_ABI;
766 
767 #ifndef __s390x__
768   *(short *)&closure->tramp [0] = 0x0d10;   /* basr %r1,0 */
769   *(short *)&closure->tramp [2] = 0x9801;   /* lm %r0,%r1,6(%r1) */
770   *(short *)&closure->tramp [4] = 0x1006;
771   *(short *)&closure->tramp [6] = 0x07f1;   /* br %r1 */
772   *(long  *)&closure->tramp [8] = (long)codeloc;
773   *(long  *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
774 #else
775   *(short *)&closure->tramp [0] = 0x0d10;   /* basr %r1,0 */
776   *(short *)&closure->tramp [2] = 0xeb01;   /* lmg %r0,%r1,14(%r1) */
777   *(short *)&closure->tramp [4] = 0x100e;
778   *(short *)&closure->tramp [6] = 0x0004;
779   *(short *)&closure->tramp [8] = 0x07f1;   /* br %r1 */
780   *(long  *)&closure->tramp[16] = (long)codeloc;
781   *(long  *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
782 #endif
783 
784   closure->cif = cif;
785   closure->user_data = user_data;
786   closure->fun = fun;
787 
788   return FFI_OK;
789 }
790 
791 /*======================== End of Routine ============================*/
792 
793