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

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

#countcontent
1n/a/* ----------------------------------------------------------------------
2n/a ffi.c - Copyright (c) 2013 Imagination Technologies
3n/a
4n/a Meta Foreign Function Interface
5n/a Permission is hereby granted, free of charge, to any person obtaining
6n/a a copy of this software and associated documentation files (the
7n/a `Software''), to deal in the Software without restriction, including
8n/a without limitation the rights to use, copy, modify, merge, publish,
9n/a distribute, sublicense, and/or sell copies of the Software, and to
10n/a permit persons to whom the Software is furnished to do so, subject to
11n/a the following conditions:
12n/a
13n/a The above copyright notice and this permission notice shall be included
14n/a in all copies or substantial portions of the Software.
15n/a
16n/a THE SOFTWARE IS PROVIDED `AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
17n/a OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18n/a MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19n/a IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
20n/a OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21n/a ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22n/a OTHER DEALINGS IN THE SOFTWARE.
23n/a----------------------------------------------------------------------- */
24n/a
25n/a#include <ffi.h>
26n/a#include <ffi_common.h>
27n/a
28n/a#include <stdlib.h>
29n/a
30n/a#define MIN(a,b) (((a) < (b)) ? (a) : (b))
31n/a
32n/a/*
33n/a * ffi_prep_args is called by the assembly routine once stack space has been
34n/a * allocated for the function's arguments
35n/a */
36n/a
37n/aunsigned int ffi_prep_args(char *stack, extended_cif *ecif)
38n/a{
39n/a register unsigned int i;
40n/a register void **p_argv;
41n/a register char *argp;
42n/a register ffi_type **p_arg;
43n/a
44n/a argp = stack;
45n/a
46n/a /* Store return value */
47n/a if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
48n/a argp -= 4;
49n/a *(void **) argp = ecif->rvalue;
50n/a }
51n/a
52n/a p_argv = ecif->avalue;
53n/a
54n/a /* point to next location */
55n/a for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; (i != 0); i--, p_arg++, p_argv++)
56n/a {
57n/a size_t z;
58n/a
59n/a /* Move argp to address of argument */
60n/a z = (*p_arg)->size;
61n/a argp -= z;
62n/a
63n/a /* Align if necessary */
64n/a argp = (char *) ALIGN_DOWN(ALIGN_DOWN(argp, (*p_arg)->alignment), 4);
65n/a
66n/a if (z < sizeof(int)) {
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 case FFI_TYPE_UINT8:
74n/a *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
75n/a break;
76n/a case FFI_TYPE_SINT16:
77n/a *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
78n/a break;
79n/a case FFI_TYPE_UINT16:
80n/a *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
81n/a case FFI_TYPE_STRUCT:
82n/a memcpy(argp, *p_argv, (*p_arg)->size);
83n/a break;
84n/a default:
85n/a FFI_ASSERT(0);
86n/a }
87n/a } else if ( z == sizeof(int)) {
88n/a *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
89n/a } else {
90n/a memcpy(argp, *p_argv, z);
91n/a }
92n/a }
93n/a
94n/a /* return the size of the arguments to be passed in registers,
95n/a padded to an 8 byte boundary to preserve stack alignment */
96n/a return ALIGN(MIN(stack - argp, 6*4), 8);
97n/a}
98n/a
99n/a/* Perform machine dependent cif processing */
100n/affi_status ffi_prep_cif_machdep(ffi_cif *cif)
101n/a{
102n/a ffi_type **ptr;
103n/a unsigned i, bytes = 0;
104n/a
105n/a for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) {
106n/a if ((*ptr)->size == 0)
107n/a return FFI_BAD_TYPEDEF;
108n/a
109n/a /* Perform a sanity check on the argument type, do this
110n/a check after the initialization. */
111n/a FFI_ASSERT_VALID_TYPE(*ptr);
112n/a
113n/a /* Add any padding if necessary */
114n/a if (((*ptr)->alignment - 1) & bytes)
115n/a bytes = ALIGN(bytes, (*ptr)->alignment);
116n/a
117n/a bytes += ALIGN((*ptr)->size, 4);
118n/a }
119n/a
120n/a /* Ensure arg space is aligned to an 8-byte boundary */
121n/a bytes = ALIGN(bytes, 8);
122n/a
123n/a /* Make space for the return structure pointer */
124n/a if (cif->rtype->type == FFI_TYPE_STRUCT) {
125n/a bytes += sizeof(void*);
126n/a
127n/a /* Ensure stack is aligned to an 8-byte boundary */
128n/a bytes = ALIGN(bytes, 8);
129n/a }
130n/a
131n/a cif->bytes = bytes;
132n/a
133n/a /* Set the return type flag */
134n/a switch (cif->rtype->type) {
135n/a case FFI_TYPE_VOID:
136n/a case FFI_TYPE_FLOAT:
137n/a case FFI_TYPE_DOUBLE:
138n/a cif->flags = (unsigned) cif->rtype->type;
139n/a break;
140n/a case FFI_TYPE_SINT64:
141n/a case FFI_TYPE_UINT64:
142n/a cif->flags = (unsigned) FFI_TYPE_SINT64;
143n/a break;
144n/a case FFI_TYPE_STRUCT:
145n/a /* Meta can store return values which are <= 64 bits */
146n/a if (cif->rtype->size <= 4)
147n/a /* Returned to D0Re0 as 32-bit value */
148n/a cif->flags = (unsigned)FFI_TYPE_INT;
149n/a else if ((cif->rtype->size > 4) && (cif->rtype->size <= 8))
150n/a /* Returned valued is stored to D1Re0|R0Re0 */
151n/a cif->flags = (unsigned)FFI_TYPE_DOUBLE;
152n/a else
153n/a /* value stored in memory */
154n/a cif->flags = (unsigned)FFI_TYPE_STRUCT;
155n/a break;
156n/a default:
157n/a cif->flags = (unsigned)FFI_TYPE_INT;
158n/a break;
159n/a }
160n/a return FFI_OK;
161n/a}
162n/a
163n/aextern void ffi_call_SYSV(void (*fn)(void), extended_cif *, unsigned, unsigned, double *);
164n/a
165n/a/*
166n/a * Exported in API. Entry point
167n/a * cif -> ffi_cif object
168n/a * fn -> function pointer
169n/a * rvalue -> pointer to return value
170n/a * avalue -> vector of void * pointers pointing to memory locations holding the
171n/a * arguments
172n/a */
173n/avoid ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
174n/a{
175n/a extended_cif ecif;
176n/a
177n/a int small_struct = (((cif->flags == FFI_TYPE_INT) || (cif->flags == FFI_TYPE_DOUBLE)) && (cif->rtype->type == FFI_TYPE_STRUCT));
178n/a ecif.cif = cif;
179n/a ecif.avalue = avalue;
180n/a
181n/a double temp;
182n/a
183n/a /*
184n/a * If the return value is a struct and we don't have a return value address
185n/a * then we need to make one
186n/a */
187n/a
188n/a if ((rvalue == NULL ) && (cif->flags == FFI_TYPE_STRUCT))
189n/a ecif.rvalue = alloca(cif->rtype->size);
190n/a else if (small_struct)
191n/a ecif.rvalue = &temp;
192n/a else
193n/a ecif.rvalue = rvalue;
194n/a
195n/a switch (cif->abi) {
196n/a case FFI_SYSV:
197n/a ffi_call_SYSV(fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
198n/a break;
199n/a default:
200n/a FFI_ASSERT(0);
201n/a break;
202n/a }
203n/a
204n/a if (small_struct)
205n/a memcpy (rvalue, &temp, cif->rtype->size);
206n/a}
207n/a
208n/a/* private members */
209n/a
210n/astatic void ffi_prep_incoming_args_SYSV (char *, void **, void **,
211n/a ffi_cif*, float *);
212n/a
213n/avoid ffi_closure_SYSV (ffi_closure *);
214n/a
215n/a/* Do NOT change that without changing the FFI_TRAMPOLINE_SIZE */
216n/aextern unsigned int ffi_metag_trampoline[10]; /* 10 instructions */
217n/a
218n/a/* end of private members */
219n/a
220n/a/*
221n/a * __tramp: trampoline memory location
222n/a * __fun: assembly routine
223n/a * __ctx: memory location for wrapper
224n/a *
225n/a * At this point, tramp[0] == __ctx !
226n/a */
227n/avoid ffi_init_trampoline(unsigned char *__tramp, unsigned int __fun, unsigned int __ctx) {
228n/a memcpy (__tramp, ffi_metag_trampoline, sizeof(ffi_metag_trampoline));
229n/a *(unsigned int*) &__tramp[40] = __ctx;
230n/a *(unsigned int*) &__tramp[44] = __fun;
231n/a /* This will flush the instruction cache */
232n/a __builtin_meta2_cachewd(&__tramp[0], 1);
233n/a __builtin_meta2_cachewd(&__tramp[47], 1);
234n/a}
235n/a
236n/a
237n/a
238n/a/* the cif must already be prepared */
239n/a
240n/affi_status
241n/affi_prep_closure_loc (ffi_closure *closure,
242n/a ffi_cif* cif,
243n/a void (*fun)(ffi_cif*,void*,void**,void*),
244n/a void *user_data,
245n/a void *codeloc)
246n/a{
247n/a void (*closure_func)(ffi_closure*) = NULL;
248n/a
249n/a if (cif->abi == FFI_SYSV)
250n/a closure_func = &ffi_closure_SYSV;
251n/a else
252n/a return FFI_BAD_ABI;
253n/a
254n/a ffi_init_trampoline(
255n/a (unsigned char*)&closure->tramp[0],
256n/a (unsigned int)closure_func,
257n/a (unsigned int)codeloc);
258n/a
259n/a closure->cif = cif;
260n/a closure->user_data = user_data;
261n/a closure->fun = fun;
262n/a
263n/a return FFI_OK;
264n/a}
265n/a
266n/a
267n/a/* This function is jumped to by the trampoline */
268n/aunsigned int ffi_closure_SYSV_inner (closure, respp, args, vfp_args)
269n/a ffi_closure *closure;
270n/a void **respp;
271n/a void *args;
272n/a void *vfp_args;
273n/a{
274n/a ffi_cif *cif;
275n/a void **arg_area;
276n/a
277n/a cif = closure->cif;
278n/a arg_area = (void**) alloca (cif->nargs * sizeof (void*));
279n/a
280n/a /*
281n/a * This call will initialize ARG_AREA, such that each
282n/a * element in that array points to the corresponding
283n/a * value on the stack; and if the function returns
284n/a * a structure, it will re-set RESP to point to the
285n/a * structure return address.
286n/a */
287n/a ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
288n/a
289n/a (closure->fun) ( cif, *respp, arg_area, closure->user_data);
290n/a
291n/a return cif->flags;
292n/a}
293n/a
294n/astatic void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
295n/a void **avalue, ffi_cif *cif,
296n/a float *vfp_stack)
297n/a{
298n/a register unsigned int i;
299n/a register void **p_argv;
300n/a register char *argp;
301n/a register ffi_type **p_arg;
302n/a
303n/a /* stack points to original arguments */
304n/a argp = stack;
305n/a
306n/a /* Store return value */
307n/a if ( cif->flags == FFI_TYPE_STRUCT ) {
308n/a argp -= 4;
309n/a *rvalue = *(void **) argp;
310n/a }
311n/a
312n/a p_argv = avalue;
313n/a
314n/a for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) {
315n/a size_t z;
316n/a size_t alignment;
317n/a
318n/a alignment = (*p_arg)->alignment;
319n/a if (alignment < 4)
320n/a alignment = 4;
321n/a if ((alignment - 1) & (unsigned)argp)
322n/a argp = (char *) ALIGN(argp, alignment);
323n/a
324n/a z = (*p_arg)->size;
325n/a *p_argv = (void*) argp;
326n/a p_argv++;
327n/a argp -= z;
328n/a }
329n/a return;
330n/a}