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