merge the formfield patch from ooo-build
[ooovba.git] / bridges / source / cpp_uno / gcc3_linux_x86-64 / abi.cxx
blob2014330f6d587ee4bc8e5bd30bb558d05a104014
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: abi.cxx,v $
10 * $Revision: 1.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_bridges.hxx"
34 // This is an implementation of the x86-64 ABI as described in 'System V
35 // Application Binary Interface, AMD64 Architecture Processor Supplement'
36 // (http://www.x86-64.org/documentation/abi-0.95.pdf)
38 // The code in this file is a modification of src/x86/ffi64.c from libffi
39 // (http://sources.redhat.com/libffi/) which is under the following license:
41 /* -----------------------------------------------------------------------
42 ffi.c - Copyright (c) 2002 Bo Thorsen <bo@suse.de>
44 x86-64 Foreign Function Interface
46 Permission is hereby granted, free of charge, to any person obtaining
47 a copy of this software and associated documentation files (the
48 ``Software''), to deal in the Software without restriction, including
49 without limitation the rights to use, copy, modify, merge, publish,
50 distribute, sublicense, and/or sell copies of the Software, and to
51 permit persons to whom the Software is furnished to do so, subject to
52 the following conditions:
54 The above copyright notice and this permission notice shall be included
55 in all copies or substantial portions of the Software.
57 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
58 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
59 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
60 IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
61 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
62 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
63 OTHER DEALINGS IN THE SOFTWARE.
64 ----------------------------------------------------------------------- */
66 #include <abi.hxx>
68 #include <rtl/ustring.hxx>
70 using namespace x86_64;
72 typedef struct
74 /* Registers for argument passing. */
75 long gpr[MAX_GPR_REGS];
76 __int128_t sse[MAX_SSE_REGS];
78 /* Stack space for arguments. */
79 char argspace[0];
80 } stackLayout;
82 /* Register class used for passing given 64bit part of the argument.
83 These represent classes as documented by the PS ABI, with the exception
84 of SSESF, SSEDF classes, that are basically SSE class, just gcc will
85 use SF or DFmode move instead of DImode to avoid reformating penalties.
87 Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
88 whenever possible (upper half does contain padding).
90 enum x86_64_reg_class
92 X86_64_NO_CLASS,
93 X86_64_INTEGER_CLASS,
94 X86_64_INTEGERSI_CLASS,
95 X86_64_SSE_CLASS,
96 X86_64_SSESF_CLASS,
97 X86_64_SSEDF_CLASS,
98 X86_64_SSEUP_CLASS,
99 X86_64_X87_CLASS,
100 X86_64_X87UP_CLASS,
101 X86_64_MEMORY_CLASS
104 #define MAX_CLASSES 4
106 #define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
108 /* x86-64 register passing implementation. See x86-64 ABI for details. Goal
109 of this code is to classify each 8bytes of incoming argument by the register
110 class and assign registers accordingly. */
112 /* Return the union class of CLASS1 and CLASS2.
113 See the x86-64 PS ABI for details. */
115 static enum x86_64_reg_class
116 merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
118 /* Rule #1: If both classes are equal, this is the resulting class. */
119 if (class1 == class2)
120 return class1;
122 /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
123 the other class. */
124 if (class1 == X86_64_NO_CLASS)
125 return class2;
126 if (class2 == X86_64_NO_CLASS)
127 return class1;
129 /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
130 if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
131 return X86_64_MEMORY_CLASS;
133 /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
134 if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
135 || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
136 return X86_64_INTEGERSI_CLASS;
137 if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
138 || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
139 return X86_64_INTEGER_CLASS;
141 /* Rule #5: If one of the classes is X87 or X87UP class, MEMORY is used. */
142 if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS
143 || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS)
144 return X86_64_MEMORY_CLASS;
146 /* Rule #6: Otherwise class SSE is used. */
147 return X86_64_SSE_CLASS;
150 /* Classify the argument of type TYPE and mode MODE.
151 CLASSES will be filled by the register class used to pass each word
152 of the operand. The number of words is returned. In case the parameter
153 should be passed in memory, 0 is returned. As a special case for zero
154 sized containers, classes[0] will be NO_CLASS and 1 is returned.
156 See the x86-64 PS ABI for details.
158 static int
159 classify_argument( typelib_TypeDescriptionReference *pTypeRef, enum x86_64_reg_class classes[], int &rByteOffset )
161 /* First, align to the right place. */
162 rByteOffset = ALIGN( rByteOffset, pTypeRef->pType->nAlignment );
164 switch ( pTypeRef->eTypeClass )
166 case typelib_TypeClass_VOID:
167 classes[0] = X86_64_NO_CLASS;
168 return 1;
169 case typelib_TypeClass_CHAR:
170 case typelib_TypeClass_BOOLEAN:
171 case typelib_TypeClass_BYTE:
172 case typelib_TypeClass_SHORT:
173 case typelib_TypeClass_UNSIGNED_SHORT:
174 case typelib_TypeClass_LONG:
175 case typelib_TypeClass_UNSIGNED_LONG:
176 case typelib_TypeClass_HYPER:
177 case typelib_TypeClass_UNSIGNED_HYPER:
178 case typelib_TypeClass_ENUM:
179 if ( ( rByteOffset % 8 + pTypeRef->pType->nSize ) <= 4 )
180 classes[0] = X86_64_INTEGERSI_CLASS;
181 else
182 classes[0] = X86_64_INTEGER_CLASS;
183 return 1;
184 case typelib_TypeClass_FLOAT:
185 if ( ( rByteOffset % 8 ) == 0 )
186 classes[0] = X86_64_SSESF_CLASS;
187 else
188 classes[0] = X86_64_SSE_CLASS;
189 return 1;
190 case typelib_TypeClass_DOUBLE:
191 classes[0] = X86_64_SSEDF_CLASS;
192 return 1;
193 /*case LONGDOUBLE:
194 classes[0] = X86_64_X87_CLASS;
195 classes[1] = X86_64_X87UP_CLASS;
196 return 2;*/
197 case typelib_TypeClass_STRING:
198 case typelib_TypeClass_TYPE:
199 case typelib_TypeClass_ANY:
200 case typelib_TypeClass_TYPEDEF:
201 case typelib_TypeClass_UNION:
202 case typelib_TypeClass_SEQUENCE:
203 case typelib_TypeClass_ARRAY:
204 case typelib_TypeClass_INTERFACE:
205 return 0;
206 case typelib_TypeClass_STRUCT:
207 case typelib_TypeClass_EXCEPTION:
209 typelib_TypeDescription * pTypeDescr = 0;
210 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
212 const int UNITS_PER_WORD = 8;
213 int words = ( pTypeDescr->nSize + UNITS_PER_WORD - 1 ) / UNITS_PER_WORD;
214 enum x86_64_reg_class subclasses[MAX_CLASSES];
216 /* If the struct is larger than 16 bytes, pass it on the stack. */
217 if ( pTypeDescr->nSize > 16 )
219 TYPELIB_DANGER_RELEASE( pTypeDescr );
220 return 0;
223 for ( int i = 0; i < words; i++ )
224 classes[i] = X86_64_NO_CLASS;
226 const typelib_CompoundTypeDescription *pStruct = reinterpret_cast<const typelib_CompoundTypeDescription*>( pTypeDescr );
228 /* Merge the fields of structure. */
229 for ( sal_Int32 nMember = 0; nMember < pStruct->nMembers; ++nMember )
231 typelib_TypeDescriptionReference *pTypeInStruct = pStruct->ppTypeRefs[ nMember ];
233 int num = classify_argument( pTypeInStruct, subclasses, rByteOffset );
235 if ( num == 0 )
237 TYPELIB_DANGER_RELEASE( pTypeDescr );
238 return 0;
241 for ( int i = 0; i < num; i++ )
243 int pos = rByteOffset / 8;
244 classes[i + pos] = merge_classes( subclasses[i], classes[i + pos] );
247 if ( pTypeInStruct->eTypeClass != typelib_TypeClass_STRUCT )
248 rByteOffset = pStruct->pMemberOffsets[ nMember ];
251 TYPELIB_DANGER_RELEASE( pTypeDescr );
253 /* Final merger cleanup. */
254 for ( int i = 0; i < words; i++ )
256 /* If one class is MEMORY, everything should be passed in
257 memory. */
258 if ( classes[i] == X86_64_MEMORY_CLASS )
259 return 0;
261 /* The X86_64_SSEUP_CLASS should be always preceded by
262 X86_64_SSE_CLASS. */
263 if ( classes[i] == X86_64_SSEUP_CLASS
264 && ( i == 0 || classes[i - 1] != X86_64_SSE_CLASS ) )
265 classes[i] = X86_64_SSE_CLASS;
267 /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
268 if ( classes[i] == X86_64_X87UP_CLASS
269 && ( i == 0 || classes[i - 1] != X86_64_X87_CLASS ) )
270 classes[i] = X86_64_SSE_CLASS;
272 return words;
275 default:
276 #if OSL_DEBUG_LEVEL > 1
277 OSL_TRACE( "Unhandled case: pType->eTypeClass == %d\n", pTypeRef->eTypeClass );
278 #endif
279 OSL_ASSERT(0);
281 return 0; /* Never reached. */
284 /* Examine the argument and return set number of register required in each
285 class. Return 0 iff parameter should be passed in memory. */
286 bool x86_64::examine_argument( typelib_TypeDescriptionReference *pTypeRef, bool bInReturn, int &nUsedGPR, int &nUsedSSE )
288 enum x86_64_reg_class classes[MAX_CLASSES];
289 int offset = 0;
290 int n;
292 n = classify_argument( pTypeRef, classes, offset );
294 if ( n == 0 )
295 return false;
297 nUsedGPR = 0;
298 nUsedSSE = 0;
299 for ( n--; n >= 0; n-- )
300 switch ( classes[n] )
302 case X86_64_INTEGER_CLASS:
303 case X86_64_INTEGERSI_CLASS:
304 nUsedGPR++;
305 break;
306 case X86_64_SSE_CLASS:
307 case X86_64_SSESF_CLASS:
308 case X86_64_SSEDF_CLASS:
309 nUsedSSE++;
310 break;
311 case X86_64_NO_CLASS:
312 case X86_64_SSEUP_CLASS:
313 break;
314 case X86_64_X87_CLASS:
315 case X86_64_X87UP_CLASS:
316 if ( !bInReturn )
317 return false;
318 break;
319 default:
320 #if OSL_DEBUG_LEVEL > 1
321 OSL_TRACE( "Unhandled case: classes[n] == %d\n", classes[n] );
322 #endif
323 OSL_ASSERT(0);
325 return true;
328 bool x86_64::return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
330 int g, s;
332 return examine_argument( pTypeRef, true, g, s ) == 0;
335 void x86_64::fill_struct( typelib_TypeDescriptionReference *pTypeRef, void * const *pGPR, void * const *pSSE, void *pStruct )
337 enum x86_64_reg_class classes[MAX_CLASSES];
338 int offset = 0;
339 int n;
341 n = classify_argument( pTypeRef, classes, offset );
343 sal_uInt64 *pStructAlign = reinterpret_cast<sal_uInt64 *>( pStruct );
344 for ( n--; n >= 0; n-- )
345 switch ( classes[n] )
347 case X86_64_INTEGER_CLASS:
348 case X86_64_INTEGERSI_CLASS:
349 *pStructAlign++ = *reinterpret_cast<sal_uInt64 *>( *pGPR++ );
350 break;
351 case X86_64_SSE_CLASS:
352 case X86_64_SSESF_CLASS:
353 case X86_64_SSEDF_CLASS:
354 *pStructAlign++ = *reinterpret_cast<sal_uInt64 *>( *pSSE++ );
355 break;
356 default:
357 break;
361 #if 0
363 /* Functions to load floats and double to an SSE register placeholder. */
364 extern void float2sse (float, __int128_t *);
365 extern void double2sse (double, __int128_t *);
366 extern void floatfloat2sse (void *, __int128_t *);
368 /* Functions to put the floats and doubles back. */
369 extern float sse2float (__int128_t *);
370 extern double sse2double (__int128_t *);
371 extern void sse2floatfloat(__int128_t *, void *);
373 /*@-exportheader@*/
374 void
375 ffi_prep_args (stackLayout *stack, extended_cif *ecif)
376 /*@=exportheader@*/
378 int gprcount, ssecount, i, g, s;
379 void **p_argv;
380 void *argp = &stack->argspace;
381 ffi_type **p_arg;
383 /* First check if the return value should be passed in memory. If so,
384 pass the pointer as the first argument. */
385 gprcount = ssecount = 0;
386 if (ecif->cif->rtype->type != FFI_TYPE_VOID
387 && examine_argument (ecif->cif->rtype, 1, &g, &s) == 0)
388 (void *)stack->gpr[gprcount++] = ecif->rvalue;
390 for (i=ecif->cif->nargs, p_arg=ecif->cif->arg_types, p_argv = ecif->avalue;
391 i!=0; i--, p_arg++, p_argv++)
393 int in_register = 0;
395 switch ((*p_arg)->type)
397 case FFI_TYPE_SINT8:
398 case FFI_TYPE_SINT16:
399 case FFI_TYPE_SINT32:
400 case FFI_TYPE_SINT64:
401 case FFI_TYPE_UINT8:
402 case FFI_TYPE_UINT16:
403 case FFI_TYPE_UINT32:
404 case FFI_TYPE_UINT64:
405 case FFI_TYPE_POINTER:
406 if (gprcount < MAX_GPR_REGS)
408 stack->gpr[gprcount] = 0;
409 stack->gpr[gprcount++] = *(long long *)(*p_argv);
410 in_register = 1;
412 break;
414 case FFI_TYPE_FLOAT:
415 if (ssecount < MAX_SSE_REGS)
417 float2sse (*(float *)(*p_argv), &stack->sse[ssecount++]);
418 in_register = 1;
420 break;
422 case FFI_TYPE_DOUBLE:
423 if (ssecount < MAX_SSE_REGS)
425 double2sse (*(double *)(*p_argv), &stack->sse[ssecount++]);
426 in_register = 1;
428 break;
431 if (in_register)
432 continue;
434 /* Either all places in registers where filled, or this is a
435 type that potentially goes into a memory slot. */
436 if (examine_argument (*p_arg, 0, &g, &s) == 0
437 || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
439 /* Pass this argument in memory. */
440 argp = (void *)ALIGN(argp, (*p_arg)->alignment);
441 memcpy (argp, *p_argv, (*p_arg)->size);
442 argp += (*p_arg)->size;
444 else
446 /* All easy cases are eliminated. Now fire the big guns. */
448 enum x86_64_reg_class classes[MAX_CLASSES];
449 int offset = 0, j, num;
450 void *a;
452 num = classify_argument (*p_arg, classes, &offset);
453 for (j=0, a=*p_argv; j<num; j++, a+=8)
455 switch (classes[j])
457 case X86_64_INTEGER_CLASS:
458 case X86_64_INTEGERSI_CLASS:
459 stack->gpr[gprcount++] = *(long long *)a;
460 break;
461 case X86_64_SSE_CLASS:
462 floatfloat2sse (a, &stack->sse[ssecount++]);
463 break;
464 case X86_64_SSESF_CLASS:
465 float2sse (*(float *)a, &stack->sse[ssecount++]);
466 break;
467 case X86_64_SSEDF_CLASS:
468 double2sse (*(double *)a, &stack->sse[ssecount++]);
469 break;
470 default:
471 abort();
478 /* Perform machine dependent cif processing. */
479 ffi_status
480 ffi_prep_cif_machdep (ffi_cif *cif)
482 int gprcount, ssecount, i, g, s;
484 gprcount = ssecount = 0;
486 /* Reset the byte count. We handle this size estimation here. */
487 cif->bytes = 0;
489 /* If the return value should be passed in memory, pass the pointer
490 as the first argument. The actual memory isn't allocated here. */
491 if (cif->rtype->type != FFI_TYPE_VOID
492 && examine_argument (cif->rtype, 1, &g, &s) == 0)
493 gprcount = 1;
495 /* Go over all arguments and determine the way they should be passed.
496 If it's in a register and there is space for it, let that be so. If
497 not, add it's size to the stack byte count. */
498 for (i=0; i<cif->nargs; i++)
500 if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0
501 || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
503 /* This is passed in memory. First align to the basic type. */
504 cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment);
506 /* Stack arguments are *always* at least 8 byte aligned. */
507 cif->bytes = ALIGN(cif->bytes, 8);
509 /* Now add the size of this argument. */
510 cif->bytes += cif->arg_types[i]->size;
512 else
514 gprcount += g;
515 ssecount += s;
519 /* Set the flag for the closures return. */
520 switch (cif->rtype->type)
522 case FFI_TYPE_VOID:
523 case FFI_TYPE_STRUCT:
524 case FFI_TYPE_SINT64:
525 case FFI_TYPE_FLOAT:
526 case FFI_TYPE_DOUBLE:
527 case FFI_TYPE_LONGDOUBLE:
528 cif->flags = (unsigned) cif->rtype->type;
529 break;
531 case FFI_TYPE_UINT64:
532 cif->flags = FFI_TYPE_SINT64;
533 break;
535 default:
536 cif->flags = FFI_TYPE_INT;
537 break;
540 return FFI_OK;
543 typedef struct
545 long gpr[2];
546 __int128_t sse[2];
547 long double st0;
548 } return_value;
550 //#endif
552 void
553 ffi_fill_return_value (return_value *rv, extended_cif *ecif)
555 enum x86_64_reg_class classes[MAX_CLASSES];
556 int i = 0, num;
557 long *gpr = rv->gpr;
558 __int128_t *sse = rv->sse;
559 signed char sc;
560 signed short ss;
562 /* This is needed because of the way x86-64 handles signed short
563 integers. */
564 switch (ecif->cif->rtype->type)
566 case FFI_TYPE_SINT8:
567 sc = *(signed char *)gpr;
568 *(long long *)ecif->rvalue = (long long)sc;
569 return;
570 case FFI_TYPE_SINT16:
571 ss = *(signed short *)gpr;
572 *(long long *)ecif->rvalue = (long long)ss;
573 return;
574 default:
575 /* Just continue. */
579 num = classify_argument (ecif->cif->rtype, classes, &i);
581 if (num == 0)
582 /* Return in memory. */
583 ecif->rvalue = (void *) rv->gpr[0];
584 else if (num == 2 && classes[0] == X86_64_X87_CLASS &&
585 classes[1] == X86_64_X87UP_CLASS)
586 /* This is a long double (this is easiest to handle this way instead
587 of an eightbyte at a time as in the loop below. */
588 *((long double *)ecif->rvalue) = rv->st0;
589 else
591 void *a;
593 for (i=0, a=ecif->rvalue; i<num; i++, a+=8)
595 switch (classes[i])
597 case X86_64_INTEGER_CLASS:
598 case X86_64_INTEGERSI_CLASS:
599 *(long long *)a = *gpr;
600 gpr++;
601 break;
602 case X86_64_SSE_CLASS:
603 sse2floatfloat (sse++, a);
604 break;
605 case X86_64_SSESF_CLASS:
606 *(float *)a = sse2float (sse++);
607 break;
608 case X86_64_SSEDF_CLASS:
609 *(double *)a = sse2double (sse++);
610 break;
611 default:
612 abort();
618 //#if 0
620 /*@-declundef@*/
621 /*@-exportheader@*/
622 extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *),
623 void (*) (return_value *, extended_cif *),
624 /*@out@*/ extended_cif *,
625 unsigned, /*@out@*/ unsigned *, void (*fn)());
626 /*@=declundef@*/
627 /*@=exportheader@*/
629 void ffi_call(/*@dependent@*/ ffi_cif *cif,
630 void (*fn)(),
631 /*@out@*/ void *rvalue,
632 /*@dependent@*/ void **avalue)
634 extended_cif ecif;
635 int dummy;
637 ecif.cif = cif;
638 ecif.avalue = avalue;
640 /* If the return value is a struct and we don't have a return */
641 /* value address then we need to make one */
643 if ((rvalue == NULL) &&
644 (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0))
646 /*@-sysunrecog@*/
647 ecif.rvalue = alloca(cif->rtype->size);
648 /*@=sysunrecog@*/
650 else
651 ecif.rvalue = rvalue;
653 /* Stack must always be 16byte aligned. Make it so. */
654 cif->bytes = ALIGN(cif->bytes, 16);
656 switch (cif->abi)
658 case FFI_SYSV:
659 /* Calling 32bit code from 64bit is not possible */
660 FFI_ASSERT(0);
661 break;
663 case FFI_UNIX64:
664 /*@-usedef@*/
665 ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif,
666 cif->bytes, ecif.rvalue, fn);
667 /*@=usedef@*/
668 break;
670 default:
671 FFI_ASSERT(0);
672 break;
676 extern void ffi_closure_UNIX64(void);
678 ffi_status
679 ffi_prep_closure (ffi_closure* closure,
680 ffi_cif* cif,
681 void (*fun)(ffi_cif*, void*, void**, void*),
682 void *user_data)
684 volatile unsigned short *tramp;
686 /* FFI_ASSERT (cif->abi == FFI_OSF); */
688 tramp = (volatile unsigned short *) &closure->tramp[0];
689 tramp[0] = 0xbb49; /* mov <code>, %r11 */
690 tramp[5] = 0xba49; /* mov <data>, %r10 */
691 tramp[10] = 0xff49; /* jmp *%r11 */
692 tramp[11] = 0x00e3;
693 *(void * volatile *) &tramp[1] = ffi_closure_UNIX64;
694 *(void * volatile *) &tramp[6] = closure;
696 closure->cif = cif;
697 closure->fun = fun;
698 closure->user_data = user_data;
700 return FFI_OK;
704 ffi_closure_UNIX64_inner(ffi_closure *closure, va_list l, void *rp)
706 ffi_cif *cif;
707 void **avalue;
708 ffi_type **arg_types;
709 long i, avn, argn;
711 cif = closure->cif;
712 avalue = alloca(cif->nargs * sizeof(void *));
714 argn = 0;
716 i = 0;
717 avn = cif->nargs;
718 arg_types = cif->arg_types;
720 /* Grab the addresses of the arguments from the stack frame. */
721 while (i < avn)
723 switch (arg_types[i]->type)
725 case FFI_TYPE_SINT8:
726 case FFI_TYPE_UINT8:
727 case FFI_TYPE_SINT16:
728 case FFI_TYPE_UINT16:
729 case FFI_TYPE_SINT32:
730 case FFI_TYPE_UINT32:
731 case FFI_TYPE_SINT64:
732 case FFI_TYPE_UINT64:
733 case FFI_TYPE_POINTER:
735 if (l->gp_offset > 48-8)
737 avalue[i] = l->overflow_arg_area;
738 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
740 else
742 avalue[i] = (char *)l->reg_save_area + l->gp_offset;
743 l->gp_offset += 8;
746 break;
748 case FFI_TYPE_STRUCT:
749 /* FIXME */
750 FFI_ASSERT(0);
751 break;
753 case FFI_TYPE_DOUBLE:
755 if (l->fp_offset > 176-16)
757 avalue[i] = l->overflow_arg_area;
758 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
760 else
762 avalue[i] = (char *)l->reg_save_area + l->fp_offset;
763 l->fp_offset += 16;
766 #if DEBUG_FFI
767 fprintf (stderr, "double arg %d = %g\n", i, *(double *)avalue[i]);
768 #endif
769 break;
771 case FFI_TYPE_FLOAT:
773 if (l->fp_offset > 176-16)
775 avalue[i] = l->overflow_arg_area;
776 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
778 else
780 avalue[i] = (char *)l->reg_save_area + l->fp_offset;
781 l->fp_offset += 16;
784 #if DEBUG_FFI
785 fprintf (stderr, "float arg %d = %g\n", i, *(float *)avalue[i]);
786 #endif
787 break;
789 default:
790 FFI_ASSERT(0);
793 argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG;
794 i++;
797 /* Invoke the closure. */
798 (closure->fun) (cif, rp, avalue, closure->user_data);
800 /* FIXME: Structs not supported. */
801 FFI_ASSERT(cif->rtype->type != FFI_TYPE_STRUCT);
803 /* Tell ffi_closure_UNIX64 how to perform return type promotions. */
805 return cif->rtype->type;
808 #endif