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 *
endian_adjust(void * addr,size_t len)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
hfa_type_size(int type)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
hfa_type_load(fpreg * fpaddr,int type,void * addr)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
hfa_type_store(int type,void * addr,fpreg * fpaddr)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
hfa_element_type(ffi_type * type,int nested)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
ffi_prep_cif_machdep(ffi_cif * cif)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
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)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
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)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
ffi_closure_unix_inner(ffi_closure * closure,struct ia64_args * stack,void * rvalue,void * r8)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 }
587