OSDN Git Service

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