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