~ubuntu-branches/ubuntu/saucy/mozjs17/saucy

« back to all changes in this revision

Viewing changes to js/src/ctypes/libffi/src/powerpc/ffi.c

  • Committer: Package Import Robot
  • Author(s): Rico Tzschichholz
  • Date: 2013-05-25 12:24:23 UTC
  • Revision ID: package-import@ubuntu.com-20130525122423-zmxucrhtensw90xy
Tags: upstream-17.0.0
ImportĀ upstreamĀ versionĀ 17.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -----------------------------------------------------------------------
 
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
}