OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libffi/] [src/] [s390/] [ffi.c] - Blame information for rev 756

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.