Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / ctypes / libffi / src / s390 / ffi.c
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
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
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
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
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
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
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