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

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

#countcontent
1n/a/* -----------------------------------------------------------------------
2n/a ffi.c - Copyright (C) 2012, 2013 Anthony Green
3n/a
4n/a Moxie Foreign Function Interface
5n/a
6n/a Permission is hereby granted, free of charge, to any person obtaining
7n/a a copy of this software and associated documentation files (the
8n/a ``Software''), to deal in the Software without restriction, including
9n/a without limitation the rights to use, copy, modify, merge, publish,
10n/a distribute, sublicense, and/or sell copies of the Software, and to
11n/a permit persons to whom the Software is furnished to do so, subject to
12n/a the following conditions:
13n/a
14n/a The above copyright notice and this permission notice shall be included
15n/a in all copies or substantial portions of the Software.
16n/a
17n/a THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18n/a EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19n/a MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20n/a NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21n/a HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22n/a WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23n/a OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24n/a DEALINGS IN THE SOFTWARE.
25n/a ----------------------------------------------------------------------- */
26n/a
27n/a#include <ffi.h>
28n/a#include <ffi_common.h>
29n/a
30n/a#include <stdlib.h>
31n/a
32n/a/* ffi_prep_args is called by the assembly routine once stack space
33n/a has been allocated for the function's arguments */
34n/a
35n/avoid *ffi_prep_args(char *stack, extended_cif *ecif)
36n/a{
37n/a register unsigned int i;
38n/a register void **p_argv;
39n/a register char *argp;
40n/a register ffi_type **p_arg;
41n/a register int count = 0;
42n/a
43n/a p_argv = ecif->avalue;
44n/a argp = stack;
45n/a
46n/a if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
47n/a {
48n/a *(void **) argp = ecif->rvalue;
49n/a argp += 4;
50n/a }
51n/a
52n/a for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
53n/a (i != 0);
54n/a i--, p_arg++)
55n/a {
56n/a size_t z;
57n/a
58n/a z = (*p_arg)->size;
59n/a
60n/a if ((*p_arg)->type == FFI_TYPE_STRUCT)
61n/a {
62n/a z = sizeof(void*);
63n/a *(void **) argp = *p_argv;
64n/a }
65n/a else if (z < sizeof(int))
66n/a {
67n/a z = sizeof(int);
68n/a switch ((*p_arg)->type)
69n/a {
70n/a case FFI_TYPE_SINT8:
71n/a *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
72n/a break;
73n/a
74n/a case FFI_TYPE_UINT8:
75n/a *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
76n/a break;
77n/a
78n/a case FFI_TYPE_SINT16:
79n/a *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
80n/a break;
81n/a
82n/a case FFI_TYPE_UINT16:
83n/a *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
84n/a break;
85n/a
86n/a default:
87n/a FFI_ASSERT(0);
88n/a }
89n/a }
90n/a else if (z == sizeof(int))
91n/a {
92n/a *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
93n/a }
94n/a else
95n/a {
96n/a memcpy(argp, *p_argv, z);
97n/a }
98n/a p_argv++;
99n/a argp += z;
100n/a count += z;
101n/a }
102n/a
103n/a return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
104n/a}
105n/a
106n/a/* Perform machine dependent cif processing */
107n/affi_status ffi_prep_cif_machdep(ffi_cif *cif)
108n/a{
109n/a if (cif->rtype->type == FFI_TYPE_STRUCT)
110n/a cif->flags = -1;
111n/a else
112n/a cif->flags = cif->rtype->size;
113n/a
114n/a cif->bytes = ALIGN (cif->bytes, 8);
115n/a
116n/a return FFI_OK;
117n/a}
118n/a
119n/aextern void ffi_call_EABI(void *(*)(char *, extended_cif *),
120n/a extended_cif *,
121n/a unsigned, unsigned,
122n/a unsigned *,
123n/a void (*fn)(void));
124n/a
125n/avoid ffi_call(ffi_cif *cif,
126n/a void (*fn)(void),
127n/a void *rvalue,
128n/a void **avalue)
129n/a{
130n/a extended_cif ecif;
131n/a
132n/a ecif.cif = cif;
133n/a ecif.avalue = avalue;
134n/a
135n/a /* If the return value is a struct and we don't have a return */
136n/a /* value address then we need to make one */
137n/a
138n/a if ((rvalue == NULL) &&
139n/a (cif->rtype->type == FFI_TYPE_STRUCT))
140n/a {
141n/a ecif.rvalue = alloca(cif->rtype->size);
142n/a }
143n/a else
144n/a ecif.rvalue = rvalue;
145n/a
146n/a switch (cif->abi)
147n/a {
148n/a case FFI_EABI:
149n/a ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
150n/a cif->flags, ecif.rvalue, fn);
151n/a break;
152n/a default:
153n/a FFI_ASSERT(0);
154n/a break;
155n/a }
156n/a}
157n/a
158n/avoid ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
159n/a unsigned arg4, unsigned arg5, unsigned arg6)
160n/a{
161n/a /* This function is called by a trampoline. The trampoline stows a
162n/a pointer to the ffi_closure object in $r7. We must save this
163n/a pointer in a place that will persist while we do our work. */
164n/a register ffi_closure *creg __asm__ ("$r12");
165n/a ffi_closure *closure = creg;
166n/a
167n/a /* Arguments that don't fit in registers are found on the stack
168n/a at a fixed offset above the current frame pointer. */
169n/a register char *frame_pointer __asm__ ("$fp");
170n/a
171n/a /* Pointer to a struct return value. */
172n/a void *struct_rvalue = (void *) arg1;
173n/a
174n/a /* 6 words reserved for register args + 3 words from jsr */
175n/a char *stack_args = frame_pointer + 9*4;
176n/a
177n/a /* Lay the register arguments down in a continuous chunk of memory. */
178n/a unsigned register_args[6] =
179n/a { arg1, arg2, arg3, arg4, arg5, arg6 };
180n/a char *register_args_ptr = (char *) register_args;
181n/a
182n/a ffi_cif *cif = closure->cif;
183n/a ffi_type **arg_types = cif->arg_types;
184n/a void **avalue = alloca (cif->nargs * sizeof(void *));
185n/a char *ptr = (char *) register_args;
186n/a int i;
187n/a
188n/a /* preserve struct type return pointer passing */
189n/a if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
190n/a ptr += 4;
191n/a register_args_ptr = (char *)&register_args[1];
192n/a }
193n/a
194n/a /* Find the address of each argument. */
195n/a for (i = 0; i < cif->nargs; i++)
196n/a {
197n/a switch (arg_types[i]->type)
198n/a {
199n/a case FFI_TYPE_SINT8:
200n/a case FFI_TYPE_UINT8:
201n/a avalue[i] = ptr + 3;
202n/a break;
203n/a case FFI_TYPE_SINT16:
204n/a case FFI_TYPE_UINT16:
205n/a avalue[i] = ptr + 2;
206n/a break;
207n/a case FFI_TYPE_SINT32:
208n/a case FFI_TYPE_UINT32:
209n/a case FFI_TYPE_FLOAT:
210n/a case FFI_TYPE_POINTER:
211n/a avalue[i] = ptr;
212n/a break;
213n/a case FFI_TYPE_STRUCT:
214n/a avalue[i] = *(void**)ptr;
215n/a break;
216n/a default:
217n/a /* This is an 8-byte value. */
218n/a avalue[i] = ptr;
219n/a ptr += 4;
220n/a break;
221n/a }
222n/a ptr += 4;
223n/a
224n/a /* If we've handled more arguments than fit in registers,
225n/a start looking at the those passed on the stack. */
226n/a if (ptr == &register_args[6])
227n/a ptr = stack_args;
228n/a }
229n/a
230n/a /* Invoke the closure. */
231n/a if (cif->rtype && (cif->rtype->type == FFI_TYPE_STRUCT))
232n/a {
233n/a (closure->fun) (cif, struct_rvalue, avalue, closure->user_data);
234n/a }
235n/a else
236n/a {
237n/a /* Allocate space for the return value and call the function. */
238n/a long long rvalue;
239n/a (closure->fun) (cif, &rvalue, avalue, closure->user_data);
240n/a asm ("mov $r12, %0\n ld.l $r0, ($r12)\n ldo.l $r1, 4($r12)" : : "r" (&rvalue));
241n/a }
242n/a}
243n/a
244n/affi_status
245n/affi_prep_closure_loc (ffi_closure* closure,
246n/a ffi_cif* cif,
247n/a void (*fun)(ffi_cif*, void*, void**, void*),
248n/a void *user_data,
249n/a void *codeloc)
250n/a{
251n/a unsigned short *tramp = (unsigned short *) &closure->tramp[0];
252n/a unsigned long fn = (long) ffi_closure_eabi;
253n/a unsigned long cls = (long) codeloc;
254n/a
255n/a if (cif->abi != FFI_EABI)
256n/a return FFI_BAD_ABI;
257n/a
258n/a fn = (unsigned long) ffi_closure_eabi;
259n/a
260n/a tramp[0] = 0x01e0; /* ldi.l $r7, .... */
261n/a tramp[1] = cls >> 16;
262n/a tramp[2] = cls & 0xffff;
263n/a tramp[3] = 0x1a00; /* jmpa .... */
264n/a tramp[4] = fn >> 16;
265n/a tramp[5] = fn & 0xffff;
266n/a
267n/a closure->cif = cif;
268n/a closure->fun = fun;
269n/a closure->user_data = user_data;
270n/a
271n/a return FFI_OK;
272n/a}