Ruby  2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
ffi_sysv.c
Go to the documentation of this file.
1 /* -----------------------------------------------------------------------
2  ffi_sysv.c - Copyright (C) 2013 IBM
3  Copyright (C) 2011 Anthony Green
4  Copyright (C) 2011 Kyle Moffett
5  Copyright (C) 2008 Red Hat, Inc
6  Copyright (C) 2007, 2008 Free Software Foundation, Inc
7  Copyright (c) 1998 Geoffrey Keating
8 
9  PowerPC Foreign Function Interface
10 
11  Permission is hereby granted, free of charge, to any person obtaining
12  a copy of this software and associated documentation files (the
13  ``Software''), to deal in the Software without restriction, including
14  without limitation the rights to use, copy, modify, merge, publish,
15  distribute, sublicense, and/or sell copies of the Software, and to
16  permit persons to whom the Software is furnished to do so, subject to
17  the following conditions:
18 
19  The above copyright notice and this permission notice shall be included
20  in all copies or substantial portions of the Software.
21 
22  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
26  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  OTHER DEALINGS IN THE SOFTWARE.
29  ----------------------------------------------------------------------- */
30 
31 #include "ffi.h"
32 
33 #ifndef POWERPC64
34 #include "ffi_common.h"
35 #include "ffi_powerpc.h"
36 
37 
38 /* About the SYSV ABI. */
39 #define ASM_NEEDS_REGISTERS 4
40 #define NUM_GPR_ARG_REGISTERS 8
41 #define NUM_FPR_ARG_REGISTERS 8
42 
43 
44 #if HAVE_LONG_DOUBLE_VARIANT && FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
45 /* Adjust size of ffi_type_longdouble. */
46 void FFI_HIDDEN
48 {
49  if ((abi & (FFI_SYSV | FFI_SYSV_LONG_DOUBLE_128)) == FFI_SYSV)
50  {
51  ffi_type_longdouble.size = 8;
52  ffi_type_longdouble.alignment = 8;
53  }
54  else
55  {
56  ffi_type_longdouble.size = 16;
57  ffi_type_longdouble.alignment = 16;
58  }
59 }
60 #endif
61 
62 /* Transform long double, double and float to other types as per abi. */
63 static int
64 translate_float (int abi, int type)
65 {
66 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
68  && (abi & FFI_SYSV_LONG_DOUBLE_128) == 0)
69  type = FFI_TYPE_DOUBLE;
70 #endif
71  if ((abi & FFI_SYSV_SOFT_FLOAT) != 0)
72  {
73  if (type == FFI_TYPE_FLOAT)
74  type = FFI_TYPE_UINT32;
75  else if (type == FFI_TYPE_DOUBLE)
76  type = FFI_TYPE_UINT64;
77 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
78  else if (type == FFI_TYPE_LONGDOUBLE)
80  }
81  else if ((abi & FFI_SYSV_IBM_LONG_DOUBLE) == 0)
82  {
84  type = FFI_TYPE_STRUCT;
85 #endif
86  }
87  return type;
88 }
89 
90 /* Perform machine dependent cif processing */
91 static ffi_status
92 ffi_prep_cif_sysv_core (ffi_cif *cif)
93 {
94  ffi_type **ptr;
95  unsigned bytes;
96  unsigned i, fparg_count = 0, intarg_count = 0;
97  unsigned flags = cif->flags;
98  unsigned struct_copy_size = 0;
99  unsigned type = cif->rtype->type;
100  unsigned size = cif->rtype->size;
101 
102  /* The machine-independent calculation of cif->bytes doesn't work
103  for us. Redo the calculation. */
104 
105  /* Space for the frame pointer, callee's LR, and the asm's temp regs. */
106  bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof (int);
107 
108  /* Space for the GPR registers. */
109  bytes += NUM_GPR_ARG_REGISTERS * sizeof (int);
110 
111  /* Return value handling. The rules for SYSV are as follows:
112  - 32-bit (or less) integer values are returned in gpr3;
113  - Structures of size <= 4 bytes also returned in gpr3;
114  - 64-bit integer values and structures between 5 and 8 bytes are returned
115  in gpr3 and gpr4;
116  - Larger structures are allocated space and a pointer is passed as
117  the first argument.
118  - Single/double FP values are returned in fpr1;
119  - long doubles (if not equivalent to double) are returned in
120  fpr1,fpr2 for Linux and as for large structs for SysV. */
121 
122  type = translate_float (cif->abi, type);
123 
124  switch (type)
125  {
126 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
127  case FFI_TYPE_LONGDOUBLE:
128  flags |= FLAG_RETURNS_128BITS;
129  /* Fall through. */
130 #endif
131  case FFI_TYPE_DOUBLE:
132  flags |= FLAG_RETURNS_64BITS;
133  /* Fall through. */
134  case FFI_TYPE_FLOAT:
135  flags |= FLAG_RETURNS_FP;
136 #ifdef __NO_FPRS__
137  return FFI_BAD_ABI;
138 #endif
139  break;
140 
141  case FFI_TYPE_UINT128:
142  flags |= FLAG_RETURNS_128BITS;
143  /* Fall through. */
144  case FFI_TYPE_UINT64:
145  case FFI_TYPE_SINT64:
146  flags |= FLAG_RETURNS_64BITS;
147  break;
148 
149  case FFI_TYPE_STRUCT:
150  /* The final SYSV ABI says that structures smaller or equal 8 bytes
151  are returned in r3/r4. A draft ABI used by linux instead
152  returns them in memory. */
153  if ((cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8)
154  {
155  flags |= FLAG_RETURNS_SMST;
156  break;
157  }
158  intarg_count++;
159  flags |= FLAG_RETVAL_REFERENCE;
160  /* Fall through. */
161  case FFI_TYPE_VOID:
162  flags |= FLAG_RETURNS_NOTHING;
163  break;
164 
165  default:
166  /* Returns 32-bit integer, or similar. Nothing to do here. */
167  break;
168  }
169 
170  /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
171  first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
172  goes on the stack. Structures and long doubles (if not equivalent
173  to double) are passed as a pointer to a copy of the structure.
174  Stuff on the stack needs to keep proper alignment. */
175  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
176  {
177  unsigned short typenum = (*ptr)->type;
178 
179  typenum = translate_float (cif->abi, typenum);
180 
181  switch (typenum)
182  {
183 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
184  case FFI_TYPE_LONGDOUBLE:
185  fparg_count++;
186  /* Fall thru */
187 #endif
188  case FFI_TYPE_DOUBLE:
189  fparg_count++;
190  /* If this FP arg is going on the stack, it must be
191  8-byte-aligned. */
192  if (fparg_count > NUM_FPR_ARG_REGISTERS
193  && intarg_count >= NUM_GPR_ARG_REGISTERS
194  && intarg_count % 2 != 0)
195  intarg_count++;
196 #ifdef __NO_FPRS__
197  return FFI_BAD_ABI;
198 #endif
199  break;
200 
201  case FFI_TYPE_FLOAT:
202  fparg_count++;
203 #ifdef __NO_FPRS__
204  return FFI_BAD_ABI;
205 #endif
206  break;
207 
208  case FFI_TYPE_UINT128:
209  /* A long double in FFI_LINUX_SOFT_FLOAT can use only a set
210  of four consecutive gprs. If we do not have enough, we
211  have to adjust the intarg_count value. */
212  if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
213  && intarg_count < NUM_GPR_ARG_REGISTERS)
214  intarg_count = NUM_GPR_ARG_REGISTERS;
215  intarg_count += 4;
216  break;
217 
218  case FFI_TYPE_UINT64:
219  case FFI_TYPE_SINT64:
220  /* 'long long' arguments are passed as two words, but
221  either both words must fit in registers or both go
222  on the stack. If they go on the stack, they must
223  be 8-byte-aligned.
224 
225  Also, only certain register pairs can be used for
226  passing long long int -- specifically (r3,r4), (r5,r6),
227  (r7,r8), (r9,r10). */
228  if (intarg_count == NUM_GPR_ARG_REGISTERS-1
229  || intarg_count % 2 != 0)
230  intarg_count++;
231  intarg_count += 2;
232  break;
233 
234  case FFI_TYPE_STRUCT:
235  /* We must allocate space for a copy of these to enforce
236  pass-by-value. Pad the space up to a multiple of 16
237  bytes (the maximum alignment required for anything under
238  the SYSV ABI). */
239  struct_copy_size += ((*ptr)->size + 15) & ~0xF;
240  /* Fall through (allocate space for the pointer). */
241 
242  case FFI_TYPE_POINTER:
243  case FFI_TYPE_INT:
244  case FFI_TYPE_UINT32:
245  case FFI_TYPE_SINT32:
246  case FFI_TYPE_UINT16:
247  case FFI_TYPE_SINT16:
248  case FFI_TYPE_UINT8:
249  case FFI_TYPE_SINT8:
250  /* Everything else is passed as a 4-byte word in a GPR, either
251  the object itself or a pointer to it. */
252  intarg_count++;
253  break;
254 
255  default:
256  FFI_ASSERT (0);
257  }
258  }
259 
260  if (fparg_count != 0)
261  flags |= FLAG_FP_ARGUMENTS;
262  if (intarg_count > 4)
263  flags |= FLAG_4_GPR_ARGUMENTS;
264  if (struct_copy_size != 0)
265  flags |= FLAG_ARG_NEEDS_COPY;
266 
267  /* Space for the FPR registers, if needed. */
268  if (fparg_count != 0)
269  bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
270 
271  /* Stack space. */
272  if (intarg_count > NUM_GPR_ARG_REGISTERS)
273  bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
274  if (fparg_count > NUM_FPR_ARG_REGISTERS)
275  bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
276 
277  /* The stack space allocated needs to be a multiple of 16 bytes. */
278  bytes = (bytes + 15) & ~0xF;
279 
280  /* Add in the space for the copied structures. */
281  bytes += struct_copy_size;
282 
283  cif->flags = flags;
284  cif->bytes = bytes;
285 
286  return FFI_OK;
287 }
288 
289 ffi_status FFI_HIDDEN
290 ffi_prep_cif_sysv (ffi_cif *cif)
291 {
292  if ((cif->abi & FFI_SYSV) == 0)
293  {
294  /* This call is from old code. Translate to new ABI values. */
295  cif->flags |= FLAG_COMPAT;
296  switch (cif->abi)
297  {
298  default:
299  return FFI_BAD_ABI;
300 
301  case FFI_COMPAT_SYSV:
303  break;
304 
305  case FFI_COMPAT_GCC_SYSV:
306  cif->abi = FFI_SYSV | FFI_SYSV_LONG_DOUBLE_128;
307  break;
308 
309  case FFI_COMPAT_LINUX:
310  cif->abi = (FFI_SYSV | FFI_SYSV_IBM_LONG_DOUBLE
312  break;
313 
317  break;
318  }
319  }
320  return ffi_prep_cif_sysv_core (cif);
321 }
322 
323 /* ffi_prep_args_SYSV is called by the assembly routine once stack space
324  has been allocated for the function's arguments.
325 
326  The stack layout we want looks like this:
327 
328  | Return address from ffi_call_SYSV 4bytes | higher addresses
329  |--------------------------------------------|
330  | Previous backchain pointer 4 | stack pointer here
331  |--------------------------------------------|<+ <<< on entry to
332  | Saved r28-r31 4*4 | | ffi_call_SYSV
333  |--------------------------------------------| |
334  | GPR registers r3-r10 8*4 | | ffi_call_SYSV
335  |--------------------------------------------| |
336  | FPR registers f1-f8 (optional) 8*8 | |
337  |--------------------------------------------| | stack |
338  | Space for copied structures | | grows |
339  |--------------------------------------------| | down V
340  | Parameters that didn't fit in registers | |
341  |--------------------------------------------| | lower addresses
342  | Space for callee's LR 4 | |
343  |--------------------------------------------| | stack pointer here
344  | Current backchain pointer 4 |-/ during
345  |--------------------------------------------| <<< ffi_call_SYSV
346 
347 */
348 
349 void FFI_HIDDEN
350 ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
351 {
352  const unsigned bytes = ecif->cif->bytes;
353  const unsigned flags = ecif->cif->flags;
354 
355  typedef union
356  {
357  char *c;
358  unsigned *u;
359  long long *ll;
360  float *f;
361  double *d;
362  } valp;
363 
364  /* 'stacktop' points at the previous backchain pointer. */
365  valp stacktop;
366 
367  /* 'gpr_base' points at the space for gpr3, and grows upwards as
368  we use GPR registers. */
369  valp gpr_base;
370  int intarg_count;
371 
372 #ifndef __NO_FPRS__
373  /* 'fpr_base' points at the space for fpr1, and grows upwards as
374  we use FPR registers. */
375  valp fpr_base;
376  int fparg_count;
377 #endif
378 
379  /* 'copy_space' grows down as we put structures in it. It should
380  stay 16-byte aligned. */
381  valp copy_space;
382 
383  /* 'next_arg' grows up as we put parameters in it. */
384  valp next_arg;
385 
386  int i;
387  ffi_type **ptr;
388 #ifndef __NO_FPRS__
389  double double_tmp;
390 #endif
391  union
392  {
393  void **v;
394  char **c;
395  signed char **sc;
396  unsigned char **uc;
397  signed short **ss;
398  unsigned short **us;
399  unsigned int **ui;
400  long long **ll;
401  float **f;
402  double **d;
403  } p_argv;
404  size_t struct_copy_size;
405  unsigned gprvalue;
406 
407  stacktop.c = (char *) stack + bytes;
408  gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
409  intarg_count = 0;
410 #ifndef __NO_FPRS__
411  fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
412  fparg_count = 0;
413  copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
414 #else
415  copy_space.c = gpr_base.c;
416 #endif
417  next_arg.u = stack + 2;
418 
419  /* Check that everything starts aligned properly. */
420  FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
421  FFI_ASSERT (((unsigned long) copy_space.c & 0xF) == 0);
422  FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
423  FFI_ASSERT ((bytes & 0xF) == 0);
424  FFI_ASSERT (copy_space.c >= next_arg.c);
425 
426  /* Deal with return values that are actually pass-by-reference. */
427  if (flags & FLAG_RETVAL_REFERENCE)
428  {
429  *gpr_base.u++ = (unsigned long) (char *) ecif->rvalue;
430  intarg_count++;
431  }
432 
433  /* Now for the arguments. */
434  p_argv.v = ecif->avalue;
435  for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
436  i > 0;
437  i--, ptr++, p_argv.v++)
438  {
439  unsigned int typenum = (*ptr)->type;
440 
441  typenum = translate_float (ecif->cif->abi, typenum);
442 
443  /* Now test the translated value */
444  switch (typenum)
445  {
446 #ifndef __NO_FPRS__
447 # if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
448  case FFI_TYPE_LONGDOUBLE:
449  double_tmp = (*p_argv.d)[0];
450 
451  if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
452  {
453  if (intarg_count >= NUM_GPR_ARG_REGISTERS
454  && intarg_count % 2 != 0)
455  {
456  intarg_count++;
457  next_arg.u++;
458  }
459  *next_arg.d = double_tmp;
460  next_arg.u += 2;
461  double_tmp = (*p_argv.d)[1];
462  *next_arg.d = double_tmp;
463  next_arg.u += 2;
464  }
465  else
466  {
467  *fpr_base.d++ = double_tmp;
468  double_tmp = (*p_argv.d)[1];
469  *fpr_base.d++ = double_tmp;
470  }
471 
472  fparg_count += 2;
473  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
474  break;
475 # endif
476  case FFI_TYPE_DOUBLE:
477  double_tmp = **p_argv.d;
478 
479  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
480  {
481  if (intarg_count >= NUM_GPR_ARG_REGISTERS
482  && intarg_count % 2 != 0)
483  {
484  intarg_count++;
485  next_arg.u++;
486  }
487  *next_arg.d = double_tmp;
488  next_arg.u += 2;
489  }
490  else
491  *fpr_base.d++ = double_tmp;
492  fparg_count++;
493  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
494  break;
495 
496  case FFI_TYPE_FLOAT:
497  double_tmp = **p_argv.f;
498  if (fparg_count >= NUM_FPR_ARG_REGISTERS)
499  {
500  *next_arg.f = (float) double_tmp;
501  next_arg.u += 1;
502  intarg_count++;
503  }
504  else
505  *fpr_base.d++ = double_tmp;
506  fparg_count++;
507  FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
508  break;
509 #endif /* have FPRs */
510 
511  case FFI_TYPE_UINT128:
512  /* The soft float ABI for long doubles works like this, a long double
513  is passed in four consecutive GPRs if available. A maximum of 2
514  long doubles can be passed in gprs. If we do not have 4 GPRs
515  left, the long double is passed on the stack, 4-byte aligned. */
516  {
517  unsigned int int_tmp;
518  unsigned int ii;
519  if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
520  {
521  if (intarg_count < NUM_GPR_ARG_REGISTERS)
522  intarg_count = NUM_GPR_ARG_REGISTERS;
523  for (ii = 0; ii < 4; ii++)
524  {
525  int_tmp = (*p_argv.ui)[ii];
526  *next_arg.u++ = int_tmp;
527  }
528  }
529  else
530  {
531  for (ii = 0; ii < 4; ii++)
532  {
533  int_tmp = (*p_argv.ui)[ii];
534  *gpr_base.u++ = int_tmp;
535  }
536  }
537  intarg_count += 4;
538  break;
539  }
540 
541  case FFI_TYPE_UINT64:
542  case FFI_TYPE_SINT64:
543  if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
544  intarg_count++;
545  if (intarg_count >= NUM_GPR_ARG_REGISTERS)
546  {
547  if (intarg_count % 2 != 0)
548  {
549  intarg_count++;
550  next_arg.u++;
551  }
552  *next_arg.ll = **p_argv.ll;
553  next_arg.u += 2;
554  }
555  else
556  {
557  /* The abi states only certain register pairs can be
558  used for passing long long int specifically (r3,r4),
559  (r5,r6), (r7,r8), (r9,r10). If next arg is long long
560  but not correct starting register of pair then skip
561  until the proper starting register. */
562  if (intarg_count % 2 != 0)
563  {
564  intarg_count ++;
565  gpr_base.u++;
566  }
567  *gpr_base.ll++ = **p_argv.ll;
568  }
569  intarg_count += 2;
570  break;
571 
572  case FFI_TYPE_STRUCT:
573  struct_copy_size = ((*ptr)->size + 15) & ~0xF;
574  copy_space.c -= struct_copy_size;
575  memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
576 
577  gprvalue = (unsigned long) copy_space.c;
578 
579  FFI_ASSERT (copy_space.c > next_arg.c);
581  goto putgpr;
582 
583  case FFI_TYPE_UINT8:
584  gprvalue = **p_argv.uc;
585  goto putgpr;
586  case FFI_TYPE_SINT8:
587  gprvalue = **p_argv.sc;
588  goto putgpr;
589  case FFI_TYPE_UINT16:
590  gprvalue = **p_argv.us;
591  goto putgpr;
592  case FFI_TYPE_SINT16:
593  gprvalue = **p_argv.ss;
594  goto putgpr;
595 
596  case FFI_TYPE_INT:
597  case FFI_TYPE_UINT32:
598  case FFI_TYPE_SINT32:
599  case FFI_TYPE_POINTER:
600 
601  gprvalue = **p_argv.ui;
602 
603  putgpr:
604  if (intarg_count >= NUM_GPR_ARG_REGISTERS)
605  *next_arg.u++ = gprvalue;
606  else
607  *gpr_base.u++ = gprvalue;
608  intarg_count++;
609  break;
610  }
611  }
612 
613  /* Check that we didn't overrun the stack... */
614  FFI_ASSERT (copy_space.c >= next_arg.c);
615  FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
616  /* The assert below is testing that the number of integer arguments agrees
617  with the number found in ffi_prep_cif_machdep(). However, intarg_count
618  is incremented whenever we place an FP arg on the stack, so account for
619  that before our assert test. */
620 #ifndef __NO_FPRS__
621  if (fparg_count > NUM_FPR_ARG_REGISTERS)
622  intarg_count -= fparg_count - NUM_FPR_ARG_REGISTERS;
623  FFI_ASSERT (fpr_base.u
624  <= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
625 #endif
626  FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
627 }
628 
629 #define MIN_CACHE_LINE_SIZE 8
630 
631 static void
632 flush_icache (char *wraddr, char *xaddr, int size)
633 {
634  int i;
635  for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
636  __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
637  : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
638  __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
639  : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
640  : "memory");
641 }
642 
643 ffi_status FFI_HIDDEN
644 ffi_prep_closure_loc_sysv (ffi_closure *closure,
645  ffi_cif *cif,
646  void (*fun) (ffi_cif *, void *, void **, void *),
647  void *user_data,
648  void *codeloc)
649 {
650  unsigned int *tramp;
651 
652  if (cif->abi < FFI_SYSV || cif->abi >= FFI_LAST_ABI)
653  return FFI_BAD_ABI;
654 
655  tramp = (unsigned int *) &closure->tramp[0];
656  tramp[0] = 0x7c0802a6; /* mflr r0 */
657  tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
658  tramp[4] = 0x7d6802a6; /* mflr r11 */
659  tramp[5] = 0x7c0803a6; /* mtlr r0 */
660  tramp[6] = 0x800b0000; /* lwz r0,0(r11) */
661  tramp[7] = 0x816b0004; /* lwz r11,4(r11) */
662  tramp[8] = 0x7c0903a6; /* mtctr r0 */
663  tramp[9] = 0x4e800420; /* bctr */
664  *(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
665  *(void **) &tramp[3] = codeloc; /* context */
666 
667  /* Flush the icache. */
668  flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
669 
670  closure->cif = cif;
671  closure->fun = fun;
672  closure->user_data = user_data;
673 
674  return FFI_OK;
675 }
676 
677 /* Basically the trampoline invokes ffi_closure_SYSV, and on
678  entry, r11 holds the address of the closure.
679  After storing the registers that could possibly contain
680  parameters to be passed into the stack frame and setting
681  up space for a return value, ffi_closure_SYSV invokes the
682  following helper function to do most of the work. */
683 
684 int
685 ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
686  unsigned long *pgr, ffi_dblfl *pfr,
687  unsigned long *pst)
688 {
689  /* rvalue is the pointer to space for return value in closure assembly */
690  /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
691  /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */
692  /* pst is the pointer to outgoing parameter stack in original caller */
693 
694  void ** avalue;
695  ffi_type ** arg_types;
696  long i, avn;
697 #ifndef __NO_FPRS__
698  long nf = 0; /* number of floating registers already used */
699 #endif
700  long ng = 0; /* number of general registers already used */
701 
702  ffi_cif *cif = closure->cif;
703  unsigned size = cif->rtype->size;
704  unsigned short rtypenum = cif->rtype->type;
705 
706  avalue = alloca (cif->nargs * sizeof (void *));
707 
708  /* First translate for softfloat/nonlinux */
709  rtypenum = translate_float (cif->abi, rtypenum);
710 
711  /* Copy the caller's structure return value address so that the closure
712  returns the data directly to the caller.
713  For FFI_SYSV the result is passed in r3/r4 if the struct size is less
714  or equal 8 bytes. */
715  if (rtypenum == FFI_TYPE_STRUCT
716  && !((cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8))
717  {
718  rvalue = (void *) *pgr;
719  ng++;
720  pgr++;
721  }
722 
723  i = 0;
724  avn = cif->nargs;
725  arg_types = cif->arg_types;
726 
727  /* Grab the addresses of the arguments from the stack frame. */
728  while (i < avn) {
729  unsigned short typenum = arg_types[i]->type;
730 
731  /* We may need to handle some values depending on ABI. */
732  typenum = translate_float (cif->abi, typenum);
733 
734  switch (typenum)
735  {
736 #ifndef __NO_FPRS__
737  case FFI_TYPE_FLOAT:
738  /* Unfortunately float values are stored as doubles
739  in the ffi_closure_SYSV code (since we don't check
740  the type in that routine). */
741  if (nf < NUM_FPR_ARG_REGISTERS)
742  {
743  /* FIXME? here we are really changing the values
744  stored in the original calling routines outgoing
745  parameter stack. This is probably a really
746  naughty thing to do but... */
747  double temp = pfr->d;
748  pfr->f = (float) temp;
749  avalue[i] = pfr;
750  nf++;
751  pfr++;
752  }
753  else
754  {
755  avalue[i] = pst;
756  pst += 1;
757  }
758  break;
759 
760  case FFI_TYPE_DOUBLE:
761  if (nf < NUM_FPR_ARG_REGISTERS)
762  {
763  avalue[i] = pfr;
764  nf++;
765  pfr++;
766  }
767  else
768  {
769  if (((long) pst) & 4)
770  pst++;
771  avalue[i] = pst;
772  pst += 2;
773  }
774  break;
775 
776 # if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
777  case FFI_TYPE_LONGDOUBLE:
778  if (nf < NUM_FPR_ARG_REGISTERS - 1)
779  {
780  avalue[i] = pfr;
781  pfr += 2;
782  nf += 2;
783  }
784  else
785  {
786  if (((long) pst) & 4)
787  pst++;
788  avalue[i] = pst;
789  pst += 4;
790  nf = 8;
791  }
792  break;
793 # endif
794 #endif
795 
796  case FFI_TYPE_UINT128:
797  /* Test if for the whole long double, 4 gprs are available.
798  otherwise the stuff ends up on the stack. */
799  if (ng < NUM_GPR_ARG_REGISTERS - 3)
800  {
801  avalue[i] = pgr;
802  pgr += 4;
803  ng += 4;
804  }
805  else
806  {
807  avalue[i] = pst;
808  pst += 4;
809  ng = 8+4;
810  }
811  break;
812 
813  case FFI_TYPE_SINT8:
814  case FFI_TYPE_UINT8:
815 #ifndef __LITTLE_ENDIAN__
816  if (ng < NUM_GPR_ARG_REGISTERS)
817  {
818  avalue[i] = (char *) pgr + 3;
819  ng++;
820  pgr++;
821  }
822  else
823  {
824  avalue[i] = (char *) pst + 3;
825  pst++;
826  }
827  break;
828 #endif
829 
830  case FFI_TYPE_SINT16:
831  case FFI_TYPE_UINT16:
832 #ifndef __LITTLE_ENDIAN__
833  if (ng < NUM_GPR_ARG_REGISTERS)
834  {
835  avalue[i] = (char *) pgr + 2;
836  ng++;
837  pgr++;
838  }
839  else
840  {
841  avalue[i] = (char *) pst + 2;
842  pst++;
843  }
844  break;
845 #endif
846 
847  case FFI_TYPE_SINT32:
848  case FFI_TYPE_UINT32:
849  case FFI_TYPE_POINTER:
850  if (ng < NUM_GPR_ARG_REGISTERS)
851  {
852  avalue[i] = pgr;
853  ng++;
854  pgr++;
855  }
856  else
857  {
858  avalue[i] = pst;
859  pst++;
860  }
861  break;
862 
863  case FFI_TYPE_STRUCT:
864  /* Structs are passed by reference. The address will appear in a
865  gpr if it is one of the first 8 arguments. */
866  if (ng < NUM_GPR_ARG_REGISTERS)
867  {
868  avalue[i] = (void *) *pgr;
869  ng++;
870  pgr++;
871  }
872  else
873  {
874  avalue[i] = (void *) *pst;
875  pst++;
876  }
877  break;
878 
879  case FFI_TYPE_SINT64:
880  case FFI_TYPE_UINT64:
881  /* Passing long long ints are complex, they must
882  be passed in suitable register pairs such as
883  (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
884  and if the entire pair aren't available then the outgoing
885  parameter stack is used for both but an alignment of 8
886  must will be kept. So we must either look in pgr
887  or pst to find the correct address for this type
888  of parameter. */
889  if (ng < NUM_GPR_ARG_REGISTERS - 1)
890  {
891  if (ng & 1)
892  {
893  /* skip r4, r6, r8 as starting points */
894  ng++;
895  pgr++;
896  }
897  avalue[i] = pgr;
898  ng += 2;
899  pgr += 2;
900  }
901  else
902  {
903  if (((long) pst) & 4)
904  pst++;
905  avalue[i] = pst;
906  pst += 2;
908  }
909  break;
910 
911  default:
912  FFI_ASSERT (0);
913  }
914 
915  i++;
916  }
917 
918  (closure->fun) (cif, rvalue, avalue, closure->user_data);
919 
920  /* Tell ffi_closure_SYSV how to perform return type promotions.
921  Because the FFI_SYSV ABI returns the structures <= 8 bytes in
922  r3/r4 we have to tell ffi_closure_SYSV how to treat them. We
923  combine the base type FFI_SYSV_TYPE_SMALL_STRUCT with the size of
924  the struct less one. We never have a struct with size zero.
925  See the comment in ffitarget.h about ordering. */
926  if (rtypenum == FFI_TYPE_STRUCT
927  && (cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8)
928  return FFI_SYSV_TYPE_SMALL_STRUCT - 1 + size;
929  return rtypenum;
930 }
931 #endif
FFI_SYSV_SOFT_FLOAT
@ FFI_SYSV_SOFT_FLOAT
Definition: ffitarget.h:109
MIN_CACHE_LINE_SIZE
#define MIN_CACHE_LINE_SIZE
Definition: ffi_sysv.c:629
FFI_COMPAT_LINUX
@ FFI_COMPAT_LINUX
Definition: ffitarget.h:82
FFI_ASSERT
#define FFI_ASSERT(x)
Definition: ffi_common.h:72
FFI_TYPE_UINT128
#define FFI_TYPE_UINT128
Definition: ffitarget.h:149
ffi_dblfl::d
double d
Definition: ffi_darwin.c:1104
ffi_closure_helper_SYSV
int ffi_closure_helper_SYSV(ffi_closure *closure, void *rvalue, unsigned long *pgr, ffi_dblfl *pfr, unsigned long *pst)
Definition: ffi_sysv.c:685
FFI_TYPE_LONGDOUBLE
#define FFI_TYPE_LONGDOUBLE
Definition: ffi.c:40
ffi_abi
ffi_abi
Definition: ffitarget.h:34
extended_cif::rvalue
void * rvalue
Definition: ffi_common.h:89
int
__inline__ int
Definition: rb_mjit_min_header-2.7.2.h:2877
i
uint32_t i
Definition: rb_mjit_min_header-2.7.2.h:5499
ffi_prep_args_SYSV
void FFI_HIDDEN ffi_prep_args_SYSV(extended_cif *ecif, unsigned *const stack)
Definition: ffi_sysv.c:350
FLAG_COMPAT
@ FLAG_COMPAT
Definition: ffi_powerpc.h:42
long
#define long
Definition: rb_mjit_min_header-2.7.2.h:2921
FLAG_4_GPR_ARGUMENTS
@ FLAG_4_GPR_ARGUMENTS
Definition: ffi_darwin.c:52
ffi_common.h
FFI_HIDDEN
const UINT64 ffi_template_tramp_tile[] FFI_HIDDEN
FFI_SYSV_STRUCT_RET
@ FFI_SYSV_STRUCT_RET
Definition: ffitarget.h:110
NUM_FPR_ARG_REGISTERS
#define NUM_FPR_ARG_REGISTERS
Definition: ffi_sysv.c:41
FFI_TRAMPOLINE_SIZE
#define FFI_TRAMPOLINE_SIZE
Definition: ffitarget.h:45
alloca
#define alloca(size)
Definition: rb_mjit_min_header-2.7.2.h:2525
FFI_SYSV
@ FFI_SYSV
Definition: ffitarget.h:36
ptr
struct RIMemo * ptr
Definition: debug.c:65
FFI_COMPAT_GCC_SYSV
@ FFI_COMPAT_GCC_SYSV
Definition: ffitarget.h:80
FLAG_RETURNS_FP
@ FLAG_RETURNS_FP
Definition: ffi_darwin.c:45
FLAG_FP_ARGUMENTS
@ FLAG_FP_ARGUMENTS
Definition: ffi_darwin.c:51
FLAG_ARG_NEEDS_COPY
@ FLAG_ARG_NEEDS_COPY
Definition: ffi_darwin.c:50
ffi_dblfl::f
float f
Definition: ffi_darwin.c:1103
NUM_GPR_ARG_REGISTERS
#define NUM_GPR_ARG_REGISTERS
Definition: ffi_sysv.c:40
FFI_COMPAT_SYSV
@ FFI_COMPAT_SYSV
Definition: ffitarget.h:79
FLAG_RETVAL_REFERENCE
@ FLAG_RETVAL_REFERENCE
Definition: ffi_darwin.c:53
FFI_COMPAT_LINUX_SOFT_FLOAT
@ FFI_COMPAT_LINUX_SOFT_FLOAT
Definition: ffitarget.h:83
FFI_LAST_ABI
@ FFI_LAST_ABI
Definition: ffitarget.h:37
FFI_SYSV_TYPE_SMALL_STRUCT
#define FFI_SYSV_TYPE_SMALL_STRUCT
Definition: ffitarget.h:152
ffi_prep_cif_sysv
ffi_status FFI_HIDDEN ffi_prep_cif_sysv(ffi_cif *cif)
Definition: ffi_sysv.c:290
size
int size
Definition: encoding.c:58
extended_cif
Definition: ffi_common.h:87
FLAG_RETURNS_64BITS
@ FLAG_RETURNS_64BITS
Definition: ffi_darwin.c:46
FLAG_RETURNS_SMST
@ FLAG_RETURNS_SMST
Definition: ffi_powerpc.h:34
ffi_closure_SYSV
void ffi_closure_SYSV(ffi_closure *)
Definition: ffi.c:420
FFI_SYSV_IBM_LONG_DOUBLE
@ FFI_SYSV_IBM_LONG_DOUBLE
Definition: ffitarget.h:111
ffi_powerpc.h
f
#define f
ASM_NEEDS_REGISTERS
#define ASM_NEEDS_REGISTERS
Definition: ffi_sysv.c:39
extended_cif::avalue
void ** avalue
Definition: ffi_common.h:90
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
ffi_prep_closure_loc_sysv
ffi_status FFI_HIDDEN ffi_prep_closure_loc_sysv(ffi_closure *closure, ffi_cif *cif, void(*fun)(ffi_cif *, void *, void **, void *), void *user_data, void *codeloc)
Definition: ffi_sysv.c:644
__asm__
#define __asm__
Definition: Context.c:12
ffi_dblfl
Definition: ffi_darwin.c:1102
FFI_SYSV_LONG_DOUBLE_128
@ FFI_SYSV_LONG_DOUBLE_128
Definition: ffitarget.h:112
v
int VALUE v
Definition: rb_mjit_min_header-2.7.2.h:12380
FLAG_RETURNS_128BITS
@ FLAG_RETURNS_128BITS
Definition: ffi_darwin.c:43
FLAG_RETURNS_NOTHING
@ FLAG_RETURNS_NOTHING
Definition: ffi_darwin.c:44
extended_cif::cif
ffi_cif * cif
Definition: ffi_common.h:88
double
double
Definition: rb_mjit_min_header-2.7.2.h:5958
ffi_prep_types_sysv
void FFI_HIDDEN ffi_prep_types_sysv(ffi_abi)
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39