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