• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
219 	{
220 	  type = ffi_check_struct_type (*ptr);
221 
222 	  /* If we pass the struct via pointer, copy the data.  */
223 	  if (type == FFI_TYPE_POINTER)
224 	    {
225 	      p_struct -= ROUND_SIZE ((*ptr)->size);
226 	      memcpy (p_struct, (char *)arg, (*ptr)->size);
227 	      arg = &p_struct;
228 	    }
229 	}
230 
231       /* Now handle all primitive int/pointer/float data types.  */
232       switch (type)
233 	{
234 	  case FFI_TYPE_DOUBLE:
235 	    if (n_fpr < MAX_FPRARGS)
236 	      p_fpr[n_fpr++] = *(unsigned long long *) arg;
237 	    else
238 #ifdef __s390x__
239 	      p_ov[n_ov++] = *(unsigned long *) arg;
240 #else
241 	      p_ov[n_ov++] = ((unsigned long *) arg)[0],
242 	      p_ov[n_ov++] = ((unsigned long *) arg)[1];
243 #endif
244 	    break;
245 
246 	  case FFI_TYPE_FLOAT:
247 	    if (n_fpr < MAX_FPRARGS)
248 	      p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32;
249 	    else
250 	      p_ov[n_ov++] = *(unsigned int *) arg;
251 	    break;
252 
253 	  case FFI_TYPE_POINTER:
254 	    if (n_gpr < MAX_GPRARGS)
255 	      p_gpr[n_gpr++] = (unsigned long)*(unsigned char **) arg;
256 	    else
257 	      p_ov[n_ov++] = (unsigned long)*(unsigned char **) arg;
258 	    break;
259 
260 	  case FFI_TYPE_UINT64:
261 	  case FFI_TYPE_SINT64:
262 #ifdef __s390x__
263 	    if (n_gpr < MAX_GPRARGS)
264 	      p_gpr[n_gpr++] = *(unsigned long *) arg;
265 	    else
266 	      p_ov[n_ov++] = *(unsigned long *) arg;
267 #else
268 	    if (n_gpr == MAX_GPRARGS-1)
269 	      n_gpr = MAX_GPRARGS;
270 	    if (n_gpr < MAX_GPRARGS)
271 	      p_gpr[n_gpr++] = ((unsigned long *) arg)[0],
272 	      p_gpr[n_gpr++] = ((unsigned long *) arg)[1];
273 	    else
274 	      p_ov[n_ov++] = ((unsigned long *) arg)[0],
275 	      p_ov[n_ov++] = ((unsigned long *) arg)[1];
276 #endif
277 	    break;
278 
279 	  case FFI_TYPE_UINT32:
280 	    if (n_gpr < MAX_GPRARGS)
281 	      p_gpr[n_gpr++] = *(unsigned int *) arg;
282 	    else
283 	      p_ov[n_ov++] = *(unsigned int *) arg;
284 	    break;
285 
286 	  case FFI_TYPE_INT:
287 	  case FFI_TYPE_SINT32:
288 	    if (n_gpr < MAX_GPRARGS)
289 	      p_gpr[n_gpr++] = *(signed int *) arg;
290 	    else
291 	      p_ov[n_ov++] = *(signed int *) arg;
292 	    break;
293 
294 	  case FFI_TYPE_UINT16:
295 	    if (n_gpr < MAX_GPRARGS)
296 	      p_gpr[n_gpr++] = *(unsigned short *) arg;
297 	    else
298 	      p_ov[n_ov++] = *(unsigned short *) arg;
299 	    break;
300 
301 	  case FFI_TYPE_SINT16:
302 	    if (n_gpr < MAX_GPRARGS)
303 	      p_gpr[n_gpr++] = *(signed short *) arg;
304 	    else
305 	      p_ov[n_ov++] = *(signed short *) arg;
306 	    break;
307 
308 	  case FFI_TYPE_UINT8:
309 	    if (n_gpr < MAX_GPRARGS)
310 	      p_gpr[n_gpr++] = *(unsigned char *) arg;
311 	    else
312 	      p_ov[n_ov++] = *(unsigned char *) arg;
313 	    break;
314 
315 	  case FFI_TYPE_SINT8:
316 	    if (n_gpr < MAX_GPRARGS)
317 	      p_gpr[n_gpr++] = *(signed char *) arg;
318 	    else
319 	      p_ov[n_ov++] = *(signed char *) arg;
320 	    break;
321 
322 	  default:
323 	    FFI_ASSERT (0);
324 	    break;
325         }
326     }
327 }
328 
329 /*======================== End of Routine ============================*/
330 
331 /*====================================================================*/
332 /*                                                                    */
333 /* Name     - ffi_prep_cif_machdep.                                   */
334 /*                                                                    */
335 /* Function - Perform machine dependent CIF processing.               */
336 /*                                                                    */
337 /*====================================================================*/
338 
339 ffi_status
ffi_prep_cif_machdep(ffi_cif * cif)340 ffi_prep_cif_machdep(ffi_cif *cif)
341 {
342   size_t struct_size = 0;
343   int n_gpr = 0;
344   int n_fpr = 0;
345   int n_ov = 0;
346 
347   ffi_type **ptr;
348   int i;
349 
350   /* Determine return value handling.  */
351 
352   switch (cif->rtype->type)
353     {
354       /* Void is easy.  */
355       case FFI_TYPE_VOID:
356 	cif->flags = FFI390_RET_VOID;
357 	break;
358 
359       /* Structures are returned via a hidden pointer.  */
360       case FFI_TYPE_STRUCT:
361 	cif->flags = FFI390_RET_STRUCT;
362 	n_gpr++;  /* We need one GPR to pass the pointer.  */
363 	break;
364 
365       /* Floating point values are returned in fpr 0.  */
366       case FFI_TYPE_FLOAT:
367 	cif->flags = FFI390_RET_FLOAT;
368 	break;
369 
370       case FFI_TYPE_DOUBLE:
371 	cif->flags = FFI390_RET_DOUBLE;
372 	break;
373 
374 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
375       case FFI_TYPE_LONGDOUBLE:
376 	cif->flags = FFI390_RET_STRUCT;
377 	n_gpr++;
378 	break;
379 #endif
380       /* Integer values are returned in gpr 2 (and gpr 3
381 	 for 64-bit values on 31-bit machines).  */
382       case FFI_TYPE_UINT64:
383       case FFI_TYPE_SINT64:
384 	cif->flags = FFI390_RET_INT64;
385 	break;
386 
387       case FFI_TYPE_POINTER:
388       case FFI_TYPE_INT:
389       case FFI_TYPE_UINT32:
390       case FFI_TYPE_SINT32:
391       case FFI_TYPE_UINT16:
392       case FFI_TYPE_SINT16:
393       case FFI_TYPE_UINT8:
394       case FFI_TYPE_SINT8:
395 	/* These are to be extended to word size.  */
396 #ifdef __s390x__
397 	cif->flags = FFI390_RET_INT64;
398 #else
399 	cif->flags = FFI390_RET_INT32;
400 #endif
401 	break;
402 
403       default:
404         FFI_ASSERT (0);
405         break;
406     }
407 
408   /* Now for the arguments.  */
409 
410   for (ptr = cif->arg_types, i = cif->nargs;
411        i > 0;
412        i--, ptr++)
413     {
414       int type = (*ptr)->type;
415 
416 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
417       /* 16-byte long double is passed like a struct.  */
418       if (type == FFI_TYPE_LONGDOUBLE)
419 	type = FFI_TYPE_STRUCT;
420 #endif
421 
422       /* Check how a structure type is passed.  */
423       if (type == FFI_TYPE_STRUCT)
424 	{
425 	  type = ffi_check_struct_type (*ptr);
426 
427 	  /* If we pass the struct via pointer, we must reserve space
428 	     to copy its data for proper call-by-value semantics.  */
429 	  if (type == FFI_TYPE_POINTER)
430 	    struct_size += ROUND_SIZE ((*ptr)->size);
431 	}
432 
433       /* Now handle all primitive int/float data types.  */
434       switch (type)
435 	{
436 	  /* The first MAX_FPRARGS floating point arguments
437 	     go in FPRs, the rest overflow to the stack.  */
438 
439 	  case FFI_TYPE_DOUBLE:
440 	    if (n_fpr < MAX_FPRARGS)
441 	      n_fpr++;
442 	    else
443 	      n_ov += sizeof (double) / sizeof (long);
444 	    break;
445 
446 	  case FFI_TYPE_FLOAT:
447 	    if (n_fpr < MAX_FPRARGS)
448 	      n_fpr++;
449 	    else
450 	      n_ov++;
451 	    break;
452 
453 	  /* On 31-bit machines, 64-bit integers are passed in GPR pairs,
454 	     if one is still available, or else on the stack.  If only one
455 	     register is free, skip the register (it won't be used for any
456 	     subsequent argument either).  */
457 
458 #ifndef __s390x__
459 	  case FFI_TYPE_UINT64:
460 	  case FFI_TYPE_SINT64:
461 	    if (n_gpr == MAX_GPRARGS-1)
462 	      n_gpr = MAX_GPRARGS;
463 	    if (n_gpr < MAX_GPRARGS)
464 	      n_gpr += 2;
465 	    else
466 	      n_ov += 2;
467 	    break;
468 #endif
469 
470 	  /* Everything else is passed in GPRs (until MAX_GPRARGS
471 	     have been used) or overflows to the stack.  */
472 
473 	  default:
474 	    if (n_gpr < MAX_GPRARGS)
475 	      n_gpr++;
476 	    else
477 	      n_ov++;
478 	    break;
479         }
480     }
481 
482   /* Total stack space as required for overflow arguments
483      and temporary structure copies.  */
484 
485   cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
486 
487   return FFI_OK;
488 }
489 
490 /*======================== End of Routine ============================*/
491 
492 /*====================================================================*/
493 /*                                                                    */
494 /* Name     - ffi_call.                                               */
495 /*                                                                    */
496 /* Function - Call the FFI routine.                                   */
497 /*                                                                    */
498 /*====================================================================*/
499 
500 void
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)501 ffi_call(ffi_cif *cif,
502 	 void (*fn)(void),
503 	 void *rvalue,
504 	 void **avalue)
505 {
506   int ret_type = cif->flags;
507   extended_cif ecif;
508 
509   ecif.cif    = cif;
510   ecif.avalue = avalue;
511   ecif.rvalue = rvalue;
512 
513   /* If we don't have a return value, we need to fake one.  */
514   if (rvalue == NULL)
515     {
516       if (ret_type == FFI390_RET_STRUCT)
517 	ecif.rvalue = alloca (cif->rtype->size);
518       else
519 	ret_type = FFI390_RET_VOID;
520     }
521 
522   switch (cif->abi)
523     {
524       case FFI_SYSV:
525         ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
526 		       ret_type, ecif.rvalue, fn);
527         break;
528 
529       default:
530         FFI_ASSERT (0);
531         break;
532     }
533 }
534 
535 /*======================== End of Routine ============================*/
536 
537 /*====================================================================*/
538 /*                                                                    */
539 /* Name     - ffi_closure_helper_SYSV.                                */
540 /*                                                                    */
541 /* Function - Call a FFI closure target function.                     */
542 /*                                                                    */
543 /*====================================================================*/
544 
545 void
ffi_closure_helper_SYSV(ffi_closure * closure,unsigned long * p_gpr,unsigned long long * p_fpr,unsigned long * p_ov)546 ffi_closure_helper_SYSV (ffi_closure *closure,
547 			 unsigned long *p_gpr,
548 			 unsigned long long *p_fpr,
549 			 unsigned long *p_ov)
550 {
551   unsigned long long ret_buffer;
552 
553   void *rvalue = &ret_buffer;
554   void **avalue;
555   void **p_arg;
556 
557   int n_gpr = 0;
558   int n_fpr = 0;
559   int n_ov = 0;
560 
561   ffi_type **ptr;
562   int i;
563 
564   /* Allocate buffer for argument list pointers.  */
565 
566   p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
567 
568   /* If we returning a structure, pass the structure address
569      directly to the target function.  Otherwise, have the target
570      function store the return value to the GPR save area.  */
571 
572   if (closure->cif->flags == FFI390_RET_STRUCT)
573     rvalue = (void *) p_gpr[n_gpr++];
574 
575   /* Now for the arguments.  */
576 
577   for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
578        i > 0;
579        i--, p_arg++, ptr++)
580     {
581       int deref_struct_pointer = 0;
582       int type = (*ptr)->type;
583 
584 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
585       /* 16-byte long double is passed like a struct.  */
586       if (type == FFI_TYPE_LONGDOUBLE)
587 	type = FFI_TYPE_STRUCT;
588 #endif
589 
590       /* Check how a structure type is passed.  */
591       if (type == FFI_TYPE_STRUCT)
592 	{
593 	  type = ffi_check_struct_type (*ptr);
594 
595 	  /* If we pass the struct via pointer, remember to
596 	     retrieve the pointer later.  */
597 	  if (type == FFI_TYPE_POINTER)
598 	    deref_struct_pointer = 1;
599 	}
600 
601       /* Pointers are passed like UINTs of the same size.  */
602       if (type == FFI_TYPE_POINTER)
603 #ifdef __s390x__
604 	type = FFI_TYPE_UINT64;
605 #else
606 	type = FFI_TYPE_UINT32;
607 #endif
608 
609       /* Now handle all primitive int/float data types.  */
610       switch (type)
611 	{
612 	  case FFI_TYPE_DOUBLE:
613 	    if (n_fpr < MAX_FPRARGS)
614 	      *p_arg = &p_fpr[n_fpr++];
615 	    else
616 	      *p_arg = &p_ov[n_ov],
617 	      n_ov += sizeof (double) / sizeof (long);
618 	    break;
619 
620 	  case FFI_TYPE_FLOAT:
621 	    if (n_fpr < MAX_FPRARGS)
622 	      *p_arg = &p_fpr[n_fpr++];
623 	    else
624 	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
625 	    break;
626 
627 	  case FFI_TYPE_UINT64:
628 	  case FFI_TYPE_SINT64:
629 #ifdef __s390x__
630 	    if (n_gpr < MAX_GPRARGS)
631 	      *p_arg = &p_gpr[n_gpr++];
632 	    else
633 	      *p_arg = &p_ov[n_ov++];
634 #else
635 	    if (n_gpr == MAX_GPRARGS-1)
636 	      n_gpr = MAX_GPRARGS;
637 	    if (n_gpr < MAX_GPRARGS)
638 	      *p_arg = &p_gpr[n_gpr], n_gpr += 2;
639 	    else
640 	      *p_arg = &p_ov[n_ov], n_ov += 2;
641 #endif
642 	    break;
643 
644 	  case FFI_TYPE_INT:
645 	  case FFI_TYPE_UINT32:
646 	  case FFI_TYPE_SINT32:
647 	    if (n_gpr < MAX_GPRARGS)
648 	      *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4;
649 	    else
650 	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
651 	    break;
652 
653 	  case FFI_TYPE_UINT16:
654 	  case FFI_TYPE_SINT16:
655 	    if (n_gpr < MAX_GPRARGS)
656 	      *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2;
657 	    else
658 	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2;
659 	    break;
660 
661 	  case FFI_TYPE_UINT8:
662 	  case FFI_TYPE_SINT8:
663 	    if (n_gpr < MAX_GPRARGS)
664 	      *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1;
665 	    else
666 	      *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
667 	    break;
668 
669 	  default:
670 	    FFI_ASSERT (0);
671 	    break;
672         }
673 
674       /* If this is a struct passed via pointer, we need to
675 	 actually retrieve that pointer.  */
676       if (deref_struct_pointer)
677 	*p_arg = *(void **)*p_arg;
678     }
679 
680 
681   /* Call the target function.  */
682   (closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
683 
684   /* Convert the return value.  */
685   switch (closure->cif->rtype->type)
686     {
687       /* Void is easy, and so is struct.  */
688       case FFI_TYPE_VOID:
689       case FFI_TYPE_STRUCT:
690 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
691       case FFI_TYPE_LONGDOUBLE:
692 #endif
693 	break;
694 
695       /* Floating point values are returned in fpr 0.  */
696       case FFI_TYPE_FLOAT:
697 	p_fpr[0] = (long long) *(unsigned int *) rvalue << 32;
698 	break;
699 
700       case FFI_TYPE_DOUBLE:
701 	p_fpr[0] = *(unsigned long long *) rvalue;
702 	break;
703 
704       /* Integer values are returned in gpr 2 (and gpr 3
705 	 for 64-bit values on 31-bit machines).  */
706       case FFI_TYPE_UINT64:
707       case FFI_TYPE_SINT64:
708 #ifdef __s390x__
709 	p_gpr[0] = *(unsigned long *) rvalue;
710 #else
711 	p_gpr[0] = ((unsigned long *) rvalue)[0],
712 	p_gpr[1] = ((unsigned long *) rvalue)[1];
713 #endif
714 	break;
715 
716       case FFI_TYPE_POINTER:
717       case FFI_TYPE_UINT32:
718       case FFI_TYPE_UINT16:
719       case FFI_TYPE_UINT8:
720 	p_gpr[0] = *(unsigned long *) rvalue;
721 	break;
722 
723       case FFI_TYPE_INT:
724       case FFI_TYPE_SINT32:
725       case FFI_TYPE_SINT16:
726       case FFI_TYPE_SINT8:
727 	p_gpr[0] = *(signed long *) rvalue;
728 	break;
729 
730       default:
731         FFI_ASSERT (0);
732         break;
733     }
734 }
735 
736 /*======================== End of Routine ============================*/
737 
738 /*====================================================================*/
739 /*                                                                    */
740 /* Name     - ffi_prep_closure_loc.                                   */
741 /*                                                                    */
742 /* Function - Prepare a FFI closure.                                  */
743 /*                                                                    */
744 /*====================================================================*/
745 
746 ffi_status
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)747 ffi_prep_closure_loc (ffi_closure *closure,
748 		      ffi_cif *cif,
749 		      void (*fun) (ffi_cif *, void *, void **, void *),
750 		      void *user_data,
751 		      void *codeloc)
752 {
753   FFI_ASSERT (cif->abi == FFI_SYSV);
754 
755 #ifndef __s390x__
756   *(short *)&closure->tramp [0] = 0x0d10;   /* basr %r1,0 */
757   *(short *)&closure->tramp [2] = 0x9801;   /* lm %r0,%r1,6(%r1) */
758   *(short *)&closure->tramp [4] = 0x1006;
759   *(short *)&closure->tramp [6] = 0x07f1;   /* br %r1 */
760   *(long  *)&closure->tramp [8] = (long)codeloc;
761   *(long  *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
762 #else
763   *(short *)&closure->tramp [0] = 0x0d10;   /* basr %r1,0 */
764   *(short *)&closure->tramp [2] = 0xeb01;   /* lmg %r0,%r1,14(%r1) */
765   *(short *)&closure->tramp [4] = 0x100e;
766   *(short *)&closure->tramp [6] = 0x0004;
767   *(short *)&closure->tramp [8] = 0x07f1;   /* br %r1 */
768   *(long  *)&closure->tramp[16] = (long)codeloc;
769   *(long  *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
770 #endif
771 
772   closure->cif = cif;
773   closure->user_data = user_data;
774   closure->fun = fun;
775 
776   return FFI_OK;
777 }
778 
779 /*======================== End of Routine ============================*/
780 
781