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

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

#countcontent
1n/a/* -----------------------------------------------------------------------
2n/a ffi.c - Copyright (c) 2012, 2013 Xilinx, Inc
3n/a
4n/a MicroBlaze 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/aextern void ffi_call_SYSV(void (*)(void*, extended_cif*), extended_cif*,
31n/a unsigned int, unsigned int, unsigned int*, void (*fn)(void),
32n/a unsigned int, unsigned int);
33n/a
34n/aextern void ffi_closure_SYSV(void);
35n/a
36n/a#define WORD_SIZE sizeof(unsigned int)
37n/a#define ARGS_REGISTER_SIZE (WORD_SIZE * 6)
38n/a#define WORD_ALIGN(x) ALIGN(x, WORD_SIZE)
39n/a
40n/a/* ffi_prep_args is called by the assembly routine once stack space
41n/a has been allocated for the function's arguments */
42n/avoid ffi_prep_args(void* stack, extended_cif* ecif)
43n/a{
44n/a unsigned int i;
45n/a ffi_type** p_arg;
46n/a void** p_argv;
47n/a void* stack_args_p = stack;
48n/a
49n/a p_argv = ecif->avalue;
50n/a
51n/a if (ecif == NULL || ecif->cif == NULL) {
52n/a return; /* no description to prepare */
53n/a }
54n/a
55n/a if ((ecif->cif->rtype != NULL) &&
56n/a (ecif->cif->rtype->type == FFI_TYPE_STRUCT))
57n/a {
58n/a /* if return type is a struct which is referenced on the stack/reg5,
59n/a * by a pointer. Stored the return value pointer in r5.
60n/a */
61n/a char* addr = stack_args_p;
62n/a memcpy(addr, &(ecif->rvalue), WORD_SIZE);
63n/a stack_args_p += WORD_SIZE;
64n/a }
65n/a
66n/a if (ecif->avalue == NULL) {
67n/a return; /* no arguments to prepare */
68n/a }
69n/a
70n/a for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs;
71n/a i++, p_arg++)
72n/a {
73n/a size_t size = (*p_arg)->size;
74n/a int type = (*p_arg)->type;
75n/a void* value = p_argv[i];
76n/a char* addr = stack_args_p;
77n/a int aligned_size = WORD_ALIGN(size);
78n/a
79n/a /* force word alignment on the stack */
80n/a stack_args_p += aligned_size;
81n/a
82n/a switch (type)
83n/a {
84n/a case FFI_TYPE_UINT8:
85n/a *(unsigned int *)addr = (unsigned int)*(UINT8*)(value);
86n/a break;
87n/a case FFI_TYPE_SINT8:
88n/a *(signed int *)addr = (signed int)*(SINT8*)(value);
89n/a break;
90n/a case FFI_TYPE_UINT16:
91n/a *(unsigned int *)addr = (unsigned int)*(UINT16*)(value);
92n/a break;
93n/a case FFI_TYPE_SINT16:
94n/a *(signed int *)addr = (signed int)*(SINT16*)(value);
95n/a break;
96n/a case FFI_TYPE_STRUCT:
97n/a#if __BIG_ENDIAN__
98n/a /*
99n/a * MicroBlaze toolchain appears to emit:
100n/a * bsrli r5, r5, 8 (caller)
101n/a * ...
102n/a * <branch to callee>
103n/a * ...
104n/a * bslli r5, r5, 8 (callee)
105n/a *
106n/a * For structs like "struct a { uint8_t a[3]; };", when passed
107n/a * by value.
108n/a *
109n/a * Structs like "struct b { uint16_t a; };" are also expected
110n/a * to be packed strangely in registers.
111n/a *
112n/a * This appears to be because the microblaze toolchain expects
113n/a * "struct b == uint16_t", which is only any issue for big
114n/a * endian.
115n/a *
116n/a * The following is a work around for big-endian only, for the
117n/a * above mentioned case, it will re-align the contents of a
118n/a * <= 3-byte struct value.
119n/a */
120n/a if (size < WORD_SIZE)
121n/a {
122n/a memcpy (addr + (WORD_SIZE - size), value, size);
123n/a break;
124n/a }
125n/a#endif
126n/a case FFI_TYPE_SINT32:
127n/a case FFI_TYPE_UINT32:
128n/a case FFI_TYPE_FLOAT:
129n/a case FFI_TYPE_SINT64:
130n/a case FFI_TYPE_UINT64:
131n/a case FFI_TYPE_DOUBLE:
132n/a default:
133n/a memcpy(addr, value, aligned_size);
134n/a }
135n/a }
136n/a}
137n/a
138n/affi_status ffi_prep_cif_machdep(ffi_cif* cif)
139n/a{
140n/a /* check ABI */
141n/a switch (cif->abi)
142n/a {
143n/a case FFI_SYSV:
144n/a break;
145n/a default:
146n/a return FFI_BAD_ABI;
147n/a }
148n/a return FFI_OK;
149n/a}
150n/a
151n/avoid ffi_call(ffi_cif* cif, void (*fn)(void), void* rvalue, void** avalue)
152n/a{
153n/a extended_cif ecif;
154n/a ecif.cif = cif;
155n/a ecif.avalue = avalue;
156n/a
157n/a /* If the return value is a struct and we don't have a return */
158n/a /* value address then we need to make one */
159n/a if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
160n/a ecif.rvalue = alloca(cif->rtype->size);
161n/a } else {
162n/a ecif.rvalue = rvalue;
163n/a }
164n/a
165n/a switch (cif->abi)
166n/a {
167n/a case FFI_SYSV:
168n/a ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags,
169n/a ecif.rvalue, fn, cif->rtype->type, cif->rtype->size);
170n/a break;
171n/a default:
172n/a FFI_ASSERT(0);
173n/a break;
174n/a }
175n/a}
176n/a
177n/avoid ffi_closure_call_SYSV(void* register_args, void* stack_args,
178n/a ffi_closure* closure, void* rvalue,
179n/a unsigned int* rtype, unsigned int* rsize)
180n/a{
181n/a /* prepare arguments for closure call */
182n/a ffi_cif* cif = closure->cif;
183n/a ffi_type** arg_types = cif->arg_types;
184n/a
185n/a /* re-allocate data for the args. This needs to be done in order to keep
186n/a * multi-word objects (e.g. structs) in contiguous memory. Callers are not
187n/a * required to store the value of args in the lower 6 words in the stack
188n/a * (although they are allocated in the stack).
189n/a */
190n/a char* stackclone = alloca(cif->bytes);
191n/a void** avalue = alloca(cif->nargs * sizeof(void*));
192n/a void* struct_rvalue = NULL;
193n/a char* ptr = stackclone;
194n/a int i;
195n/a
196n/a /* copy registers into stack clone */
197n/a int registers_used = cif->bytes;
198n/a if (registers_used > ARGS_REGISTER_SIZE) {
199n/a registers_used = ARGS_REGISTER_SIZE;
200n/a }
201n/a memcpy(stackclone, register_args, registers_used);
202n/a
203n/a /* copy stack allocated args into stack clone */
204n/a if (cif->bytes > ARGS_REGISTER_SIZE) {
205n/a int stack_used = cif->bytes - ARGS_REGISTER_SIZE;
206n/a memcpy(stackclone + ARGS_REGISTER_SIZE, stack_args, stack_used);
207n/a }
208n/a
209n/a /* preserve struct type return pointer passing */
210n/a if ((cif->rtype != NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) {
211n/a struct_rvalue = *((void**)ptr);
212n/a ptr += WORD_SIZE;
213n/a }
214n/a
215n/a /* populate arg pointer list */
216n/a for (i = 0; i < cif->nargs; i++)
217n/a {
218n/a switch (arg_types[i]->type)
219n/a {
220n/a case FFI_TYPE_SINT8:
221n/a case FFI_TYPE_UINT8:
222n/a#ifdef __BIG_ENDIAN__
223n/a avalue[i] = ptr + 3;
224n/a#else
225n/a avalue[i] = ptr;
226n/a#endif
227n/a break;
228n/a case FFI_TYPE_SINT16:
229n/a case FFI_TYPE_UINT16:
230n/a#ifdef __BIG_ENDIAN__
231n/a avalue[i] = ptr + 2;
232n/a#else
233n/a avalue[i] = ptr;
234n/a#endif
235n/a break;
236n/a case FFI_TYPE_STRUCT:
237n/a#if __BIG_ENDIAN__
238n/a /*
239n/a * Work around strange ABI behaviour.
240n/a * (see info in ffi_prep_args)
241n/a */
242n/a if (arg_types[i]->size < WORD_SIZE)
243n/a {
244n/a memcpy (ptr, ptr + (WORD_SIZE - arg_types[i]->size), arg_types[i]->size);
245n/a }
246n/a#endif
247n/a avalue[i] = (void*)ptr;
248n/a break;
249n/a case FFI_TYPE_UINT64:
250n/a case FFI_TYPE_SINT64:
251n/a case FFI_TYPE_DOUBLE:
252n/a avalue[i] = ptr;
253n/a break;
254n/a case FFI_TYPE_SINT32:
255n/a case FFI_TYPE_UINT32:
256n/a case FFI_TYPE_FLOAT:
257n/a default:
258n/a /* default 4-byte argument */
259n/a avalue[i] = ptr;
260n/a break;
261n/a }
262n/a ptr += WORD_ALIGN(arg_types[i]->size);
263n/a }
264n/a
265n/a /* set the return type info passed back to the wrapper */
266n/a *rsize = cif->rtype->size;
267n/a *rtype = cif->rtype->type;
268n/a if (struct_rvalue != NULL) {
269n/a closure->fun(cif, struct_rvalue, avalue, closure->user_data);
270n/a /* copy struct return pointer value into function return value */
271n/a *((void**)rvalue) = struct_rvalue;
272n/a } else {
273n/a closure->fun(cif, rvalue, avalue, closure->user_data);
274n/a }
275n/a}
276n/a
277n/affi_status ffi_prep_closure_loc(
278n/a ffi_closure* closure, ffi_cif* cif,
279n/a void (*fun)(ffi_cif*, void*, void**, void*),
280n/a void* user_data, void* codeloc)
281n/a{
282n/a unsigned long* tramp = (unsigned long*)&(closure->tramp[0]);
283n/a unsigned long cls = (unsigned long)codeloc;
284n/a unsigned long fn = 0;
285n/a unsigned long fn_closure_call_sysv = (unsigned long)ffi_closure_call_SYSV;
286n/a
287n/a closure->cif = cif;
288n/a closure->fun = fun;
289n/a closure->user_data = user_data;
290n/a
291n/a switch (cif->abi)
292n/a {
293n/a case FFI_SYSV:
294n/a fn = (unsigned long)ffi_closure_SYSV;
295n/a
296n/a /* load r11 (temp) with fn */
297n/a /* imm fn(upper) */
298n/a tramp[0] = 0xb0000000 | ((fn >> 16) & 0xffff);
299n/a /* addik r11, r0, fn(lower) */
300n/a tramp[1] = 0x31600000 | (fn & 0xffff);
301n/a
302n/a /* load r12 (temp) with cls */
303n/a /* imm cls(upper) */
304n/a tramp[2] = 0xb0000000 | ((cls >> 16) & 0xffff);
305n/a /* addik r12, r0, cls(lower) */
306n/a tramp[3] = 0x31800000 | (cls & 0xffff);
307n/a
308n/a /* load r3 (temp) with ffi_closure_call_SYSV */
309n/a /* imm fn_closure_call_sysv(upper) */
310n/a tramp[4] = 0xb0000000 | ((fn_closure_call_sysv >> 16) & 0xffff);
311n/a /* addik r3, r0, fn_closure_call_sysv(lower) */
312n/a tramp[5] = 0x30600000 | (fn_closure_call_sysv & 0xffff);
313n/a /* branch/jump to address stored in r11 (fn) */
314n/a tramp[6] = 0x98085800; /* bra r11 */
315n/a
316n/a break;
317n/a default:
318n/a return FFI_BAD_ABI;
319n/a }
320n/a return FFI_OK;
321n/a}