~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#if defined(__ppc__) || defined(__ppc64__)
 
2
 
 
3
/* -----------------------------------------------------------------------
 
4
   ffi.c - Copyright (c) 1998 Geoffrey Keating
 
5
 
 
6
   PowerPC Foreign Function Interface
 
7
 
 
8
   Darwin ABI support (c) 2001 John Hornkvist
 
9
   AIX ABI support (c) 2002 Free Software Foundation, Inc.
 
10
 
 
11
   Permission is hereby granted, free of charge, to any person obtaining
 
12
   a copy of this software and associated documentation files (the
 
13
   ``Software''), to deal in the Software without restriction, including
 
14
   without limitation the rights to use, copy, modify, merge, publish,
 
15
   distribute, sublicense, and/or sell copies of the Software, and to
 
16
   permit persons to whom the Software is furnished to do so, subject to
 
17
   the following conditions:
 
18
 
 
19
   The above copyright notice and this permission notice shall be included
 
20
   in all copies or substantial portions of the Software.
 
21
 
 
22
   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
23
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
24
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
25
   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
26
   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
27
   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
28
   OTHER DEALINGS IN THE SOFTWARE.
 
29
   ----------------------------------------------------------------------- */
 
30
 
 
31
#include "ffi.h"
 
32
#include "ffi_common.h"
 
33
 
 
34
#include <stdbool.h>
 
35
#include <stdio.h>
 
36
#include <stdlib.h>
 
37
#include "ppc-darwin.h"
 
38
#include <architecture/ppc/mode_independent_asm.h>
 
39
 
 
40
#if 0
 
41
#if defined(POWERPC_DARWIN)
 
42
#include <libkern/OSCacheControl.h>     // for sys_icache_invalidate()
 
43
#endif
 
44
 
 
45
#else 
 
46
 
 
47
/* Explicit prototype instead of including a header to allow compilation
 
48
 * on Tiger systems.
 
49
 */
 
50
 
 
51
#pragma weak sys_icache_invalidate
 
52
extern void sys_icache_invalidate(void *start, size_t len);
 
53
 
 
54
#endif
 
55
 
 
56
extern void ffi_closure_ASM(void);
 
57
 
 
58
// The layout of a function descriptor.  A C function pointer really
 
59
// points to one of these.
 
60
typedef struct aix_fd_struct {
 
61
  void* code_pointer;
 
62
  void* toc;
 
63
} aix_fd;
 
64
 
 
65
/* ffi_prep_args is called by the assembly routine once stack space
 
66
   has been allocated for the function's arguments.
 
67
 
 
68
   The stack layout we want looks like this:
 
69
 
 
70
   |   Return address from ffi_call_DARWIN      |       higher addresses
 
71
   |--------------------------------------------|
 
72
   |   Previous backchain pointer      4/8      |           stack pointer here
 
73
   |--------------------------------------------|-\ <<< on entry to
 
74
   |   Saved r28-r31                 (4/8)*4    | |         ffi_call_DARWIN
 
75
   |--------------------------------------------| |
 
76
   |   Parameters      (at least 8*(4/8)=32/64) | | (176) +112 - +288
 
77
   |--------------------------------------------| |
 
78
   |   Space for GPR2                  4/8      | |
 
79
   |--------------------------------------------| |     stack   |
 
80
   |   Reserved                                          (4/8)*2    | | grows   |
 
81
   |--------------------------------------------| |     down    V
 
82
   |   Space for callee's LR           4/8      | |
 
83
   |--------------------------------------------| |     lower addresses
 
84
   |   Saved CR                        4/8      | |
 
85
   |--------------------------------------------| |     stack pointer here
 
86
   |   Current backchain pointer       4/8      | |     during
 
87
   |--------------------------------------------|-/ <<< ffi_call_DARWIN
 
88
 
 
89
        Note: ppc64 CR is saved in the low word of a long on the stack.
 
90
*/
 
91
 
 
92
/*@-exportheader@*/
 
93
void
 
94
ffi_prep_args(
 
95
        extended_cif*   inEcif,
 
96
        unsigned *const stack)
 
97
/*@=exportheader@*/
 
98
{
 
99
        /*      Copy the ecif to a local var so we can trample the arg.
 
100
                BC note: test this with GP later for possible problems...       */
 
101
        volatile extended_cif*  ecif    = inEcif;
 
102
 
 
103
        const unsigned bytes    = ecif->cif->bytes;
 
104
        const unsigned flags    = ecif->cif->flags;
 
105
 
 
106
        /*      Cast the stack arg from int* to long*. sizeof(long) == 4 in 32-bit mode
 
107
                and 8 in 64-bit mode.   */
 
108
        unsigned long *const longStack  = (unsigned long *const)stack;
 
109
 
 
110
        /* 'stacktop' points at the previous backchain pointer. */
 
111
#if defined(__ppc64__)
 
112
        //      In ppc-darwin.s, an extra 96 bytes is reserved for the linkage area,
 
113
        //      saved registers, and an extra FPR.
 
114
        unsigned long *const stacktop   =
 
115
                (unsigned long *)(unsigned long)((char*)longStack + bytes + 96);
 
116
#elif defined(__ppc__)
 
117
        unsigned long *const stacktop   = longStack + (bytes / sizeof(long));
 
118
#else
 
119
#error undefined architecture
 
120
#endif
 
121
 
 
122
        /* 'fpr_base' points at the space for fpr1, and grows upwards as
 
123
                we use FPR registers.  */
 
124
        double*         fpr_base = (double*)(stacktop - ASM_NEEDS_REGISTERS) -
 
125
                NUM_FPR_ARG_REGISTERS;
 
126
 
 
127
#if defined(__ppc64__)
 
128
        //      64-bit saves an extra register, and uses an extra FPR. Knock fpr_base
 
129
        //      down a couple pegs.
 
130
        fpr_base -= 2;
 
131
#endif
 
132
 
 
133
        unsigned int    fparg_count = 0;
 
134
 
 
135
        /* 'next_arg' grows up as we put parameters in it.  */
 
136
        unsigned long*  next_arg = longStack + 6; /* 6 reserved positions.  */
 
137
 
 
138
        int                             i;
 
139
        double                  double_tmp;
 
140
        void**                  p_argv = ecif->avalue;
 
141
        unsigned long   gprvalue;
 
142
        ffi_type**              ptr = ecif->cif->arg_types;
 
143
 
 
144
        /* Check that everything starts aligned properly.  */
 
145
        FFI_ASSERT(stack == SF_ROUND(stack));
 
146
        FFI_ASSERT(stacktop == SF_ROUND(stacktop));
 
147
        FFI_ASSERT(bytes == SF_ROUND(bytes));
 
148
 
 
149
        /*      Deal with return values that are actually pass-by-reference.
 
150
                Rule:
 
151
                Return values are referenced by r3, so r4 is the first parameter.  */
 
152
 
 
153
        if (flags & FLAG_RETVAL_REFERENCE)
 
154
                *next_arg++ = (unsigned long)(char*)ecif->rvalue;
 
155
 
 
156
        /* Now for the arguments.  */
 
157
        for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++)
 
158
    {
 
159
                switch ((*ptr)->type)
 
160
                {
 
161
                        /*      If a floating-point parameter appears before all of the general-
 
162
                                purpose registers are filled, the corresponding GPRs that match
 
163
                                the size of the floating-point parameter are shadowed for the
 
164
                                benefit of vararg and pre-ANSI functions.       */
 
165
                        case FFI_TYPE_FLOAT:
 
166
                                double_tmp = *(float*)*p_argv;
 
167
 
 
168
                                if (fparg_count < NUM_FPR_ARG_REGISTERS)
 
169
                                        *fpr_base++ = double_tmp;
 
170
 
 
171
                                *(double*)next_arg = double_tmp;
 
172
 
 
173
                                next_arg++;
 
174
                                fparg_count++;
 
175
                                FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
 
176
 
 
177
                                break;
 
178
 
 
179
                        case FFI_TYPE_DOUBLE:
 
180
                                double_tmp = *(double*)*p_argv;
 
181
 
 
182
                                if (fparg_count < NUM_FPR_ARG_REGISTERS)
 
183
                                        *fpr_base++ = double_tmp;
 
184
 
 
185
                                *(double*)next_arg = double_tmp;
 
186
 
 
187
                                next_arg += MODE_CHOICE(2,1);
 
188
                                fparg_count++;
 
189
                                FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
 
190
 
 
191
                                break;
 
192
 
 
193
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 
194
                        case FFI_TYPE_LONGDOUBLE:
 
195
#if defined(__ppc64__)
 
196
                                if (fparg_count < NUM_FPR_ARG_REGISTERS)
 
197
                                        *(long double*)fpr_base = *(long double*)*p_argv;
 
198
#elif defined(__ppc__)
 
199
                                if (fparg_count < NUM_FPR_ARG_REGISTERS - 1)
 
200
                                        *(long double*)fpr_base = *(long double*)*p_argv;
 
201
                                else if (fparg_count == NUM_FPR_ARG_REGISTERS - 1)
 
202
                                        *(double*)fpr_base      = *(double*)*p_argv;
 
203
#else
 
204
#error undefined architecture
 
205
#endif
 
206
 
 
207
                                *(long double*)next_arg = *(long double*)*p_argv;
 
208
                                fparg_count += 2;
 
209
                                fpr_base += 2;
 
210
                                next_arg += MODE_CHOICE(4,2);
 
211
                                FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
 
212
 
 
213
                                break;
 
214
#endif  //      FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 
215
 
 
216
                        case FFI_TYPE_UINT64:
 
217
                        case FFI_TYPE_SINT64:
 
218
#if defined(__ppc64__)
 
219
                                gprvalue = *(long long*)*p_argv;
 
220
                                goto putgpr;
 
221
#elif defined(__ppc__)
 
222
                                *(long long*)next_arg = *(long long*)*p_argv;
 
223
                                next_arg += 2;
 
224
                                break;
 
225
#else
 
226
#error undefined architecture
 
227
#endif
 
228
 
 
229
                        case FFI_TYPE_POINTER:
 
230
                                gprvalue = *(unsigned long*)*p_argv;
 
231
                                goto putgpr;
 
232
 
 
233
                        case FFI_TYPE_UINT8:
 
234
                                gprvalue = *(unsigned char*)*p_argv;
 
235
                                goto putgpr;
 
236
 
 
237
                        case FFI_TYPE_SINT8:
 
238
                                gprvalue = *(signed char*)*p_argv;
 
239
                                goto putgpr;
 
240
 
 
241
                        case FFI_TYPE_UINT16:
 
242
                                gprvalue = *(unsigned short*)*p_argv;
 
243
                                goto putgpr;
 
244
 
 
245
                        case FFI_TYPE_SINT16:
 
246
                                gprvalue = *(signed short*)*p_argv;
 
247
                                goto putgpr;
 
248
 
 
249
                        case FFI_TYPE_STRUCT:
 
250
                        {
 
251
#if defined(__ppc64__)
 
252
                                unsigned int    gprSize = 0;
 
253
                                unsigned int    fprSize = 0;
 
254
 
 
255
                                ffi64_struct_to_reg_form(*ptr, (char*)*p_argv, NULL, &fparg_count,
 
256
                                        (char*)next_arg, &gprSize, (char*)fpr_base, &fprSize);
 
257
                                next_arg += gprSize / sizeof(long);
 
258
                                fpr_base += fprSize / sizeof(double);
 
259
 
 
260
#elif defined(__ppc__)
 
261
                                char*   dest_cpy = (char*)next_arg;
 
262
 
 
263
                        /*      Structures that match the basic modes (QI 1 byte, HI 2 bytes,
 
264
                                SI 4 bytes) are aligned as if they were those modes.
 
265
                                Structures with 3 byte in size are padded upwards.  */
 
266
                                unsigned size_al = (*ptr)->size;
 
267
 
 
268
                        /*      If the first member of the struct is a double, then align
 
269
                                the struct to double-word.  */
 
270
                                if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
 
271
                                        size_al = ALIGN((*ptr)->size, 8);
 
272
 
 
273
                                if (ecif->cif->abi == FFI_DARWIN)
 
274
                                {
 
275
                                        if (size_al < 3)
 
276
                                                dest_cpy += 4 - size_al;
 
277
                                }
 
278
 
 
279
                                memcpy((char*)dest_cpy, (char*)*p_argv, size_al);
 
280
                                next_arg += (size_al + 3) / 4;
 
281
#else
 
282
#error undefined architecture
 
283
#endif
 
284
                                break;
 
285
                        }
 
286
 
 
287
                        case FFI_TYPE_INT:
 
288
                        case FFI_TYPE_UINT32:
 
289
                        case FFI_TYPE_SINT32:
 
290
                                gprvalue = *(unsigned*)*p_argv;
 
291
 
 
292
putgpr:
 
293
                                *next_arg++ = gprvalue;
 
294
                                break;
 
295
 
 
296
                        default:
 
297
                                break;
 
298
                }
 
299
        }
 
300
 
 
301
  /* Check that we didn't overrun the stack...  */
 
302
  //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
 
303
  //FFI_ASSERT((unsigned *)fpr_base
 
304
  //         <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
 
305
  //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
 
306
}
 
307
 
 
308
#if defined(__ppc64__)
 
309
 
 
310
bool
 
311
ffi64_struct_contains_fp(
 
312
        const ffi_type* inType)
 
313
{
 
314
        bool                    containsFP      = false;
 
315
        unsigned int    i;
 
316
 
 
317
        for (i = 0; inType->elements[i] != NULL && !containsFP; i++)
 
318
        {
 
319
                if (inType->elements[i]->type == FFI_TYPE_FLOAT         ||
 
320
                        inType->elements[i]->type == FFI_TYPE_DOUBLE    ||
 
321
                        inType->elements[i]->type == FFI_TYPE_LONGDOUBLE)
 
322
                        containsFP = true;
 
323
                else if (inType->elements[i]->type == FFI_TYPE_STRUCT)
 
324
                        containsFP = ffi64_struct_contains_fp(inType->elements[i]);
 
325
        }
 
326
 
 
327
        return containsFP;
 
328
}
 
329
 
 
330
#endif  // defined(__ppc64__)
 
331
 
 
332
/* Perform machine dependent cif processing.  */
 
333
ffi_status
 
334
ffi_prep_cif_machdep(
 
335
        ffi_cif*        cif)
 
336
{
 
337
        /* All this is for the DARWIN ABI.  */
 
338
        int                             i;
 
339
        ffi_type**              ptr;
 
340
        int                             intarg_count = 0;
 
341
        int                             fparg_count = 0;
 
342
        unsigned int    flags = 0;
 
343
        unsigned int    size_al = 0;
 
344
 
 
345
        /*      All the machine-independent calculation of cif->bytes will be wrong.
 
346
                Redo the calculation for DARWIN.  */
 
347
 
 
348
        /*      Space for the frame pointer, callee's LR, CR, etc, and for
 
349
                the asm's temp regs.  */
 
350
        unsigned int    bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long);
 
351
 
 
352
        /*      Return value handling.  The rules are as follows:
 
353
                - 32-bit (or less) integer values are returned in gpr3;
 
354
                - Structures of size <= 4 bytes also returned in gpr3;
 
355
                - 64-bit integer values and structures between 5 and 8 bytes are
 
356
                        returned in gpr3 and gpr4;
 
357
                - Single/double FP values are returned in fpr1;
 
358
                - Long double FP (if not equivalent to double) values are returned in
 
359
                        fpr1 and fpr2;
 
360
                - Larger structures values are allocated space and a pointer is passed
 
361
                        as the first argument.  */
 
362
        switch (cif->rtype->type)
 
363
        {
 
364
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 
365
                case FFI_TYPE_LONGDOUBLE:
 
366
                        flags |= FLAG_RETURNS_128BITS;
 
367
                        flags |= FLAG_RETURNS_FP;
 
368
                        break;
 
369
#endif  // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 
370
 
 
371
                case FFI_TYPE_DOUBLE:
 
372
                        flags |= FLAG_RETURNS_64BITS;
 
373
                        /* Fall through.  */
 
374
                case FFI_TYPE_FLOAT:
 
375
                        flags |= FLAG_RETURNS_FP;
 
376
                        break;
 
377
 
 
378
#if defined(__ppc64__)
 
379
                case FFI_TYPE_POINTER:
 
380
#endif
 
381
                case FFI_TYPE_UINT64:
 
382
                case FFI_TYPE_SINT64:
 
383
                        flags |= FLAG_RETURNS_64BITS;
 
384
                        break;
 
385
 
 
386
                case FFI_TYPE_STRUCT:
 
387
                {
 
388
#if defined(__ppc64__)
 
389
 
 
390
                        if (ffi64_stret_needs_ptr(cif->rtype, NULL, NULL))
 
391
                        {
 
392
                                flags |= FLAG_RETVAL_REFERENCE;
 
393
                                flags |= FLAG_RETURNS_NOTHING;
 
394
                                intarg_count++;
 
395
                        }
 
396
                        else
 
397
                        {
 
398
                                flags |= FLAG_RETURNS_STRUCT;
 
399
 
 
400
                                if (ffi64_struct_contains_fp(cif->rtype))
 
401
                                        flags |= FLAG_STRUCT_CONTAINS_FP;
 
402
                        }
 
403
 
 
404
#elif defined(__ppc__)
 
405
 
 
406
                        flags |= FLAG_RETVAL_REFERENCE;
 
407
                        flags |= FLAG_RETURNS_NOTHING;
 
408
                        intarg_count++;
 
409
 
 
410
#else
 
411
#error undefined architecture
 
412
#endif
 
413
                        break;
 
414
                }
 
415
 
 
416
                case FFI_TYPE_VOID:
 
417
                        flags |= FLAG_RETURNS_NOTHING;
 
418
                        break;
 
419
 
 
420
                default:
 
421
                        /* Returns 32-bit integer, or similar.  Nothing to do here.  */
 
422
                        break;
 
423
        }
 
424
 
 
425
        /*      The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
 
426
                first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
 
427
                goes on the stack.  Structures are passed as a pointer to a copy of
 
428
                the structure. Stuff on the stack needs to keep proper alignment.  */
 
429
        for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
 
430
        {
 
431
                switch ((*ptr)->type)
 
432
                {
 
433
                        case FFI_TYPE_FLOAT:
 
434
                        case FFI_TYPE_DOUBLE:
 
435
                                fparg_count++;
 
436
                                /*      If this FP arg is going on the stack, it must be
 
437
                                        8-byte-aligned.  */
 
438
                                if (fparg_count > NUM_FPR_ARG_REGISTERS
 
439
                                        && intarg_count % 2 != 0)
 
440
                                        intarg_count++;
 
441
                                break;
 
442
 
 
443
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 
444
                        case FFI_TYPE_LONGDOUBLE:
 
445
                                fparg_count += 2;
 
446
                                /*      If this FP arg is going on the stack, it must be
 
447
                                        8-byte-aligned.  */
 
448
 
 
449
                                if (
 
450
#if defined(__ppc64__)
 
451
                                        fparg_count > NUM_FPR_ARG_REGISTERS + 1
 
452
#elif defined(__ppc__)
 
453
                                        fparg_count > NUM_FPR_ARG_REGISTERS
 
454
#else
 
455
#error undefined architecture
 
456
#endif
 
457
                                        && intarg_count % 2 != 0)
 
458
                                        intarg_count++;
 
459
 
 
460
                                intarg_count += 2;
 
461
                                break;
 
462
#endif  // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 
463
 
 
464
                        case FFI_TYPE_UINT64:
 
465
                        case FFI_TYPE_SINT64:
 
466
                                /*      'long long' arguments are passed as two words, but
 
467
                                        either both words must fit in registers or both go
 
468
                                        on the stack.  If they go on the stack, they must
 
469
                                        be 8-byte-aligned.  */
 
470
                                if (intarg_count == NUM_GPR_ARG_REGISTERS - 1
 
471
                                        || (intarg_count >= NUM_GPR_ARG_REGISTERS
 
472
                                        && intarg_count % 2 != 0))
 
473
                                        intarg_count++;
 
474
 
 
475
                                intarg_count += MODE_CHOICE(2,1);
 
476
 
 
477
                                break;
 
478
 
 
479
                        case FFI_TYPE_STRUCT:
 
480
                                size_al = (*ptr)->size;
 
481
                                /*      If the first member of the struct is a double, then align
 
482
                                        the struct to double-word.  */
 
483
                                if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
 
484
                                        size_al = ALIGN((*ptr)->size, 8);
 
485
 
 
486
#if defined(__ppc64__)
 
487
                                // Look for FP struct members.
 
488
                                unsigned int    j;
 
489
 
 
490
                                for (j = 0; (*ptr)->elements[j] != NULL; j++)
 
491
                                {
 
492
                                        if ((*ptr)->elements[j]->type == FFI_TYPE_FLOAT ||
 
493
                                                (*ptr)->elements[j]->type == FFI_TYPE_DOUBLE)
 
494
                                        {
 
495
                                                fparg_count++;
 
496
 
 
497
                                                if (fparg_count > NUM_FPR_ARG_REGISTERS)
 
498
                                                        intarg_count++;
 
499
                                        }
 
500
                                        else if ((*ptr)->elements[j]->type == FFI_TYPE_LONGDOUBLE)
 
501
                                        {
 
502
                                                fparg_count += 2;
 
503
 
 
504
                                                if (fparg_count > NUM_FPR_ARG_REGISTERS + 1)
 
505
                                                        intarg_count += 2;
 
506
                                        }
 
507
                                        else
 
508
                                                intarg_count++;
 
509
                                }
 
510
#elif defined(__ppc__)
 
511
                                intarg_count += (size_al + 3) / 4;
 
512
#else
 
513
#error undefined architecture
 
514
#endif
 
515
 
 
516
                                break;
 
517
 
 
518
                        default:
 
519
                                /*      Everything else is passed as a 4/8-byte word in a GPR, either
 
520
                                        the object itself or a pointer to it.  */
 
521
                                intarg_count++;
 
522
                                break;
 
523
                }
 
524
        }
 
525
 
 
526
        /* Space for the FPR registers, if needed.  */
 
527
        if (fparg_count != 0)
 
528
        {
 
529
                flags |= FLAG_FP_ARGUMENTS;
 
530
#if defined(__ppc64__)
 
531
                bytes += (NUM_FPR_ARG_REGISTERS + 1) * sizeof(double);
 
532
#elif defined(__ppc__)
 
533
                bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
 
534
#else
 
535
#error undefined architecture
 
536
#endif
 
537
        }
 
538
 
 
539
        /* Stack space.  */
 
540
#if defined(__ppc64__)
 
541
        if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS)
 
542
                bytes += (intarg_count + fparg_count) * sizeof(long);
 
543
#elif defined(__ppc__)
 
544
        if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
 
545
                bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
 
546
#else
 
547
#error undefined architecture
 
548
#endif
 
549
        else
 
550
                bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
 
551
 
 
552
        /* The stack space allocated needs to be a multiple of 16/32 bytes.  */
 
553
        bytes = SF_ROUND(bytes);
 
554
 
 
555
        cif->flags = flags;
 
556
        cif->bytes = bytes;
 
557
 
 
558
        return FFI_OK;
 
559
}
 
560
 
 
561
/*@-declundef@*/
 
562
/*@-exportheader@*/
 
563
extern void
 
564
ffi_call_AIX(
 
565
/*@out@*/       extended_cif*,
 
566
                        unsigned,
 
567
                        unsigned,
 
568
/*@out@*/       unsigned*,
 
569
                        void (*fn)(void),
 
570
                        void (*fn2)(extended_cif*, unsigned *const));
 
571
 
 
572
extern void
 
573
ffi_call_DARWIN(
 
574
/*@out@*/       extended_cif*,
 
575
                        unsigned long,
 
576
                        unsigned,
 
577
/*@out@*/       unsigned*,
 
578
                        void (*fn)(void),
 
579
                        void (*fn2)(extended_cif*, unsigned *const));
 
580
/*@=declundef@*/
 
581
/*@=exportheader@*/
 
582
 
 
583
void
 
584
ffi_call(
 
585
/*@dependent@*/ ffi_cif*        cif,
 
586
                                void            (*fn)(void),
 
587
/*@out@*/               void*           rvalue,
 
588
/*@dependent@*/ void**          avalue)
 
589
{
 
590
        extended_cif ecif;
 
591
 
 
592
        ecif.cif = cif;
 
593
        ecif.avalue = avalue;
 
594
 
 
595
        /*      If the return value is a struct and we don't have a return
 
596
                value address then we need to make one.  */
 
597
        if ((rvalue == NULL) &&
 
598
                (cif->rtype->type == FFI_TYPE_STRUCT))
 
599
        {
 
600
                /*@-sysunrecog@*/
 
601
                ecif.rvalue = alloca(cif->rtype->size);
 
602
                /*@=sysunrecog@*/
 
603
        }
 
604
        else
 
605
                ecif.rvalue = rvalue;
 
606
 
 
607
        switch (cif->abi)
 
608
        {
 
609
                case FFI_AIX:
 
610
                        /*@-usedef@*/
 
611
                        ffi_call_AIX(&ecif, -cif->bytes,
 
612
                                cif->flags, ecif.rvalue, fn, ffi_prep_args);
 
613
                        /*@=usedef@*/
 
614
                        break;
 
615
 
 
616
                case FFI_DARWIN:
 
617
                        /*@-usedef@*/
 
618
                        ffi_call_DARWIN(&ecif, -(long)cif->bytes,
 
619
                                cif->flags, ecif.rvalue, fn, ffi_prep_args);
 
620
                        /*@=usedef@*/
 
621
                        break;
 
622
 
 
623
                default:
 
624
                        FFI_ASSERT(0);
 
625
                        break;
 
626
    }
 
627
}
 
628
 
 
629
/* here I'd like to add the stack frame layout we use in darwin_closure.S
 
630
   and aix_clsoure.S
 
631
 
 
632
   SP previous -> +---------------------------------------+ <--- child frame
 
633
                  | back chain to caller 4                |
 
634
                  +---------------------------------------+ 4
 
635
                  | saved CR 4                            |
 
636
                  +---------------------------------------+ 8
 
637
                  | saved LR 4                            |
 
638
                  +---------------------------------------+ 12
 
639
                  | reserved for compilers 4              |
 
640
                  +---------------------------------------+ 16
 
641
                  | reserved for binders 4                |
 
642
                  +---------------------------------------+ 20
 
643
                  | saved TOC pointer 4                   |
 
644
                  +---------------------------------------+ 24
 
645
                  | always reserved 8*4=32 (previous GPRs)|
 
646
                  | according to the linkage convention   |
 
647
                  | from AIX                              |
 
648
                  +---------------------------------------+ 56
 
649
                  | our FPR area 13*8=104                 |
 
650
                  | f1                                    |
 
651
                  | .                                     |
 
652
                  | f13                                   |
 
653
                  +---------------------------------------+ 160
 
654
                  | result area 8                         |
 
655
                  +---------------------------------------+ 168
 
656
                  | alignement to the next multiple of 16 |
 
657
SP current -->    +---------------------------------------+ 176 <- parent frame
 
658
                  | back chain to caller 4                |
 
659
                  +---------------------------------------+ 180
 
660
                  | saved CR 4                            |
 
661
                  +---------------------------------------+ 184
 
662
                  | saved LR 4                            |
 
663
                  +---------------------------------------+ 188
 
664
                  | reserved for compilers 4              |
 
665
                  +---------------------------------------+ 192
 
666
                  | reserved for binders 4                |
 
667
                  +---------------------------------------+ 196
 
668
                  | saved TOC pointer 4                   |
 
669
                  +---------------------------------------+ 200
 
670
                  | always reserved 8*4=32  we store our  |
 
671
                  | GPRs here                             |
 
672
                  | r3                                    |
 
673
                  | .                                     |
 
674
                  | r10                                   |
 
675
                  +---------------------------------------+ 232
 
676
                  | overflow part                         |
 
677
                  +---------------------------------------+ xxx
 
678
                  | ????                                  |
 
679
                  +---------------------------------------+ xxx
 
680
*/
 
681
 
 
682
#if !defined(POWERPC_DARWIN)
 
683
 
 
684
#define MIN_LINE_SIZE 32
 
685
 
 
686
static void
 
687
flush_icache(
 
688
        char*   addr)
 
689
{
 
690
#ifndef _AIX
 
691
        __asm__ volatile (
 
692
                "dcbf 0,%0\n"
 
693
                "sync\n"
 
694
                "icbi 0,%0\n"
 
695
                "sync\n"
 
696
                "isync"
 
697
                : : "r" (addr) : "memory");
 
698
#endif
 
699
}
 
700
 
 
701
static void
 
702
flush_range(
 
703
        char*   addr,
 
704
        int             size)
 
705
{
 
706
        int i;
 
707
 
 
708
        for (i = 0; i < size; i += MIN_LINE_SIZE)
 
709
                flush_icache(addr + i);
 
710
 
 
711
        flush_icache(addr + size - 1);
 
712
}
 
713
 
 
714
#endif  // !defined(POWERPC_DARWIN)
 
715
 
 
716
ffi_status
 
717
ffi_prep_closure(
 
718
        ffi_closure*    closure,
 
719
        ffi_cif*                cif,
 
720
        void                    (*fun)(ffi_cif*, void*, void**, void*),
 
721
        void*                   user_data)
 
722
{
 
723
        switch (cif->abi)
 
724
        {
 
725
                case FFI_DARWIN:
 
726
                {
 
727
                        FFI_ASSERT (cif->abi == FFI_DARWIN);
 
728
 
 
729
                        unsigned int*   tramp = (unsigned int*)&closure->tramp[0];
 
730
 
 
731
#if defined(__ppc64__)
 
732
                        tramp[0] = 0x7c0802a6;  //      mflr    r0
 
733
                        tramp[1] = 0x429f0005;  //      bcl             20,31,+0x8
 
734
                        tramp[2] = 0x7d6802a6;  //      mflr    r11
 
735
                        tramp[3] = 0x7c0803a6;  //      mtlr    r0
 
736
                        tramp[4] = 0xe98b0018;  //      ld              r12,24(r11)
 
737
                        tramp[5] = 0x7d8903a6;  //      mtctr   r12
 
738
                        tramp[6] = 0xe96b0020;  //      ld              r11,32(r11)
 
739
                        tramp[7] = 0x4e800420;  //      bctr
 
740
                        *(unsigned long*)&tramp[8] = (unsigned long)ffi_closure_ASM;
 
741
                        *(unsigned long*)&tramp[10] = (unsigned long)closure;
 
742
#elif defined(__ppc__)
 
743
                        tramp[0] = 0x7c0802a6;  //      mflr    r0
 
744
                        tramp[1] = 0x429f0005;  //      bcl             20,31,+0x8
 
745
                        tramp[2] = 0x7d6802a6;  //      mflr    r11
 
746
                        tramp[3] = 0x7c0803a6;  //      mtlr    r0
 
747
                        tramp[4] = 0x818b0018;  //      lwz             r12,24(r11)
 
748
                        tramp[5] = 0x7d8903a6;  //      mtctr   r12
 
749
                        tramp[6] = 0x816b001c;  //      lwz             r11,28(r11)
 
750
                        tramp[7] = 0x4e800420;  //      bctr
 
751
                        tramp[8] = (unsigned long)ffi_closure_ASM;
 
752
                        tramp[9] = (unsigned long)closure;
 
753
#else
 
754
#error undefined architecture
 
755
#endif
 
756
 
 
757
                        closure->cif = cif;
 
758
                        closure->fun = fun;
 
759
                        closure->user_data = user_data;
 
760
 
 
761
                        // Flush the icache. Only necessary on Darwin.
 
762
#if defined(POWERPC_DARWIN)
 
763
                        if (sys_icache_invalidate) {
 
764
                                sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE);
 
765
                        }
 
766
#else
 
767
                        flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE);
 
768
#endif
 
769
 
 
770
                        break;
 
771
                }
 
772
 
 
773
                case FFI_AIX:
 
774
                {
 
775
                        FFI_ASSERT (cif->abi == FFI_AIX);
 
776
 
 
777
                        ffi_aix_trampoline_struct*      tramp_aix =
 
778
                                (ffi_aix_trampoline_struct*)(closure->tramp);
 
779
                        aix_fd* fd = (aix_fd*)(void*)ffi_closure_ASM;
 
780
 
 
781
                        tramp_aix->code_pointer = fd->code_pointer;
 
782
                        tramp_aix->toc = fd->toc;
 
783
                        tramp_aix->static_chain = closure;
 
784
                        closure->cif = cif;
 
785
                        closure->fun = fun;
 
786
                        closure->user_data = user_data;
 
787
                        break;
 
788
                }
 
789
 
 
790
                default:
 
791
                        return FFI_BAD_ABI;
 
792
        }
 
793
 
 
794
        return FFI_OK;
 
795
}
 
796
 
 
797
#if defined(__ppc__)
 
798
        typedef double ldbits[2];
 
799
 
 
800
        typedef union
 
801
        {
 
802
                ldbits lb;
 
803
                long double ld;
 
804
        } ldu;
 
805
#endif
 
806
 
 
807
/*      The trampoline invokes ffi_closure_ASM, and on entry, r11 holds the
 
808
        address of the closure. After storing the registers that could possibly
 
809
        contain parameters to be passed into the stack frame and setting up space
 
810
        for a return value, ffi_closure_ASM invokes the following helper function
 
811
        to do most of the work.  */
 
812
int
 
813
ffi_closure_helper_DARWIN(
 
814
        ffi_closure*    closure,
 
815
        void*                   rvalue,
 
816
        unsigned long*  pgr,
 
817
        ffi_dblfl*              pfr)
 
818
{
 
819
        /*      rvalue is the pointer to space for return value in closure assembly
 
820
                pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
 
821
                pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM.  */
 
822
 
 
823
#if defined(__ppc__)
 
824
        ldu     temp_ld;
 
825
#endif
 
826
 
 
827
        double                          temp;
 
828
        unsigned int            i;
 
829
        unsigned int            nf = 0; /* number of FPRs already used.  */
 
830
        unsigned int            ng = 0; /* number of GPRs already used.  */
 
831
        ffi_cif*                        cif = closure->cif;
 
832
        unsigned int                            avn = cif->nargs;
 
833
        void**                          avalue = alloca(cif->nargs * sizeof(void*));
 
834
        ffi_type**                      arg_types = cif->arg_types;
 
835
 
 
836
        /*      Copy the caller's structure return value address so that the closure
 
837
                returns the data directly to the caller.  */
 
838
#if defined(__ppc64__)
 
839
        if (cif->rtype->type == FFI_TYPE_STRUCT &&
 
840
                ffi64_stret_needs_ptr(cif->rtype, NULL, NULL))
 
841
#elif defined(__ppc__)
 
842
        if (cif->rtype->type == FFI_TYPE_STRUCT)
 
843
#else
 
844
#error undefined architecture
 
845
#endif
 
846
        {
 
847
                rvalue = (void*)*pgr;
 
848
                pgr++;
 
849
                ng++;
 
850
        }
 
851
 
 
852
        /* Grab the addresses of the arguments from the stack frame.  */
 
853
        for (i = 0; i < avn; i++)
 
854
        {
 
855
                switch (arg_types[i]->type)
 
856
                {
 
857
                        case FFI_TYPE_SINT8:
 
858
                        case FFI_TYPE_UINT8:
 
859
                                avalue[i] = (char*)pgr + MODE_CHOICE(3,7);
 
860
                                ng++;
 
861
                                pgr++;
 
862
                                break;
 
863
 
 
864
                        case FFI_TYPE_SINT16:
 
865
                        case FFI_TYPE_UINT16:
 
866
                                avalue[i] = (char*)pgr + MODE_CHOICE(2,6);
 
867
                                ng++;
 
868
                                pgr++;
 
869
                                break;
 
870
 
 
871
#if defined(__ppc__)
 
872
                        case FFI_TYPE_POINTER:
 
873
#endif
 
874
                        case FFI_TYPE_SINT32:
 
875
                        case FFI_TYPE_UINT32:
 
876
                                avalue[i] = (char*)pgr + MODE_CHOICE(0,4);
 
877
                                ng++;
 
878
                                pgr++;
 
879
 
 
880
                                break;
 
881
 
 
882
                        case FFI_TYPE_STRUCT:
 
883
                                if (cif->abi == FFI_DARWIN)
 
884
                                {
 
885
#if defined(__ppc64__)
 
886
                                        unsigned int    gprSize = 0;
 
887
                                        unsigned int    fprSize = 0;
 
888
                                        unsigned int    savedFPRSize = fprSize;
 
889
 
 
890
                                        avalue[i] = alloca(arg_types[i]->size);
 
891
                                        ffi64_struct_to_ram_form(arg_types[i], (const char*)pgr,
 
892
                                                &gprSize, (const char*)pfr, &fprSize, &nf, avalue[i], NULL);
 
893
 
 
894
                                        ng      += gprSize / sizeof(long);
 
895
                                        pgr     += gprSize / sizeof(long);
 
896
                                        pfr     += (fprSize - savedFPRSize) / sizeof(double);
 
897
 
 
898
#elif defined(__ppc__)
 
899
                                        /*      Structures that match the basic modes (QI 1 byte, HI 2 bytes,
 
900
                                                SI 4 bytes) are aligned as if they were those modes.  */
 
901
                                        unsigned int    size_al = size_al = arg_types[i]->size;
 
902
 
 
903
                                        /*      If the first member of the struct is a double, then align
 
904
                                                the struct to double-word.  */
 
905
                                        if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE)
 
906
                                                size_al = ALIGN(arg_types[i]->size, 8);
 
907
 
 
908
                                        if (size_al < 3)
 
909
                                                avalue[i] = (char*)pgr + MODE_CHOICE(4,8) - size_al;
 
910
                                        else
 
911
                                                avalue[i] = (char*)pgr;
 
912
 
 
913
                                        ng      += (size_al + 3) / sizeof(long);
 
914
                                        pgr += (size_al + 3) / sizeof(long);
 
915
#else
 
916
#error undefined architecture
 
917
#endif
 
918
                                }
 
919
 
 
920
                                break;
 
921
 
 
922
#if defined(__ppc64__)
 
923
                        case FFI_TYPE_POINTER:
 
924
#endif
 
925
                        case FFI_TYPE_SINT64:
 
926
                        case FFI_TYPE_UINT64:
 
927
                                /* Long long ints are passed in 1 or 2 GPRs.  */
 
928
                                avalue[i] = pgr;
 
929
                                ng += MODE_CHOICE(2,1);
 
930
                                pgr += MODE_CHOICE(2,1);
 
931
 
 
932
                                break;
 
933
 
 
934
                        case FFI_TYPE_FLOAT:
 
935
                                /*      A float value consumes a GPR.
 
936
                                        There are 13 64-bit floating point registers.  */
 
937
                                if (nf < NUM_FPR_ARG_REGISTERS)
 
938
                                {
 
939
                                        temp = pfr->d;
 
940
                                        pfr->f = (float)temp;
 
941
                                        avalue[i] = pfr;
 
942
                                        pfr++;
 
943
                                }
 
944
                                else
 
945
                                        avalue[i] = pgr;
 
946
 
 
947
                                nf++;
 
948
                                ng++;
 
949
                                pgr++;
 
950
                                break;
 
951
 
 
952
                        case FFI_TYPE_DOUBLE:
 
953
                                /*      A double value consumes one or two GPRs.
 
954
                                        There are 13 64bit floating point registers.  */
 
955
                                if (nf < NUM_FPR_ARG_REGISTERS)
 
956
                                {
 
957
                                        avalue[i] = pfr;
 
958
                                        pfr++;
 
959
                                }
 
960
                                else
 
961
                                        avalue[i] = pgr;
 
962
 
 
963
                                nf++;
 
964
                                ng += MODE_CHOICE(2,1);
 
965
                                pgr += MODE_CHOICE(2,1);
 
966
 
 
967
                                break;
 
968
 
 
969
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
 
970
 
 
971
                        case FFI_TYPE_LONGDOUBLE:
 
972
#if defined(__ppc64__)
 
973
                                if (nf < NUM_FPR_ARG_REGISTERS)
 
974
                                {
 
975
                                        avalue[i] = pfr;
 
976
                                        pfr += 2;
 
977
                                }
 
978
#elif defined(__ppc__)
 
979
                                /*      A long double value consumes 2/4 GPRs and 2 FPRs.
 
980
                                        There are 13 64bit floating point registers.  */
 
981
                                if (nf < NUM_FPR_ARG_REGISTERS - 1)
 
982
                                {
 
983
                                        avalue[i] = pfr;
 
984
                                        pfr += 2;
 
985
                                }
 
986
                                /*      Here we have the situation where one part of the long double
 
987
                                        is stored in fpr13 and the other part is already on the stack.
 
988
                                        We use a union to pass the long double to avalue[i].  */
 
989
                                else if (nf == NUM_FPR_ARG_REGISTERS - 1)
 
990
                                {
 
991
                                        memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
 
992
                                        memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
 
993
                                        avalue[i] = &temp_ld.ld;
 
994
                                }
 
995
#else
 
996
#error undefined architecture
 
997
#endif
 
998
                                else
 
999
                                        avalue[i] = pgr;
 
1000
 
 
1001
                                nf += 2;
 
1002
                                ng += MODE_CHOICE(4,2);
 
1003
                                pgr += MODE_CHOICE(4,2);
 
1004
 
 
1005
                                break;
 
1006
 
 
1007
#endif  /*      FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE  */
 
1008
 
 
1009
                        default:
 
1010
                                FFI_ASSERT(0);
 
1011
                                break;
 
1012
                }
 
1013
        }
 
1014
 
 
1015
        (closure->fun)(cif, rvalue, avalue, closure->user_data);
 
1016
 
 
1017
        /* Tell ffi_closure_ASM to perform return type promotions.  */
 
1018
        return cif->rtype->type;
 
1019
}
 
1020
 
 
1021
#if defined(__ppc64__)
 
1022
 
 
1023
/*      ffi64_struct_to_ram_form
 
1024
 
 
1025
        Rebuild a struct's natural layout from buffers of concatenated registers.
 
1026
        Return the number of registers used.
 
1027
        inGPRs[0-7] == r3, inFPRs[0-7] == f1 ...
 
1028
*/
 
1029
void
 
1030
ffi64_struct_to_ram_form(
 
1031
        const ffi_type* inType,
 
1032
        const char*             inGPRs,
 
1033
        unsigned int*   ioGPRMarker,
 
1034
        const char*             inFPRs,
 
1035
        unsigned int*   ioFPRMarker,
 
1036
        unsigned int*   ioFPRsUsed,
 
1037
        char*                   outStruct,      // caller-allocated
 
1038
        unsigned int*   ioStructMarker)
 
1039
{
 
1040
        unsigned int    srcGMarker              = 0;
 
1041
        unsigned int    srcFMarker              = 0;
 
1042
        unsigned int    savedFMarker    = 0;
 
1043
        unsigned int    fprsUsed                = 0;
 
1044
        unsigned int    savedFPRsUsed   = 0;
 
1045
        unsigned int    destMarker              = 0;
 
1046
 
 
1047
        static unsigned int     recurseCount    = 0;
 
1048
 
 
1049
        if (ioGPRMarker)
 
1050
                srcGMarker      = *ioGPRMarker;
 
1051
 
 
1052
        if (ioFPRMarker)
 
1053
        {
 
1054
                srcFMarker              = *ioFPRMarker;
 
1055
                savedFMarker    = srcFMarker;
 
1056
        }
 
1057
 
 
1058
        if (ioFPRsUsed)
 
1059
        {
 
1060
                fprsUsed                = *ioFPRsUsed;
 
1061
                savedFPRsUsed   = fprsUsed;
 
1062
        }
 
1063
 
 
1064
        if (ioStructMarker)
 
1065
                destMarker      = *ioStructMarker;
 
1066
 
 
1067
        size_t                  i;
 
1068
 
 
1069
        switch (inType->size)
 
1070
        {
 
1071
                case 1: case 2: case 4:
 
1072
                        srcGMarker += 8 - inType->size;
 
1073
                        break;
 
1074
 
 
1075
                default:
 
1076
                        break;
 
1077
        }
 
1078
 
 
1079
        for (i = 0; inType->elements[i] != NULL; i++)
 
1080
        {
 
1081
                switch (inType->elements[i]->type)
 
1082
                {
 
1083
                        case FFI_TYPE_FLOAT:
 
1084
                                srcFMarker = ALIGN(srcFMarker, 4);
 
1085
                                srcGMarker = ALIGN(srcGMarker, 4);
 
1086
                                destMarker = ALIGN(destMarker, 4);
 
1087
 
 
1088
                                if (fprsUsed < NUM_FPR_ARG_REGISTERS)
 
1089
                                {
 
1090
                                        *(float*)&outStruct[destMarker] =
 
1091
                                                (float)*(double*)&inFPRs[srcFMarker];
 
1092
                                        srcFMarker += 8;
 
1093
                                        fprsUsed++;
 
1094
                                }
 
1095
                                else
 
1096
                                        *(float*)&outStruct[destMarker] =
 
1097
                                                (float)*(double*)&inGPRs[srcGMarker];
 
1098
 
 
1099
                                srcGMarker += 4;
 
1100
                                destMarker += 4;
 
1101
 
 
1102
                                // Skip to next GPR if next element won't fit and we're
 
1103
                                // not already at a register boundary.
 
1104
                                if (inType->elements[i + 1] != NULL && (destMarker % 8))
 
1105
                                {
 
1106
                                        if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) &&
 
1107
                                                (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) ||
 
1108
                                                (ALIGN(srcGMarker, 8) - srcGMarker) < 2) &&
 
1109
                                                (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) ||
 
1110
                                                (ALIGN(srcGMarker, 8) - srcGMarker) < 4))
 
1111
                                                srcGMarker      = ALIGN(srcGMarker, 8);
 
1112
                                }
 
1113
 
 
1114
                                break;
 
1115
 
 
1116
                        case FFI_TYPE_DOUBLE:
 
1117
                                srcFMarker = ALIGN(srcFMarker, 8);
 
1118
                                destMarker = ALIGN(destMarker, 8);
 
1119
 
 
1120
                                if (fprsUsed < NUM_FPR_ARG_REGISTERS)
 
1121
                                {
 
1122
                                        *(double*)&outStruct[destMarker]        =
 
1123
                                                *(double*)&inFPRs[srcFMarker];
 
1124
                                        srcFMarker += 8;
 
1125
                                        fprsUsed++;
 
1126
                                }
 
1127
                                else
 
1128
                                        *(double*)&outStruct[destMarker]        =
 
1129
                                                *(double*)&inGPRs[srcGMarker];
 
1130
 
 
1131
                                destMarker += 8;
 
1132
 
 
1133
                                // Skip next GPR
 
1134
                                srcGMarker += 8;
 
1135
                                srcGMarker = ALIGN(srcGMarker, 8);
 
1136
 
 
1137
                                break;
 
1138
 
 
1139
                        case FFI_TYPE_LONGDOUBLE:
 
1140
                                destMarker = ALIGN(destMarker, 16);
 
1141
 
 
1142
                                if (fprsUsed < NUM_FPR_ARG_REGISTERS)
 
1143
                                {
 
1144
                                        srcFMarker = ALIGN(srcFMarker, 8);
 
1145
                                        srcGMarker = ALIGN(srcGMarker, 8);
 
1146
                                        *(long double*)&outStruct[destMarker]   =
 
1147
                                                *(long double*)&inFPRs[srcFMarker];
 
1148
                                        srcFMarker += 16;
 
1149
                                        fprsUsed += 2;
 
1150
                                }
 
1151
                                else
 
1152
                                {
 
1153
                                        srcFMarker = ALIGN(srcFMarker, 16);
 
1154
                                        srcGMarker = ALIGN(srcGMarker, 16);
 
1155
                                        *(long double*)&outStruct[destMarker]   =
 
1156
                                                *(long double*)&inGPRs[srcGMarker];
 
1157
                                }
 
1158
 
 
1159
                                destMarker += 16;
 
1160
 
 
1161
                                // Skip next 2 GPRs
 
1162
                                srcGMarker += 16;
 
1163
                                srcGMarker = ALIGN(srcGMarker, 8);
 
1164
 
 
1165
                                break;
 
1166
 
 
1167
                        case FFI_TYPE_UINT8:
 
1168
                        case FFI_TYPE_SINT8:
 
1169
                        {
 
1170
                                if (inType->alignment == 1)     // chars only
 
1171
                                {
 
1172
                                        if (inType->size == 1)
 
1173
                                                outStruct[destMarker++] = inGPRs[srcGMarker++];
 
1174
                                        else if (inType->size == 2)
 
1175
                                        {
 
1176
                                                outStruct[destMarker++] = inGPRs[srcGMarker++];
 
1177
                                                outStruct[destMarker++] = inGPRs[srcGMarker++];
 
1178
                                                i++;
 
1179
                                        }
 
1180
                                        else
 
1181
                                        {
 
1182
                                                memcpy(&outStruct[destMarker],
 
1183
                                                        &inGPRs[srcGMarker], inType->size);
 
1184
                                                srcGMarker += inType->size;
 
1185
                                                destMarker += inType->size;
 
1186
                                                i += inType->size - 1;
 
1187
                                        }
 
1188
                                }
 
1189
                                else    // chars and other stuff
 
1190
                                {
 
1191
                                        outStruct[destMarker++] = inGPRs[srcGMarker++];
 
1192
 
 
1193
                                        // Skip to next GPR if next element won't fit and we're
 
1194
                                        // not already at a register boundary.
 
1195
                                        if (inType->elements[i + 1] != NULL && (srcGMarker % 8))
 
1196
                                        {
 
1197
                                                if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) &&
 
1198
                                                        (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) ||
 
1199
                                                        (ALIGN(srcGMarker, 8) - srcGMarker) < 2) &&
 
1200
                                                        (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) ||
 
1201
                                                        (ALIGN(srcGMarker, 8) - srcGMarker) < 4))
 
1202
                                                        srcGMarker      = ALIGN(srcGMarker, inType->alignment); // was 8
 
1203
                                        }
 
1204
                                }
 
1205
 
 
1206
                                break;
 
1207
                        }
 
1208
 
 
1209
                        case FFI_TYPE_UINT16:
 
1210
                        case FFI_TYPE_SINT16:
 
1211
                                srcGMarker = ALIGN(srcGMarker, 2);
 
1212
                                destMarker = ALIGN(destMarker, 2);
 
1213
 
 
1214
                                *(short*)&outStruct[destMarker] =
 
1215
                                        *(short*)&inGPRs[srcGMarker];
 
1216
                                srcGMarker += 2;
 
1217
                                destMarker += 2;
 
1218
 
 
1219
                                break;
 
1220
 
 
1221
                        case FFI_TYPE_INT:
 
1222
                        case FFI_TYPE_UINT32:
 
1223
                        case FFI_TYPE_SINT32:
 
1224
                                srcGMarker = ALIGN(srcGMarker, 4);
 
1225
                                destMarker = ALIGN(destMarker, 4);
 
1226
 
 
1227
                                *(int*)&outStruct[destMarker] =
 
1228
                                        *(int*)&inGPRs[srcGMarker];
 
1229
                                srcGMarker += 4;
 
1230
                                destMarker += 4;
 
1231
 
 
1232
                                break;
 
1233
 
 
1234
                        case FFI_TYPE_POINTER:
 
1235
                        case FFI_TYPE_UINT64:
 
1236
                        case FFI_TYPE_SINT64:
 
1237
                                srcGMarker = ALIGN(srcGMarker, 8);
 
1238
                                destMarker = ALIGN(destMarker, 8);
 
1239
 
 
1240
                                *(long long*)&outStruct[destMarker] =
 
1241
                                        *(long long*)&inGPRs[srcGMarker];
 
1242
                                srcGMarker += 8;
 
1243
                                destMarker += 8;
 
1244
 
 
1245
                                break;
 
1246
 
 
1247
                        case FFI_TYPE_STRUCT:
 
1248
                                recurseCount++;
 
1249
                                ffi64_struct_to_ram_form(inType->elements[i], inGPRs,
 
1250
                                        &srcGMarker, inFPRs, &srcFMarker, &fprsUsed,
 
1251
                                        outStruct, &destMarker);
 
1252
                                recurseCount--;
 
1253
                                break;
 
1254
 
 
1255
                        default:
 
1256
                                FFI_ASSERT(0);  // unknown element type
 
1257
                                break;
 
1258
                }
 
1259
        }
 
1260
 
 
1261
        srcGMarker = ALIGN(srcGMarker, inType->alignment);
 
1262
 
 
1263
        // Take care of the special case for 16-byte structs, but not for
 
1264
        // nested structs.
 
1265
        if (recurseCount == 0 && srcGMarker == 16)
 
1266
        {
 
1267
                *(long double*)&outStruct[0] = *(long double*)&inGPRs[0];
 
1268
                srcFMarker      = savedFMarker;
 
1269
                fprsUsed        = savedFPRsUsed;
 
1270
        }
 
1271
 
 
1272
        if (ioGPRMarker)
 
1273
                *ioGPRMarker = ALIGN(srcGMarker, 8);
 
1274
 
 
1275
        if (ioFPRMarker)
 
1276
                *ioFPRMarker = srcFMarker;
 
1277
 
 
1278
        if (ioFPRsUsed)
 
1279
                *ioFPRsUsed     = fprsUsed;
 
1280
 
 
1281
        if (ioStructMarker)
 
1282
                *ioStructMarker = ALIGN(destMarker, 8);
 
1283
}
 
1284
 
 
1285
/*      ffi64_struct_to_reg_form
 
1286
 
 
1287
        Copy a struct's elements into buffers that can be sliced into registers.
 
1288
        Return the sizes of the output buffers in bytes. Pass NULL buffer pointers
 
1289
        to calculate size only.
 
1290
        outGPRs[0-7] == r3, outFPRs[0-7] == f1 ...
 
1291
*/
 
1292
void
 
1293
ffi64_struct_to_reg_form(
 
1294
        const ffi_type* inType,
 
1295
        const char*             inStruct,
 
1296
        unsigned int*   ioStructMarker,
 
1297
        unsigned int*   ioFPRsUsed,
 
1298
        char*                   outGPRs,        // caller-allocated
 
1299
        unsigned int*   ioGPRSize,
 
1300
        char*                   outFPRs,        // caller-allocated
 
1301
        unsigned int*   ioFPRSize)
 
1302
{
 
1303
        size_t                  i;
 
1304
        unsigned int    srcMarker               = 0;
 
1305
        unsigned int    destGMarker             = 0;
 
1306
        unsigned int    destFMarker             = 0;
 
1307
        unsigned int    savedFMarker    = 0;
 
1308
        unsigned int    fprsUsed                = 0;
 
1309
        unsigned int    savedFPRsUsed   = 0;
 
1310
 
 
1311
        static unsigned int     recurseCount    = 0;
 
1312
 
 
1313
        if (ioStructMarker)
 
1314
                srcMarker       = *ioStructMarker;
 
1315
 
 
1316
        if (ioFPRsUsed)
 
1317
        {
 
1318
                fprsUsed                = *ioFPRsUsed;
 
1319
                savedFPRsUsed   = fprsUsed;
 
1320
        }
 
1321
 
 
1322
        if (ioGPRSize)
 
1323
                destGMarker     = *ioGPRSize;
 
1324
 
 
1325
        if (ioFPRSize)
 
1326
        {
 
1327
                destFMarker             = *ioFPRSize;
 
1328
                savedFMarker    = destFMarker;
 
1329
        }
 
1330
 
 
1331
        switch (inType->size)
 
1332
        {
 
1333
                case 1: case 2: case 4:
 
1334
                        destGMarker += 8 - inType->size;
 
1335
                        break;
 
1336
 
 
1337
                default:
 
1338
                        break;
 
1339
        }
 
1340
 
 
1341
        for (i = 0; inType->elements[i] != NULL; i++)
 
1342
        {
 
1343
                switch (inType->elements[i]->type)
 
1344
                {
 
1345
                        // Shadow floating-point types in GPRs for vararg and pre-ANSI
 
1346
                        // functions.
 
1347
                        case FFI_TYPE_FLOAT:
 
1348
                                // Nudge markers to next 4/8-byte boundary
 
1349
                                srcMarker = ALIGN(srcMarker, 4);
 
1350
                                destGMarker = ALIGN(destGMarker, 4);
 
1351
                                destFMarker = ALIGN(destFMarker, 8);
 
1352
 
 
1353
                                if (fprsUsed < NUM_FPR_ARG_REGISTERS)
 
1354
                                {
 
1355
                                        if (outFPRs != NULL && inStruct != NULL)
 
1356
                                                *(double*)&outFPRs[destFMarker] =
 
1357
                                                        (double)*(float*)&inStruct[srcMarker];
 
1358
 
 
1359
                                        destFMarker += 8;
 
1360
                                        fprsUsed++;
 
1361
                                }
 
1362
 
 
1363
                                if (outGPRs != NULL && inStruct != NULL)
 
1364
                                        *(double*)&outGPRs[destGMarker] =
 
1365
                                                (double)*(float*)&inStruct[srcMarker];
 
1366
 
 
1367
                                srcMarker += 4;
 
1368
                                destGMarker += 4;
 
1369
 
 
1370
                                // Skip to next GPR if next element won't fit and we're
 
1371
                                // not already at a register boundary.
 
1372
                                if (inType->elements[i + 1] != NULL && (srcMarker % 8))
 
1373
                                {
 
1374
                                        if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) &&
 
1375
                                                (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) ||
 
1376
                                                (ALIGN(destGMarker, 8) - destGMarker) < 2) &&
 
1377
                                                (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) ||
 
1378
                                                (ALIGN(destGMarker, 8) - destGMarker) < 4))
 
1379
                                                destGMarker     = ALIGN(destGMarker, 8);
 
1380
                                }
 
1381
 
 
1382
                                break;
 
1383
 
 
1384
                        case FFI_TYPE_DOUBLE:
 
1385
                                srcMarker = ALIGN(srcMarker, 8);
 
1386
                                destFMarker = ALIGN(destFMarker, 8);
 
1387
 
 
1388
                                if (fprsUsed < NUM_FPR_ARG_REGISTERS)
 
1389
                                {
 
1390
                                        if (outFPRs != NULL && inStruct != NULL)
 
1391
                                                *(double*)&outFPRs[destFMarker] =
 
1392
                                                        *(double*)&inStruct[srcMarker];
 
1393
 
 
1394
                                        destFMarker += 8;
 
1395
                                        fprsUsed++;
 
1396
                                }
 
1397
 
 
1398
                                if (outGPRs != NULL && inStruct != NULL)
 
1399
                                        *(double*)&outGPRs[destGMarker] =
 
1400
                                                *(double*)&inStruct[srcMarker];
 
1401
 
 
1402
                                srcMarker += 8;
 
1403
 
 
1404
                                // Skip next GPR
 
1405
                                destGMarker += 8;
 
1406
                                destGMarker = ALIGN(destGMarker, 8);
 
1407
 
 
1408
                                break;
 
1409
 
 
1410
                        case FFI_TYPE_LONGDOUBLE:
 
1411
                                srcMarker = ALIGN(srcMarker, 16);
 
1412
 
 
1413
                                if (fprsUsed < NUM_FPR_ARG_REGISTERS)
 
1414
                                {
 
1415
                                        destFMarker = ALIGN(destFMarker, 8);
 
1416
                                        destGMarker = ALIGN(destGMarker, 8);
 
1417
 
 
1418
                                        if (outFPRs != NULL && inStruct != NULL)
 
1419
                                                *(long double*)&outFPRs[destFMarker] =
 
1420
                                                        *(long double*)&inStruct[srcMarker];
 
1421
 
 
1422
                                        if (outGPRs != NULL && inStruct != NULL)
 
1423
                                                *(long double*)&outGPRs[destGMarker] =
 
1424
                                                        *(long double*)&inStruct[srcMarker];
 
1425
 
 
1426
                                        destFMarker += 16;
 
1427
                                        fprsUsed += 2;
 
1428
                                }
 
1429
                                else
 
1430
                                {
 
1431
                                        destGMarker = ALIGN(destGMarker, 16);
 
1432
 
 
1433
                                         if (outGPRs != NULL && inStruct != NULL)
 
1434
                                                *(long double*)&outGPRs[destGMarker] =
 
1435
                                                        *(long double*)&inStruct[srcMarker];
 
1436
                                }
 
1437
 
 
1438
                                srcMarker += 16;
 
1439
                                destGMarker += 16;      // Skip next 2 GPRs
 
1440
                                destGMarker = ALIGN(destGMarker, 8);    // was 16
 
1441
 
 
1442
                                break;
 
1443
 
 
1444
                        case FFI_TYPE_UINT8:
 
1445
                        case FFI_TYPE_SINT8:
 
1446
                                if (inType->alignment == 1)     // bytes only
 
1447
                                {
 
1448
                                        if (inType->size == 1)
 
1449
                                        {
 
1450
                                                if (outGPRs != NULL && inStruct != NULL)
 
1451
                                                        outGPRs[destGMarker] = inStruct[srcMarker];
 
1452
 
 
1453
                                                srcMarker++;
 
1454
                                                destGMarker++;
 
1455
                                        }
 
1456
                                        else if (inType->size == 2)
 
1457
                                        {
 
1458
                                                if (outGPRs != NULL && inStruct != NULL)
 
1459
                                                {
 
1460
                                                        outGPRs[destGMarker] = inStruct[srcMarker];
 
1461
                                                        outGPRs[destGMarker + 1] = inStruct[srcMarker + 1];
 
1462
                                                }
 
1463
 
 
1464
                                                srcMarker += 2;
 
1465
                                                destGMarker += 2;
 
1466
 
 
1467
                                                i++;
 
1468
                                        }
 
1469
                                        else
 
1470
                                        {
 
1471
                                                if (outGPRs != NULL && inStruct != NULL)
 
1472
                                                {
 
1473
                                                        // Avoid memcpy for small chunks.
 
1474
                                                        if (inType->size <= sizeof(long))
 
1475
                                                                *(long*)&outGPRs[destGMarker] =
 
1476
                                                                        *(long*)&inStruct[srcMarker];
 
1477
                                                        else
 
1478
                                                                memcpy(&outGPRs[destGMarker],
 
1479
                                                                        &inStruct[srcMarker], inType->size);
 
1480
                                                }
 
1481
                                                
 
1482
                                                srcMarker += inType->size;
 
1483
                                                destGMarker += inType->size;
 
1484
                                                i += inType->size - 1;
 
1485
                                        }
 
1486
                                }
 
1487
                                else    // bytes and other stuff
 
1488
                                {
 
1489
                                        if (outGPRs != NULL && inStruct != NULL)
 
1490
                                                outGPRs[destGMarker] = inStruct[srcMarker];
 
1491
 
 
1492
                                        srcMarker++;
 
1493
                                        destGMarker++;
 
1494
 
 
1495
                                        // Skip to next GPR if next element won't fit and we're
 
1496
                                        // not already at a register boundary.
 
1497
                                        if (inType->elements[i + 1] != NULL && (destGMarker % 8))
 
1498
                                        {
 
1499
                                                if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) &&
 
1500
                                                        (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) ||
 
1501
                                                        (ALIGN(destGMarker, 8) - destGMarker) < 2) &&
 
1502
                                                        (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) ||
 
1503
                                                        (ALIGN(destGMarker, 8) - destGMarker) < 4))
 
1504
                                                        destGMarker     = ALIGN(destGMarker, inType->alignment);        // was 8
 
1505
                                        }
 
1506
                                }
 
1507
 
 
1508
                                break;
 
1509
 
 
1510
                        case FFI_TYPE_UINT16:
 
1511
                        case FFI_TYPE_SINT16:
 
1512
                                srcMarker = ALIGN(srcMarker, 2);
 
1513
                                destGMarker = ALIGN(destGMarker, 2);
 
1514
 
 
1515
                                if (outGPRs != NULL && inStruct != NULL)
 
1516
                                        *(short*)&outGPRs[destGMarker] =
 
1517
                                                *(short*)&inStruct[srcMarker];
 
1518
 
 
1519
                                srcMarker += 2;
 
1520
                                destGMarker += 2;
 
1521
 
 
1522
                                if (inType->elements[i + 1] == NULL)
 
1523
                                        destGMarker     = ALIGN(destGMarker, inType->alignment);
 
1524
 
 
1525
                                break;
 
1526
 
 
1527
                        case FFI_TYPE_INT:
 
1528
                        case FFI_TYPE_UINT32:
 
1529
                        case FFI_TYPE_SINT32:
 
1530
                                srcMarker = ALIGN(srcMarker, 4);
 
1531
                                destGMarker = ALIGN(destGMarker, 4);
 
1532
 
 
1533
                                if (outGPRs != NULL && inStruct != NULL)
 
1534
                                        *(int*)&outGPRs[destGMarker] =
 
1535
                                                *(int*)&inStruct[srcMarker];
 
1536
 
 
1537
                                srcMarker += 4;
 
1538
                                destGMarker += 4;
 
1539
 
 
1540
                                break;
 
1541
 
 
1542
                        case FFI_TYPE_POINTER:
 
1543
                        case FFI_TYPE_UINT64:
 
1544
                        case FFI_TYPE_SINT64:
 
1545
                                srcMarker = ALIGN(srcMarker, 8);
 
1546
                                destGMarker = ALIGN(destGMarker, 8);
 
1547
 
 
1548
                                if (outGPRs != NULL && inStruct != NULL)
 
1549
                                        *(long long*)&outGPRs[destGMarker] =
 
1550
                                                *(long long*)&inStruct[srcMarker];
 
1551
 
 
1552
                                srcMarker += 8;
 
1553
                                destGMarker += 8;
 
1554
 
 
1555
                                if (inType->elements[i + 1] == NULL)
 
1556
                                        destGMarker     = ALIGN(destGMarker, inType->alignment);
 
1557
 
 
1558
                                break;
 
1559
 
 
1560
                        case FFI_TYPE_STRUCT:
 
1561
                                recurseCount++;
 
1562
                                ffi64_struct_to_reg_form(inType->elements[i],
 
1563
                                        inStruct, &srcMarker, &fprsUsed, outGPRs, 
 
1564
                                        &destGMarker, outFPRs, &destFMarker);
 
1565
                                recurseCount--;
 
1566
                                break;
 
1567
 
 
1568
                        default:
 
1569
                                FFI_ASSERT(0);
 
1570
                                break;
 
1571
                }
 
1572
        }
 
1573
 
 
1574
        destGMarker     = ALIGN(destGMarker, inType->alignment);
 
1575
 
 
1576
        // Take care of the special case for 16-byte structs, but not for
 
1577
        // nested structs.
 
1578
        if (recurseCount == 0 && destGMarker == 16)
 
1579
        {
 
1580
                if (outGPRs != NULL && inStruct != NULL)
 
1581
                        *(long double*)&outGPRs[0] = *(long double*)&inStruct[0];
 
1582
 
 
1583
                destFMarker     = savedFMarker;
 
1584
                fprsUsed        = savedFPRsUsed;
 
1585
        }
 
1586
 
 
1587
        if (ioStructMarker)
 
1588
                *ioStructMarker = ALIGN(srcMarker, 8);
 
1589
 
 
1590
        if (ioFPRsUsed)
 
1591
                *ioFPRsUsed     = fprsUsed;
 
1592
 
 
1593
        if (ioGPRSize)
 
1594
                *ioGPRSize = ALIGN(destGMarker, 8);
 
1595
 
 
1596
        if (ioFPRSize)
 
1597
                *ioFPRSize = ALIGN(destFMarker, 8);
 
1598
}
 
1599
 
 
1600
/*      ffi64_stret_needs_ptr
 
1601
 
 
1602
        Determine whether a returned struct needs a pointer in r3 or can fit
 
1603
        in registers.
 
1604
*/
 
1605
 
 
1606
bool
 
1607
ffi64_stret_needs_ptr(
 
1608
        const ffi_type* inType,
 
1609
        unsigned short* ioGPRCount,
 
1610
        unsigned short* ioFPRCount)
 
1611
{
 
1612
        // Obvious case first- struct is larger than combined FPR size.
 
1613
        if (inType->size > 14 * 8)
 
1614
                return true;
 
1615
 
 
1616
        // Now the struct can physically fit in registers, determine if it
 
1617
        // also fits logically.
 
1618
        bool                    needsPtr        = false;
 
1619
        unsigned short  gprsUsed        = 0;
 
1620
        unsigned short  fprsUsed        = 0;
 
1621
        size_t                  i;
 
1622
 
 
1623
        if (ioGPRCount)
 
1624
                gprsUsed = *ioGPRCount;
 
1625
 
 
1626
        if (ioFPRCount)
 
1627
                fprsUsed = *ioFPRCount;
 
1628
 
 
1629
        for (i = 0; inType->elements[i] != NULL && !needsPtr; i++)
 
1630
        {
 
1631
                switch (inType->elements[i]->type)
 
1632
                {
 
1633
                        case FFI_TYPE_FLOAT:
 
1634
                        case FFI_TYPE_DOUBLE:
 
1635
                                gprsUsed++;
 
1636
                                fprsUsed++;
 
1637
 
 
1638
                                if (fprsUsed > 13)
 
1639
                                        needsPtr = true;
 
1640
 
 
1641
                                break;
 
1642
 
 
1643
                        case FFI_TYPE_LONGDOUBLE:
 
1644
                                gprsUsed += 2;
 
1645
                                fprsUsed += 2;
 
1646
 
 
1647
                                if (fprsUsed > 14)
 
1648
                                        needsPtr = true;
 
1649
 
 
1650
                                break;
 
1651
 
 
1652
                        case FFI_TYPE_UINT8:
 
1653
                        case FFI_TYPE_SINT8:
 
1654
                        {
 
1655
                                gprsUsed++;
 
1656
 
 
1657
                                if (gprsUsed > 8)
 
1658
                                {
 
1659
                                        needsPtr = true;
 
1660
                                        break;
 
1661
                                }
 
1662
 
 
1663
                                if (inType->elements[i + 1] == NULL)    // last byte in the struct
 
1664
                                        break;
 
1665
 
 
1666
                                // Count possible contiguous bytes ahead, up to 8.
 
1667
                                unsigned short j;
 
1668
 
 
1669
                                for (j = 1; j < 8; j++)
 
1670
                                {
 
1671
                                        if (inType->elements[i + j] == NULL ||
 
1672
                                                !FFI_TYPE_1_BYTE(inType->elements[i + j]->type))
 
1673
                                                break;
 
1674
                                }
 
1675
 
 
1676
                                i += j - 1;     // allow for i++ before the test condition
 
1677
 
 
1678
                                break;
 
1679
                        }
 
1680
 
 
1681
                        case FFI_TYPE_UINT16:
 
1682
                        case FFI_TYPE_SINT16:
 
1683
                        case FFI_TYPE_INT:
 
1684
                        case FFI_TYPE_UINT32:
 
1685
                        case FFI_TYPE_SINT32:
 
1686
                        case FFI_TYPE_POINTER:
 
1687
                        case FFI_TYPE_UINT64:
 
1688
                        case FFI_TYPE_SINT64:
 
1689
                                gprsUsed++;
 
1690
 
 
1691
                                if (gprsUsed > 8)
 
1692
                                        needsPtr = true;
 
1693
 
 
1694
                                break;
 
1695
 
 
1696
                        case FFI_TYPE_STRUCT:
 
1697
                                needsPtr = ffi64_stret_needs_ptr(
 
1698
                                        inType->elements[i], &gprsUsed, &fprsUsed);
 
1699
 
 
1700
                                break;
 
1701
 
 
1702
                        default:
 
1703
                                FFI_ASSERT(0);
 
1704
                                break;
 
1705
                }
 
1706
        }
 
1707
 
 
1708
        if (ioGPRCount)
 
1709
                *ioGPRCount = gprsUsed;
 
1710
 
 
1711
        if (ioFPRCount)
 
1712
                *ioFPRCount = fprsUsed;
 
1713
 
 
1714
        return needsPtr;
 
1715
}
 
1716
 
 
1717
/*      ffi64_data_size
 
1718
 
 
1719
        Calculate the size in bytes of an ffi type.
 
1720
*/
 
1721
 
 
1722
unsigned int
 
1723
ffi64_data_size(
 
1724
        const ffi_type* inType)
 
1725
{
 
1726
        unsigned int    size = 0;
 
1727
 
 
1728
        switch (inType->type)
 
1729
        {
 
1730
                case FFI_TYPE_UINT8:
 
1731
                case FFI_TYPE_SINT8:
 
1732
                        size = 1;
 
1733
                        break;
 
1734
 
 
1735
                case FFI_TYPE_UINT16:
 
1736
                case FFI_TYPE_SINT16:
 
1737
                        size = 2;
 
1738
                        break;
 
1739
 
 
1740
                case FFI_TYPE_INT:
 
1741
                case FFI_TYPE_UINT32:
 
1742
                case FFI_TYPE_SINT32:
 
1743
                case FFI_TYPE_FLOAT:
 
1744
                        size = 4;
 
1745
                        break;
 
1746
 
 
1747
                case FFI_TYPE_POINTER:
 
1748
                case FFI_TYPE_UINT64:
 
1749
                case FFI_TYPE_SINT64:
 
1750
                case FFI_TYPE_DOUBLE:
 
1751
                        size = 8;
 
1752
                        break;
 
1753
 
 
1754
                case FFI_TYPE_LONGDOUBLE:
 
1755
                        size = 16;
 
1756
                        break;
 
1757
 
 
1758
                case FFI_TYPE_STRUCT:
 
1759
                        ffi64_struct_to_reg_form(
 
1760
                                inType, NULL, NULL, NULL, NULL, &size, NULL, NULL);
 
1761
                        break;
 
1762
 
 
1763
                case FFI_TYPE_VOID:
 
1764
                        break;
 
1765
 
 
1766
                default:
 
1767
                        FFI_ASSERT(0);
 
1768
                        break;
 
1769
        }
 
1770
 
 
1771
        return size;
 
1772
}
 
1773
 
 
1774
#endif  /*      defined(__ppc64__)      */
 
1775
#endif  /* __ppc__ || __ppc64__ */