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

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

#countcontent
1n/a/* libffi support for Altera Nios II.
2n/a
3n/a Copyright (c) 2013 Mentor Graphics.
4n/a
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
14n/a included in all copies or substantial portions of the Software.
15n/a
16n/a THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
17n/a EXPRESS 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 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20n/a CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21n/a TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22n/a SOFTWARE OR THE USE OR 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/* The Nios II Processor Reference Handbook defines the procedure call
31n/a ABI as follows.
32n/a
33n/a Arguments are passed as if a structure containing the types of
34n/a the arguments were constructed. The first 16 bytes are passed in r4
35n/a through r7, the remainder on the stack. The first 16 bytes of a function
36n/a taking variable arguments are passed in r4-r7 in the same way.
37n/a
38n/a Return values of types up to 8 bytes are returned in r2 and r3. For
39n/a return values greater than 8 bytes, the caller must allocate memory for
40n/a the result and pass the address as if it were argument 0.
41n/a
42n/a While this isn't specified explicitly in the ABI documentation, GCC
43n/a promotes integral arguments smaller than int size to 32 bits.
44n/a
45n/a Also of note, the ABI specifies that all structure objects are
46n/a aligned to 32 bits even if all their fields have a smaller natural
47n/a alignment. See FFI_AGGREGATE_ALIGNMENT. */
48n/a
49n/a
50n/a/* Declare the assembly language hooks. */
51n/a
52n/aextern UINT64 ffi_call_sysv (void (*) (char *, extended_cif *),
53n/a extended_cif *,
54n/a unsigned,
55n/a void (*fn) (void));
56n/aextern void ffi_closure_sysv (void);
57n/a
58n/a/* Perform machine-dependent cif processing. */
59n/a
60n/affi_status ffi_prep_cif_machdep (ffi_cif *cif)
61n/a{
62n/a /* We always want at least 16 bytes in the parameter block since it
63n/a simplifies the low-level call function. Also round the parameter
64n/a block size up to a multiple of 4 bytes to preserve
65n/a 32-bit alignment of the stack pointer. */
66n/a if (cif->bytes < 16)
67n/a cif->bytes = 16;
68n/a else
69n/a cif->bytes = (cif->bytes + 3) & ~3;
70n/a
71n/a return FFI_OK;
72n/a}
73n/a
74n/a
75n/a/* ffi_prep_args is called by the assembly routine to transfer arguments
76n/a to the stack using the pointers in the ecif array.
77n/a Note that the stack buffer is big enough to fit all the arguments,
78n/a but the first 16 bytes will be copied to registers for the actual
79n/a call. */
80n/a
81n/avoid ffi_prep_args (char *stack, extended_cif *ecif)
82n/a{
83n/a char *argp = stack;
84n/a unsigned int i;
85n/a
86n/a /* The implicit return value pointer is passed as if it were a hidden
87n/a first argument. */
88n/a if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
89n/a && ecif->cif->rtype->size > 8)
90n/a {
91n/a (*(void **) argp) = ecif->rvalue;
92n/a argp += 4;
93n/a }
94n/a
95n/a for (i = 0; i < ecif->cif->nargs; i++)
96n/a {
97n/a void *avalue = ecif->avalue[i];
98n/a ffi_type *atype = ecif->cif->arg_types[i];
99n/a size_t size = atype->size;
100n/a size_t alignment = atype->alignment;
101n/a
102n/a /* Align argp as appropriate for the argument type. */
103n/a if ((alignment - 1) & (unsigned) argp)
104n/a argp = (char *) ALIGN (argp, alignment);
105n/a
106n/a /* Copy the argument, promoting integral types smaller than a
107n/a word to word size. */
108n/a if (size < sizeof (int))
109n/a {
110n/a size = sizeof (int);
111n/a switch (atype->type)
112n/a {
113n/a case FFI_TYPE_SINT8:
114n/a *(signed int *) argp = (signed int) *(SINT8 *) avalue;
115n/a break;
116n/a
117n/a case FFI_TYPE_UINT8:
118n/a *(unsigned int *) argp = (unsigned int) *(UINT8 *) avalue;
119n/a break;
120n/a
121n/a case FFI_TYPE_SINT16:
122n/a *(signed int *) argp = (signed int) *(SINT16 *) avalue;
123n/a break;
124n/a
125n/a case FFI_TYPE_UINT16:
126n/a *(unsigned int *) argp = (unsigned int) *(UINT16 *) avalue;
127n/a break;
128n/a
129n/a case FFI_TYPE_STRUCT:
130n/a memcpy (argp, avalue, atype->size);
131n/a break;
132n/a
133n/a default:
134n/a FFI_ASSERT(0);
135n/a }
136n/a }
137n/a else if (size == sizeof (int))
138n/a *(unsigned int *) argp = (unsigned int) *(UINT32 *) avalue;
139n/a else
140n/a memcpy (argp, avalue, size);
141n/a argp += size;
142n/a }
143n/a}
144n/a
145n/a
146n/a/* Call FN using the prepared CIF. RVALUE points to space allocated by
147n/a the caller for the return value, and AVALUE is an array of argument
148n/a pointers. */
149n/a
150n/avoid ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
151n/a{
152n/a
153n/a extended_cif ecif;
154n/a UINT64 result;
155n/a
156n/a /* If bigret is true, this is the case where a return value of larger
157n/a than 8 bytes is handled by being passed by reference as an implicit
158n/a argument. */
159n/a int bigret = (cif->rtype->type == FFI_TYPE_STRUCT
160n/a && cif->rtype->size > 8);
161n/a
162n/a ecif.cif = cif;
163n/a ecif.avalue = avalue;
164n/a
165n/a /* Allocate space for return value if this is the pass-by-reference case
166n/a and the caller did not provide a buffer. */
167n/a if (rvalue == NULL && bigret)
168n/a ecif.rvalue = alloca (cif->rtype->size);
169n/a else
170n/a ecif.rvalue = rvalue;
171n/a
172n/a result = ffi_call_sysv (ffi_prep_args, &ecif, cif->bytes, fn);
173n/a
174n/a /* Now result contains the 64 bit contents returned from fn in
175n/a r2 and r3. Copy the value of the appropriate size to the user-provided
176n/a rvalue buffer. */
177n/a if (rvalue && !bigret)
178n/a switch (cif->rtype->size)
179n/a {
180n/a case 1:
181n/a *(UINT8 *)rvalue = (UINT8) result;
182n/a break;
183n/a case 2:
184n/a *(UINT16 *)rvalue = (UINT16) result;
185n/a break;
186n/a case 4:
187n/a *(UINT32 *)rvalue = (UINT32) result;
188n/a break;
189n/a case 8:
190n/a *(UINT64 *)rvalue = (UINT64) result;
191n/a break;
192n/a default:
193n/a memcpy (rvalue, (void *)&result, cif->rtype->size);
194n/a break;
195n/a }
196n/a}
197n/a
198n/a/* This function is invoked from the closure trampoline to invoke
199n/a CLOSURE with argument block ARGS. Parse ARGS according to
200n/a CLOSURE->cfi and invoke CLOSURE->fun. */
201n/a
202n/astatic UINT64
203n/affi_closure_helper (unsigned char *args,
204n/a ffi_closure *closure)
205n/a{
206n/a ffi_cif *cif = closure->cif;
207n/a unsigned char *argp = args;
208n/a void **parsed_args = alloca (cif->nargs * sizeof (void *));
209n/a UINT64 result;
210n/a void *retptr;
211n/a unsigned int i;
212n/a
213n/a /* First figure out what to do about the return type. If this is the
214n/a big-structure-return case, the first arg is the hidden return buffer
215n/a allocated by the caller. */
216n/a if (cif->rtype->type == FFI_TYPE_STRUCT
217n/a && cif->rtype->size > 8)
218n/a {
219n/a retptr = *((void **) argp);
220n/a argp += 4;
221n/a }
222n/a else
223n/a retptr = (void *) &result;
224n/a
225n/a /* Fill in the array of argument pointers. */
226n/a for (i = 0; i < cif->nargs; i++)
227n/a {
228n/a size_t size = cif->arg_types[i]->size;
229n/a size_t alignment = cif->arg_types[i]->alignment;
230n/a
231n/a /* Align argp as appropriate for the argument type. */
232n/a if ((alignment - 1) & (unsigned) argp)
233n/a argp = (char *) ALIGN (argp, alignment);
234n/a
235n/a /* Arguments smaller than an int are promoted to int. */
236n/a if (size < sizeof (int))
237n/a size = sizeof (int);
238n/a
239n/a /* Store the pointer. */
240n/a parsed_args[i] = argp;
241n/a argp += size;
242n/a }
243n/a
244n/a /* Call the user-supplied function. */
245n/a (closure->fun) (cif, retptr, parsed_args, closure->user_data);
246n/a return result;
247n/a}
248n/a
249n/a
250n/a/* Initialize CLOSURE with a trampoline to call FUN with
251n/a CIF and USER_DATA. */
252n/affi_status
253n/affi_prep_closure_loc (ffi_closure* closure,
254n/a ffi_cif* cif,
255n/a void (*fun) (ffi_cif*, void*, void**, void*),
256n/a void *user_data,
257n/a void *codeloc)
258n/a{
259n/a unsigned int *tramp = (unsigned int *) &closure->tramp[0];
260n/a int i;
261n/a
262n/a if (cif->abi != FFI_SYSV)
263n/a return FFI_BAD_ABI;
264n/a
265n/a /* The trampoline looks like:
266n/a movhi r8, %hi(ffi_closure_sysv)
267n/a ori r8, r8, %lo(ffi_closure_sysv)
268n/a movhi r9, %hi(ffi_closure_helper)
269n/a ori r0, r9, %lo(ffi_closure_helper)
270n/a movhi r10, %hi(closure)
271n/a ori r10, r10, %lo(closure)
272n/a jmp r8
273n/a and then ffi_closure_sysv retrieves the closure pointer out of r10
274n/a in addition to the arguments passed in the normal way for the call,
275n/a and invokes ffi_closure_helper. We encode the pointer to
276n/a ffi_closure_helper in the trampoline because making a PIC call
277n/a to it in ffi_closure_sysv would be messy (it would have to indirect
278n/a through the GOT). */
279n/a
280n/a#define HI(x) ((((unsigned int) (x)) >> 16) & 0xffff)
281n/a#define LO(x) (((unsigned int) (x)) & 0xffff)
282n/a tramp[0] = (0 << 27) | (8 << 22) | (HI (ffi_closure_sysv) << 6) | 0x34;
283n/a tramp[1] = (8 << 27) | (8 << 22) | (LO (ffi_closure_sysv) << 6) | 0x14;
284n/a tramp[2] = (0 << 27) | (9 << 22) | (HI (ffi_closure_helper) << 6) | 0x34;
285n/a tramp[3] = (9 << 27) | (9 << 22) | (LO (ffi_closure_helper) << 6) | 0x14;
286n/a tramp[4] = (0 << 27) | (10 << 22) | (HI (closure) << 6) | 0x34;
287n/a tramp[5] = (10 << 27) | (10 << 22) | (LO (closure) << 6) | 0x14;
288n/a tramp[6] = (8 << 27) | (0x0d << 11) | 0x3a;
289n/a#undef HI
290n/a#undef LO
291n/a
292n/a /* Flush the caches.
293n/a See Example 9-4 in the Nios II Software Developer's Handbook. */
294n/a for (i = 0; i < 7; i++)
295n/a asm volatile ("flushd 0(%0); flushi %0" :: "r"(tramp + i) : "memory");
296n/a asm volatile ("flushp" ::: "memory");
297n/a
298n/a closure->cif = cif;
299n/a closure->fun = fun;
300n/a closure->user_data = user_data;
301n/a
302n/a return FFI_OK;
303n/a}
304n/a