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

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

#countcontent
1n/a/* -----------------------------------------------------------------------
2n/a ffi.c - Copyright (c) 2003, 2004, 2006, 2007, 2012 Kaz Kojima
3n/a Copyright (c) 2008 Anthony Green
4n/a
5n/a SuperH SHmedia Foreign Function Interface
6n/a
7n/a Permission is hereby granted, free of charge, to any person obtaining
8n/a a copy of this software and associated documentation files (the
9n/a ``Software''), to deal in the Software without restriction, including
10n/a without limitation the rights to use, copy, modify, merge, publish,
11n/a distribute, sublicense, and/or sell copies of the Software, and to
12n/a permit persons to whom the Software is furnished to do so, subject to
13n/a the following conditions:
14n/a
15n/a The above copyright notice and this permission notice shall be included
16n/a in all copies or substantial portions of the Software.
17n/a
18n/a THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19n/a EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20n/a MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21n/a NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22n/a HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23n/a WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24n/a OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25n/a DEALINGS IN THE SOFTWARE.
26n/a ----------------------------------------------------------------------- */
27n/a
28n/a#include <ffi.h>
29n/a#include <ffi_common.h>
30n/a
31n/a#include <stdlib.h>
32n/a
33n/a#define NGREGARG 8
34n/a#define NFREGARG 12
35n/a
36n/astatic int
37n/areturn_type (ffi_type *arg)
38n/a{
39n/a
40n/a if (arg->type != FFI_TYPE_STRUCT)
41n/a return arg->type;
42n/a
43n/a /* gcc uses r2 if the result can be packed in on register. */
44n/a if (arg->size <= sizeof (UINT8))
45n/a return FFI_TYPE_UINT8;
46n/a else if (arg->size <= sizeof (UINT16))
47n/a return FFI_TYPE_UINT16;
48n/a else if (arg->size <= sizeof (UINT32))
49n/a return FFI_TYPE_UINT32;
50n/a else if (arg->size <= sizeof (UINT64))
51n/a return FFI_TYPE_UINT64;
52n/a
53n/a return FFI_TYPE_STRUCT;
54n/a}
55n/a
56n/a/* ffi_prep_args is called by the assembly routine once stack space
57n/a has been allocated for the function's arguments */
58n/a
59n/avoid ffi_prep_args(char *stack, extended_cif *ecif)
60n/a{
61n/a register unsigned int i;
62n/a register unsigned int avn;
63n/a register void **p_argv;
64n/a register char *argp;
65n/a register ffi_type **p_arg;
66n/a
67n/a argp = stack;
68n/a
69n/a if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
70n/a {
71n/a *(void **) argp = ecif->rvalue;
72n/a argp += sizeof (UINT64);
73n/a }
74n/a
75n/a avn = ecif->cif->nargs;
76n/a p_argv = ecif->avalue;
77n/a
78n/a for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
79n/a {
80n/a size_t z;
81n/a int align;
82n/a
83n/a z = (*p_arg)->size;
84n/a align = (*p_arg)->alignment;
85n/a if (z < sizeof (UINT32))
86n/a {
87n/a switch ((*p_arg)->type)
88n/a {
89n/a case FFI_TYPE_SINT8:
90n/a *(SINT64 *) argp = (SINT64) *(SINT8 *)(*p_argv);
91n/a break;
92n/a
93n/a case FFI_TYPE_UINT8:
94n/a *(UINT64 *) argp = (UINT64) *(UINT8 *)(*p_argv);
95n/a break;
96n/a
97n/a case FFI_TYPE_SINT16:
98n/a *(SINT64 *) argp = (SINT64) *(SINT16 *)(*p_argv);
99n/a break;
100n/a
101n/a case FFI_TYPE_UINT16:
102n/a *(UINT64 *) argp = (UINT64) *(UINT16 *)(*p_argv);
103n/a break;
104n/a
105n/a case FFI_TYPE_STRUCT:
106n/a memcpy (argp, *p_argv, z);
107n/a break;
108n/a
109n/a default:
110n/a FFI_ASSERT(0);
111n/a }
112n/a argp += sizeof (UINT64);
113n/a }
114n/a else if (z == sizeof (UINT32) && align == sizeof (UINT32))
115n/a {
116n/a switch ((*p_arg)->type)
117n/a {
118n/a case FFI_TYPE_INT:
119n/a case FFI_TYPE_SINT32:
120n/a *(SINT64 *) argp = (SINT64) *(SINT32 *) (*p_argv);
121n/a break;
122n/a
123n/a case FFI_TYPE_FLOAT:
124n/a case FFI_TYPE_POINTER:
125n/a case FFI_TYPE_UINT32:
126n/a case FFI_TYPE_STRUCT:
127n/a *(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv);
128n/a break;
129n/a
130n/a default:
131n/a FFI_ASSERT(0);
132n/a break;
133n/a }
134n/a argp += sizeof (UINT64);
135n/a }
136n/a else if (z == sizeof (UINT64)
137n/a && align == sizeof (UINT64)
138n/a && ((int) *p_argv & (sizeof (UINT64) - 1)) == 0)
139n/a {
140n/a *(UINT64 *) argp = *(UINT64 *) (*p_argv);
141n/a argp += sizeof (UINT64);
142n/a }
143n/a else
144n/a {
145n/a int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
146n/a
147n/a memcpy (argp, *p_argv, z);
148n/a argp += n * sizeof (UINT64);
149n/a }
150n/a }
151n/a
152n/a return;
153n/a}
154n/a
155n/a/* Perform machine dependent cif processing */
156n/affi_status ffi_prep_cif_machdep(ffi_cif *cif)
157n/a{
158n/a int i, j;
159n/a int size, type;
160n/a int n, m;
161n/a int greg;
162n/a int freg;
163n/a int fpair = -1;
164n/a
165n/a greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0);
166n/a freg = 0;
167n/a cif->flags2 = 0;
168n/a
169n/a for (i = j = 0; i < cif->nargs; i++)
170n/a {
171n/a type = (cif->arg_types)[i]->type;
172n/a switch (type)
173n/a {
174n/a case FFI_TYPE_FLOAT:
175n/a greg++;
176n/a cif->bytes += sizeof (UINT64) - sizeof (float);
177n/a if (freg >= NFREGARG - 1)
178n/a continue;
179n/a if (fpair < 0)
180n/a {
181n/a fpair = freg;
182n/a freg += 2;
183n/a }
184n/a else
185n/a fpair = -1;
186n/a cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
187n/a break;
188n/a
189n/a case FFI_TYPE_DOUBLE:
190n/a if (greg++ >= NGREGARG && (freg + 1) >= NFREGARG)
191n/a continue;
192n/a if ((freg + 1) < NFREGARG)
193n/a {
194n/a freg += 2;
195n/a cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
196n/a }
197n/a else
198n/a cif->flags2 += FFI_TYPE_INT << (2 * j++);
199n/a break;
200n/a
201n/a default:
202n/a size = (cif->arg_types)[i]->size;
203n/a if (size < sizeof (UINT64))
204n/a cif->bytes += sizeof (UINT64) - size;
205n/a n = (size + sizeof (UINT64) - 1) / sizeof (UINT64);
206n/a if (greg >= NGREGARG)
207n/a continue;
208n/a else if (greg + n - 1 >= NGREGARG)
209n/a greg = NGREGARG;
210n/a else
211n/a greg += n;
212n/a for (m = 0; m < n; m++)
213n/a cif->flags2 += FFI_TYPE_INT << (2 * j++);
214n/a break;
215n/a }
216n/a }
217n/a
218n/a /* Set the return type flag */
219n/a switch (cif->rtype->type)
220n/a {
221n/a case FFI_TYPE_STRUCT:
222n/a cif->flags = return_type (cif->rtype);
223n/a break;
224n/a
225n/a case FFI_TYPE_VOID:
226n/a case FFI_TYPE_FLOAT:
227n/a case FFI_TYPE_DOUBLE:
228n/a case FFI_TYPE_SINT64:
229n/a case FFI_TYPE_UINT64:
230n/a cif->flags = cif->rtype->type;
231n/a break;
232n/a
233n/a default:
234n/a cif->flags = FFI_TYPE_INT;
235n/a break;
236n/a }
237n/a
238n/a return FFI_OK;
239n/a}
240n/a
241n/a/*@-declundef@*/
242n/a/*@-exportheader@*/
243n/aextern void ffi_call_SYSV(void (*)(char *, extended_cif *),
244n/a /*@out@*/ extended_cif *,
245n/a unsigned, unsigned, long long,
246n/a /*@out@*/ unsigned *,
247n/a void (*fn)(void));
248n/a/*@=declundef@*/
249n/a/*@=exportheader@*/
250n/a
251n/avoid ffi_call(/*@dependent@*/ ffi_cif *cif,
252n/a void (*fn)(void),
253n/a /*@out@*/ void *rvalue,
254n/a /*@dependent@*/ void **avalue)
255n/a{
256n/a extended_cif ecif;
257n/a UINT64 trvalue;
258n/a
259n/a ecif.cif = cif;
260n/a ecif.avalue = avalue;
261n/a
262n/a /* If the return value is a struct and we don't have a return */
263n/a /* value address then we need to make one */
264n/a
265n/a if (cif->rtype->type == FFI_TYPE_STRUCT
266n/a && return_type (cif->rtype) != FFI_TYPE_STRUCT)
267n/a ecif.rvalue = &trvalue;
268n/a else if ((rvalue == NULL) &&
269n/a (cif->rtype->type == FFI_TYPE_STRUCT))
270n/a {
271n/a ecif.rvalue = alloca(cif->rtype->size);
272n/a }
273n/a else
274n/a ecif.rvalue = rvalue;
275n/a
276n/a switch (cif->abi)
277n/a {
278n/a case FFI_SYSV:
279n/a ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, cif->flags2,
280n/a ecif.rvalue, fn);
281n/a break;
282n/a default:
283n/a FFI_ASSERT(0);
284n/a break;
285n/a }
286n/a
287n/a if (rvalue
288n/a && cif->rtype->type == FFI_TYPE_STRUCT
289n/a && return_type (cif->rtype) != FFI_TYPE_STRUCT)
290n/a memcpy (rvalue, &trvalue, cif->rtype->size);
291n/a}
292n/a
293n/aextern void ffi_closure_SYSV (void);
294n/aextern void __ic_invalidate (void *line);
295n/a
296n/affi_status
297n/affi_prep_closure_loc (ffi_closure *closure,
298n/a ffi_cif *cif,
299n/a void (*fun)(ffi_cif*, void*, void**, void*),
300n/a void *user_data,
301n/a void *codeloc)
302n/a{
303n/a unsigned int *tramp;
304n/a
305n/a if (cif->abi != FFI_SYSV)
306n/a return FFI_BAD_ABI;
307n/a
308n/a tramp = (unsigned int *) &closure->tramp[0];
309n/a /* Since ffi_closure is an aligned object, the ffi trampoline is
310n/a called as an SHcompact code. Sigh.
311n/a SHcompact part:
312n/a mova @(1,pc),r0; add #1,r0; jmp @r0; nop;
313n/a SHmedia part:
314n/a movi fnaddr >> 16,r1; shori fnaddr,r1; ptabs/l r1,tr0
315n/a movi cxt >> 16,r1; shori cxt,r1; blink tr0,r63 */
316n/a#ifdef __LITTLE_ENDIAN__
317n/a tramp[0] = 0x7001c701;
318n/a tramp[1] = 0x0009402b;
319n/a#else
320n/a tramp[0] = 0xc7017001;
321n/a tramp[1] = 0x402b0009;
322n/a#endif
323n/a tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10;
324n/a tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10;
325n/a tramp[4] = 0x6bf10600;
326n/a tramp[5] = 0xcc000010 | (((UINT32) codeloc) >> 16) << 10;
327n/a tramp[6] = 0xc8000010 | (((UINT32) codeloc) & 0xffff) << 10;
328n/a tramp[7] = 0x4401fff0;
329n/a
330n/a closure->cif = cif;
331n/a closure->fun = fun;
332n/a closure->user_data = user_data;
333n/a
334n/a /* Flush the icache. */
335n/a asm volatile ("ocbwb %0,0; synco; icbi %1,0; synci" : : "r" (tramp),
336n/a "r"(codeloc));
337n/a
338n/a return FFI_OK;
339n/a}
340n/a
341n/a/* Basically the trampoline invokes ffi_closure_SYSV, and on
342n/a * entry, r3 holds the address of the closure.
343n/a * After storing the registers that could possibly contain
344n/a * parameters to be passed into the stack frame and setting
345n/a * up space for a return value, ffi_closure_SYSV invokes the
346n/a * following helper function to do most of the work.
347n/a */
348n/a
349n/aint
350n/affi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
351n/a UINT64 *pgr, UINT64 *pfr, UINT64 *pst)
352n/a{
353n/a void **avalue;
354n/a ffi_type **p_arg;
355n/a int i, avn;
356n/a int greg, freg;
357n/a ffi_cif *cif;
358n/a int fpair = -1;
359n/a
360n/a cif = closure->cif;
361n/a avalue = alloca (cif->nargs * sizeof (void *));
362n/a
363n/a /* Copy the caller's structure return value address so that the closure
364n/a returns the data directly to the caller. */
365n/a if (return_type (cif->rtype) == FFI_TYPE_STRUCT)
366n/a {
367n/a rvalue = (UINT64 *) *pgr;
368n/a greg = 1;
369n/a }
370n/a else
371n/a greg = 0;
372n/a
373n/a freg = 0;
374n/a cif = closure->cif;
375n/a avn = cif->nargs;
376n/a
377n/a /* Grab the addresses of the arguments from the stack frame. */
378n/a for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
379n/a {
380n/a size_t z;
381n/a void *p;
382n/a
383n/a z = (*p_arg)->size;
384n/a if (z < sizeof (UINT32))
385n/a {
386n/a p = pgr + greg++;
387n/a
388n/a switch ((*p_arg)->type)
389n/a {
390n/a case FFI_TYPE_SINT8:
391n/a case FFI_TYPE_UINT8:
392n/a case FFI_TYPE_SINT16:
393n/a case FFI_TYPE_UINT16:
394n/a case FFI_TYPE_STRUCT:
395n/a#ifdef __LITTLE_ENDIAN__
396n/a avalue[i] = p;
397n/a#else
398n/a avalue[i] = ((char *) p) + sizeof (UINT32) - z;
399n/a#endif
400n/a break;
401n/a
402n/a default:
403n/a FFI_ASSERT(0);
404n/a }
405n/a }
406n/a else if (z == sizeof (UINT32))
407n/a {
408n/a if ((*p_arg)->type == FFI_TYPE_FLOAT)
409n/a {
410n/a if (freg < NFREGARG - 1)
411n/a {
412n/a if (fpair >= 0)
413n/a {
414n/a avalue[i] = (UINT32 *) pfr + fpair;
415n/a fpair = -1;
416n/a }
417n/a else
418n/a {
419n/a#ifdef __LITTLE_ENDIAN__
420n/a fpair = freg;
421n/a avalue[i] = (UINT32 *) pfr + (1 ^ freg);
422n/a#else
423n/a fpair = 1 ^ freg;
424n/a avalue[i] = (UINT32 *) pfr + freg;
425n/a#endif
426n/a freg += 2;
427n/a }
428n/a }
429n/a else
430n/a#ifdef __LITTLE_ENDIAN__
431n/a avalue[i] = pgr + greg;
432n/a#else
433n/a avalue[i] = (UINT32 *) (pgr + greg) + 1;
434n/a#endif
435n/a }
436n/a else
437n/a#ifdef __LITTLE_ENDIAN__
438n/a avalue[i] = pgr + greg;
439n/a#else
440n/a avalue[i] = (UINT32 *) (pgr + greg) + 1;
441n/a#endif
442n/a greg++;
443n/a }
444n/a else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
445n/a {
446n/a if (freg + 1 >= NFREGARG)
447n/a avalue[i] = pgr + greg;
448n/a else
449n/a {
450n/a avalue[i] = pfr + (freg >> 1);
451n/a freg += 2;
452n/a }
453n/a greg++;
454n/a }
455n/a else
456n/a {
457n/a int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
458n/a
459n/a avalue[i] = pgr + greg;
460n/a greg += n;
461n/a }
462n/a }
463n/a
464n/a (closure->fun) (cif, rvalue, avalue, closure->user_data);
465n/a
466n/a /* Tell ffi_closure_SYSV how to perform return type promotions. */
467n/a return return_type (cif->rtype);
468n/a}
469n/a