ยปCore Development>Code coverage>Modules/_ctypes/libffi/src/sparc/ffi.c

Python code coverage for Modules/_ctypes/libffi/src/sparc/ffi.c

#countcontent
1n/a/* -----------------------------------------------------------------------
2n/a ffi.c - Copyright (c) 2011, 2013 Anthony Green
3n/a Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
4n/a
5n/a SPARC Foreign Function Interface
6n/a
7n/a Permission is hereby granted, free of charge, to any person obtaining
8n/a a copy of this software and associated documentation files (the
9n/a ``Software''), to deal in the Software without restriction, including
10n/a without limitation the rights to use, copy, modify, merge, publish,
11n/a distribute, sublicense, and/or sell copies of the Software, and to
12n/a permit persons to whom the Software is furnished to do so, subject to
13n/a the following conditions:
14n/a
15n/a The above copyright notice and this permission notice shall be included
16n/a in all copies or substantial portions of the Software.
17n/a
18n/a THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19n/a EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20n/a MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21n/a NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22n/a HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23n/a WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24n/a OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25n/a DEALINGS IN THE SOFTWARE.
26n/a ----------------------------------------------------------------------- */
27n/a
28n/a#include <ffi.h>
29n/a#include <ffi_common.h>
30n/a
31n/a#include <stdlib.h>
32n/a
33n/a
34n/a/* ffi_prep_args is called by the assembly routine once stack space
35n/a has been allocated for the function's arguments */
36n/a
37n/avoid ffi_prep_args_v8(char *stack, extended_cif *ecif)
38n/a{
39n/a int i;
40n/a void **p_argv;
41n/a char *argp;
42n/a ffi_type **p_arg;
43n/a
44n/a /* Skip 16 words for the window save area */
45n/a argp = stack + 16*sizeof(int);
46n/a
47n/a /* This should only really be done when we are returning a structure,
48n/a however, it's faster just to do it all the time...
49n/a
50n/a if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */
51n/a *(int *) argp = (long)ecif->rvalue;
52n/a
53n/a /* And 1 word for the structure return value. */
54n/a argp += sizeof(int);
55n/a
56n/a#ifdef USING_PURIFY
57n/a /* Purify will probably complain in our assembly routine, unless we
58n/a zero out this memory. */
59n/a
60n/a ((int*)argp)[0] = 0;
61n/a ((int*)argp)[1] = 0;
62n/a ((int*)argp)[2] = 0;
63n/a ((int*)argp)[3] = 0;
64n/a ((int*)argp)[4] = 0;
65n/a ((int*)argp)[5] = 0;
66n/a#endif
67n/a
68n/a p_argv = ecif->avalue;
69n/a
70n/a for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
71n/a {
72n/a size_t z;
73n/a
74n/a if ((*p_arg)->type == FFI_TYPE_STRUCT
75n/a#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
76n/a || (*p_arg)->type == FFI_TYPE_LONGDOUBLE
77n/a#endif
78n/a )
79n/a {
80n/a *(unsigned int *) argp = (unsigned long)(* p_argv);
81n/a z = sizeof(int);
82n/a }
83n/a else
84n/a {
85n/a z = (*p_arg)->size;
86n/a if (z < sizeof(int))
87n/a {
88n/a z = sizeof(int);
89n/a switch ((*p_arg)->type)
90n/a {
91n/a case FFI_TYPE_SINT8:
92n/a *(signed int *) argp = *(SINT8 *)(* p_argv);
93n/a break;
94n/a
95n/a case FFI_TYPE_UINT8:
96n/a *(unsigned int *) argp = *(UINT8 *)(* p_argv);
97n/a break;
98n/a
99n/a case FFI_TYPE_SINT16:
100n/a *(signed int *) argp = *(SINT16 *)(* p_argv);
101n/a break;
102n/a
103n/a case FFI_TYPE_UINT16:
104n/a *(unsigned int *) argp = *(UINT16 *)(* p_argv);
105n/a break;
106n/a
107n/a default:
108n/a FFI_ASSERT(0);
109n/a }
110n/a }
111n/a else
112n/a {
113n/a memcpy(argp, *p_argv, z);
114n/a }
115n/a }
116n/a p_argv++;
117n/a argp += z;
118n/a }
119n/a
120n/a return;
121n/a}
122n/a
123n/aint ffi_prep_args_v9(char *stack, extended_cif *ecif)
124n/a{
125n/a int i, ret = 0;
126n/a int tmp;
127n/a void **p_argv;
128n/a char *argp;
129n/a ffi_type **p_arg;
130n/a
131n/a tmp = 0;
132n/a
133n/a /* Skip 16 words for the window save area */
134n/a argp = stack + 16*sizeof(long long);
135n/a
136n/a#ifdef USING_PURIFY
137n/a /* Purify will probably complain in our assembly routine, unless we
138n/a zero out this memory. */
139n/a
140n/a ((long long*)argp)[0] = 0;
141n/a ((long long*)argp)[1] = 0;
142n/a ((long long*)argp)[2] = 0;
143n/a ((long long*)argp)[3] = 0;
144n/a ((long long*)argp)[4] = 0;
145n/a ((long long*)argp)[5] = 0;
146n/a#endif
147n/a
148n/a p_argv = ecif->avalue;
149n/a
150n/a if (ecif->cif->rtype->type == FFI_TYPE_STRUCT &&
151n/a ecif->cif->rtype->size > 32)
152n/a {
153n/a *(unsigned long long *) argp = (unsigned long)ecif->rvalue;
154n/a argp += sizeof(long long);
155n/a tmp = 1;
156n/a }
157n/a
158n/a for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
159n/a i++, p_arg++)
160n/a {
161n/a size_t z;
162n/a
163n/a z = (*p_arg)->size;
164n/a switch ((*p_arg)->type)
165n/a {
166n/a case FFI_TYPE_STRUCT:
167n/a if (z > 16)
168n/a {
169n/a /* For structures larger than 16 bytes we pass reference. */
170n/a *(unsigned long long *) argp = (unsigned long)* p_argv;
171n/a argp += sizeof(long long);
172n/a tmp++;
173n/a p_argv++;
174n/a continue;
175n/a }
176n/a /* FALLTHROUGH */
177n/a case FFI_TYPE_FLOAT:
178n/a case FFI_TYPE_DOUBLE:
179n/a#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
180n/a case FFI_TYPE_LONGDOUBLE:
181n/a#endif
182n/a ret = 1; /* We should promote into FP regs as well as integer. */
183n/a break;
184n/a }
185n/a if (z < sizeof(long long))
186n/a {
187n/a switch ((*p_arg)->type)
188n/a {
189n/a case FFI_TYPE_SINT8:
190n/a *(signed long long *) argp = *(SINT8 *)(* p_argv);
191n/a break;
192n/a
193n/a case FFI_TYPE_UINT8:
194n/a *(unsigned long long *) argp = *(UINT8 *)(* p_argv);
195n/a break;
196n/a
197n/a case FFI_TYPE_SINT16:
198n/a *(signed long long *) argp = *(SINT16 *)(* p_argv);
199n/a break;
200n/a
201n/a case FFI_TYPE_UINT16:
202n/a *(unsigned long long *) argp = *(UINT16 *)(* p_argv);
203n/a break;
204n/a
205n/a case FFI_TYPE_SINT32:
206n/a *(signed long long *) argp = *(SINT32 *)(* p_argv);
207n/a break;
208n/a
209n/a case FFI_TYPE_UINT32:
210n/a *(unsigned long long *) argp = *(UINT32 *)(* p_argv);
211n/a break;
212n/a
213n/a case FFI_TYPE_FLOAT:
214n/a *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */
215n/a break;
216n/a
217n/a case FFI_TYPE_STRUCT:
218n/a memcpy(argp, *p_argv, z);
219n/a break;
220n/a
221n/a default:
222n/a FFI_ASSERT(0);
223n/a }
224n/a z = sizeof(long long);
225n/a tmp++;
226n/a }
227n/a else if (z == sizeof(long long))
228n/a {
229n/a memcpy(argp, *p_argv, z);
230n/a z = sizeof(long long);
231n/a tmp++;
232n/a }
233n/a else
234n/a {
235n/a if ((tmp & 1) && (*p_arg)->alignment > 8)
236n/a {
237n/a tmp++;
238n/a argp += sizeof(long long);
239n/a }
240n/a memcpy(argp, *p_argv, z);
241n/a z = 2 * sizeof(long long);
242n/a tmp += 2;
243n/a }
244n/a p_argv++;
245n/a argp += z;
246n/a }
247n/a
248n/a return ret;
249n/a}
250n/a
251n/a/* Perform machine dependent cif processing */
252n/affi_status ffi_prep_cif_machdep(ffi_cif *cif)
253n/a{
254n/a int wordsize;
255n/a
256n/a if (cif->abi != FFI_V9)
257n/a {
258n/a wordsize = 4;
259n/a
260n/a /* If we are returning a struct, this will already have been added.
261n/a Otherwise we need to add it because it's always got to be there! */
262n/a
263n/a if (cif->rtype->type != FFI_TYPE_STRUCT)
264n/a cif->bytes += wordsize;
265n/a
266n/a /* sparc call frames require that space is allocated for 6 args,
267n/a even if they aren't used. Make that space if necessary. */
268n/a
269n/a if (cif->bytes < 4*6+4)
270n/a cif->bytes = 4*6+4;
271n/a }
272n/a else
273n/a {
274n/a wordsize = 8;
275n/a
276n/a /* sparc call frames require that space is allocated for 6 args,
277n/a even if they aren't used. Make that space if necessary. */
278n/a
279n/a if (cif->bytes < 8*6)
280n/a cif->bytes = 8*6;
281n/a }
282n/a
283n/a /* Adjust cif->bytes. to include 16 words for the window save area,
284n/a and maybe the struct/union return pointer area, */
285n/a
286n/a cif->bytes += 16 * wordsize;
287n/a
288n/a /* The stack must be 2 word aligned, so round bytes up
289n/a appropriately. */
290n/a
291n/a cif->bytes = ALIGN(cif->bytes, 2 * wordsize);
292n/a
293n/a /* Set the return type flag */
294n/a switch (cif->rtype->type)
295n/a {
296n/a case FFI_TYPE_VOID:
297n/a case FFI_TYPE_FLOAT:
298n/a case FFI_TYPE_DOUBLE:
299n/a#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
300n/a case FFI_TYPE_LONGDOUBLE:
301n/a#endif
302n/a cif->flags = cif->rtype->type;
303n/a break;
304n/a
305n/a case FFI_TYPE_STRUCT:
306n/a if (cif->abi == FFI_V9 && cif->rtype->size > 32)
307n/a cif->flags = FFI_TYPE_VOID;
308n/a else
309n/a cif->flags = FFI_TYPE_STRUCT;
310n/a break;
311n/a
312n/a case FFI_TYPE_SINT8:
313n/a case FFI_TYPE_UINT8:
314n/a case FFI_TYPE_SINT16:
315n/a case FFI_TYPE_UINT16:
316n/a if (cif->abi == FFI_V9)
317n/a cif->flags = FFI_TYPE_INT;
318n/a else
319n/a cif->flags = cif->rtype->type;
320n/a break;
321n/a
322n/a case FFI_TYPE_SINT64:
323n/a case FFI_TYPE_UINT64:
324n/a if (cif->abi == FFI_V9)
325n/a cif->flags = FFI_TYPE_INT;
326n/a else
327n/a cif->flags = FFI_TYPE_SINT64;
328n/a break;
329n/a
330n/a default:
331n/a cif->flags = FFI_TYPE_INT;
332n/a break;
333n/a }
334n/a return FFI_OK;
335n/a}
336n/a
337n/aint ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt)
338n/a{
339n/a ffi_type **ptr = &arg->elements[0];
340n/a
341n/a while (*ptr != NULL)
342n/a {
343n/a if (off & ((*ptr)->alignment - 1))
344n/a off = ALIGN(off, (*ptr)->alignment);
345n/a
346n/a switch ((*ptr)->type)
347n/a {
348n/a case FFI_TYPE_STRUCT:
349n/a off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt);
350n/a off = ALIGN(off, FFI_SIZEOF_ARG);
351n/a break;
352n/a case FFI_TYPE_FLOAT:
353n/a case FFI_TYPE_DOUBLE:
354n/a#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
355n/a case FFI_TYPE_LONGDOUBLE:
356n/a#endif
357n/a memmove(ret + off, flt + off, (*ptr)->size);
358n/a off += (*ptr)->size;
359n/a break;
360n/a default:
361n/a memmove(ret + off, intg + off, (*ptr)->size);
362n/a off += (*ptr)->size;
363n/a break;
364n/a }
365n/a ptr++;
366n/a }
367n/a return off;
368n/a}
369n/a
370n/a
371n/a#ifdef SPARC64
372n/aextern int ffi_call_v9(void *, extended_cif *, unsigned,
373n/a unsigned, unsigned *, void (*fn)(void));
374n/a#else
375n/aextern int ffi_call_v8(void *, extended_cif *, unsigned,
376n/a unsigned, unsigned *, void (*fn)(void));
377n/a#endif
378n/a
379n/a#ifndef __GNUC__
380n/avoid ffi_flush_icache (void *, size_t);
381n/a#endif
382n/a
383n/avoid ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
384n/a{
385n/a extended_cif ecif;
386n/a void *rval = rvalue;
387n/a
388n/a ecif.cif = cif;
389n/a ecif.avalue = avalue;
390n/a
391n/a /* If the return value is a struct and we don't have a return */
392n/a /* value address then we need to make one */
393n/a
394n/a ecif.rvalue = rvalue;
395n/a if (cif->rtype->type == FFI_TYPE_STRUCT)
396n/a {
397n/a if (cif->rtype->size <= 32)
398n/a rval = alloca(64);
399n/a else
400n/a {
401n/a rval = NULL;
402n/a if (rvalue == NULL)
403n/a ecif.rvalue = alloca(cif->rtype->size);
404n/a }
405n/a }
406n/a
407n/a switch (cif->abi)
408n/a {
409n/a case FFI_V8:
410n/a#ifdef SPARC64
411n/a /* We don't yet support calling 32bit code from 64bit */
412n/a FFI_ASSERT(0);
413n/a#else
414n/a if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT
415n/a#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
416n/a || cif->flags == FFI_TYPE_LONGDOUBLE
417n/a#endif
418n/a ))
419n/a {
420n/a /* For v8, we need an "unimp" with size of returning struct */
421n/a /* behind "call", so we alloc some executable space for it. */
422n/a /* l7 is used, we need to make sure v8.S doesn't use %l7. */
423n/a unsigned int *call_struct = NULL;
424n/a ffi_closure_alloc(32, (void **)&call_struct);
425n/a if (call_struct)
426n/a {
427n/a unsigned long f = (unsigned long)fn;
428n/a call_struct[0] = 0xae10001f; /* mov %i7, %l7 */
429n/a call_struct[1] = 0xbe10000f; /* mov %o7, %i7 */
430n/a call_struct[2] = 0x03000000 | f >> 10; /* sethi %hi(fn), %g1 */
431n/a call_struct[3] = 0x9fc06000 | (f & 0x3ff); /* jmp %g1+%lo(fn), %o7 */
432n/a call_struct[4] = 0x01000000; /* nop */
433n/a if (cif->rtype->size < 0x7f)
434n/a call_struct[5] = cif->rtype->size; /* unimp */
435n/a else
436n/a call_struct[5] = 0x01000000; /* nop */
437n/a call_struct[6] = 0x81c7e008; /* ret */
438n/a call_struct[7] = 0xbe100017; /* mov %l7, %i7 */
439n/a#ifdef __GNUC__
440n/a asm volatile ("iflush %0; iflush %0+8; iflush %0+16; iflush %0+24" : :
441n/a "r" (call_struct) : "memory");
442n/a /* SPARC v8 requires 5 instructions for flush to be visible */
443n/a asm volatile ("nop; nop; nop; nop; nop");
444n/a#else
445n/a ffi_flush_icache (call_struct, 32);
446n/a#endif
447n/a ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
448n/a cif->flags, rvalue, call_struct);
449n/a ffi_closure_free(call_struct);
450n/a }
451n/a else
452n/a {
453n/a ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
454n/a cif->flags, rvalue, fn);
455n/a }
456n/a }
457n/a else
458n/a {
459n/a ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
460n/a cif->flags, rvalue, fn);
461n/a }
462n/a#endif
463n/a break;
464n/a case FFI_V9:
465n/a#ifdef SPARC64
466n/a ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes,
467n/a cif->flags, rval, fn);
468n/a if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
469n/a ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);
470n/a#else
471n/a /* And vice versa */
472n/a FFI_ASSERT(0);
473n/a#endif
474n/a break;
475n/a default:
476n/a FFI_ASSERT(0);
477n/a break;
478n/a }
479n/a}
480n/a
481n/a
482n/a#ifdef SPARC64
483n/aextern void ffi_closure_v9(void);
484n/a#else
485n/aextern void ffi_closure_v8(void);
486n/a#endif
487n/a
488n/affi_status
489n/affi_prep_closure_loc (ffi_closure* closure,
490n/a ffi_cif* cif,
491n/a void (*fun)(ffi_cif*, void*, void**, void*),
492n/a void *user_data,
493n/a void *codeloc)
494n/a{
495n/a unsigned int *tramp = (unsigned int *) &closure->tramp[0];
496n/a unsigned long fn;
497n/a#ifdef SPARC64
498n/a /* Trampoline address is equal to the closure address. We take advantage
499n/a of that to reduce the trampoline size by 8 bytes. */
500n/a if (cif->abi != FFI_V9)
501n/a return FFI_BAD_ABI;
502n/a fn = (unsigned long) ffi_closure_v9;
503n/a tramp[0] = 0x83414000; /* rd %pc, %g1 */
504n/a tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */
505n/a tramp[2] = 0x81c14000; /* jmp %g5 */
506n/a tramp[3] = 0x01000000; /* nop */
507n/a *((unsigned long *) &tramp[4]) = fn;
508n/a#else
509n/a unsigned long ctx = (unsigned long) codeloc;
510n/a if (cif->abi != FFI_V8)
511n/a return FFI_BAD_ABI;
512n/a fn = (unsigned long) ffi_closure_v8;
513n/a tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
514n/a tramp[1] = 0x05000000 | ctx >> 10; /* sethi %hi(ctx), %g2 */
515n/a tramp[2] = 0x81c06000 | (fn & 0x3ff); /* jmp %g1+%lo(fn) */
516n/a tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or %g2, %lo(ctx) */
517n/a#endif
518n/a
519n/a closure->cif = cif;
520n/a closure->fun = fun;
521n/a closure->user_data = user_data;
522n/a
523n/a /* Flush the Icache. closure is 8 bytes aligned. */
524n/a#ifdef __GNUC__
525n/a#ifdef SPARC64
526n/a asm volatile ("flush %0; flush %0+8" : : "r" (closure) : "memory");
527n/a#else
528n/a asm volatile ("iflush %0; iflush %0+8" : : "r" (closure) : "memory");
529n/a /* SPARC v8 requires 5 instructions for flush to be visible */
530n/a asm volatile ("nop; nop; nop; nop; nop");
531n/a#endif
532n/a#else
533n/a ffi_flush_icache (closure, 16);
534n/a#endif
535n/a
536n/a return FFI_OK;
537n/a}
538n/a
539n/aint
540n/affi_closure_sparc_inner_v8(ffi_closure *closure,
541n/a void *rvalue, unsigned long *gpr, unsigned long *scratch)
542n/a{
543n/a ffi_cif *cif;
544n/a ffi_type **arg_types;
545n/a void **avalue;
546n/a int i, argn;
547n/a
548n/a cif = closure->cif;
549n/a arg_types = cif->arg_types;
550n/a avalue = alloca(cif->nargs * sizeof(void *));
551n/a
552n/a /* Copy the caller's structure return address so that the closure
553n/a returns the data directly to the caller. */
554n/a if (cif->flags == FFI_TYPE_STRUCT
555n/a#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
556n/a || cif->flags == FFI_TYPE_LONGDOUBLE
557n/a#endif
558n/a )
559n/a rvalue = (void *) gpr[0];
560n/a
561n/a /* Always skip the structure return address. */
562n/a argn = 1;
563n/a
564n/a /* Grab the addresses of the arguments from the stack frame. */
565n/a for (i = 0; i < cif->nargs; i++)
566n/a {
567n/a if (arg_types[i]->type == FFI_TYPE_STRUCT
568n/a#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
569n/a || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
570n/a#endif
571n/a )
572n/a {
573n/a /* Straight copy of invisible reference. */
574n/a avalue[i] = (void *)gpr[argn++];
575n/a }
576n/a else if ((arg_types[i]->type == FFI_TYPE_DOUBLE
577n/a || arg_types[i]->type == FFI_TYPE_SINT64
578n/a || arg_types[i]->type == FFI_TYPE_UINT64)
579n/a /* gpr is 8-byte aligned. */
580n/a && (argn % 2) != 0)
581n/a {
582n/a /* Align on a 8-byte boundary. */
583n/a scratch[0] = gpr[argn];
584n/a scratch[1] = gpr[argn+1];
585n/a avalue[i] = scratch;
586n/a scratch -= 2;
587n/a argn += 2;
588n/a }
589n/a else
590n/a {
591n/a /* Always right-justify. */
592n/a argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
593n/a avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
594n/a }
595n/a }
596n/a
597n/a /* Invoke the closure. */
598n/a (closure->fun) (cif, rvalue, avalue, closure->user_data);
599n/a
600n/a /* Tell ffi_closure_sparc how to perform return type promotions. */
601n/a return cif->rtype->type;
602n/a}
603n/a
604n/aint
605n/affi_closure_sparc_inner_v9(ffi_closure *closure,
606n/a void *rvalue, unsigned long *gpr, double *fpr)
607n/a{
608n/a ffi_cif *cif;
609n/a ffi_type **arg_types;
610n/a void **avalue;
611n/a int i, argn, fp_slot_max;
612n/a
613n/a cif = closure->cif;
614n/a arg_types = cif->arg_types;
615n/a avalue = alloca(cif->nargs * sizeof(void *));
616n/a
617n/a /* Copy the caller's structure return address so that the closure
618n/a returns the data directly to the caller. */
619n/a if (cif->flags == FFI_TYPE_VOID
620n/a && cif->rtype->type == FFI_TYPE_STRUCT)
621n/a {
622n/a rvalue = (void *) gpr[0];
623n/a /* Skip the structure return address. */
624n/a argn = 1;
625n/a }
626n/a else
627n/a argn = 0;
628n/a
629n/a fp_slot_max = 16 - argn;
630n/a
631n/a /* Grab the addresses of the arguments from the stack frame. */
632n/a for (i = 0; i < cif->nargs; i++)
633n/a {
634n/a if (arg_types[i]->type == FFI_TYPE_STRUCT)
635n/a {
636n/a if (arg_types[i]->size > 16)
637n/a {
638n/a /* Straight copy of invisible reference. */
639n/a avalue[i] = (void *)gpr[argn++];
640n/a }
641n/a else
642n/a {
643n/a /* Left-justify. */
644n/a ffi_v9_layout_struct(arg_types[i],
645n/a 0,
646n/a (char *) &gpr[argn],
647n/a (char *) &gpr[argn],
648n/a (char *) &fpr[argn]);
649n/a avalue[i] = &gpr[argn];
650n/a argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
651n/a }
652n/a }
653n/a else
654n/a {
655n/a /* Right-justify. */
656n/a argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
657n/a
658n/a /* Align on a 16-byte boundary. */
659n/a#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
660n/a if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0)
661n/a argn++;
662n/a#endif
663n/a if (i < fp_slot_max
664n/a && (arg_types[i]->type == FFI_TYPE_FLOAT
665n/a || arg_types[i]->type == FFI_TYPE_DOUBLE
666n/a#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
667n/a || arg_types[i]->type == FFI_TYPE_LONGDOUBLE
668n/a#endif
669n/a ))
670n/a avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size;
671n/a else
672n/a avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size;
673n/a }
674n/a }
675n/a
676n/a /* Invoke the closure. */
677n/a (closure->fun) (cif, rvalue, avalue, closure->user_data);
678n/a
679n/a /* Tell ffi_closure_sparc how to perform return type promotions. */
680n/a return cif->rtype->type;
681n/a}