~ubuntu-branches/ubuntu/lucid/gauche-c-wrapper/lucid

« back to all changes in this revision

Viewing changes to libffi/src/s390/ffi.c

  • Committer: Bazaar Package Importer
  • Author(s): NIIBE Yutaka
  • Date: 2008-04-07 09:15:03 UTC
  • Revision ID: james.westby@ubuntu.com-20080407091503-wu0h414koe95kj4i
Tags: upstream-0.5.2
ImportĀ upstreamĀ versionĀ 0.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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