OSDN Git Service

cheets: Add external/wayland and external/cheets-libffi
[android-x86/external-libffi.git] / src / ia64 / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 1998, 2007, 2008, 2012 Red Hat, Inc.
3            Copyright (c) 2000 Hewlett Packard Company
4            Copyright (c) 2011 Anthony Green
5    
6    IA64 Foreign Function Interface 
7
8    Permission is hereby granted, free of charge, to any person obtaining
9    a copy of this software and associated documentation files (the
10    ``Software''), to deal in the Software without restriction, including
11    without limitation the rights to use, copy, modify, merge, publish,
12    distribute, sublicense, and/or sell copies of the Software, and to
13    permit persons to whom the Software is furnished to do so, subject to
14    the following conditions:
15
16    The above copyright notice and this permission notice shall be included
17    in all copies or substantial portions of the Software.
18
19    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
20    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26    DEALINGS IN THE SOFTWARE.
27    ----------------------------------------------------------------------- */
28
29 #include <ffi.h>
30 #include <ffi_common.h>
31
32 #include <stdlib.h>
33 #include <stdbool.h>
34 #include <float.h>
35
36 #include "ia64_flags.h"
37
38 /* A 64-bit pointer value.  In LP64 mode, this is effectively a plain
39    pointer.  In ILP32 mode, it's a pointer that's been extended to 
40    64 bits by "addp4".  */
41 typedef void *PTR64 __attribute__((mode(DI)));
42
43 /* Memory image of fp register contents.  This is the implementation
44    specific format used by ldf.fill/stf.spill.  All we care about is
45    that it wants a 16 byte aligned slot.  */
46 typedef struct
47 {
48   UINT64 x[2] __attribute__((aligned(16)));
49 } fpreg;
50
51
52 /* The stack layout given to ffi_call_unix and ffi_closure_unix_inner.  */
53
54 struct ia64_args
55 {
56   fpreg fp_regs[8];     /* Contents of 8 fp arg registers.  */
57   UINT64 gp_regs[8];    /* Contents of 8 gp arg registers.  */
58   UINT64 other_args[];  /* Arguments passed on stack, variable size.  */
59 };
60
61
62 /* Adjust ADDR, a pointer to an 8 byte slot, to point to the low LEN bytes.  */
63
64 static inline void *
65 endian_adjust (void *addr, size_t len)
66 {
67 #ifdef __BIG_ENDIAN__
68   return addr + (8 - len);
69 #else
70   return addr;
71 #endif
72 }
73
74 /* Store VALUE to ADDR in the current cpu implementation's fp spill format.
75    This is a macro instead of a function, so that it works for all 3 floating
76    point types without type conversions.  Type conversion to long double breaks
77    the denorm support.  */
78
79 #define stf_spill(addr, value)  \
80   asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value));
81
82 /* Load a value from ADDR, which is in the current cpu implementation's
83    fp spill format.  As above, this must also be a macro.  */
84
85 #define ldf_fill(result, addr)  \
86   asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr));
87
88 /* Return the size of the C type associated with with TYPE.  Which will
89    be one of the FFI_IA64_TYPE_HFA_* values.  */
90
91 static size_t
92 hfa_type_size (int type)
93 {
94   switch (type)
95     {
96     case FFI_IA64_TYPE_HFA_FLOAT:
97       return sizeof(float);
98     case FFI_IA64_TYPE_HFA_DOUBLE:
99       return sizeof(double);
100     case FFI_IA64_TYPE_HFA_LDOUBLE:
101       return sizeof(__float80);
102     default:
103       abort ();
104     }
105 }
106
107 /* Load from ADDR a value indicated by TYPE.  Which will be one of
108    the FFI_IA64_TYPE_HFA_* values.  */
109
110 static void
111 hfa_type_load (fpreg *fpaddr, int type, void *addr)
112 {
113   switch (type)
114     {
115     case FFI_IA64_TYPE_HFA_FLOAT:
116       stf_spill (fpaddr, *(float *) addr);
117       return;
118     case FFI_IA64_TYPE_HFA_DOUBLE:
119       stf_spill (fpaddr, *(double *) addr);
120       return;
121     case FFI_IA64_TYPE_HFA_LDOUBLE:
122       stf_spill (fpaddr, *(__float80 *) addr);
123       return;
124     default:
125       abort ();
126     }
127 }
128
129 /* Load VALUE into ADDR as indicated by TYPE.  Which will be one of
130    the FFI_IA64_TYPE_HFA_* values.  */
131
132 static void
133 hfa_type_store (int type, void *addr, fpreg *fpaddr)
134 {
135   switch (type)
136     {
137     case FFI_IA64_TYPE_HFA_FLOAT:
138       {
139         float result;
140         ldf_fill (result, fpaddr);
141         *(float *) addr = result;
142         break;
143       }
144     case FFI_IA64_TYPE_HFA_DOUBLE:
145       {
146         double result;
147         ldf_fill (result, fpaddr);
148         *(double *) addr = result;
149         break;
150       }
151     case FFI_IA64_TYPE_HFA_LDOUBLE:
152       {
153         __float80 result;
154         ldf_fill (result, fpaddr);
155         *(__float80 *) addr = result;
156         break;
157       }
158     default:
159       abort ();
160     }
161 }
162
163 /* Is TYPE a struct containing floats, doubles, or extended doubles,
164    all of the same fp type?  If so, return the element type.  Return
165    FFI_TYPE_VOID if not.  */
166
167 static int
168 hfa_element_type (ffi_type *type, int nested)
169 {
170   int element = FFI_TYPE_VOID;
171
172   switch (type->type)
173     {
174     case FFI_TYPE_FLOAT:
175       /* We want to return VOID for raw floating-point types, but the
176          synthetic HFA type if we're nested within an aggregate.  */
177       if (nested)
178         element = FFI_IA64_TYPE_HFA_FLOAT;
179       break;
180
181     case FFI_TYPE_DOUBLE:
182       /* Similarly.  */
183       if (nested)
184         element = FFI_IA64_TYPE_HFA_DOUBLE;
185       break;
186
187     case FFI_TYPE_LONGDOUBLE:
188       /* Similarly, except that that HFA is true for double extended,
189          but not quad precision.  Both have sizeof == 16, so tell the
190          difference based on the precision.  */
191       if (LDBL_MANT_DIG == 64 && nested)
192         element = FFI_IA64_TYPE_HFA_LDOUBLE;
193       break;
194
195     case FFI_TYPE_STRUCT:
196       {
197         ffi_type **ptr = &type->elements[0];
198
199         for (ptr = &type->elements[0]; *ptr ; ptr++)
200           {
201             int sub_element = hfa_element_type (*ptr, 1);
202             if (sub_element == FFI_TYPE_VOID)
203               return FFI_TYPE_VOID;
204
205             if (element == FFI_TYPE_VOID)
206               element = sub_element;
207             else if (element != sub_element)
208               return FFI_TYPE_VOID;
209           }
210       }
211       break;
212
213     default:
214       return FFI_TYPE_VOID;
215     }
216
217   return element;
218 }
219
220
221 /* Perform machine dependent cif processing. */
222
223 ffi_status
224 ffi_prep_cif_machdep(ffi_cif *cif)
225 {
226   int flags;
227
228   /* Adjust cif->bytes to include space for the bits of the ia64_args frame
229      that precedes the integer register portion.  The estimate that the
230      generic bits did for the argument space required is good enough for the
231      integer component.  */
232   cif->bytes += offsetof(struct ia64_args, gp_regs[0]);
233   if (cif->bytes < sizeof(struct ia64_args))
234     cif->bytes = sizeof(struct ia64_args);
235
236   /* Set the return type flag. */
237   flags = cif->rtype->type;
238   switch (cif->rtype->type)
239     {
240     case FFI_TYPE_LONGDOUBLE:
241       /* Leave FFI_TYPE_LONGDOUBLE as meaning double extended precision,
242          and encode quad precision as a two-word integer structure.  */
243       if (LDBL_MANT_DIG != 64)
244         flags = FFI_IA64_TYPE_SMALL_STRUCT | (16 << 8);
245       break;
246
247     case FFI_TYPE_STRUCT:
248       {
249         size_t size = cif->rtype->size;
250         int hfa_type = hfa_element_type (cif->rtype, 0);
251
252         if (hfa_type != FFI_TYPE_VOID)
253           {
254             size_t nelts = size / hfa_type_size (hfa_type);
255             if (nelts <= 8)
256               flags = hfa_type | (size << 8);
257           }
258         else
259           {
260             if (size <= 32)
261               flags = FFI_IA64_TYPE_SMALL_STRUCT | (size << 8);
262           }
263       }
264       break;
265
266     default:
267       break;
268     }
269   cif->flags = flags;
270
271   return FFI_OK;
272 }
273
274 extern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(void), UINT64);
275
276 void
277 ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
278 {
279   struct ia64_args *stack;
280   long i, avn, gpcount, fpcount;
281   ffi_type **p_arg;
282
283   FFI_ASSERT (cif->abi == FFI_UNIX);
284
285   /* If we have no spot for a return value, make one.  */
286   if (rvalue == NULL && cif->rtype->type != FFI_TYPE_VOID)
287     rvalue = alloca (cif->rtype->size);
288     
289   /* Allocate the stack frame.  */
290   stack = alloca (cif->bytes);
291
292   gpcount = fpcount = 0;
293   avn = cif->nargs;
294   for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
295     {
296       switch ((*p_arg)->type)
297         {
298         case FFI_TYPE_SINT8:
299           stack->gp_regs[gpcount++] = *(SINT8 *)avalue[i];
300           break;
301         case FFI_TYPE_UINT8:
302           stack->gp_regs[gpcount++] = *(UINT8 *)avalue[i];
303           break;
304         case FFI_TYPE_SINT16:
305           stack->gp_regs[gpcount++] = *(SINT16 *)avalue[i];
306           break;
307         case FFI_TYPE_UINT16:
308           stack->gp_regs[gpcount++] = *(UINT16 *)avalue[i];
309           break;
310         case FFI_TYPE_SINT32:
311           stack->gp_regs[gpcount++] = *(SINT32 *)avalue[i];
312           break;
313         case FFI_TYPE_UINT32:
314           stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
315           break;
316         case FFI_TYPE_SINT64:
317         case FFI_TYPE_UINT64:
318           stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
319           break;
320
321         case FFI_TYPE_POINTER:
322           stack->gp_regs[gpcount++] = (UINT64)(PTR64) *(void **)avalue[i];
323           break;
324
325         case FFI_TYPE_FLOAT:
326           if (gpcount < 8 && fpcount < 8)
327             stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]);
328           {
329             UINT32 tmp;
330             memcpy (&tmp, avalue[i], sizeof (UINT32));
331             stack->gp_regs[gpcount++] = tmp;
332           }
333           break;
334
335         case FFI_TYPE_DOUBLE:
336           if (gpcount < 8 && fpcount < 8)
337             stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]);
338           memcpy (&stack->gp_regs[gpcount++], avalue[i], sizeof (UINT64));
339           break;
340
341         case FFI_TYPE_LONGDOUBLE:
342           if (gpcount & 1)
343             gpcount++;
344           if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
345             stf_spill (&stack->fp_regs[fpcount++], *(__float80 *)avalue[i]);
346           memcpy (&stack->gp_regs[gpcount], avalue[i], 16);
347           gpcount += 2;
348           break;
349
350         case FFI_TYPE_STRUCT:
351           {
352             size_t size = (*p_arg)->size;
353             size_t align = (*p_arg)->alignment;
354             int hfa_type = hfa_element_type (*p_arg, 0);
355
356             FFI_ASSERT (align <= 16);
357             if (align == 16 && (gpcount & 1))
358               gpcount++;
359
360             if (hfa_type != FFI_TYPE_VOID)
361               {
362                 size_t hfa_size = hfa_type_size (hfa_type);
363                 size_t offset = 0;
364                 size_t gp_offset = gpcount * 8;
365
366                 while (fpcount < 8
367                        && offset < size
368                        && gp_offset < 8 * 8)
369                   {
370                     hfa_type_load (&stack->fp_regs[fpcount], hfa_type,
371                                    avalue[i] + offset);
372                     offset += hfa_size;
373                     gp_offset += hfa_size;
374                     fpcount += 1;
375                   }
376               }
377
378             memcpy (&stack->gp_regs[gpcount], avalue[i], size);
379             gpcount += (size + 7) / 8;
380           }
381           break;
382
383         default:
384           abort ();
385         }
386     }
387
388   ffi_call_unix (stack, rvalue, fn, cif->flags);
389 }
390
391 /* Closures represent a pair consisting of a function pointer, and
392    some user data.  A closure is invoked by reinterpreting the closure
393    as a function pointer, and branching to it.  Thus we can make an
394    interpreted function callable as a C function: We turn the
395    interpreter itself, together with a pointer specifying the
396    interpreted procedure, into a closure.
397
398    For IA64, function pointer are already pairs consisting of a code
399    pointer, and a gp pointer.  The latter is needed to access global
400    variables.  Here we set up such a pair as the first two words of
401    the closure (in the "trampoline" area), but we replace the gp
402    pointer with a pointer to the closure itself.  We also add the real
403    gp pointer to the closure.  This allows the function entry code to
404    both retrieve the user data, and to restore the correct gp pointer.  */
405
406 extern void ffi_closure_unix ();
407
408 ffi_status
409 ffi_prep_closure_loc (ffi_closure* closure,
410                       ffi_cif* cif,
411                       void (*fun)(ffi_cif*,void*,void**,void*),
412                       void *user_data,
413                       void *codeloc)
414 {
415   /* The layout of a function descriptor.  A C function pointer really 
416      points to one of these.  */
417   struct ia64_fd
418   {
419     UINT64 code_pointer;
420     UINT64 gp;
421   };
422
423   struct ffi_ia64_trampoline_struct
424   {
425     UINT64 code_pointer;        /* Pointer to ffi_closure_unix.  */
426     UINT64 fake_gp;             /* Pointer to closure, installed as gp.  */
427     UINT64 real_gp;             /* Real gp value.  */
428   };
429
430   struct ffi_ia64_trampoline_struct *tramp;
431   struct ia64_fd *fd;
432
433   if (cif->abi != FFI_UNIX)
434     return FFI_BAD_ABI;
435
436   tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
437   fd = (struct ia64_fd *)(void *)ffi_closure_unix;
438
439   tramp->code_pointer = fd->code_pointer;
440   tramp->real_gp = fd->gp;
441   tramp->fake_gp = (UINT64)(PTR64)codeloc;
442   closure->cif = cif;
443   closure->user_data = user_data;
444   closure->fun = fun;
445
446   return FFI_OK;
447 }
448
449
450 UINT64
451 ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
452                         void *rvalue, void *r8)
453 {
454   ffi_cif *cif;
455   void **avalue;
456   ffi_type **p_arg;
457   long i, avn, gpcount, fpcount;
458
459   cif = closure->cif;
460   avn = cif->nargs;
461   avalue = alloca (avn * sizeof (void *));
462
463   /* If the structure return value is passed in memory get that location
464      from r8 so as to pass the value directly back to the caller.  */
465   if (cif->flags == FFI_TYPE_STRUCT)
466     rvalue = r8;
467
468   gpcount = fpcount = 0;
469   for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
470     {
471       switch ((*p_arg)->type)
472         {
473         case FFI_TYPE_SINT8:
474         case FFI_TYPE_UINT8:
475           avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 1);
476           break;
477         case FFI_TYPE_SINT16:
478         case FFI_TYPE_UINT16:
479           avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 2);
480           break;
481         case FFI_TYPE_SINT32:
482         case FFI_TYPE_UINT32:
483           avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 4);
484           break;
485         case FFI_TYPE_SINT64:
486         case FFI_TYPE_UINT64:
487           avalue[i] = &stack->gp_regs[gpcount++];
488           break;
489         case FFI_TYPE_POINTER:
490           avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], sizeof(void*));
491           break;
492
493         case FFI_TYPE_FLOAT:
494           if (gpcount < 8 && fpcount < 8)
495             {
496               fpreg *addr = &stack->fp_regs[fpcount++];
497               float result;
498               avalue[i] = addr;
499               ldf_fill (result, addr);
500               *(float *)addr = result;
501             }
502           else
503             avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4);
504           gpcount++;
505           break;
506
507         case FFI_TYPE_DOUBLE:
508           if (gpcount < 8 && fpcount < 8)
509             {
510               fpreg *addr = &stack->fp_regs[fpcount++];
511               double result;
512               avalue[i] = addr;
513               ldf_fill (result, addr);
514               *(double *)addr = result;
515             }
516           else
517             avalue[i] = &stack->gp_regs[gpcount];
518           gpcount++;
519           break;
520
521         case FFI_TYPE_LONGDOUBLE:
522           if (gpcount & 1)
523             gpcount++;
524           if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
525             {
526               fpreg *addr = &stack->fp_regs[fpcount++];
527               __float80 result;
528               avalue[i] = addr;
529               ldf_fill (result, addr);
530               *(__float80 *)addr = result;
531             }
532           else
533             avalue[i] = &stack->gp_regs[gpcount];
534           gpcount += 2;
535           break;
536
537         case FFI_TYPE_STRUCT:
538           {
539             size_t size = (*p_arg)->size;
540             size_t align = (*p_arg)->alignment;
541             int hfa_type = hfa_element_type (*p_arg, 0);
542
543             FFI_ASSERT (align <= 16);
544             if (align == 16 && (gpcount & 1))
545               gpcount++;
546
547             if (hfa_type != FFI_TYPE_VOID)
548               {
549                 size_t hfa_size = hfa_type_size (hfa_type);
550                 size_t offset = 0;
551                 size_t gp_offset = gpcount * 8;
552                 void *addr = alloca (size);
553
554                 avalue[i] = addr;
555
556                 while (fpcount < 8
557                        && offset < size
558                        && gp_offset < 8 * 8)
559                   {
560                     hfa_type_store (hfa_type, addr + offset,
561                                     &stack->fp_regs[fpcount]);
562                     offset += hfa_size;
563                     gp_offset += hfa_size;
564                     fpcount += 1;
565                   }
566
567                 if (offset < size)
568                   memcpy (addr + offset, (char *)stack->gp_regs + gp_offset,
569                           size - offset);
570               }
571             else
572               avalue[i] = &stack->gp_regs[gpcount];
573
574             gpcount += (size + 7) / 8;
575           }
576           break;
577
578         default:
579           abort ();
580         }
581     }
582
583   closure->fun (cif, rvalue, avalue, closure->user_data);
584
585   return cif->flags;
586 }