merge the formfield patch from ooo-build
[ooovba.git] / bridges / source / cpp_uno / gcc3_freebsd_x86-64 / abi.cxx
blob236e1fc357c619b0783d62afc9bd9303874c4e0f
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.4 $
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;
359 #if 0
361 /* Functions to load floats and double to an SSE register placeholder. */
362 extern void float2sse (float, __int128_t *);
363 extern void double2sse (double, __int128_t *);
364 extern void floatfloat2sse (void *, __int128_t *);
366 /* Functions to put the floats and doubles back. */
367 extern float sse2float (__int128_t *);
368 extern double sse2double (__int128_t *);
369 extern void sse2floatfloat(__int128_t *, void *);
371 /*@-exportheader@*/
372 void
373 ffi_prep_args (stackLayout *stack, extended_cif *ecif)
374 /*@=exportheader@*/
376 int gprcount, ssecount, i, g, s;
377 void **p_argv;
378 void *argp = &stack->argspace;
379 ffi_type **p_arg;
381 /* First check if the return value should be passed in memory. If so,
382 pass the pointer as the first argument. */
383 gprcount = ssecount = 0;
384 if (ecif->cif->rtype->type != FFI_TYPE_VOID
385 && examine_argument (ecif->cif->rtype, 1, &g, &s) == 0)
386 (void *)stack->gpr[gprcount++] = ecif->rvalue;
388 for (i=ecif->cif->nargs, p_arg=ecif->cif->arg_types, p_argv = ecif->avalue;
389 i!=0; i--, p_arg++, p_argv++)
391 int in_register = 0;
393 switch ((*p_arg)->type)
395 case FFI_TYPE_SINT8:
396 case FFI_TYPE_SINT16:
397 case FFI_TYPE_SINT32:
398 case FFI_TYPE_SINT64:
399 case FFI_TYPE_UINT8:
400 case FFI_TYPE_UINT16:
401 case FFI_TYPE_UINT32:
402 case FFI_TYPE_UINT64:
403 case FFI_TYPE_POINTER:
404 if (gprcount < MAX_GPR_REGS)
406 stack->gpr[gprcount] = 0;
407 stack->gpr[gprcount++] = *(long long *)(*p_argv);
408 in_register = 1;
410 break;
412 case FFI_TYPE_FLOAT:
413 if (ssecount < MAX_SSE_REGS)
415 float2sse (*(float *)(*p_argv), &stack->sse[ssecount++]);
416 in_register = 1;
418 break;
420 case FFI_TYPE_DOUBLE:
421 if (ssecount < MAX_SSE_REGS)
423 double2sse (*(double *)(*p_argv), &stack->sse[ssecount++]);
424 in_register = 1;
426 break;
429 if (in_register)
430 continue;
432 /* Either all places in registers where filled, or this is a
433 type that potentially goes into a memory slot. */
434 if (examine_argument (*p_arg, 0, &g, &s) == 0
435 || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
437 /* Pass this argument in memory. */
438 argp = (void *)ALIGN(argp, (*p_arg)->alignment);
439 memcpy (argp, *p_argv, (*p_arg)->size);
440 argp += (*p_arg)->size;
442 else
444 /* All easy cases are eliminated. Now fire the big guns. */
446 enum x86_64_reg_class classes[MAX_CLASSES];
447 int offset = 0, j, num;
448 void *a;
450 num = classify_argument (*p_arg, classes, &offset);
451 for (j=0, a=*p_argv; j<num; j++, a+=8)
453 switch (classes[j])
455 case X86_64_INTEGER_CLASS:
456 case X86_64_INTEGERSI_CLASS:
457 stack->gpr[gprcount++] = *(long long *)a;
458 break;
459 case X86_64_SSE_CLASS:
460 floatfloat2sse (a, &stack->sse[ssecount++]);
461 break;
462 case X86_64_SSESF_CLASS:
463 float2sse (*(float *)a, &stack->sse[ssecount++]);
464 break;
465 case X86_64_SSEDF_CLASS:
466 double2sse (*(double *)a, &stack->sse[ssecount++]);
467 break;
468 default:
469 abort();
476 /* Perform machine dependent cif processing. */
477 ffi_status
478 ffi_prep_cif_machdep (ffi_cif *cif)
480 int gprcount, ssecount, i, g, s;
482 gprcount = ssecount = 0;
484 /* Reset the byte count. We handle this size estimation here. */
485 cif->bytes = 0;
487 /* If the return value should be passed in memory, pass the pointer
488 as the first argument. The actual memory isn't allocated here. */
489 if (cif->rtype->type != FFI_TYPE_VOID
490 && examine_argument (cif->rtype, 1, &g, &s) == 0)
491 gprcount = 1;
493 /* Go over all arguments and determine the way they should be passed.
494 If it's in a register and there is space for it, let that be so. If
495 not, add it's size to the stack byte count. */
496 for (i=0; i<cif->nargs; i++)
498 if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0
499 || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
501 /* This is passed in memory. First align to the basic type. */
502 cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment);
504 /* Stack arguments are *always* at least 8 byte aligned. */
505 cif->bytes = ALIGN(cif->bytes, 8);
507 /* Now add the size of this argument. */
508 cif->bytes += cif->arg_types[i]->size;
510 else
512 gprcount += g;
513 ssecount += s;
517 /* Set the flag for the closures return. */
518 switch (cif->rtype->type)
520 case FFI_TYPE_VOID:
521 case FFI_TYPE_STRUCT:
522 case FFI_TYPE_SINT64:
523 case FFI_TYPE_FLOAT:
524 case FFI_TYPE_DOUBLE:
525 case FFI_TYPE_LONGDOUBLE:
526 cif->flags = (unsigned) cif->rtype->type;
527 break;
529 case FFI_TYPE_UINT64:
530 cif->flags = FFI_TYPE_SINT64;
531 break;
533 default:
534 cif->flags = FFI_TYPE_INT;
535 break;
538 return FFI_OK;
541 typedef struct
543 long gpr[2];
544 __int128_t sse[2];
545 long double st0;
546 } return_value;
548 //#endif
550 void
551 ffi_fill_return_value (return_value *rv, extended_cif *ecif)
553 enum x86_64_reg_class classes[MAX_CLASSES];
554 int i = 0, num;
555 long *gpr = rv->gpr;
556 __int128_t *sse = rv->sse;
557 signed char sc;
558 signed short ss;
560 /* This is needed because of the way x86-64 handles signed short
561 integers. */
562 switch (ecif->cif->rtype->type)
564 case FFI_TYPE_SINT8:
565 sc = *(signed char *)gpr;
566 *(long long *)ecif->rvalue = (long long)sc;
567 return;
568 case FFI_TYPE_SINT16:
569 ss = *(signed short *)gpr;
570 *(long long *)ecif->rvalue = (long long)ss;
571 return;
572 default:
573 /* Just continue. */
577 num = classify_argument (ecif->cif->rtype, classes, &i);
579 if (num == 0)
580 /* Return in memory. */
581 ecif->rvalue = (void *) rv->gpr[0];
582 else if (num == 2 && classes[0] == X86_64_X87_CLASS &&
583 classes[1] == X86_64_X87UP_CLASS)
584 /* This is a long double (this is easiest to handle this way instead
585 of an eightbyte at a time as in the loop below. */
586 *((long double *)ecif->rvalue) = rv->st0;
587 else
589 void *a;
591 for (i=0, a=ecif->rvalue; i<num; i++, a+=8)
593 switch (classes[i])
595 case X86_64_INTEGER_CLASS:
596 case X86_64_INTEGERSI_CLASS:
597 *(long long *)a = *gpr;
598 gpr++;
599 break;
600 case X86_64_SSE_CLASS:
601 sse2floatfloat (sse++, a);
602 break;
603 case X86_64_SSESF_CLASS:
604 *(float *)a = sse2float (sse++);
605 break;
606 case X86_64_SSEDF_CLASS:
607 *(double *)a = sse2double (sse++);
608 break;
609 default:
610 abort();
616 //#if 0
618 /*@-declundef@*/
619 /*@-exportheader@*/
620 extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *),
621 void (*) (return_value *, extended_cif *),
622 /*@out@*/ extended_cif *,
623 unsigned, /*@out@*/ unsigned *, void (*fn)());
624 /*@=declundef@*/
625 /*@=exportheader@*/
627 void ffi_call(/*@dependent@*/ ffi_cif *cif,
628 void (*fn)(),
629 /*@out@*/ void *rvalue,
630 /*@dependent@*/ void **avalue)
632 extended_cif ecif;
633 int dummy;
635 ecif.cif = cif;
636 ecif.avalue = avalue;
638 /* If the return value is a struct and we don't have a return */
639 /* value address then we need to make one */
641 if ((rvalue == NULL) &&
642 (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0))
644 /*@-sysunrecog@*/
645 ecif.rvalue = alloca(cif->rtype->size);
646 /*@=sysunrecog@*/
648 else
649 ecif.rvalue = rvalue;
651 /* Stack must always be 16byte aligned. Make it so. */
652 cif->bytes = ALIGN(cif->bytes, 16);
654 switch (cif->abi)
656 case FFI_SYSV:
657 /* Calling 32bit code from 64bit is not possible */
658 FFI_ASSERT(0);
659 break;
661 case FFI_UNIX64:
662 /*@-usedef@*/
663 ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif,
664 cif->bytes, ecif.rvalue, fn);
665 /*@=usedef@*/
666 break;
668 default:
669 FFI_ASSERT(0);
670 break;
674 extern void ffi_closure_UNIX64(void);
676 ffi_status
677 ffi_prep_closure (ffi_closure* closure,
678 ffi_cif* cif,
679 void (*fun)(ffi_cif*, void*, void**, void*),
680 void *user_data)
682 volatile unsigned short *tramp;
684 /* FFI_ASSERT (cif->abi == FFI_OSF); */
686 tramp = (volatile unsigned short *) &closure->tramp[0];
687 tramp[0] = 0xbb49; /* mov <code>, %r11 */
688 tramp[5] = 0xba49; /* mov <data>, %r10 */
689 tramp[10] = 0xff49; /* jmp *%r11 */
690 tramp[11] = 0x00e3;
691 *(void * volatile *) &tramp[1] = ffi_closure_UNIX64;
692 *(void * volatile *) &tramp[6] = closure;
694 closure->cif = cif;
695 closure->fun = fun;
696 closure->user_data = user_data;
698 return FFI_OK;
702 ffi_closure_UNIX64_inner(ffi_closure *closure, va_list l, void *rp)
704 ffi_cif *cif;
705 void **avalue;
706 ffi_type **arg_types;
707 long i, avn, argn;
709 cif = closure->cif;
710 avalue = alloca(cif->nargs * sizeof(void *));
712 argn = 0;
714 i = 0;
715 avn = cif->nargs;
716 arg_types = cif->arg_types;
718 /* Grab the addresses of the arguments from the stack frame. */
719 while (i < avn)
721 switch (arg_types[i]->type)
723 case FFI_TYPE_SINT8:
724 case FFI_TYPE_UINT8:
725 case FFI_TYPE_SINT16:
726 case FFI_TYPE_UINT16:
727 case FFI_TYPE_SINT32:
728 case FFI_TYPE_UINT32:
729 case FFI_TYPE_SINT64:
730 case FFI_TYPE_UINT64:
731 case FFI_TYPE_POINTER:
733 if (l->gp_offset > 48-8)
735 avalue[i] = l->overflow_arg_area;
736 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
738 else
740 avalue[i] = (char *)l->reg_save_area + l->gp_offset;
741 l->gp_offset += 8;
744 break;
746 case FFI_TYPE_STRUCT:
747 /* FIXME */
748 FFI_ASSERT(0);
749 break;
751 case FFI_TYPE_DOUBLE:
753 if (l->fp_offset > 176-16)
755 avalue[i] = l->overflow_arg_area;
756 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
758 else
760 avalue[i] = (char *)l->reg_save_area + l->fp_offset;
761 l->fp_offset += 16;
764 #if DEBUG_FFI
765 fprintf (stderr, "double arg %d = %g\n", i, *(double *)avalue[i]);
766 #endif
767 break;
769 case FFI_TYPE_FLOAT:
771 if (l->fp_offset > 176-16)
773 avalue[i] = l->overflow_arg_area;
774 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
776 else
778 avalue[i] = (char *)l->reg_save_area + l->fp_offset;
779 l->fp_offset += 16;
782 #if DEBUG_FFI
783 fprintf (stderr, "float arg %d = %g\n", i, *(float *)avalue[i]);
784 #endif
785 break;
787 default:
788 FFI_ASSERT(0);
791 argn += ALIGN(arg_types[i]->size, SIZEOF_ARG) / SIZEOF_ARG;
792 i++;
795 /* Invoke the closure. */
796 (closure->fun) (cif, rp, avalue, closure->user_data);
798 /* FIXME: Structs not supported. */
799 FFI_ASSERT(cif->rtype->type != FFI_TYPE_STRUCT);
801 /* Tell ffi_closure_UNIX64 how to perform return type promotions. */
803 return cif->rtype->type;
806 #endif