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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 732 jeremybenn
/* -----------------------------------------------------------------------
2
   ffi.c - Copyright (c) 1998 Geoffrey Keating
3
   Copyright (C) 2007, 2008 Free Software Foundation, Inc
4
   Copyright (C) 2008 Red Hat, Inc
5
 
6
   PowerPC Foreign Function Interface
7
 
8
   Permission is hereby granted, free of charge, to any person obtaining
9
   a copy of this software and associated documentation files (the
10
   ``Software''), to deal in the Software without restriction, including
11
   without limitation the rights to use, copy, modify, merge, publish,
12
   distribute, sublicense, and/or sell copies of the Software, and to
13
   permit persons to whom the Software is furnished to do so, subject to
14
   the following conditions:
15
 
16
   The above copyright notice and this permission notice shall be included
17
   in all copies or substantial portions of the Software.
18
 
19
   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22
   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
23
   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24
   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
   OTHER DEALINGS IN THE SOFTWARE.
26
   ----------------------------------------------------------------------- */
27
 
28
#include <ffi.h>
29
#include <ffi_common.h>
30
 
31
#include <stdlib.h>
32
#include <stdio.h>
33
 
34
 
35
extern void ffi_closure_SYSV (void);
36
extern void FFI_HIDDEN ffi_closure_LINUX64 (void);
37
 
38
enum {
39
  /* The assembly depends on these exact flags.  */
40
  FLAG_RETURNS_SMST     = 1 << (31-31), /* Used for FFI_SYSV small structs.  */
41
  FLAG_RETURNS_NOTHING  = 1 << (31-30), /* These go in cr7 */
42
  FLAG_RETURNS_FP       = 1 << (31-29),
43
  FLAG_RETURNS_64BITS   = 1 << (31-28),
44
 
45
  FLAG_RETURNS_128BITS  = 1 << (31-27), /* cr6  */
46
  FLAG_SYSV_SMST_R4     = 1 << (31-26), /* use r4 for FFI_SYSV 8 byte
47
                                           structs.  */
48
  FLAG_SYSV_SMST_R3     = 1 << (31-25), /* use r3 for FFI_SYSV 4 byte
49
                                           structs.  */
50
  /* Bits (31-24) through (31-19) store shift value for SMST */
51
 
52
  FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
53
  FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI */
54
  FLAG_4_GPR_ARGUMENTS  = 1 << (31- 5),
55
  FLAG_RETVAL_REFERENCE = 1 << (31- 4)
56
};
57
 
58
/* About the SYSV ABI.  */
59
unsigned int NUM_GPR_ARG_REGISTERS = 8;
60
#ifndef __NO_FPRS__
61
unsigned int NUM_FPR_ARG_REGISTERS = 8;
62
#else
63
unsigned int NUM_FPR_ARG_REGISTERS = 0;
64
#endif
65
 
66
enum { ASM_NEEDS_REGISTERS = 4 };
67
 
68
/* ffi_prep_args_SYSV is called by the assembly routine once stack space
69
   has been allocated for the function's arguments.
70
 
71
   The stack layout we want looks like this:
72
 
73
   |   Return address from ffi_call_SYSV 4bytes |       higher addresses
74
   |--------------------------------------------|
75
   |   Previous backchain pointer       4       |       stack pointer here
76
   |--------------------------------------------|<+ <<< on entry to
77
   |   Saved r28-r31                    4*4     | |     ffi_call_SYSV
78
   |--------------------------------------------| |
79
   |   GPR registers r3-r10             8*4     | |     ffi_call_SYSV
80
   |--------------------------------------------| |
81
   |   FPR registers f1-f8 (optional)   8*8     | |
82
   |--------------------------------------------| |     stack   |
83
   |   Space for copied structures              | |     grows   |
84
   |--------------------------------------------| |     down    V
85
   |   Parameters that didn't fit in registers  | |
86
   |--------------------------------------------| |     lower addresses
87
   |   Space for callee's LR            4       | |
88
   |--------------------------------------------| |     stack pointer here
89
   |   Current backchain pointer        4       |-/     during
90
   |--------------------------------------------|   <<< ffi_call_SYSV
91
 
92
*/
93
 
94
void
95
ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
96
{
97
  const unsigned bytes = ecif->cif->bytes;
98
  const unsigned flags = ecif->cif->flags;
99
 
100
  typedef union {
101
    char *c;
102
    unsigned *u;
103
    long long *ll;
104
    float *f;
105
    double *d;
106
  } valp;
107
 
108
  /* 'stacktop' points at the previous backchain pointer.  */
109
  valp stacktop;
110
 
111
  /* 'gpr_base' points at the space for gpr3, and grows upwards as
112
     we use GPR registers.  */
113
  valp gpr_base;
114
  int intarg_count;
115
 
116
  /* 'fpr_base' points at the space for fpr1, and grows upwards as
117
     we use FPR registers.  */
118
  valp fpr_base;
119
  int fparg_count;
120
 
121
  /* 'copy_space' grows down as we put structures in it.  It should
122
     stay 16-byte aligned.  */
123
  valp copy_space;
124
 
125
  /* 'next_arg' grows up as we put parameters in it.  */
126
  valp next_arg;
127
 
128
  int i, ii MAYBE_UNUSED;
129
  ffi_type **ptr;
130
  double double_tmp;
131
  union {
132
    void **v;
133
    char **c;
134
    signed char **sc;
135
    unsigned char **uc;
136
    signed short **ss;
137
    unsigned short **us;
138
    unsigned int **ui;
139
    long long **ll;
140
    float **f;
141
    double **d;
142
  } p_argv;
143
  size_t struct_copy_size;
144
  unsigned gprvalue;
145
 
146
  if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
147
    NUM_FPR_ARG_REGISTERS = 0;
148
 
149
  stacktop.c = (char *) stack + bytes;
150
  gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
151
  intarg_count = 0;
152
  fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
153
  fparg_count = 0;
154
  copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
155
  next_arg.u = stack + 2;
156
 
157
  /* Check that everything starts aligned properly.  */
158
  FFI_ASSERT (((unsigned) (char *) stack & 0xF) == 0);
159
  FFI_ASSERT (((unsigned) copy_space.c & 0xF) == 0);
160
  FFI_ASSERT (((unsigned) stacktop.c & 0xF) == 0);
161
  FFI_ASSERT ((bytes & 0xF) == 0);
162
  FFI_ASSERT (copy_space.c >= next_arg.c);
163
 
164
  /* Deal with return values that are actually pass-by-reference.  */
165
  if (flags & FLAG_RETVAL_REFERENCE)
166
    {
167
      *gpr_base.u++ = (unsigned long) (char *) ecif->rvalue;
168
      intarg_count++;
169
    }
170
 
171
  /* Now for the arguments.  */
172
  p_argv.v = ecif->avalue;
173
  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
174
       i > 0;
175
       i--, ptr++, p_argv.v++)
176
    {
177
      switch ((*ptr)->type)
178
        {
179
        case FFI_TYPE_FLOAT:
180
          /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
181
          if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
182
            goto soft_float_prep;
183
          double_tmp = **p_argv.f;
184
          if (fparg_count >= NUM_FPR_ARG_REGISTERS)
185
            {
186
              *next_arg.f = (float) double_tmp;
187
              next_arg.u += 1;
188
              intarg_count++;
189
            }
190
          else
191
            *fpr_base.d++ = double_tmp;
192
          fparg_count++;
193
          FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
194
          break;
195
 
196
        case FFI_TYPE_DOUBLE:
197
          /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
198
          if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
199
            goto soft_double_prep;
200
          double_tmp = **p_argv.d;
201
 
202
          if (fparg_count >= NUM_FPR_ARG_REGISTERS)
203
            {
204
              if (intarg_count >= NUM_GPR_ARG_REGISTERS
205
                  && intarg_count % 2 != 0)
206
                {
207
                  intarg_count++;
208
                  next_arg.u++;
209
                }
210
              *next_arg.d = double_tmp;
211
              next_arg.u += 2;
212
            }
213
          else
214
            *fpr_base.d++ = double_tmp;
215
          fparg_count++;
216
          FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
217
          break;
218
 
219
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
220
        case FFI_TYPE_LONGDOUBLE:
221
          if ((ecif->cif->abi != FFI_LINUX)
222
                && (ecif->cif->abi != FFI_LINUX_SOFT_FLOAT))
223
            goto do_struct;
224
          /* The soft float ABI for long doubles works like this,
225
             a long double is passed in four consecutive gprs if available.
226
             A maximum of 2 long doubles can be passed in gprs.
227
             If we do not have 4 gprs left, the long double is passed on the
228
             stack, 4-byte aligned.  */
229
          if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
230
            {
231
              unsigned int int_tmp = (*p_argv.ui)[0];
232
              if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
233
                {
234
                  if (intarg_count < NUM_GPR_ARG_REGISTERS)
235
                    intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
236
                  *next_arg.u = int_tmp;
237
                  next_arg.u++;
238
                  for (ii = 1; ii < 4; ii++)
239
                    {
240
                      int_tmp = (*p_argv.ui)[ii];
241
                      *next_arg.u = int_tmp;
242
                      next_arg.u++;
243
                    }
244
                }
245
              else
246
                {
247
                  *gpr_base.u++ = int_tmp;
248
                  for (ii = 1; ii < 4; ii++)
249
                    {
250
                      int_tmp = (*p_argv.ui)[ii];
251
                      *gpr_base.u++ = int_tmp;
252
                    }
253
                }
254
              intarg_count +=4;
255
            }
256
          else
257
            {
258
              double_tmp = (*p_argv.d)[0];
259
 
260
              if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
261
                {
262
                  if (intarg_count >= NUM_GPR_ARG_REGISTERS
263
                      && intarg_count % 2 != 0)
264
                    {
265
                      intarg_count++;
266
                      next_arg.u++;
267
                    }
268
                  *next_arg.d = double_tmp;
269
                  next_arg.u += 2;
270
                  double_tmp = (*p_argv.d)[1];
271
                  *next_arg.d = double_tmp;
272
                  next_arg.u += 2;
273
                }
274
              else
275
                {
276
                  *fpr_base.d++ = double_tmp;
277
                  double_tmp = (*p_argv.d)[1];
278
                  *fpr_base.d++ = double_tmp;
279
                }
280
 
281
              fparg_count += 2;
282
              FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
283
            }
284
          break;
285
#endif
286
 
287
        case FFI_TYPE_UINT64:
288
        case FFI_TYPE_SINT64:
289
        soft_double_prep:
290
          if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
291
            intarg_count++;
292
          if (intarg_count >= NUM_GPR_ARG_REGISTERS)
293
            {
294
              if (intarg_count % 2 != 0)
295
                {
296
                  intarg_count++;
297
                  next_arg.u++;
298
                }
299
              *next_arg.ll = **p_argv.ll;
300
              next_arg.u += 2;
301
            }
302
          else
303
            {
304
              /* whoops: abi states only certain register pairs
305
               * can be used for passing long long int
306
               * specifically (r3,r4), (r5,r6), (r7,r8),
307
               * (r9,r10) and if next arg is long long but
308
               * not correct starting register of pair then skip
309
               * until the proper starting register
310
               */
311
              if (intarg_count % 2 != 0)
312
                {
313
                  intarg_count ++;
314
                  gpr_base.u++;
315
                }
316
              *gpr_base.ll++ = **p_argv.ll;
317
            }
318
          intarg_count += 2;
319
          break;
320
 
321
        case FFI_TYPE_STRUCT:
322
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
323
        do_struct:
324
#endif
325
          struct_copy_size = ((*ptr)->size + 15) & ~0xF;
326
          copy_space.c -= struct_copy_size;
327
          memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
328
 
329
          gprvalue = (unsigned long) copy_space.c;
330
 
331
          FFI_ASSERT (copy_space.c > next_arg.c);
332
          FFI_ASSERT (flags & FLAG_ARG_NEEDS_COPY);
333
          goto putgpr;
334
 
335
        case FFI_TYPE_UINT8:
336
          gprvalue = **p_argv.uc;
337
          goto putgpr;
338
        case FFI_TYPE_SINT8:
339
          gprvalue = **p_argv.sc;
340
          goto putgpr;
341
        case FFI_TYPE_UINT16:
342
          gprvalue = **p_argv.us;
343
          goto putgpr;
344
        case FFI_TYPE_SINT16:
345
          gprvalue = **p_argv.ss;
346
          goto putgpr;
347
 
348
        case FFI_TYPE_INT:
349
        case FFI_TYPE_UINT32:
350
        case FFI_TYPE_SINT32:
351
        case FFI_TYPE_POINTER:
352
        soft_float_prep:
353
 
354
          gprvalue = **p_argv.ui;
355
 
356
        putgpr:
357
          if (intarg_count >= NUM_GPR_ARG_REGISTERS)
358
            *next_arg.u++ = gprvalue;
359
          else
360
            *gpr_base.u++ = gprvalue;
361
          intarg_count++;
362
          break;
363
        }
364
    }
365
 
366
  /* Check that we didn't overrun the stack...  */
367
  FFI_ASSERT (copy_space.c >= next_arg.c);
368
  FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
369
  FFI_ASSERT (fpr_base.u
370
              <= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
371
  FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
372
}
373
 
374
/* About the LINUX64 ABI.  */
375
enum {
376
  NUM_GPR_ARG_REGISTERS64 = 8,
377
  NUM_FPR_ARG_REGISTERS64 = 13
378
};
379
enum { ASM_NEEDS_REGISTERS64 = 4 };
380
 
381
/* ffi_prep_args64 is called by the assembly routine once stack space
382
   has been allocated for the function's arguments.
383
 
384
   The stack layout we want looks like this:
385
 
386
   |   Ret addr from ffi_call_LINUX64   8bytes  |       higher addresses
387
   |--------------------------------------------|
388
   |   CR save area                     8bytes  |
389
   |--------------------------------------------|
390
   |   Previous backchain pointer       8       |       stack pointer here
391
   |--------------------------------------------|<+ <<< on entry to
392
   |   Saved r28-r31                    4*8     | |     ffi_call_LINUX64
393
   |--------------------------------------------| |
394
   |   GPR registers r3-r10             8*8     | |
395
   |--------------------------------------------| |
396
   |   FPR registers f1-f13 (optional)  13*8    | |
397
   |--------------------------------------------| |
398
   |   Parameter save area                      | |
399
   |--------------------------------------------| |
400
   |   TOC save area                    8       | |
401
   |--------------------------------------------| |     stack   |
402
   |   Linker doubleword                8       | |     grows   |
403
   |--------------------------------------------| |     down    V
404
   |   Compiler doubleword              8       | |
405
   |--------------------------------------------| |     lower addresses
406
   |   Space for callee's LR            8       | |
407
   |--------------------------------------------| |
408
   |   CR save area                     8       | |
409
   |--------------------------------------------| |     stack pointer here
410
   |   Current backchain pointer        8       |-/     during
411
   |--------------------------------------------|   <<< ffi_call_LINUX64
412
 
413
*/
414
 
415
void FFI_HIDDEN
416
ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
417
{
418
  const unsigned long bytes = ecif->cif->bytes;
419
  const unsigned long flags = ecif->cif->flags;
420
 
421
  typedef union {
422
    char *c;
423
    unsigned long *ul;
424
    float *f;
425
    double *d;
426
  } valp;
427
 
428
  /* 'stacktop' points at the previous backchain pointer.  */
429
  valp stacktop;
430
 
431
  /* 'next_arg' points at the space for gpr3, and grows upwards as
432
     we use GPR registers, then continues at rest.  */
433
  valp gpr_base;
434
  valp gpr_end;
435
  valp rest;
436
  valp next_arg;
437
 
438
  /* 'fpr_base' points at the space for fpr3, and grows upwards as
439
     we use FPR registers.  */
440
  valp fpr_base;
441
  int fparg_count;
442
 
443
  int i, words;
444
  ffi_type **ptr;
445
  double double_tmp;
446
  union {
447
    void **v;
448
    char **c;
449
    signed char **sc;
450
    unsigned char **uc;
451
    signed short **ss;
452
    unsigned short **us;
453
    signed int **si;
454
    unsigned int **ui;
455
    unsigned long **ul;
456
    float **f;
457
    double **d;
458
  } p_argv;
459
  unsigned long gprvalue;
460
 
461
  stacktop.c = (char *) stack + bytes;
462
  gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64;
463
  gpr_end.ul = gpr_base.ul + NUM_GPR_ARG_REGISTERS64;
464
  rest.ul = stack + 6 + NUM_GPR_ARG_REGISTERS64;
465
  fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64;
466
  fparg_count = 0;
467
  next_arg.ul = gpr_base.ul;
468
 
469
  /* Check that everything starts aligned properly.  */
470
  FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
471
  FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
472
  FFI_ASSERT ((bytes & 0xF) == 0);
473
 
474
  /* Deal with return values that are actually pass-by-reference.  */
475
  if (flags & FLAG_RETVAL_REFERENCE)
476
    *next_arg.ul++ = (unsigned long) (char *) ecif->rvalue;
477
 
478
  /* Now for the arguments.  */
479
  p_argv.v = ecif->avalue;
480
  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
481
       i > 0;
482
       i--, ptr++, p_argv.v++)
483
    {
484
      switch ((*ptr)->type)
485
        {
486
        case FFI_TYPE_FLOAT:
487
          double_tmp = **p_argv.f;
488
          *next_arg.f = (float) double_tmp;
489
          if (++next_arg.ul == gpr_end.ul)
490
            next_arg.ul = rest.ul;
491
          if (fparg_count < NUM_FPR_ARG_REGISTERS64)
492
            *fpr_base.d++ = double_tmp;
493
          fparg_count++;
494
          FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
495
          break;
496
 
497
        case FFI_TYPE_DOUBLE:
498
          double_tmp = **p_argv.d;
499
          *next_arg.d = double_tmp;
500
          if (++next_arg.ul == gpr_end.ul)
501
            next_arg.ul = rest.ul;
502
          if (fparg_count < NUM_FPR_ARG_REGISTERS64)
503
            *fpr_base.d++ = double_tmp;
504
          fparg_count++;
505
          FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
506
          break;
507
 
508
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
509
        case FFI_TYPE_LONGDOUBLE:
510
          double_tmp = (*p_argv.d)[0];
511
          *next_arg.d = double_tmp;
512
          if (++next_arg.ul == gpr_end.ul)
513
            next_arg.ul = rest.ul;
514
          if (fparg_count < NUM_FPR_ARG_REGISTERS64)
515
            *fpr_base.d++ = double_tmp;
516
          fparg_count++;
517
          double_tmp = (*p_argv.d)[1];
518
          *next_arg.d = double_tmp;
519
          if (++next_arg.ul == gpr_end.ul)
520
            next_arg.ul = rest.ul;
521
          if (fparg_count < NUM_FPR_ARG_REGISTERS64)
522
            *fpr_base.d++ = double_tmp;
523
          fparg_count++;
524
          FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
525
          FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
526
          break;
527
#endif
528
 
529
        case FFI_TYPE_STRUCT:
530
          words = ((*ptr)->size + 7) / 8;
531
          if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
532
            {
533
              size_t first = gpr_end.c - next_arg.c;
534
              memcpy (next_arg.c, *p_argv.c, first);
535
              memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first);
536
              next_arg.c = rest.c + words * 8 - first;
537
            }
538
          else
539
            {
540
              char *where = next_arg.c;
541
 
542
              /* Structures with size less than eight bytes are passed
543
                 left-padded.  */
544
              if ((*ptr)->size < 8)
545
                where += 8 - (*ptr)->size;
546
 
547
              memcpy (where, *p_argv.c, (*ptr)->size);
548
              next_arg.ul += words;
549
              if (next_arg.ul == gpr_end.ul)
550
                next_arg.ul = rest.ul;
551
            }
552
          break;
553
 
554
        case FFI_TYPE_UINT8:
555
          gprvalue = **p_argv.uc;
556
          goto putgpr;
557
        case FFI_TYPE_SINT8:
558
          gprvalue = **p_argv.sc;
559
          goto putgpr;
560
        case FFI_TYPE_UINT16:
561
          gprvalue = **p_argv.us;
562
          goto putgpr;
563
        case FFI_TYPE_SINT16:
564
          gprvalue = **p_argv.ss;
565
          goto putgpr;
566
        case FFI_TYPE_UINT32:
567
          gprvalue = **p_argv.ui;
568
          goto putgpr;
569
        case FFI_TYPE_INT:
570
        case FFI_TYPE_SINT32:
571
          gprvalue = **p_argv.si;
572
          goto putgpr;
573
 
574
        case FFI_TYPE_UINT64:
575
        case FFI_TYPE_SINT64:
576
        case FFI_TYPE_POINTER:
577
          gprvalue = **p_argv.ul;
578
        putgpr:
579
          *next_arg.ul++ = gprvalue;
580
          if (next_arg.ul == gpr_end.ul)
581
            next_arg.ul = rest.ul;
582
          break;
583
        }
584
    }
585
 
586
  FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS
587
              || (next_arg.ul >= gpr_base.ul
588
                  && next_arg.ul <= gpr_base.ul + 4));
589
}
590
 
591
 
592
 
593
/* Perform machine dependent cif processing */
594
ffi_status
595
ffi_prep_cif_machdep (ffi_cif *cif)
596
{
597
  /* All this is for the SYSV and LINUX64 ABI.  */
598
  int i;
599
  ffi_type **ptr;
600
  unsigned bytes;
601
  int fparg_count = 0, intarg_count = 0;
602
  unsigned flags = 0;
603
  unsigned struct_copy_size = 0;
604
  unsigned type = cif->rtype->type;
605
  unsigned size = cif->rtype->size;
606
 
607
  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
608
    NUM_FPR_ARG_REGISTERS = 0;
609
 
610
  if (cif->abi != FFI_LINUX64)
611
    {
612
      /* All the machine-independent calculation of cif->bytes will be wrong.
613
         Redo the calculation for SYSV.  */
614
 
615
      /* Space for the frame pointer, callee's LR, and the asm's temp regs.  */
616
      bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof (int);
617
 
618
      /* Space for the GPR registers.  */
619
      bytes += NUM_GPR_ARG_REGISTERS * sizeof (int);
620
    }
621
  else
622
    {
623
      /* 64-bit ABI.  */
624
 
625
      /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
626
         regs.  */
627
      bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof (long);
628
 
629
      /* Space for the mandatory parm save area and general registers.  */
630
      bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long);
631
    }
632
 
633
  /* Return value handling.  The rules for SYSV are as follows:
634
     - 32-bit (or less) integer values are returned in gpr3;
635
     - Structures of size <= 4 bytes also returned in gpr3;
636
     - 64-bit integer values and structures between 5 and 8 bytes are returned
637
     in gpr3 and gpr4;
638
     - Single/double FP values are returned in fpr1;
639
     - Larger structures are allocated space and a pointer is passed as
640
     the first argument.
641
     - long doubles (if not equivalent to double) are returned in
642
     fpr1,fpr2 for Linux and as for large structs for SysV.
643
     For LINUX64:
644
     - integer values in gpr3;
645
     - Structures/Unions by reference;
646
     - Single/double FP values in fpr1, long double in fpr1,fpr2.
647
     - soft-float float/doubles are treated as UINT32/UINT64 respectivley.
648
     - soft-float long doubles are returned in gpr3-gpr6.  */
649
  switch (type)
650
    {
651
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
652
    case FFI_TYPE_LONGDOUBLE:
653
      if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64
654
        && cif->abi != FFI_LINUX_SOFT_FLOAT)
655
        goto byref;
656
      flags |= FLAG_RETURNS_128BITS;
657
      /* Fall through.  */
658
#endif
659
    case FFI_TYPE_DOUBLE:
660
      flags |= FLAG_RETURNS_64BITS;
661
      /* Fall through.  */
662
    case FFI_TYPE_FLOAT:
663
      /* With FFI_LINUX_SOFT_FLOAT no fp registers are used.  */
664
      if (cif->abi != FFI_LINUX_SOFT_FLOAT)
665
        flags |= FLAG_RETURNS_FP;
666
      break;
667
 
668
    case FFI_TYPE_UINT64:
669
    case FFI_TYPE_SINT64:
670
      flags |= FLAG_RETURNS_64BITS;
671
      break;
672
 
673
    case FFI_TYPE_STRUCT:
674
      if (cif->abi == FFI_SYSV)
675
        {
676
          /* The final SYSV ABI says that structures smaller or equal 8 bytes
677
             are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
678
             in memory.  */
679
 
680
          /* Treat structs with size <= 8 bytes.  */
681
          if (size <= 8)
682
            {
683
              flags |= FLAG_RETURNS_SMST;
684
              /* These structs are returned in r3. We pack the type and the
685
                 precalculated shift value (needed in the sysv.S) into flags.
686
                 The same applies for the structs returned in r3/r4.  */
687
              if (size <= 4)
688
                {
689
                  flags |= FLAG_SYSV_SMST_R3;
690
                  flags |= 8 * (4 - size) << 8;
691
                  break;
692
                }
693
              /* These structs are returned in r3 and r4. See above.   */
694
              if  (size <= 8)
695
                {
696
                  flags |= FLAG_SYSV_SMST_R3 | FLAG_SYSV_SMST_R4;
697
                  flags |= 8 * (8 - size) << 8;
698
                  break;
699
                }
700
            }
701
        }
702
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
703
    byref:
704
#endif
705
      intarg_count++;
706
      flags |= FLAG_RETVAL_REFERENCE;
707
      /* Fall through.  */
708
    case FFI_TYPE_VOID:
709
      flags |= FLAG_RETURNS_NOTHING;
710
      break;
711
 
712
    default:
713
      /* Returns 32-bit integer, or similar.  Nothing to do here.  */
714
      break;
715
    }
716
 
717
  if (cif->abi != FFI_LINUX64)
718
    /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
719
       first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
720
       goes on the stack.  Structures and long doubles (if not equivalent
721
       to double) are passed as a pointer to a copy of the structure.
722
       Stuff on the stack needs to keep proper alignment.  */
723
    for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
724
      {
725
        switch ((*ptr)->type)
726
          {
727
          case FFI_TYPE_FLOAT:
728
            /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
729
            if (cif->abi == FFI_LINUX_SOFT_FLOAT)
730
              goto soft_float_cif;
731
            fparg_count++;
732
            /* floating singles are not 8-aligned on stack */
733
            break;
734
 
735
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
736
          case FFI_TYPE_LONGDOUBLE:
737
            if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
738
              goto do_struct;
739
            if (cif->abi == FFI_LINUX_SOFT_FLOAT)
740
              {
741
                if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
742
                  || intarg_count < NUM_GPR_ARG_REGISTERS)
743
                  /* A long double in FFI_LINUX_SOFT_FLOAT can use only
744
                     a set of four consecutive gprs. If we have not enough,
745
                     we have to adjust the intarg_count value.  */
746
                  intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
747
                intarg_count += 4;
748
                break;
749
              }
750
            else
751
              fparg_count++;
752
            /* Fall thru */
753
#endif
754
          case FFI_TYPE_DOUBLE:
755
            /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
756
            if (cif->abi == FFI_LINUX_SOFT_FLOAT)
757
              goto soft_double_cif;
758
            fparg_count++;
759
            /* If this FP arg is going on the stack, it must be
760
               8-byte-aligned.  */
761
            if (fparg_count > NUM_FPR_ARG_REGISTERS
762
                && intarg_count >= NUM_GPR_ARG_REGISTERS
763
                && intarg_count % 2 != 0)
764
              intarg_count++;
765
            break;
766
 
767
          case FFI_TYPE_UINT64:
768
          case FFI_TYPE_SINT64:
769
          soft_double_cif:
770
            /* 'long long' arguments are passed as two words, but
771
               either both words must fit in registers or both go
772
               on the stack.  If they go on the stack, they must
773
               be 8-byte-aligned.
774
 
775
               Also, only certain register pairs can be used for
776
               passing long long int -- specifically (r3,r4), (r5,r6),
777
               (r7,r8), (r9,r10).
778
            */
779
            if (intarg_count == NUM_GPR_ARG_REGISTERS-1
780
                || intarg_count % 2 != 0)
781
              intarg_count++;
782
            intarg_count += 2;
783
            break;
784
 
785
          case FFI_TYPE_STRUCT:
786
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
787
          do_struct:
788
#endif
789
            /* We must allocate space for a copy of these to enforce
790
               pass-by-value.  Pad the space up to a multiple of 16
791
               bytes (the maximum alignment required for anything under
792
               the SYSV ABI).  */
793
            struct_copy_size += ((*ptr)->size + 15) & ~0xF;
794
            /* Fall through (allocate space for the pointer).  */
795
 
796
          default:
797
          soft_float_cif:
798
            /* Everything else is passed as a 4-byte word in a GPR, either
799
               the object itself or a pointer to it.  */
800
            intarg_count++;
801
            break;
802
          }
803
      }
804
  else
805
    for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
806
      {
807
        switch ((*ptr)->type)
808
          {
809
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
810
          case FFI_TYPE_LONGDOUBLE:
811
            if (cif->abi == FFI_LINUX_SOFT_FLOAT)
812
              intarg_count += 4;
813
            else
814
              {
815
                fparg_count += 2;
816
                intarg_count += 2;
817
              }
818
            break;
819
#endif
820
          case FFI_TYPE_FLOAT:
821
          case FFI_TYPE_DOUBLE:
822
            fparg_count++;
823
            intarg_count++;
824
            break;
825
 
826
          case FFI_TYPE_STRUCT:
827
            intarg_count += ((*ptr)->size + 7) / 8;
828
            break;
829
 
830
          default:
831
            /* Everything else is passed as a 8-byte word in a GPR, either
832
               the object itself or a pointer to it.  */
833
            intarg_count++;
834
            break;
835
          }
836
      }
837
 
838
  if (fparg_count != 0)
839
    flags |= FLAG_FP_ARGUMENTS;
840
  if (intarg_count > 4)
841
    flags |= FLAG_4_GPR_ARGUMENTS;
842
  if (struct_copy_size != 0)
843
    flags |= FLAG_ARG_NEEDS_COPY;
844
 
845
  if (cif->abi != FFI_LINUX64)
846
    {
847
      /* Space for the FPR registers, if needed.  */
848
      if (fparg_count != 0)
849
        bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
850
 
851
      /* Stack space.  */
852
      if (intarg_count > NUM_GPR_ARG_REGISTERS)
853
        bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
854
      if (fparg_count > NUM_FPR_ARG_REGISTERS)
855
        bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
856
    }
857
  else
858
    {
859
      /* Space for the FPR registers, if needed.  */
860
      if (fparg_count != 0)
861
        bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
862
 
863
      /* Stack space.  */
864
      if (intarg_count > NUM_GPR_ARG_REGISTERS64)
865
        bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof (long);
866
    }
867
 
868
  /* The stack space allocated needs to be a multiple of 16 bytes.  */
869
  bytes = (bytes + 15) & ~0xF;
870
 
871
  /* Add in the space for the copied structures.  */
872
  bytes += struct_copy_size;
873
 
874
  cif->flags = flags;
875
  cif->bytes = bytes;
876
 
877
  return FFI_OK;
878
}
879
 
880
extern void ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
881
                          void (*fn)(void));
882
extern void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long,
883
                                        unsigned long, unsigned long *,
884
                                        void (*fn)(void));
885
 
886
void
887
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
888
{
889
  extended_cif ecif;
890
 
891
  ecif.cif = cif;
892
  ecif.avalue = avalue;
893
 
894
  /* If the return value is a struct and we don't have a return */
895
  /* value address then we need to make one                     */
896
 
897
  if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
898
    {
899
      ecif.rvalue = alloca(cif->rtype->size);
900
    }
901
  else
902
    ecif.rvalue = rvalue;
903
 
904
 
905
  switch (cif->abi)
906
    {
907
#ifndef POWERPC64
908
    case FFI_SYSV:
909
    case FFI_GCC_SYSV:
910
    case FFI_LINUX:
911
    case FFI_LINUX_SOFT_FLOAT:
912
      ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
913
      break;
914
#else
915
    case FFI_LINUX64:
916
      ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
917
      break;
918
#endif
919
    default:
920
      FFI_ASSERT (0);
921
      break;
922
    }
923
}
924
 
925
 
926
#ifndef POWERPC64
927
#define MIN_CACHE_LINE_SIZE 8
928
 
929
static void
930
flush_icache (char *wraddr, char *xaddr, int size)
931
{
932
  int i;
933
  for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
934
    __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
935
                      : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
936
  __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
937
                    : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
938
                    : "memory");
939
}
940
#endif
941
 
942
ffi_status
943
ffi_prep_closure_loc (ffi_closure *closure,
944
                      ffi_cif *cif,
945
                      void (*fun) (ffi_cif *, void *, void **, void *),
946
                      void *user_data,
947
                      void *codeloc)
948
{
949
#ifdef POWERPC64
950
  void **tramp = (void **) &closure->tramp[0];
951
 
952
  FFI_ASSERT (cif->abi == FFI_LINUX64);
953
  /* Copy function address and TOC from ffi_closure_LINUX64.  */
954
  memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
955
  tramp[2] = codeloc;
956
#else
957
  unsigned int *tramp;
958
 
959
  FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV);
960
 
961
  tramp = (unsigned int *) &closure->tramp[0];
962
  tramp[0] = 0x7c0802a6;  /*   mflr    r0 */
963
  tramp[1] = 0x4800000d;  /*   bl      10 <trampoline_initial+0x10> */
964
  tramp[4] = 0x7d6802a6;  /*   mflr    r11 */
965
  tramp[5] = 0x7c0803a6;  /*   mtlr    r0 */
966
  tramp[6] = 0x800b0000;  /*   lwz     r0,0(r11) */
967
  tramp[7] = 0x816b0004;  /*   lwz     r11,4(r11) */
968
  tramp[8] = 0x7c0903a6;  /*   mtctr   r0 */
969
  tramp[9] = 0x4e800420;  /*   bctr */
970
  *(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
971
  *(void **) &tramp[3] = codeloc;                   /* context */
972
 
973
  /* Flush the icache.  */
974
  flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
975
#endif
976
 
977
  closure->cif = cif;
978
  closure->fun = fun;
979
  closure->user_data = user_data;
980
 
981
  return FFI_OK;
982
}
983
 
984
typedef union
985
{
986
  float f;
987
  double d;
988
} ffi_dblfl;
989
 
990
int ffi_closure_helper_SYSV (ffi_closure *, void *, unsigned long *,
991
                             ffi_dblfl *, unsigned long *);
992
 
993
/* Basically the trampoline invokes ffi_closure_SYSV, and on
994
 * entry, r11 holds the address of the closure.
995
 * After storing the registers that could possibly contain
996
 * parameters to be passed into the stack frame and setting
997
 * up space for a return value, ffi_closure_SYSV invokes the
998
 * following helper function to do most of the work
999
 */
1000
 
1001
int
1002
ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
1003
                         unsigned long *pgr, ffi_dblfl *pfr,
1004
                         unsigned long *pst)
1005
{
1006
  /* rvalue is the pointer to space for return value in closure assembly */
1007
  /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
1008
  /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV  */
1009
  /* pst is the pointer to outgoing parameter stack in original caller */
1010
 
1011
  void **          avalue;
1012
  ffi_type **      arg_types;
1013
  long             i, avn;
1014
  long             nf;   /* number of floating registers already used */
1015
  long             ng;   /* number of general registers already used */
1016
  ffi_cif *        cif;
1017
  double           temp;
1018
  unsigned         size;
1019
 
1020
  cif = closure->cif;
1021
  avalue = alloca (cif->nargs * sizeof (void *));
1022
  size = cif->rtype->size;
1023
 
1024
  nf = 0;
1025
  ng = 0;
1026
 
1027
  /* Copy the caller's structure return value address so that the closure
1028
     returns the data directly to the caller.
1029
     For FFI_SYSV the result is passed in r3/r4 if the struct size is less
1030
     or equal 8 bytes.  */
1031
 
1032
  if ((cif->rtype->type == FFI_TYPE_STRUCT
1033
       && !((cif->abi == FFI_SYSV) && (size <= 8)))
1034
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1035
      || (cif->rtype->type == FFI_TYPE_LONGDOUBLE
1036
          && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
1037
#endif
1038
      )
1039
    {
1040
      rvalue = (void *) *pgr;
1041
      ng++;
1042
      pgr++;
1043
    }
1044
 
1045
  i = 0;
1046
  avn = cif->nargs;
1047
  arg_types = cif->arg_types;
1048
 
1049
  /* Grab the addresses of the arguments from the stack frame.  */
1050
  while (i < avn)
1051
    {
1052
      switch (arg_types[i]->type)
1053
        {
1054
        case FFI_TYPE_SINT8:
1055
        case FFI_TYPE_UINT8:
1056
          /* there are 8 gpr registers used to pass values */
1057
          if (ng < 8)
1058
            {
1059
              avalue[i] = (char *) pgr + 3;
1060
              ng++;
1061
              pgr++;
1062
            }
1063
          else
1064
            {
1065
              avalue[i] = (char *) pst + 3;
1066
              pst++;
1067
            }
1068
          break;
1069
 
1070
        case FFI_TYPE_SINT16:
1071
        case FFI_TYPE_UINT16:
1072
          /* there are 8 gpr registers used to pass values */
1073
          if (ng < 8)
1074
            {
1075
              avalue[i] = (char *) pgr + 2;
1076
              ng++;
1077
              pgr++;
1078
            }
1079
          else
1080
            {
1081
              avalue[i] = (char *) pst + 2;
1082
              pst++;
1083
            }
1084
          break;
1085
 
1086
        case FFI_TYPE_SINT32:
1087
        case FFI_TYPE_UINT32:
1088
        case FFI_TYPE_POINTER:
1089
        soft_float_closure:
1090
          /* there are 8 gpr registers used to pass values */
1091
          if (ng < 8)
1092
            {
1093
              avalue[i] = pgr;
1094
              ng++;
1095
              pgr++;
1096
            }
1097
          else
1098
            {
1099
              avalue[i] = pst;
1100
              pst++;
1101
            }
1102
          break;
1103
 
1104
        case FFI_TYPE_STRUCT:
1105
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1106
        do_struct:
1107
#endif
1108
          /* Structs are passed by reference. The address will appear in a
1109
             gpr if it is one of the first 8 arguments.  */
1110
          if (ng < 8)
1111
            {
1112
              avalue[i] = (void *) *pgr;
1113
              ng++;
1114
              pgr++;
1115
            }
1116
          else
1117
            {
1118
              avalue[i] = (void *) *pst;
1119
              pst++;
1120
            }
1121
          break;
1122
 
1123
        case FFI_TYPE_SINT64:
1124
        case FFI_TYPE_UINT64:
1125
        soft_double_closure:
1126
          /* passing long long ints are complex, they must
1127
           * be passed in suitable register pairs such as
1128
           * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
1129
           * and if the entire pair aren't available then the outgoing
1130
           * parameter stack is used for both but an alignment of 8
1131
           * must will be kept.  So we must either look in pgr
1132
           * or pst to find the correct address for this type
1133
           * of parameter.
1134
           */
1135
          if (ng < 7)
1136
            {
1137
              if (ng & 0x01)
1138
                {
1139
                  /* skip r4, r6, r8 as starting points */
1140
                  ng++;
1141
                  pgr++;
1142
                }
1143
              avalue[i] = pgr;
1144
              ng += 2;
1145
              pgr += 2;
1146
            }
1147
          else
1148
            {
1149
              if (((long) pst) & 4)
1150
                pst++;
1151
              avalue[i] = pst;
1152
              pst += 2;
1153
              ng = 8;
1154
            }
1155
          break;
1156
 
1157
        case FFI_TYPE_FLOAT:
1158
          /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
1159
          if (cif->abi == FFI_LINUX_SOFT_FLOAT)
1160
            goto soft_float_closure;
1161
          /* unfortunately float values are stored as doubles
1162
           * in the ffi_closure_SYSV code (since we don't check
1163
           * the type in that routine).
1164
           */
1165
 
1166
          /* there are 8 64bit floating point registers */
1167
 
1168
          if (nf < 8)
1169
            {
1170
              temp = pfr->d;
1171
              pfr->f = (float) temp;
1172
              avalue[i] = pfr;
1173
              nf++;
1174
              pfr++;
1175
            }
1176
          else
1177
            {
1178
              /* FIXME? here we are really changing the values
1179
               * stored in the original calling routines outgoing
1180
               * parameter stack.  This is probably a really
1181
               * naughty thing to do but...
1182
               */
1183
              avalue[i] = pst;
1184
              pst += 1;
1185
            }
1186
          break;
1187
 
1188
        case FFI_TYPE_DOUBLE:
1189
          /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
1190
          if (cif->abi == FFI_LINUX_SOFT_FLOAT)
1191
            goto soft_double_closure;
1192
          /* On the outgoing stack all values are aligned to 8 */
1193
          /* there are 8 64bit floating point registers */
1194
 
1195
          if (nf < 8)
1196
            {
1197
              avalue[i] = pfr;
1198
              nf++;
1199
              pfr++;
1200
            }
1201
          else
1202
            {
1203
              if (((long) pst) & 4)
1204
                pst++;
1205
              avalue[i] = pst;
1206
              pst += 2;
1207
            }
1208
          break;
1209
 
1210
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1211
        case FFI_TYPE_LONGDOUBLE:
1212
          if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
1213
            goto do_struct;
1214
          if (cif->abi == FFI_LINUX_SOFT_FLOAT)
1215
            { /* Test if for the whole long double, 4 gprs are available.
1216
                 otherwise the stuff ends up on the stack.  */
1217
              if (ng < 5)
1218
                {
1219
                  avalue[i] = pgr;
1220
                  pgr += 4;
1221
                  ng += 4;
1222
                }
1223
              else
1224
                {
1225
                  avalue[i] = pst;
1226
                  pst += 4;
1227
                  ng = 8;
1228
                }
1229
              break;
1230
            }
1231
          if (nf < 7)
1232
            {
1233
              avalue[i] = pfr;
1234
              pfr += 2;
1235
              nf += 2;
1236
            }
1237
          else
1238
            {
1239
              if (((long) pst) & 4)
1240
                pst++;
1241
              avalue[i] = pst;
1242
              pst += 4;
1243
              nf = 8;
1244
            }
1245
          break;
1246
#endif
1247
 
1248
        default:
1249
          FFI_ASSERT (0);
1250
        }
1251
 
1252
      i++;
1253
    }
1254
 
1255
 
1256
  (closure->fun) (cif, rvalue, avalue, closure->user_data);
1257
 
1258
  /* Tell ffi_closure_SYSV how to perform return type promotions.
1259
     Because the FFI_SYSV ABI returns the structures <= 8 bytes in r3/r4
1260
     we have to tell ffi_closure_SYSV how to treat them. We combine the base
1261
     type FFI_SYSV_TYPE_SMALL_STRUCT - 1  with the size of the struct.
1262
     So a one byte struct gets the return type 16. Return type 1 to 15 are
1263
     already used and we never have a struct with size zero. That is the reason
1264
     for the subtraction of 1. See the comment in ffitarget.h about ordering.
1265
  */
1266
  if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
1267
      && size <= 8)
1268
    return (FFI_SYSV_TYPE_SMALL_STRUCT - 1) + size;
1269
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1270
  else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
1271
           && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
1272
    return FFI_TYPE_STRUCT;
1273
#endif
1274
  /* With FFI_LINUX_SOFT_FLOAT floats and doubles are handled like UINT32
1275
     respectivley UINT64.  */
1276
  if (cif->abi == FFI_LINUX_SOFT_FLOAT)
1277
    {
1278
      switch (cif->rtype->type)
1279
        {
1280
        case FFI_TYPE_FLOAT:
1281
          return FFI_TYPE_UINT32;
1282
          break;
1283
        case FFI_TYPE_DOUBLE:
1284
          return FFI_TYPE_UINT64;
1285
          break;
1286
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1287
        case FFI_TYPE_LONGDOUBLE:
1288
          return FFI_TYPE_UINT128;
1289
          break;
1290
#endif
1291
        default:
1292
          return cif->rtype->type;
1293
        }
1294
    }
1295
  else
1296
    {
1297
      return cif->rtype->type;
1298
    }
1299
}
1300
 
1301
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
1302
                                           unsigned long *, ffi_dblfl *);
1303
 
1304
int FFI_HIDDEN
1305
ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
1306
                            unsigned long *pst, ffi_dblfl *pfr)
1307
{
1308
  /* rvalue is the pointer to space for return value in closure assembly */
1309
  /* pst is the pointer to parameter save area
1310
     (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
1311
  /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
1312
 
1313
  void **avalue;
1314
  ffi_type **arg_types;
1315
  long i, avn;
1316
  ffi_cif *cif;
1317
  ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
1318
 
1319
  cif = closure->cif;
1320
  avalue = alloca (cif->nargs * sizeof (void *));
1321
 
1322
  /* Copy the caller's structure return value address so that the closure
1323
     returns the data directly to the caller.  */
1324
  if (cif->rtype->type == FFI_TYPE_STRUCT)
1325
    {
1326
      rvalue = (void *) *pst;
1327
      pst++;
1328
    }
1329
 
1330
  i = 0;
1331
  avn = cif->nargs;
1332
  arg_types = cif->arg_types;
1333
 
1334
  /* Grab the addresses of the arguments from the stack frame.  */
1335
  while (i < avn)
1336
    {
1337
      switch (arg_types[i]->type)
1338
        {
1339
        case FFI_TYPE_SINT8:
1340
        case FFI_TYPE_UINT8:
1341
          avalue[i] = (char *) pst + 7;
1342
          pst++;
1343
          break;
1344
 
1345
        case FFI_TYPE_SINT16:
1346
        case FFI_TYPE_UINT16:
1347
          avalue[i] = (char *) pst + 6;
1348
          pst++;
1349
          break;
1350
 
1351
        case FFI_TYPE_SINT32:
1352
        case FFI_TYPE_UINT32:
1353
          avalue[i] = (char *) pst + 4;
1354
          pst++;
1355
          break;
1356
 
1357
        case FFI_TYPE_SINT64:
1358
        case FFI_TYPE_UINT64:
1359
        case FFI_TYPE_POINTER:
1360
          avalue[i] = pst;
1361
          pst++;
1362
          break;
1363
 
1364
        case FFI_TYPE_STRUCT:
1365
          /* Structures with size less than eight bytes are passed
1366
             left-padded.  */
1367
          if (arg_types[i]->size < 8)
1368
            avalue[i] = (char *) pst + 8 - arg_types[i]->size;
1369
          else
1370
            avalue[i] = pst;
1371
          pst += (arg_types[i]->size + 7) / 8;
1372
          break;
1373
 
1374
        case FFI_TYPE_FLOAT:
1375
          /* unfortunately float values are stored as doubles
1376
           * in the ffi_closure_LINUX64 code (since we don't check
1377
           * the type in that routine).
1378
           */
1379
 
1380
          /* there are 13 64bit floating point registers */
1381
 
1382
          if (pfr < end_pfr)
1383
            {
1384
              double temp = pfr->d;
1385
              pfr->f = (float) temp;
1386
              avalue[i] = pfr;
1387
              pfr++;
1388
            }
1389
          else
1390
            avalue[i] = pst;
1391
          pst++;
1392
          break;
1393
 
1394
        case FFI_TYPE_DOUBLE:
1395
          /* On the outgoing stack all values are aligned to 8 */
1396
          /* there are 13 64bit floating point registers */
1397
 
1398
          if (pfr < end_pfr)
1399
            {
1400
              avalue[i] = pfr;
1401
              pfr++;
1402
            }
1403
          else
1404
            avalue[i] = pst;
1405
          pst++;
1406
          break;
1407
 
1408
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1409
        case FFI_TYPE_LONGDOUBLE:
1410
          if (pfr + 1 < end_pfr)
1411
            {
1412
              avalue[i] = pfr;
1413
              pfr += 2;
1414
            }
1415
          else
1416
            {
1417
              if (pfr < end_pfr)
1418
                {
1419
                  /* Passed partly in f13 and partly on the stack.
1420
                     Move it all to the stack.  */
1421
                  *pst = *(unsigned long *) pfr;
1422
                  pfr++;
1423
                }
1424
              avalue[i] = pst;
1425
            }
1426
          pst += 2;
1427
          break;
1428
#endif
1429
 
1430
        default:
1431
          FFI_ASSERT (0);
1432
        }
1433
 
1434
      i++;
1435
    }
1436
 
1437
 
1438
  (closure->fun) (cif, rvalue, avalue, closure->user_data);
1439
 
1440
  /* Tell ffi_closure_LINUX64 how to perform return type promotions.  */
1441
  return cif->rtype->type;
1442
}

powered by: WebSVN 2.1.0

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