ยปCore Development>Code coverage>Modules/_ctypes/libffi_osx/x86/x86-ffi64.c

Python code coverage for Modules/_ctypes/libffi_osx/x86/x86-ffi64.c

#countcontent
1n/a#ifdef __x86_64__
2n/a
3n/a/* -----------------------------------------------------------------------
4n/a x86-ffi64.c - Copyright (c) 2002 Bo Thorsen <bo@suse.de>
5n/a
6n/a x86-64 Foreign Function Interface
7n/a
8n/a Permission is hereby granted, free of charge, to any person obtaining
9n/a a copy of this software and associated documentation files (the
10n/a ``Software''), to deal in the Software without restriction, including
11n/a without limitation the rights to use, copy, modify, merge, publish,
12n/a distribute, sublicense, and/or sell copies of the Software, and to
13n/a permit persons to whom the Software is furnished to do so, subject to
14n/a the following conditions:
15n/a
16n/a The above copyright notice and this permission notice shall be included
17n/a in all copies or substantial portions of the Software.
18n/a
19n/a THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
20n/a OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21n/a MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22n/a IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23n/a OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24n/a ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25n/a OTHER 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#include <stdarg.h>
33n/a
34n/a#define MAX_GPR_REGS 6
35n/a#define MAX_SSE_REGS 8
36n/a
37n/atypedef struct RegisterArgs {
38n/a /* Registers for argument passing. */
39n/a UINT64 gpr[MAX_GPR_REGS];
40n/a __int128_t sse[MAX_SSE_REGS];
41n/a} RegisterArgs;
42n/a
43n/aextern void
44n/affi_call_unix64(
45n/a void* args,
46n/a unsigned long bytes,
47n/a unsigned flags,
48n/a void* raddr,
49n/a void (*fnaddr)(void),
50n/a unsigned ssecount);
51n/a
52n/a/* All reference to register classes here is identical to the code in
53n/a gcc/config/i386/i386.c. Do *not* change one without the other. */
54n/a
55n/a/* Register class used for passing given 64bit part of the argument.
56n/a These represent classes as documented by the PS ABI, with the exception
57n/a of SSESF, SSEDF classes, that are basically SSE class, just gcc will
58n/a use SF or DFmode move instead of DImode to avoid reformating penalties.
59n/a
60n/a Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
61n/a whenever possible (upper half does contain padding). */
62n/aenum x86_64_reg_class
63n/a{
64n/a X86_64_NO_CLASS,
65n/a X86_64_INTEGER_CLASS,
66n/a X86_64_INTEGERSI_CLASS,
67n/a X86_64_SSE_CLASS,
68n/a X86_64_SSESF_CLASS,
69n/a X86_64_SSEDF_CLASS,
70n/a X86_64_SSEUP_CLASS,
71n/a X86_64_X87_CLASS,
72n/a X86_64_X87UP_CLASS,
73n/a X86_64_COMPLEX_X87_CLASS,
74n/a X86_64_MEMORY_CLASS
75n/a};
76n/a
77n/a#define MAX_CLASSES 4
78n/a#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
79n/a
80n/a/* x86-64 register passing implementation. See x86-64 ABI for details. Goal
81n/a of this code is to classify each 8bytes of incoming argument by the register
82n/a class and assign registers accordingly. */
83n/a
84n/a/* Return the union class of CLASS1 and CLASS2.
85n/a See the x86-64 PS ABI for details. */
86n/astatic enum x86_64_reg_class
87n/amerge_classes(
88n/a enum x86_64_reg_class class1,
89n/a enum x86_64_reg_class class2)
90n/a{
91n/a /* Rule #1: If both classes are equal, this is the resulting class. */
92n/a if (class1 == class2)
93n/a return class1;
94n/a
95n/a /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
96n/a the other class. */
97n/a if (class1 == X86_64_NO_CLASS)
98n/a return class2;
99n/a
100n/a if (class2 == X86_64_NO_CLASS)
101n/a return class1;
102n/a
103n/a /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
104n/a if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
105n/a return X86_64_MEMORY_CLASS;
106n/a
107n/a /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
108n/a if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
109n/a || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
110n/a return X86_64_INTEGERSI_CLASS;
111n/a
112n/a if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
113n/a || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
114n/a return X86_64_INTEGER_CLASS;
115n/a
116n/a /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
117n/a MEMORY is used. */
118n/a if (class1 == X86_64_X87_CLASS
119n/a || class1 == X86_64_X87UP_CLASS
120n/a || class1 == X86_64_COMPLEX_X87_CLASS
121n/a || class2 == X86_64_X87_CLASS
122n/a || class2 == X86_64_X87UP_CLASS
123n/a || class2 == X86_64_COMPLEX_X87_CLASS)
124n/a return X86_64_MEMORY_CLASS;
125n/a
126n/a /* Rule #6: Otherwise class SSE is used. */
127n/a return X86_64_SSE_CLASS;
128n/a}
129n/a
130n/a/* Classify the argument of type TYPE and mode MODE.
131n/a CLASSES will be filled by the register class used to pass each word
132n/a of the operand. The number of words is returned. In case the parameter
133n/a should be passed in memory, 0 is returned. As a special case for zero
134n/a sized containers, classes[0] will be NO_CLASS and 1 is returned.
135n/a
136n/a See the x86-64 PS ABI for details. */
137n/a
138n/astatic int
139n/aclassify_argument(
140n/a ffi_type* type,
141n/a enum x86_64_reg_class classes[],
142n/a size_t byte_offset)
143n/a{
144n/a switch (type->type)
145n/a {
146n/a case FFI_TYPE_UINT8:
147n/a case FFI_TYPE_SINT8:
148n/a case FFI_TYPE_UINT16:
149n/a case FFI_TYPE_SINT16:
150n/a case FFI_TYPE_UINT32:
151n/a case FFI_TYPE_SINT32:
152n/a case FFI_TYPE_UINT64:
153n/a case FFI_TYPE_SINT64:
154n/a case FFI_TYPE_POINTER:
155n/a#if 0
156n/a if (byte_offset + type->size <= 4)
157n/a classes[0] = X86_64_INTEGERSI_CLASS;
158n/a else
159n/a classes[0] = X86_64_INTEGER_CLASS;
160n/a
161n/a return 1;
162n/a#else
163n/a {
164n/a int size = byte_offset + type->size;
165n/a
166n/a if (size <= 4)
167n/a {
168n/a classes[0] = X86_64_INTEGERSI_CLASS;
169n/a return 1;
170n/a }
171n/a else if (size <= 8)
172n/a {
173n/a classes[0] = X86_64_INTEGER_CLASS;
174n/a return 1;
175n/a }
176n/a else if (size <= 12)
177n/a {
178n/a classes[0] = X86_64_INTEGER_CLASS;
179n/a classes[1] = X86_64_INTEGERSI_CLASS;
180n/a return 2;
181n/a }
182n/a else if (size <= 16)
183n/a {
184n/a classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
185n/a return 2;
186n/a }
187n/a else
188n/a FFI_ASSERT (0);
189n/a }
190n/a#endif
191n/a
192n/a case FFI_TYPE_FLOAT:
193n/a if (byte_offset == 0)
194n/a classes[0] = X86_64_SSESF_CLASS;
195n/a else
196n/a classes[0] = X86_64_SSE_CLASS;
197n/a
198n/a return 1;
199n/a
200n/a case FFI_TYPE_DOUBLE:
201n/a classes[0] = X86_64_SSEDF_CLASS;
202n/a return 1;
203n/a
204n/a case FFI_TYPE_LONGDOUBLE:
205n/a classes[0] = X86_64_X87_CLASS;
206n/a classes[1] = X86_64_X87UP_CLASS;
207n/a return 2;
208n/a
209n/a case FFI_TYPE_STRUCT:
210n/a {
211n/a ffi_type** ptr;
212n/a int i;
213n/a enum x86_64_reg_class subclasses[MAX_CLASSES];
214n/a const int UNITS_PER_WORD = 8;
215n/a int words =
216n/a (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
217n/a
218n/a /* If the struct is larger than 16 bytes, pass it on the stack. */
219n/a if (type->size > 16)
220n/a return 0;
221n/a
222n/a for (i = 0; i < words; i++)
223n/a classes[i] = X86_64_NO_CLASS;
224n/a
225n/a /* Merge the fields of structure. */
226n/a for (ptr = type->elements; *ptr != NULL; ptr++)
227n/a {
228n/a int num, pos;
229n/a
230n/a byte_offset = ALIGN(byte_offset, (*ptr)->alignment);
231n/a
232n/a num = classify_argument(*ptr, subclasses, byte_offset % 8);
233n/a
234n/a if (num == 0)
235n/a return 0;
236n/a
237n/a pos = byte_offset / 8;
238n/a
239n/a for (i = 0; i < num; i++)
240n/a {
241n/a classes[i + pos] =
242n/a merge_classes(subclasses[i], classes[i + pos]);
243n/a }
244n/a
245n/a byte_offset += (*ptr)->size;
246n/a }
247n/a
248n/a if (words > 2)
249n/a {
250n/a /* When size > 16 bytes, if the first one isn't
251n/a X86_64_SSE_CLASS or any other ones aren't
252n/a X86_64_SSEUP_CLASS, everything should be passed in
253n/a memory. */
254n/a if (classes[0] != X86_64_SSE_CLASS)
255n/a return 0;
256n/a
257n/a for (i = 1; i < words; i++)
258n/a if (classes[i] != X86_64_SSEUP_CLASS)
259n/a return 0;
260n/a }
261n/a
262n/a
263n/a /* Final merger cleanup. */
264n/a for (i = 0; i < words; i++)
265n/a {
266n/a /* If one class is MEMORY, everything should be passed in
267n/a memory. */
268n/a if (classes[i] == X86_64_MEMORY_CLASS)
269n/a return 0;
270n/a
271n/a /* The X86_64_SSEUP_CLASS should be always preceded by
272n/a X86_64_SSE_CLASS. */
273n/a if (classes[i] == X86_64_SSEUP_CLASS
274n/a && classes[i - 1] != X86_64_SSE_CLASS
275n/a && classes[i - 1] != X86_64_SSEUP_CLASS)
276n/a {
277n/a FFI_ASSERT(i != 0);
278n/a classes[i] = X86_64_SSE_CLASS;
279n/a }
280n/a
281n/a /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
282n/a if (classes[i] == X86_64_X87UP_CLASS
283n/a && classes[i - 1] != X86_64_X87_CLASS)
284n/a {
285n/a FFI_ASSERT(i != 0);
286n/a classes[i] = X86_64_SSE_CLASS;
287n/a }
288n/a }
289n/a
290n/a return words;
291n/a }
292n/a
293n/a default:
294n/a FFI_ASSERT(0);
295n/a }
296n/a
297n/a return 0; /* Never reached. */
298n/a}
299n/a
300n/a/* Examine the argument and return set number of register required in each
301n/a class. Return zero if parameter should be passed in memory, otherwise
302n/a the number of registers. */
303n/astatic int
304n/aexamine_argument(
305n/a ffi_type* type,
306n/a enum x86_64_reg_class classes[MAX_CLASSES],
307n/a _Bool in_return,
308n/a int* pngpr,
309n/a int* pnsse)
310n/a{
311n/a int n = classify_argument(type, classes, 0);
312n/a int ngpr = 0;
313n/a int nsse = 0;
314n/a int i;
315n/a
316n/a if (n == 0)
317n/a return 0;
318n/a
319n/a for (i = 0; i < n; ++i)
320n/a {
321n/a switch (classes[i])
322n/a {
323n/a case X86_64_INTEGER_CLASS:
324n/a case X86_64_INTEGERSI_CLASS:
325n/a ngpr++;
326n/a break;
327n/a
328n/a case X86_64_SSE_CLASS:
329n/a case X86_64_SSESF_CLASS:
330n/a case X86_64_SSEDF_CLASS:
331n/a nsse++;
332n/a break;
333n/a
334n/a case X86_64_NO_CLASS:
335n/a case X86_64_SSEUP_CLASS:
336n/a break;
337n/a
338n/a case X86_64_X87_CLASS:
339n/a case X86_64_X87UP_CLASS:
340n/a case X86_64_COMPLEX_X87_CLASS:
341n/a return in_return != 0;
342n/a
343n/a default:
344n/a abort();
345n/a }
346n/a }
347n/a
348n/a *pngpr = ngpr;
349n/a *pnsse = nsse;
350n/a
351n/a return n;
352n/a}
353n/a
354n/a/* Perform machine dependent cif processing. */
355n/affi_status
356n/affi_prep_cif_machdep(
357n/a ffi_cif* cif)
358n/a{
359n/a int gprcount = 0;
360n/a int ssecount = 0;
361n/a int flags = cif->rtype->type;
362n/a int i, avn, n, ngpr, nsse;
363n/a enum x86_64_reg_class classes[MAX_CLASSES];
364n/a size_t bytes;
365n/a
366n/a if (flags != FFI_TYPE_VOID)
367n/a {
368n/a n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
369n/a
370n/a if (n == 0)
371n/a {
372n/a /* The return value is passed in memory. A pointer to that
373n/a memory is the first argument. Allocate a register for it. */
374n/a gprcount++;
375n/a
376n/a /* We don't have to do anything in asm for the return. */
377n/a flags = FFI_TYPE_VOID;
378n/a }
379n/a else if (flags == FFI_TYPE_STRUCT)
380n/a {
381n/a /* Mark which registers the result appears in. */
382n/a _Bool sse0 = SSE_CLASS_P(classes[0]);
383n/a _Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]);
384n/a
385n/a if (sse0 && !sse1)
386n/a flags |= 1 << 8;
387n/a else if (!sse0 && sse1)
388n/a flags |= 1 << 9;
389n/a else if (sse0 && sse1)
390n/a flags |= 1 << 10;
391n/a
392n/a /* Mark the true size of the structure. */
393n/a flags |= cif->rtype->size << 12;
394n/a }
395n/a }
396n/a
397n/a /* Go over all arguments and determine the way they should be passed.
398n/a If it's in a register and there is space for it, let that be so. If
399n/a not, add it's size to the stack byte count. */
400n/a for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
401n/a {
402n/a if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
403n/a || gprcount + ngpr > MAX_GPR_REGS
404n/a || ssecount + nsse > MAX_SSE_REGS)
405n/a {
406n/a long align = cif->arg_types[i]->alignment;
407n/a
408n/a if (align < 8)
409n/a align = 8;
410n/a
411n/a bytes = ALIGN(bytes, align);
412n/a bytes += cif->arg_types[i]->size;
413n/a }
414n/a else
415n/a {
416n/a gprcount += ngpr;
417n/a ssecount += nsse;
418n/a }
419n/a }
420n/a
421n/a if (ssecount)
422n/a flags |= 1 << 11;
423n/a
424n/a cif->flags = flags;
425n/a cif->bytes = bytes;
426n/a cif->bytes = ALIGN(bytes,8);
427n/a
428n/a return FFI_OK;
429n/a}
430n/a
431n/avoid
432n/affi_call(
433n/a ffi_cif* cif,
434n/a void (*fn)(void),
435n/a void* rvalue,
436n/a void** avalue)
437n/a{
438n/a enum x86_64_reg_class classes[MAX_CLASSES];
439n/a char* stack;
440n/a char* argp;
441n/a ffi_type** arg_types;
442n/a int gprcount, ssecount, ngpr, nsse, i, avn;
443n/a _Bool ret_in_memory;
444n/a RegisterArgs* reg_args;
445n/a
446n/a /* Can't call 32-bit mode from 64-bit mode. */
447n/a FFI_ASSERT(cif->abi == FFI_UNIX64);
448n/a
449n/a /* If the return value is a struct and we don't have a return value
450n/a address then we need to make one. Note the setting of flags to
451n/a VOID above in ffi_prep_cif_machdep. */
452n/a ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
453n/a && (cif->flags & 0xff) == FFI_TYPE_VOID);
454n/a
455n/a if (rvalue == NULL && ret_in_memory)
456n/a rvalue = alloca (cif->rtype->size);
457n/a
458n/a /* Allocate the space for the arguments, plus 4 words of temp space. */
459n/a stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8);
460n/a reg_args = (RegisterArgs*)stack;
461n/a argp = stack + sizeof(RegisterArgs);
462n/a
463n/a gprcount = ssecount = 0;
464n/a
465n/a /* If the return value is passed in memory, add the pointer as the
466n/a first integer argument. */
467n/a if (ret_in_memory)
468n/a reg_args->gpr[gprcount++] = (long) rvalue;
469n/a
470n/a avn = cif->nargs;
471n/a arg_types = cif->arg_types;
472n/a
473n/a for (i = 0; i < avn; ++i)
474n/a {
475n/a size_t size = arg_types[i]->size;
476n/a int n;
477n/a
478n/a n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
479n/a
480n/a if (n == 0
481n/a || gprcount + ngpr > MAX_GPR_REGS
482n/a || ssecount + nsse > MAX_SSE_REGS)
483n/a {
484n/a long align = arg_types[i]->alignment;
485n/a
486n/a /* Stack arguments are *always* at least 8 byte aligned. */
487n/a if (align < 8)
488n/a align = 8;
489n/a
490n/a /* Pass this argument in memory. */
491n/a argp = (void *) ALIGN (argp, align);
492n/a memcpy (argp, avalue[i], size);
493n/a argp += size;
494n/a }
495n/a else
496n/a { /* The argument is passed entirely in registers. */
497n/a char *a = (char *) avalue[i];
498n/a int j;
499n/a
500n/a for (j = 0; j < n; j++, a += 8, size -= 8)
501n/a {
502n/a switch (classes[j])
503n/a {
504n/a case X86_64_INTEGER_CLASS:
505n/a case X86_64_INTEGERSI_CLASS:
506n/a reg_args->gpr[gprcount] = 0;
507n/a switch (arg_types[i]->type) {
508n/a case FFI_TYPE_SINT8:
509n/a {
510n/a int8_t shortval = *(int8_t*)a;
511n/a int64_t actval = (int64_t)shortval;
512n/a reg_args->gpr[gprcount] = actval;
513n/a /*memcpy (&reg_args->gpr[gprcount], &actval, 8);*/
514n/a break;
515n/a }
516n/a
517n/a case FFI_TYPE_SINT16:
518n/a {
519n/a int16_t shortval = *(int16_t*)a;
520n/a int64_t actval = (int64_t)shortval;
521n/a memcpy (&reg_args->gpr[gprcount], &actval, 8);
522n/a break;
523n/a }
524n/a
525n/a case FFI_TYPE_SINT32:
526n/a {
527n/a int32_t shortval = *(int32_t*)a;
528n/a int64_t actval = (int64_t)shortval;
529n/a memcpy (&reg_args->gpr[gprcount], &actval, 8);
530n/a break;
531n/a }
532n/a
533n/a case FFI_TYPE_UINT8:
534n/a {
535n/a u_int8_t shortval = *(u_int8_t*)a;
536n/a u_int64_t actval = (u_int64_t)shortval;
537n/a /*memcpy (&reg_args->gpr[gprcount], &actval, 8);*/
538n/a reg_args->gpr[gprcount] = actval;
539n/a break;
540n/a }
541n/a
542n/a case FFI_TYPE_UINT16:
543n/a {
544n/a u_int16_t shortval = *(u_int16_t*)a;
545n/a u_int64_t actval = (u_int64_t)shortval;
546n/a memcpy (&reg_args->gpr[gprcount], &actval, 8);
547n/a break;
548n/a }
549n/a
550n/a case FFI_TYPE_UINT32:
551n/a {
552n/a u_int32_t shortval = *(u_int32_t*)a;
553n/a u_int64_t actval = (u_int64_t)shortval;
554n/a memcpy (&reg_args->gpr[gprcount], &actval, 8);
555n/a break;
556n/a }
557n/a
558n/a default:
559n/a //memcpy (&reg_args->gpr[gprcount], a, size < 8 ? size : 8);
560n/a reg_args->gpr[gprcount] = *(int64_t*)a;
561n/a }
562n/a gprcount++;
563n/a break;
564n/a
565n/a case X86_64_SSE_CLASS:
566n/a case X86_64_SSEDF_CLASS:
567n/a reg_args->sse[ssecount++] = *(UINT64 *) a;
568n/a break;
569n/a
570n/a case X86_64_SSESF_CLASS:
571n/a reg_args->sse[ssecount++] = *(UINT32 *) a;
572n/a break;
573n/a
574n/a default:
575n/a abort();
576n/a }
577n/a }
578n/a }
579n/a }
580n/a
581n/a ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs),
582n/a cif->flags, rvalue, fn, ssecount);
583n/a}
584n/a
585n/aextern void ffi_closure_unix64(void);
586n/a
587n/affi_status
588n/affi_prep_closure(
589n/a ffi_closure* closure,
590n/a ffi_cif* cif,
591n/a void (*fun)(ffi_cif*, void*, void**, void*),
592n/a void* user_data)
593n/a{
594n/a volatile unsigned short* tramp;
595n/a
596n/a if (cif->abi != FFI_UNIX64)
597n/a return FFI_BAD_ABI;
598n/a
599n/a tramp = (volatile unsigned short*)&closure->tramp[0];
600n/a
601n/a tramp[0] = 0xbb49; /* mov <code>, %r11 */
602n/a *(void* volatile*)&tramp[1] = ffi_closure_unix64;
603n/a tramp[5] = 0xba49; /* mov <data>, %r10 */
604n/a *(void* volatile*)&tramp[6] = closure;
605n/a
606n/a /* Set the carry bit if the function uses any sse registers.
607n/a This is clc or stc, together with the first byte of the jmp. */
608n/a tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
609n/a tramp[11] = 0xe3ff; /* jmp *%r11 */
610n/a
611n/a closure->cif = cif;
612n/a closure->fun = fun;
613n/a closure->user_data = user_data;
614n/a
615n/a return FFI_OK;
616n/a}
617n/a
618n/a#pragma clang diagnostic push
619n/a#pragma clang diagnostic ignored "-Wmissing-prototypes"
620n/aint
621n/affi_closure_unix64_inner(
622n/a ffi_closure* closure,
623n/a void* rvalue,
624n/a RegisterArgs* reg_args,
625n/a char* argp)
626n/a#pragma clang diagnostic pop
627n/a{
628n/a ffi_cif* cif = closure->cif;
629n/a void** avalue = alloca(cif->nargs * sizeof(void *));
630n/a ffi_type** arg_types;
631n/a long i, avn;
632n/a int gprcount = 0;
633n/a int ssecount = 0;
634n/a int ngpr, nsse;
635n/a int ret;
636n/a
637n/a ret = cif->rtype->type;
638n/a
639n/a if (ret != FFI_TYPE_VOID)
640n/a {
641n/a enum x86_64_reg_class classes[MAX_CLASSES];
642n/a int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
643n/a
644n/a if (n == 0)
645n/a {
646n/a /* The return value goes in memory. Arrange for the closure
647n/a return value to go directly back to the original caller. */
648n/a rvalue = (void *) reg_args->gpr[gprcount++];
649n/a
650n/a /* We don't have to do anything in asm for the return. */
651n/a ret = FFI_TYPE_VOID;
652n/a }
653n/a else if (ret == FFI_TYPE_STRUCT && n == 2)
654n/a {
655n/a /* Mark which register the second word of the structure goes in. */
656n/a _Bool sse0 = SSE_CLASS_P (classes[0]);
657n/a _Bool sse1 = SSE_CLASS_P (classes[1]);
658n/a
659n/a if (!sse0 && sse1)
660n/a ret |= 1 << 8;
661n/a else if (sse0 && !sse1)
662n/a ret |= 1 << 9;
663n/a }
664n/a }
665n/a
666n/a avn = cif->nargs;
667n/a arg_types = cif->arg_types;
668n/a
669n/a for (i = 0; i < avn; ++i)
670n/a {
671n/a enum x86_64_reg_class classes[MAX_CLASSES];
672n/a int n;
673n/a
674n/a n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
675n/a
676n/a if (n == 0
677n/a || gprcount + ngpr > MAX_GPR_REGS
678n/a || ssecount + nsse > MAX_SSE_REGS)
679n/a {
680n/a long align = arg_types[i]->alignment;
681n/a
682n/a /* Stack arguments are *always* at least 8 byte aligned. */
683n/a if (align < 8)
684n/a align = 8;
685n/a
686n/a /* Pass this argument in memory. */
687n/a argp = (void *) ALIGN (argp, align);
688n/a avalue[i] = argp;
689n/a argp += arg_types[i]->size;
690n/a }
691n/a
692n/a#if !defined(X86_DARWIN)
693n/a /* If the argument is in a single register, or two consecutive
694n/a registers, then we can use that address directly. */
695n/a else if (n == 1 || (n == 2 &&
696n/a SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1])))
697n/a {
698n/a // The argument is in a single register.
699n/a if (SSE_CLASS_P (classes[0]))
700n/a {
701n/a avalue[i] = &reg_args->sse[ssecount];
702n/a ssecount += n;
703n/a }
704n/a else
705n/a {
706n/a avalue[i] = &reg_args->gpr[gprcount];
707n/a gprcount += n;
708n/a }
709n/a }
710n/a#endif
711n/a
712n/a /* Otherwise, allocate space to make them consecutive. */
713n/a else
714n/a {
715n/a char *a = alloca (16);
716n/a int j;
717n/a
718n/a avalue[i] = a;
719n/a
720n/a for (j = 0; j < n; j++, a += 8)
721n/a {
722n/a if (SSE_CLASS_P (classes[j]))
723n/a memcpy (a, &reg_args->sse[ssecount++], 8);
724n/a else
725n/a memcpy (a, &reg_args->gpr[gprcount++], 8);
726n/a }
727n/a }
728n/a }
729n/a
730n/a /* Invoke the closure. */
731n/a closure->fun (cif, rvalue, avalue, closure->user_data);
732n/a
733n/a /* Tell assembly how to perform return type promotions. */
734n/a return ret;
735n/a}
736n/a
737n/a#endif /* __x86_64__ */