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

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

#countcontent
1n/a/* -----------------------------------------------------------------------
2n/a ffi.c - Copyright (c) 2013 Tensilica, Inc.
3n/a
4n/a XTENSA 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/*
31n/a |----------------------------------------|
32n/a | |
33n/a on entry to ffi_call ----> |----------------------------------------|
34n/a | caller stack frame for registers a0-a3 |
35n/a |----------------------------------------|
36n/a | |
37n/a | additional arguments |
38n/a entry of the function ---> |----------------------------------------|
39n/a | copy of function arguments a2-a7 |
40n/a | - - - - - - - - - - - - - |
41n/a | |
42n/a
43n/a The area below the entry line becomes the new stack frame for the function.
44n/a
45n/a*/
46n/a
47n/a
48n/a#define FFI_TYPE_STRUCT_REGS FFI_TYPE_LAST
49n/a
50n/a
51n/aextern void ffi_call_SYSV(void *rvalue, unsigned rsize, unsigned flags,
52n/a void(*fn)(void), unsigned nbytes, extended_cif*);
53n/aextern void ffi_closure_SYSV(void) FFI_HIDDEN;
54n/a
55n/affi_status ffi_prep_cif_machdep(ffi_cif *cif)
56n/a{
57n/a switch(cif->rtype->type) {
58n/a case FFI_TYPE_SINT8:
59n/a case FFI_TYPE_UINT8:
60n/a case FFI_TYPE_SINT16:
61n/a case FFI_TYPE_UINT16:
62n/a cif->flags = cif->rtype->type;
63n/a break;
64n/a case FFI_TYPE_VOID:
65n/a case FFI_TYPE_FLOAT:
66n/a cif->flags = FFI_TYPE_UINT32;
67n/a break;
68n/a case FFI_TYPE_DOUBLE:
69n/a case FFI_TYPE_UINT64:
70n/a case FFI_TYPE_SINT64:
71n/a cif->flags = FFI_TYPE_UINT64; // cif->rtype->type;
72n/a break;
73n/a case FFI_TYPE_STRUCT:
74n/a cif->flags = FFI_TYPE_STRUCT; //_REGS;
75n/a /* Up to 16 bytes are returned in registers */
76n/a if (cif->rtype->size > 4 * 4) {
77n/a /* returned structure is referenced by a register; use 8 bytes
78n/a (including 4 bytes for potential additional alignment) */
79n/a cif->flags = FFI_TYPE_STRUCT;
80n/a cif->bytes += 8;
81n/a }
82n/a break;
83n/a
84n/a default:
85n/a cif->flags = FFI_TYPE_UINT32;
86n/a break;
87n/a }
88n/a
89n/a /* Round the stack up to a full 4 register frame, just in case
90n/a (we use this size in movsp). This way, it's also a multiple of
91n/a 8 bytes for 64-bit arguments. */
92n/a cif->bytes = ALIGN(cif->bytes, 16);
93n/a
94n/a return FFI_OK;
95n/a}
96n/a
97n/avoid ffi_prep_args(extended_cif *ecif, unsigned char* stack)
98n/a{
99n/a unsigned int i;
100n/a unsigned long *addr;
101n/a ffi_type **ptr;
102n/a
103n/a union {
104n/a void **v;
105n/a char **c;
106n/a signed char **sc;
107n/a unsigned char **uc;
108n/a signed short **ss;
109n/a unsigned short **us;
110n/a unsigned int **i;
111n/a long long **ll;
112n/a float **f;
113n/a double **d;
114n/a } p_argv;
115n/a
116n/a /* Verify that everything is aligned up properly */
117n/a FFI_ASSERT (((unsigned long) stack & 0x7) == 0);
118n/a
119n/a p_argv.v = ecif->avalue;
120n/a addr = (unsigned long*)stack;
121n/a
122n/a /* structures with a size greater than 16 bytes are passed in memory */
123n/a if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 16)
124n/a {
125n/a *addr++ = (unsigned long)ecif->rvalue;
126n/a }
127n/a
128n/a for (i = ecif->cif->nargs, ptr = ecif->cif->arg_types;
129n/a i > 0;
130n/a i--, ptr++, p_argv.v++)
131n/a {
132n/a switch ((*ptr)->type)
133n/a {
134n/a case FFI_TYPE_SINT8:
135n/a *addr++ = **p_argv.sc;
136n/a break;
137n/a case FFI_TYPE_UINT8:
138n/a *addr++ = **p_argv.uc;
139n/a break;
140n/a case FFI_TYPE_SINT16:
141n/a *addr++ = **p_argv.ss;
142n/a break;
143n/a case FFI_TYPE_UINT16:
144n/a *addr++ = **p_argv.us;
145n/a break;
146n/a case FFI_TYPE_FLOAT:
147n/a case FFI_TYPE_INT:
148n/a case FFI_TYPE_UINT32:
149n/a case FFI_TYPE_SINT32:
150n/a case FFI_TYPE_POINTER:
151n/a *addr++ = **p_argv.i;
152n/a break;
153n/a case FFI_TYPE_DOUBLE:
154n/a case FFI_TYPE_UINT64:
155n/a case FFI_TYPE_SINT64:
156n/a if (((unsigned long)addr & 4) != 0)
157n/a addr++;
158n/a *(unsigned long long*)addr = **p_argv.ll;
159n/a addr += sizeof(unsigned long long) / sizeof (addr);
160n/a break;
161n/a
162n/a case FFI_TYPE_STRUCT:
163n/a {
164n/a unsigned long offs;
165n/a unsigned long size;
166n/a
167n/a if (((unsigned long)addr & 4) != 0 && (*ptr)->alignment > 4)
168n/a addr++;
169n/a
170n/a offs = (unsigned long) addr - (unsigned long) stack;
171n/a size = (*ptr)->size;
172n/a
173n/a /* Entire structure must fit the argument registers or referenced */
174n/a if (offs < FFI_REGISTER_NARGS * 4
175n/a && offs + size > FFI_REGISTER_NARGS * 4)
176n/a addr = (unsigned long*) (stack + FFI_REGISTER_NARGS * 4);
177n/a
178n/a memcpy((char*) addr, *p_argv.c, size);
179n/a addr += (size + 3) / 4;
180n/a break;
181n/a }
182n/a
183n/a default:
184n/a FFI_ASSERT(0);
185n/a }
186n/a }
187n/a}
188n/a
189n/a
190n/avoid ffi_call(ffi_cif* cif, void(*fn)(void), void *rvalue, void **avalue)
191n/a{
192n/a extended_cif ecif;
193n/a unsigned long rsize = cif->rtype->size;
194n/a int flags = cif->flags;
195n/a void *alloc = NULL;
196n/a
197n/a ecif.cif = cif;
198n/a ecif.avalue = avalue;
199n/a
200n/a /* Note that for structures that are returned in registers (size <= 16 bytes)
201n/a we allocate a temporary buffer and use memcpy to copy it to the final
202n/a destination. The reason is that the target address might be misaligned or
203n/a the length not a multiple of 4 bytes. Handling all those cases would be
204n/a very complex. */
205n/a
206n/a if (flags == FFI_TYPE_STRUCT && (rsize <= 16 || rvalue == NULL))
207n/a {
208n/a alloc = alloca(ALIGN(rsize, 4));
209n/a ecif.rvalue = alloc;
210n/a }
211n/a else
212n/a {
213n/a ecif.rvalue = rvalue;
214n/a }
215n/a
216n/a if (cif->abi != FFI_SYSV)
217n/a FFI_ASSERT(0);
218n/a
219n/a ffi_call_SYSV (ecif.rvalue, rsize, cif->flags, fn, cif->bytes, &ecif);
220n/a
221n/a if (alloc != NULL && rvalue != NULL)
222n/a memcpy(rvalue, alloc, rsize);
223n/a}
224n/a
225n/aextern void ffi_trampoline();
226n/aextern void ffi_cacheflush(void* start, void* end);
227n/a
228n/affi_status
229n/affi_prep_closure_loc (ffi_closure* closure,
230n/a ffi_cif* cif,
231n/a void (*fun)(ffi_cif*, void*, void**, void*),
232n/a void *user_data,
233n/a void *codeloc)
234n/a{
235n/a /* copye trampoline to stack and patch 'ffi_closure_SYSV' pointer */
236n/a memcpy(closure->tramp, ffi_trampoline, FFI_TRAMPOLINE_SIZE);
237n/a *(unsigned int*)(&closure->tramp[8]) = (unsigned int)ffi_closure_SYSV;
238n/a
239n/a // Do we have this function?
240n/a // __builtin___clear_cache(closer->tramp, closer->tramp + FFI_TRAMPOLINE_SIZE)
241n/a ffi_cacheflush(closure->tramp, closure->tramp + FFI_TRAMPOLINE_SIZE);
242n/a
243n/a closure->cif = cif;
244n/a closure->fun = fun;
245n/a closure->user_data = user_data;
246n/a return FFI_OK;
247n/a}
248n/a
249n/a
250n/along FFI_HIDDEN
251n/affi_closure_SYSV_inner(ffi_closure *closure, void **values, void *rvalue)
252n/a{
253n/a ffi_cif *cif;
254n/a ffi_type **arg_types;
255n/a void **avalue;
256n/a int i, areg;
257n/a
258n/a cif = closure->cif;
259n/a if (cif->abi != FFI_SYSV)
260n/a return FFI_BAD_ABI;
261n/a
262n/a areg = 0;
263n/a
264n/a int rtype = cif->rtype->type;
265n/a if (rtype == FFI_TYPE_STRUCT && cif->rtype->size > 4 * 4)
266n/a {
267n/a rvalue = *values;
268n/a areg++;
269n/a }
270n/a
271n/a cif = closure->cif;
272n/a arg_types = cif->arg_types;
273n/a avalue = alloca(cif->nargs * sizeof(void *));
274n/a
275n/a for (i = 0; i < cif->nargs; i++)
276n/a {
277n/a if (arg_types[i]->alignment == 8 && (areg & 1) != 0)
278n/a areg++;
279n/a
280n/a // skip the entry 16,a1 framework, add 16 bytes (4 registers)
281n/a if (areg == FFI_REGISTER_NARGS)
282n/a areg += 4;
283n/a
284n/a if (arg_types[i]->type == FFI_TYPE_STRUCT)
285n/a {
286n/a int numregs = ((arg_types[i]->size + 3) & ~3) / 4;
287n/a if (areg < FFI_REGISTER_NARGS && areg + numregs > FFI_REGISTER_NARGS)
288n/a areg = FFI_REGISTER_NARGS + 4;
289n/a }
290n/a
291n/a avalue[i] = &values[areg];
292n/a areg += (arg_types[i]->size + 3) / 4;
293n/a }
294n/a
295n/a (closure->fun)(cif, rvalue, avalue, closure->user_data);
296n/a
297n/a return rtype;
298n/a}