ยปCore Development>Code coverage>Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c

Python code coverage for Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c

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