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

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

#countcontent
1n/a/* -----------------------------------------------------------------------
2n/a ffi.c - (c) 2011 Anthony Green
3n/a (c) 2008 Red Hat, Inc.
4n/a (c) 2006 Free Software Foundation, Inc.
5n/a (c) 2003-2004 Randolph Chung <tausq@debian.org>
6n/a
7n/a HPPA Foreign Function Interface
8n/a HP-UX PA ABI support
9n/a
10n/a Permission is hereby granted, free of charge, to any person obtaining
11n/a a copy of this software and associated documentation files (the
12n/a ``Software''), to deal in the Software without restriction, including
13n/a without limitation the rights to use, copy, modify, merge, publish,
14n/a distribute, sublicense, and/or sell copies of the Software, and to
15n/a permit persons to whom the Software is furnished to do so, subject to
16n/a the following conditions:
17n/a
18n/a The above copyright notice and this permission notice shall be included
19n/a in all copies or substantial portions of the Software.
20n/a
21n/a THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
22n/a EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23n/a MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24n/a NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25n/a HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26n/a WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27n/a OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28n/a DEALINGS IN THE SOFTWARE.
29n/a ----------------------------------------------------------------------- */
30n/a
31n/a#include <ffi.h>
32n/a#include <ffi_common.h>
33n/a
34n/a#include <stdlib.h>
35n/a#include <stdio.h>
36n/a
37n/a#define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
38n/a
39n/a#define MIN_STACK_SIZE 64
40n/a#define FIRST_ARG_SLOT 9
41n/a#define DEBUG_LEVEL 0
42n/a
43n/a#define fldw(addr, fpreg) \
44n/a __asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
45n/a#define fstw(fpreg, addr) \
46n/a __asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
47n/a#define fldd(addr, fpreg) \
48n/a __asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
49n/a#define fstd(fpreg, addr) \
50n/a __asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
51n/a
52n/a#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
53n/a
54n/astatic inline int ffi_struct_type(ffi_type *t)
55n/a{
56n/a size_t sz = t->size;
57n/a
58n/a /* Small structure results are passed in registers,
59n/a larger ones are passed by pointer. Note that
60n/a small structures of size 2, 4 and 8 differ from
61n/a the corresponding integer types in that they have
62n/a different alignment requirements. */
63n/a
64n/a if (sz <= 1)
65n/a return FFI_TYPE_UINT8;
66n/a else if (sz == 2)
67n/a return FFI_TYPE_SMALL_STRUCT2;
68n/a else if (sz == 3)
69n/a return FFI_TYPE_SMALL_STRUCT3;
70n/a else if (sz == 4)
71n/a return FFI_TYPE_SMALL_STRUCT4;
72n/a else if (sz == 5)
73n/a return FFI_TYPE_SMALL_STRUCT5;
74n/a else if (sz == 6)
75n/a return FFI_TYPE_SMALL_STRUCT6;
76n/a else if (sz == 7)
77n/a return FFI_TYPE_SMALL_STRUCT7;
78n/a else if (sz <= 8)
79n/a return FFI_TYPE_SMALL_STRUCT8;
80n/a else
81n/a return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */
82n/a}
83n/a
84n/a/* PA has a downward growing stack, which looks like this:
85n/a
86n/a Offset
87n/a [ Variable args ]
88n/a SP = (4*(n+9)) arg word N
89n/a ...
90n/a SP-52 arg word 4
91n/a [ Fixed args ]
92n/a SP-48 arg word 3
93n/a SP-44 arg word 2
94n/a SP-40 arg word 1
95n/a SP-36 arg word 0
96n/a [ Frame marker ]
97n/a ...
98n/a SP-20 RP
99n/a SP-4 previous SP
100n/a
101n/a The first four argument words on the stack are reserved for use by
102n/a the callee. Instead, the general and floating registers replace
103n/a the first four argument slots. Non FP arguments are passed solely
104n/a in the general registers. FP arguments are passed in both general
105n/a and floating registers when using libffi.
106n/a
107n/a Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23.
108n/a Non-FP 64-bit args are passed in register pairs, starting
109n/a on an odd numbered register (i.e. r25+r26 and r23+r24).
110n/a FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L.
111n/a FP 64-bit arguments are passed in fr5 and fr7.
112n/a
113n/a The registers are allocated in the same manner as stack slots.
114n/a This allows the callee to save its arguments on the stack if
115n/a necessary:
116n/a
117n/a arg word 3 -> gr23 or fr7L
118n/a arg word 2 -> gr24 or fr6L or fr7R
119n/a arg word 1 -> gr25 or fr5L
120n/a arg word 0 -> gr26 or fr4L or fr5R
121n/a
122n/a Note that fr4R and fr6R are never used for arguments (i.e.,
123n/a doubles are not passed in fr4 or fr6).
124n/a
125n/a The rest of the arguments are passed on the stack starting at SP-52,
126n/a but 64-bit arguments need to be aligned to an 8-byte boundary
127n/a
128n/a This means we can have holes either in the register allocation,
129n/a or in the stack. */
130n/a
131n/a/* ffi_prep_args is called by the assembly routine once stack space
132n/a has been allocated for the function's arguments
133n/a
134n/a The following code will put everything into the stack frame
135n/a (which was allocated by the asm routine), and on return
136n/a the asm routine will load the arguments that should be
137n/a passed by register into the appropriate registers
138n/a
139n/a NOTE: We load floating point args in this function... that means we
140n/a assume gcc will not mess with fp regs in here. */
141n/a
142n/avoid ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
143n/a{
144n/a register unsigned int i;
145n/a register ffi_type **p_arg;
146n/a register void **p_argv;
147n/a unsigned int slot = FIRST_ARG_SLOT;
148n/a char *dest_cpy;
149n/a size_t len;
150n/a
151n/a debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
152n/a ecif, bytes);
153n/a
154n/a p_arg = ecif->cif->arg_types;
155n/a p_argv = ecif->avalue;
156n/a
157n/a for (i = 0; i < ecif->cif->nargs; i++)
158n/a {
159n/a int type = (*p_arg)->type;
160n/a
161n/a switch (type)
162n/a {
163n/a case FFI_TYPE_SINT8:
164n/a *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
165n/a break;
166n/a
167n/a case FFI_TYPE_UINT8:
168n/a *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
169n/a break;
170n/a
171n/a case FFI_TYPE_SINT16:
172n/a *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
173n/a break;
174n/a
175n/a case FFI_TYPE_UINT16:
176n/a *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
177n/a break;
178n/a
179n/a case FFI_TYPE_UINT32:
180n/a case FFI_TYPE_SINT32:
181n/a case FFI_TYPE_POINTER:
182n/a debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
183n/a slot);
184n/a *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
185n/a break;
186n/a
187n/a case FFI_TYPE_UINT64:
188n/a case FFI_TYPE_SINT64:
189n/a /* Align slot for 64-bit type. */
190n/a slot += (slot & 1) ? 1 : 2;
191n/a *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
192n/a break;
193n/a
194n/a case FFI_TYPE_FLOAT:
195n/a /* First 4 args go in fr4L - fr7L. */
196n/a debug(3, "Storing UINT32(float) in slot %u\n", slot);
197n/a *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
198n/a switch (slot - FIRST_ARG_SLOT)
199n/a {
200n/a /* First 4 args go in fr4L - fr7L. */
201n/a case 0: fldw(stack - slot, fr4); break;
202n/a case 1: fldw(stack - slot, fr5); break;
203n/a case 2: fldw(stack - slot, fr6); break;
204n/a case 3: fldw(stack - slot, fr7); break;
205n/a }
206n/a break;
207n/a
208n/a case FFI_TYPE_DOUBLE:
209n/a /* Align slot for 64-bit type. */
210n/a slot += (slot & 1) ? 1 : 2;
211n/a debug(3, "Storing UINT64(double) at slot %u\n", slot);
212n/a *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
213n/a switch (slot - FIRST_ARG_SLOT)
214n/a {
215n/a /* First 2 args go in fr5, fr7. */
216n/a case 1: fldd(stack - slot, fr5); break;
217n/a case 3: fldd(stack - slot, fr7); break;
218n/a }
219n/a break;
220n/a
221n/a#ifdef PA_HPUX
222n/a case FFI_TYPE_LONGDOUBLE:
223n/a /* Long doubles are passed in the same manner as structures
224n/a larger than 8 bytes. */
225n/a *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
226n/a break;
227n/a#endif
228n/a
229n/a case FFI_TYPE_STRUCT:
230n/a
231n/a /* Structs smaller or equal than 4 bytes are passed in one
232n/a register. Structs smaller or equal 8 bytes are passed in two
233n/a registers. Larger structures are passed by pointer. */
234n/a
235n/a len = (*p_arg)->size;
236n/a if (len <= 4)
237n/a {
238n/a dest_cpy = (char *)(stack - slot) + 4 - len;
239n/a memcpy(dest_cpy, (char *)*p_argv, len);
240n/a }
241n/a else if (len <= 8)
242n/a {
243n/a slot += (slot & 1) ? 1 : 2;
244n/a dest_cpy = (char *)(stack - slot) + 8 - len;
245n/a memcpy(dest_cpy, (char *)*p_argv, len);
246n/a }
247n/a else
248n/a *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
249n/a break;
250n/a
251n/a default:
252n/a FFI_ASSERT(0);
253n/a }
254n/a
255n/a slot++;
256n/a p_arg++;
257n/a p_argv++;
258n/a }
259n/a
260n/a /* Make sure we didn't mess up and scribble on the stack. */
261n/a {
262n/a unsigned int n;
263n/a
264n/a debug(5, "Stack setup:\n");
265n/a for (n = 0; n < (bytes + 3) / 4; n++)
266n/a {
267n/a if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
268n/a debug(5, "%08x ", *(stack - n));
269n/a }
270n/a debug(5, "\n");
271n/a }
272n/a
273n/a FFI_ASSERT(slot * 4 <= bytes);
274n/a
275n/a return;
276n/a}
277n/a
278n/astatic void ffi_size_stack_pa32(ffi_cif *cif)
279n/a{
280n/a ffi_type **ptr;
281n/a int i;
282n/a int z = 0; /* # stack slots */
283n/a
284n/a for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
285n/a {
286n/a int type = (*ptr)->type;
287n/a
288n/a switch (type)
289n/a {
290n/a case FFI_TYPE_DOUBLE:
291n/a case FFI_TYPE_UINT64:
292n/a case FFI_TYPE_SINT64:
293n/a z += 2 + (z & 1); /* must start on even regs, so we may waste one */
294n/a break;
295n/a
296n/a#ifdef PA_HPUX
297n/a case FFI_TYPE_LONGDOUBLE:
298n/a#endif
299n/a case FFI_TYPE_STRUCT:
300n/a z += 1; /* pass by ptr, callee will copy */
301n/a break;
302n/a
303n/a default: /* <= 32-bit values */
304n/a z++;
305n/a }
306n/a }
307n/a
308n/a /* We can fit up to 6 args in the default 64-byte stack frame,
309n/a if we need more, we need more stack. */
310n/a if (z <= 6)
311n/a cif->bytes = MIN_STACK_SIZE; /* min stack size */
312n/a else
313n/a cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
314n/a
315n/a debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
316n/a}
317n/a
318n/a/* Perform machine dependent cif processing. */
319n/affi_status ffi_prep_cif_machdep(ffi_cif *cif)
320n/a{
321n/a /* Set the return type flag */
322n/a switch (cif->rtype->type)
323n/a {
324n/a case FFI_TYPE_VOID:
325n/a case FFI_TYPE_FLOAT:
326n/a case FFI_TYPE_DOUBLE:
327n/a cif->flags = (unsigned) cif->rtype->type;
328n/a break;
329n/a
330n/a#ifdef PA_HPUX
331n/a case FFI_TYPE_LONGDOUBLE:
332n/a /* Long doubles are treated like a structure. */
333n/a cif->flags = FFI_TYPE_STRUCT;
334n/a break;
335n/a#endif
336n/a
337n/a case FFI_TYPE_STRUCT:
338n/a /* For the return type we have to check the size of the structures.
339n/a If the size is smaller or equal 4 bytes, the result is given back
340n/a in one register. If the size is smaller or equal 8 bytes than we
341n/a return the result in two registers. But if the size is bigger than
342n/a 8 bytes, we work with pointers. */
343n/a cif->flags = ffi_struct_type(cif->rtype);
344n/a break;
345n/a
346n/a case FFI_TYPE_UINT64:
347n/a case FFI_TYPE_SINT64:
348n/a cif->flags = FFI_TYPE_UINT64;
349n/a break;
350n/a
351n/a default:
352n/a cif->flags = FFI_TYPE_INT;
353n/a break;
354n/a }
355n/a
356n/a /* Lucky us, because of the unique PA ABI we get to do our
357n/a own stack sizing. */
358n/a switch (cif->abi)
359n/a {
360n/a case FFI_PA32:
361n/a ffi_size_stack_pa32(cif);
362n/a break;
363n/a
364n/a default:
365n/a FFI_ASSERT(0);
366n/a break;
367n/a }
368n/a
369n/a return FFI_OK;
370n/a}
371n/a
372n/aextern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
373n/a extended_cif *, unsigned, unsigned, unsigned *,
374n/a void (*fn)(void));
375n/a
376n/avoid ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
377n/a{
378n/a extended_cif ecif;
379n/a
380n/a ecif.cif = cif;
381n/a ecif.avalue = avalue;
382n/a
383n/a /* If the return value is a struct and we don't have a return
384n/a value address then we need to make one. */
385n/a
386n/a if (rvalue == NULL
387n/a#ifdef PA_HPUX
388n/a && (cif->rtype->type == FFI_TYPE_STRUCT
389n/a || cif->rtype->type == FFI_TYPE_LONGDOUBLE))
390n/a#else
391n/a && cif->rtype->type == FFI_TYPE_STRUCT)
392n/a#endif
393n/a {
394n/a ecif.rvalue = alloca(cif->rtype->size);
395n/a }
396n/a else
397n/a ecif.rvalue = rvalue;
398n/a
399n/a
400n/a switch (cif->abi)
401n/a {
402n/a case FFI_PA32:
403n/a debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
404n/a ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
405n/a cif->flags, ecif.rvalue, fn);
406n/a break;
407n/a
408n/a default:
409n/a FFI_ASSERT(0);
410n/a break;
411n/a }
412n/a}
413n/a
414n/a#if FFI_CLOSURES
415n/a/* This is more-or-less an inverse of ffi_call -- we have arguments on
416n/a the stack, and we need to fill them into a cif structure and invoke
417n/a the user function. This really ought to be in asm to make sure
418n/a the compiler doesn't do things we don't expect. */
419n/affi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
420n/a{
421n/a ffi_cif *cif;
422n/a void **avalue;
423n/a void *rvalue;
424n/a UINT32 ret[2]; /* function can return up to 64-bits in registers */
425n/a ffi_type **p_arg;
426n/a char *tmp;
427n/a int i, avn;
428n/a unsigned int slot = FIRST_ARG_SLOT;
429n/a register UINT32 r28 asm("r28");
430n/a
431n/a cif = closure->cif;
432n/a
433n/a /* If returning via structure, callee will write to our pointer. */
434n/a if (cif->flags == FFI_TYPE_STRUCT)
435n/a rvalue = (void *)r28;
436n/a else
437n/a rvalue = &ret[0];
438n/a
439n/a avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
440n/a avn = cif->nargs;
441n/a p_arg = cif->arg_types;
442n/a
443n/a for (i = 0; i < avn; i++)
444n/a {
445n/a int type = (*p_arg)->type;
446n/a
447n/a switch (type)
448n/a {
449n/a case FFI_TYPE_SINT8:
450n/a case FFI_TYPE_UINT8:
451n/a case FFI_TYPE_SINT16:
452n/a case FFI_TYPE_UINT16:
453n/a case FFI_TYPE_SINT32:
454n/a case FFI_TYPE_UINT32:
455n/a case FFI_TYPE_POINTER:
456n/a avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
457n/a break;
458n/a
459n/a case FFI_TYPE_SINT64:
460n/a case FFI_TYPE_UINT64:
461n/a slot += (slot & 1) ? 1 : 2;
462n/a avalue[i] = (void *)(stack - slot);
463n/a break;
464n/a
465n/a case FFI_TYPE_FLOAT:
466n/a#ifdef PA_LINUX
467n/a /* The closure call is indirect. In Linux, floating point
468n/a arguments in indirect calls with a prototype are passed
469n/a in the floating point registers instead of the general
470n/a registers. So, we need to replace what was previously
471n/a stored in the current slot with the value in the
472n/a corresponding floating point register. */
473n/a switch (slot - FIRST_ARG_SLOT)
474n/a {
475n/a case 0: fstw(fr4, (void *)(stack - slot)); break;
476n/a case 1: fstw(fr5, (void *)(stack - slot)); break;
477n/a case 2: fstw(fr6, (void *)(stack - slot)); break;
478n/a case 3: fstw(fr7, (void *)(stack - slot)); break;
479n/a }
480n/a#endif
481n/a avalue[i] = (void *)(stack - slot);
482n/a break;
483n/a
484n/a case FFI_TYPE_DOUBLE:
485n/a slot += (slot & 1) ? 1 : 2;
486n/a#ifdef PA_LINUX
487n/a /* See previous comment for FFI_TYPE_FLOAT. */
488n/a switch (slot - FIRST_ARG_SLOT)
489n/a {
490n/a case 1: fstd(fr5, (void *)(stack - slot)); break;
491n/a case 3: fstd(fr7, (void *)(stack - slot)); break;
492n/a }
493n/a#endif
494n/a avalue[i] = (void *)(stack - slot);
495n/a break;
496n/a
497n/a#ifdef PA_HPUX
498n/a case FFI_TYPE_LONGDOUBLE:
499n/a /* Long doubles are treated like a big structure. */
500n/a avalue[i] = (void *) *(stack - slot);
501n/a break;
502n/a#endif
503n/a
504n/a case FFI_TYPE_STRUCT:
505n/a /* Structs smaller or equal than 4 bytes are passed in one
506n/a register. Structs smaller or equal 8 bytes are passed in two
507n/a registers. Larger structures are passed by pointer. */
508n/a if((*p_arg)->size <= 4)
509n/a {
510n/a avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
511n/a (*p_arg)->size;
512n/a }
513n/a else if ((*p_arg)->size <= 8)
514n/a {
515n/a slot += (slot & 1) ? 1 : 2;
516n/a avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
517n/a (*p_arg)->size;
518n/a }
519n/a else
520n/a avalue[i] = (void *) *(stack - slot);
521n/a break;
522n/a
523n/a default:
524n/a FFI_ASSERT(0);
525n/a }
526n/a
527n/a slot++;
528n/a p_arg++;
529n/a }
530n/a
531n/a /* Invoke the closure. */
532n/a (closure->fun) (cif, rvalue, avalue, closure->user_data);
533n/a
534n/a debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
535n/a ret[1]);
536n/a
537n/a /* Store the result using the lower 2 bytes of the flags. */
538n/a switch (cif->flags)
539n/a {
540n/a case FFI_TYPE_UINT8:
541n/a *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);
542n/a break;
543n/a case FFI_TYPE_SINT8:
544n/a *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);
545n/a break;
546n/a case FFI_TYPE_UINT16:
547n/a *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);
548n/a break;
549n/a case FFI_TYPE_SINT16:
550n/a *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);
551n/a break;
552n/a case FFI_TYPE_INT:
553n/a case FFI_TYPE_SINT32:
554n/a case FFI_TYPE_UINT32:
555n/a *(stack - FIRST_ARG_SLOT) = ret[0];
556n/a break;
557n/a case FFI_TYPE_SINT64:
558n/a case FFI_TYPE_UINT64:
559n/a *(stack - FIRST_ARG_SLOT) = ret[0];
560n/a *(stack - FIRST_ARG_SLOT - 1) = ret[1];
561n/a break;
562n/a
563n/a case FFI_TYPE_DOUBLE:
564n/a fldd(rvalue, fr4);
565n/a break;
566n/a
567n/a case FFI_TYPE_FLOAT:
568n/a fldw(rvalue, fr4);
569n/a break;
570n/a
571n/a case FFI_TYPE_STRUCT:
572n/a /* Don't need a return value, done by caller. */
573n/a break;
574n/a
575n/a case FFI_TYPE_SMALL_STRUCT2:
576n/a case FFI_TYPE_SMALL_STRUCT3:
577n/a case FFI_TYPE_SMALL_STRUCT4:
578n/a tmp = (void*)(stack - FIRST_ARG_SLOT);
579n/a tmp += 4 - cif->rtype->size;
580n/a memcpy((void*)tmp, &ret[0], cif->rtype->size);
581n/a break;
582n/a
583n/a case FFI_TYPE_SMALL_STRUCT5:
584n/a case FFI_TYPE_SMALL_STRUCT6:
585n/a case FFI_TYPE_SMALL_STRUCT7:
586n/a case FFI_TYPE_SMALL_STRUCT8:
587n/a {
588n/a unsigned int ret2[2];
589n/a int off;
590n/a
591n/a /* Right justify ret[0] and ret[1] */
592n/a switch (cif->flags)
593n/a {
594n/a case FFI_TYPE_SMALL_STRUCT5: off = 3; break;
595n/a case FFI_TYPE_SMALL_STRUCT6: off = 2; break;
596n/a case FFI_TYPE_SMALL_STRUCT7: off = 1; break;
597n/a default: off = 0; break;
598n/a }
599n/a
600n/a memset (ret2, 0, sizeof (ret2));
601n/a memcpy ((char *)ret2 + off, ret, 8 - off);
602n/a
603n/a *(stack - FIRST_ARG_SLOT) = ret2[0];
604n/a *(stack - FIRST_ARG_SLOT - 1) = ret2[1];
605n/a }
606n/a break;
607n/a
608n/a case FFI_TYPE_POINTER:
609n/a case FFI_TYPE_VOID:
610n/a break;
611n/a
612n/a default:
613n/a debug(0, "assert with cif->flags: %d\n",cif->flags);
614n/a FFI_ASSERT(0);
615n/a break;
616n/a }
617n/a return FFI_OK;
618n/a}
619n/a
620n/a/* Fill in a closure to refer to the specified fun and user_data.
621n/a cif specifies the argument and result types for fun.
622n/a The cif must already be prep'ed. */
623n/a
624n/aextern void ffi_closure_pa32(void);
625n/a
626n/affi_status
627n/affi_prep_closure_loc (ffi_closure* closure,
628n/a ffi_cif* cif,
629n/a void (*fun)(ffi_cif*,void*,void**,void*),
630n/a void *user_data,
631n/a void *codeloc)
632n/a{
633n/a UINT32 *tramp = (UINT32 *)(closure->tramp);
634n/a#ifdef PA_HPUX
635n/a UINT32 *tmp;
636n/a#endif
637n/a
638n/a if (cif->abi != FFI_PA32)
639n/a return FFI_BAD_ABI;
640n/a
641n/a /* Make a small trampoline that will branch to our
642n/a handler function. Use PC-relative addressing. */
643n/a
644n/a#ifdef PA_LINUX
645n/a tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
646n/a tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
647n/a tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */
648n/a tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
649n/a tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
650n/a tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */
651n/a tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
652n/a tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
653n/a
654n/a /* Flush d/icache -- have to flush up 2 two lines because of
655n/a alignment. */
656n/a __asm__ volatile(
657n/a "fdc 0(%0)\n\t"
658n/a "fdc %1(%0)\n\t"
659n/a "fic 0(%%sr4, %0)\n\t"
660n/a "fic %1(%%sr4, %0)\n\t"
661n/a "sync\n\t"
662n/a "nop\n\t"
663n/a "nop\n\t"
664n/a "nop\n\t"
665n/a "nop\n\t"
666n/a "nop\n\t"
667n/a "nop\n\t"
668n/a "nop\n"
669n/a :
670n/a : "r"((unsigned long)tramp & ~31),
671n/a "r"(32 /* stride */)
672n/a : "memory");
673n/a#endif
674n/a
675n/a#ifdef PA_HPUX
676n/a tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
677n/a tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
678n/a tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */
679n/a tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
680n/a tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
681n/a tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */
682n/a tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */
683n/a tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */
684n/a tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
685n/a tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
686n/a
687n/a /* Flush d/icache -- have to flush three lines because of alignment. */
688n/a __asm__ volatile(
689n/a "copy %1,%0\n\t"
690n/a "fdc,m %2(%0)\n\t"
691n/a "fdc,m %2(%0)\n\t"
692n/a "fdc,m %2(%0)\n\t"
693n/a "ldsid (%1),%0\n\t"
694n/a "mtsp %0,%%sr0\n\t"
695n/a "copy %1,%0\n\t"
696n/a "fic,m %2(%%sr0,%0)\n\t"
697n/a "fic,m %2(%%sr0,%0)\n\t"
698n/a "fic,m %2(%%sr0,%0)\n\t"
699n/a "sync\n\t"
700n/a "nop\n\t"
701n/a "nop\n\t"
702n/a "nop\n\t"
703n/a "nop\n\t"
704n/a "nop\n\t"
705n/a "nop\n\t"
706n/a "nop\n"
707n/a : "=&r" ((unsigned long)tmp)
708n/a : "r" ((unsigned long)tramp & ~31),
709n/a "r" (32/* stride */)
710n/a : "memory");
711n/a#endif
712n/a
713n/a closure->cif = cif;
714n/a closure->user_data = user_data;
715n/a closure->fun = fun;
716n/a
717n/a return FFI_OK;
718n/a}
719n/a#endif