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