Ruby  2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
ffi.c
Go to the documentation of this file.
1 /* -----------------------------------------------------------------------
2  ffi.c - (c) 2011 Anthony Green
3  (c) 2008 Red Hat, Inc.
4  (c) 2006 Free Software Foundation, Inc.
5  (c) 2003-2004 Randolph Chung <tausq@debian.org>
6 
7  HPPA Foreign Function Interface
8  HP-UX PA ABI support
9 
10  Permission is hereby granted, free of charge, to any person obtaining
11  a copy of this software and associated documentation files (the
12  ``Software''), to deal in the Software without restriction, including
13  without limitation the rights to use, copy, modify, merge, publish,
14  distribute, sublicense, and/or sell copies of the Software, and to
15  permit persons to whom the Software is furnished to do so, subject to
16  the following conditions:
17 
18  The above copyright notice and this permission notice shall be included
19  in all copies or substantial portions of the Software.
20 
21  THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
22  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  DEALINGS IN THE SOFTWARE.
29  ----------------------------------------------------------------------- */
30 
31 #include <ffi.h>
32 #include <ffi_common.h>
33 
34 #include <stdlib.h>
35 #include <stdio.h>
36 
37 #define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
38 
39 #define MIN_STACK_SIZE 64
40 #define FIRST_ARG_SLOT 9
41 #define DEBUG_LEVEL 0
42 
43 #define fldw(addr, fpreg) \
44  __asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
45 #define fstw(fpreg, addr) \
46  __asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
47 #define fldd(addr, fpreg) \
48  __asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
49 #define fstd(fpreg, addr) \
50  __asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
51 
52 #define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
53 
54 static inline int ffi_struct_type(ffi_type *t)
55 {
56  size_t sz = t->size;
57 
58  /* Small structure results are passed in registers,
59  larger ones are passed by pointer. Note that
60  small structures of size 2, 4 and 8 differ from
61  the corresponding integer types in that they have
62  different alignment requirements. */
63 
64  if (sz <= 1)
65  return FFI_TYPE_UINT8;
66  else if (sz == 2)
68  else if (sz == 3)
70  else if (sz == 4)
72  else if (sz == 5)
74  else if (sz == 6)
76  else if (sz == 7)
78  else if (sz <= 8)
80  else
81  return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */
82 }
83 
84 /* PA has a downward growing stack, which looks like this:
85 
86  Offset
87  [ Variable args ]
88  SP = (4*(n+9)) arg word N
89  ...
90  SP-52 arg word 4
91  [ Fixed args ]
92  SP-48 arg word 3
93  SP-44 arg word 2
94  SP-40 arg word 1
95  SP-36 arg word 0
96  [ Frame marker ]
97  ...
98  SP-20 RP
99  SP-4 previous SP
100 
101  The first four argument words on the stack are reserved for use by
102  the callee. Instead, the general and floating registers replace
103  the first four argument slots. Non FP arguments are passed solely
104  in the general registers. FP arguments are passed in both general
105  and floating registers when using libffi.
106 
107  Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23.
108  Non-FP 64-bit args are passed in register pairs, starting
109  on an odd numbered register (i.e. r25+r26 and r23+r24).
110  FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L.
111  FP 64-bit arguments are passed in fr5 and fr7.
112 
113  The registers are allocated in the same manner as stack slots.
114  This allows the callee to save its arguments on the stack if
115  necessary:
116 
117  arg word 3 -> gr23 or fr7L
118  arg word 2 -> gr24 or fr6L or fr7R
119  arg word 1 -> gr25 or fr5L
120  arg word 0 -> gr26 or fr4L or fr5R
121 
122  Note that fr4R and fr6R are never used for arguments (i.e.,
123  doubles are not passed in fr4 or fr6).
124 
125  The rest of the arguments are passed on the stack starting at SP-52,
126  but 64-bit arguments need to be aligned to an 8-byte boundary
127 
128  This means we can have holes either in the register allocation,
129  or in the stack. */
130 
131 /* ffi_prep_args is called by the assembly routine once stack space
132  has been allocated for the function's arguments
133 
134  The following code will put everything into the stack frame
135  (which was allocated by the asm routine), and on return
136  the asm routine will load the arguments that should be
137  passed by register into the appropriate registers
138 
139  NOTE: We load floating point args in this function... that means we
140  assume gcc will not mess with fp regs in here. */
141 
142 void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
143 {
144  register unsigned int i;
145  register ffi_type **p_arg;
146  register void **p_argv;
147  unsigned int slot = FIRST_ARG_SLOT;
148  char *dest_cpy;
149  size_t len;
150 
151  debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
152  ecif, bytes);
153 
154  p_arg = ecif->cif->arg_types;
155  p_argv = ecif->avalue;
156 
157  for (i = 0; i < ecif->cif->nargs; i++)
158  {
159  int type = (*p_arg)->type;
160 
161  switch (type)
162  {
163  case FFI_TYPE_SINT8:
164  *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
165  break;
166 
167  case FFI_TYPE_UINT8:
168  *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
169  break;
170 
171  case FFI_TYPE_SINT16:
172  *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
173  break;
174 
175  case FFI_TYPE_UINT16:
176  *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
177  break;
178 
179  case FFI_TYPE_UINT32:
180  case FFI_TYPE_SINT32:
181  case FFI_TYPE_POINTER:
182  debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
183  slot);
184  *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
185  break;
186 
187  case FFI_TYPE_UINT64:
188  case FFI_TYPE_SINT64:
189  /* Align slot for 64-bit type. */
190  slot += (slot & 1) ? 1 : 2;
191  *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
192  break;
193 
194  case FFI_TYPE_FLOAT:
195  /* First 4 args go in fr4L - fr7L. */
196  debug(3, "Storing UINT32(float) in slot %u\n", slot);
197  *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
198  switch (slot - FIRST_ARG_SLOT)
199  {
200  /* First 4 args go in fr4L - fr7L. */
201  case 0: fldw(stack - slot, fr4); break;
202  case 1: fldw(stack - slot, fr5); break;
203  case 2: fldw(stack - slot, fr6); break;
204  case 3: fldw(stack - slot, fr7); break;
205  }
206  break;
207 
208  case FFI_TYPE_DOUBLE:
209  /* Align slot for 64-bit type. */
210  slot += (slot & 1) ? 1 : 2;
211  debug(3, "Storing UINT64(double) at slot %u\n", slot);
212  *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
213  switch (slot - FIRST_ARG_SLOT)
214  {
215  /* First 2 args go in fr5, fr7. */
216  case 1: fldd(stack - slot, fr5); break;
217  case 3: fldd(stack - slot, fr7); break;
218  }
219  break;
220 
221 #ifdef PA_HPUX
222  case FFI_TYPE_LONGDOUBLE:
223  /* Long doubles are passed in the same manner as structures
224  larger than 8 bytes. */
225  *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
226  break;
227 #endif
228 
229  case FFI_TYPE_STRUCT:
230 
231  /* Structs smaller or equal than 4 bytes are passed in one
232  register. Structs smaller or equal 8 bytes are passed in two
233  registers. Larger structures are passed by pointer. */
234 
235  len = (*p_arg)->size;
236  if (len <= 4)
237  {
238  dest_cpy = (char *)(stack - slot) + 4 - len;
239  memcpy(dest_cpy, (char *)*p_argv, len);
240  }
241  else if (len <= 8)
242  {
243  slot += (slot & 1) ? 1 : 2;
244  dest_cpy = (char *)(stack - slot) + 8 - len;
245  memcpy(dest_cpy, (char *)*p_argv, len);
246  }
247  else
248  *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
249  break;
250 
251  default:
252  FFI_ASSERT(0);
253  }
254 
255  slot++;
256  p_arg++;
257  p_argv++;
258  }
259 
260  /* Make sure we didn't mess up and scribble on the stack. */
261  {
262  unsigned int n;
263 
264  debug(5, "Stack setup:\n");
265  for (n = 0; n < (bytes + 3) / 4; n++)
266  {
267  if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
268  debug(5, "%08x ", *(stack - n));
269  }
270  debug(5, "\n");
271  }
272 
273  FFI_ASSERT(slot * 4 <= bytes);
274 
275  return;
276 }
277 
278 static void ffi_size_stack_pa32(ffi_cif *cif)
279 {
280  ffi_type **ptr;
281  int i;
282  int z = 0; /* # stack slots */
283 
284  for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
285  {
286  int type = (*ptr)->type;
287 
288  switch (type)
289  {
290  case FFI_TYPE_DOUBLE:
291  case FFI_TYPE_UINT64:
292  case FFI_TYPE_SINT64:
293  z += 2 + (z & 1); /* must start on even regs, so we may waste one */
294  break;
295 
296 #ifdef PA_HPUX
297  case FFI_TYPE_LONGDOUBLE:
298 #endif
299  case FFI_TYPE_STRUCT:
300  z += 1; /* pass by ptr, callee will copy */
301  break;
302 
303  default: /* <= 32-bit values */
304  z++;
305  }
306  }
307 
308  /* We can fit up to 6 args in the default 64-byte stack frame,
309  if we need more, we need more stack. */
310  if (z <= 6)
311  cif->bytes = MIN_STACK_SIZE; /* min stack size */
312  else
313  cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
314 
315  debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
316 }
317 
318 /* Perform machine dependent cif processing. */
319 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
320 {
321  /* Set the return type flag */
322  switch (cif->rtype->type)
323  {
324  case FFI_TYPE_VOID:
325  case FFI_TYPE_FLOAT:
326  case FFI_TYPE_DOUBLE:
327  cif->flags = (unsigned) cif->rtype->type;
328  break;
329 
330 #ifdef PA_HPUX
331  case FFI_TYPE_LONGDOUBLE:
332  /* Long doubles are treated like a structure. */
333  cif->flags = FFI_TYPE_STRUCT;
334  break;
335 #endif
336 
337  case FFI_TYPE_STRUCT:
338  /* For the return type we have to check the size of the structures.
339  If the size is smaller or equal 4 bytes, the result is given back
340  in one register. If the size is smaller or equal 8 bytes than we
341  return the result in two registers. But if the size is bigger than
342  8 bytes, we work with pointers. */
343  cif->flags = ffi_struct_type(cif->rtype);
344  break;
345 
346  case FFI_TYPE_UINT64:
347  case FFI_TYPE_SINT64:
348  cif->flags = FFI_TYPE_UINT64;
349  break;
350 
351  default:
352  cif->flags = FFI_TYPE_INT;
353  break;
354  }
355 
356  /* Lucky us, because of the unique PA ABI we get to do our
357  own stack sizing. */
358  switch (cif->abi)
359  {
360  case FFI_PA32:
361  ffi_size_stack_pa32(cif);
362  break;
363 
364  default:
365  FFI_ASSERT(0);
366  break;
367  }
368 
369  return FFI_OK;
370 }
371 
372 extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
373  extended_cif *, unsigned, unsigned, unsigned *,
374  void (*fn)(void));
375 
376 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
377 {
378  extended_cif ecif;
379 
380  ecif.cif = cif;
381  ecif.avalue = avalue;
382 
383  /* If the return value is a struct and we don't have a return
384  value address then we need to make one. */
385 
386  if (rvalue == NULL
387 #ifdef PA_HPUX
388  && (cif->rtype->type == FFI_TYPE_STRUCT
389  || cif->rtype->type == FFI_TYPE_LONGDOUBLE))
390 #else
391  && cif->rtype->type == FFI_TYPE_STRUCT)
392 #endif
393  {
394  ecif.rvalue = alloca(cif->rtype->size);
395  }
396  else
397  ecif.rvalue = rvalue;
398 
399 
400  switch (cif->abi)
401  {
402  case FFI_PA32:
403  debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
404  ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
405  cif->flags, ecif.rvalue, fn);
406  break;
407 
408  default:
409  FFI_ASSERT(0);
410  break;
411  }
412 }
413 
414 #if FFI_CLOSURES
415 /* This is more-or-less an inverse of ffi_call -- we have arguments on
416  the stack, and we need to fill them into a cif structure and invoke
417  the user function. This really ought to be in asm to make sure
418  the compiler doesn't do things we don't expect. */
419 ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
420 {
421  ffi_cif *cif;
422  void **avalue;
423  void *rvalue;
424  UINT32 ret[2]; /* function can return up to 64-bits in registers */
425  ffi_type **p_arg;
426  char *tmp;
427  int i, avn;
428  unsigned int slot = FIRST_ARG_SLOT;
429  register UINT32 r28 asm("r28");
430 
431  cif = closure->cif;
432 
433  /* If returning via structure, callee will write to our pointer. */
434  if (cif->flags == FFI_TYPE_STRUCT)
435  rvalue = (void *)r28;
436  else
437  rvalue = &ret[0];
438 
439  avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
440  avn = cif->nargs;
441  p_arg = cif->arg_types;
442 
443  for (i = 0; i < avn; i++)
444  {
445  int type = (*p_arg)->type;
446 
447  switch (type)
448  {
449  case FFI_TYPE_SINT8:
450  case FFI_TYPE_UINT8:
451  case FFI_TYPE_SINT16:
452  case FFI_TYPE_UINT16:
453  case FFI_TYPE_SINT32:
454  case FFI_TYPE_UINT32:
455  case FFI_TYPE_POINTER:
456  avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
457  break;
458 
459  case FFI_TYPE_SINT64:
460  case FFI_TYPE_UINT64:
461  slot += (slot & 1) ? 1 : 2;
462  avalue[i] = (void *)(stack - slot);
463  break;
464 
465  case FFI_TYPE_FLOAT:
466 #ifdef PA_LINUX
467  /* The closure call is indirect. In Linux, floating point
468  arguments in indirect calls with a prototype are passed
469  in the floating point registers instead of the general
470  registers. So, we need to replace what was previously
471  stored in the current slot with the value in the
472  corresponding floating point register. */
473  switch (slot - FIRST_ARG_SLOT)
474  {
475  case 0: fstw(fr4, (void *)(stack - slot)); break;
476  case 1: fstw(fr5, (void *)(stack - slot)); break;
477  case 2: fstw(fr6, (void *)(stack - slot)); break;
478  case 3: fstw(fr7, (void *)(stack - slot)); break;
479  }
480 #endif
481  avalue[i] = (void *)(stack - slot);
482  break;
483 
484  case FFI_TYPE_DOUBLE:
485  slot += (slot & 1) ? 1 : 2;
486 #ifdef PA_LINUX
487  /* See previous comment for FFI_TYPE_FLOAT. */
488  switch (slot - FIRST_ARG_SLOT)
489  {
490  case 1: fstd(fr5, (void *)(stack - slot)); break;
491  case 3: fstd(fr7, (void *)(stack - slot)); break;
492  }
493 #endif
494  avalue[i] = (void *)(stack - slot);
495  break;
496 
497 #ifdef PA_HPUX
498  case FFI_TYPE_LONGDOUBLE:
499  /* Long doubles are treated like a big structure. */
500  avalue[i] = (void *) *(stack - slot);
501  break;
502 #endif
503 
504  case FFI_TYPE_STRUCT:
505  /* Structs smaller or equal than 4 bytes are passed in one
506  register. Structs smaller or equal 8 bytes are passed in two
507  registers. Larger structures are passed by pointer. */
508  if((*p_arg)->size <= 4)
509  {
510  avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
511  (*p_arg)->size;
512  }
513  else if ((*p_arg)->size <= 8)
514  {
515  slot += (slot & 1) ? 1 : 2;
516  avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
517  (*p_arg)->size;
518  }
519  else
520  avalue[i] = (void *) *(stack - slot);
521  break;
522 
523  default:
524  FFI_ASSERT(0);
525  }
526 
527  slot++;
528  p_arg++;
529  }
530 
531  /* Invoke the closure. */
532  (closure->fun) (cif, rvalue, avalue, closure->user_data);
533 
534  debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
535  ret[1]);
536 
537  /* Store the result using the lower 2 bytes of the flags. */
538  switch (cif->flags)
539  {
540  case FFI_TYPE_UINT8:
541  *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);
542  break;
543  case FFI_TYPE_SINT8:
544  *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);
545  break;
546  case FFI_TYPE_UINT16:
547  *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);
548  break;
549  case FFI_TYPE_SINT16:
550  *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);
551  break;
552  case FFI_TYPE_INT:
553  case FFI_TYPE_SINT32:
554  case FFI_TYPE_UINT32:
555  *(stack - FIRST_ARG_SLOT) = ret[0];
556  break;
557  case FFI_TYPE_SINT64:
558  case FFI_TYPE_UINT64:
559  *(stack - FIRST_ARG_SLOT) = ret[0];
560  *(stack - FIRST_ARG_SLOT - 1) = ret[1];
561  break;
562 
563  case FFI_TYPE_DOUBLE:
564  fldd(rvalue, fr4);
565  break;
566 
567  case FFI_TYPE_FLOAT:
568  fldw(rvalue, fr4);
569  break;
570 
571  case FFI_TYPE_STRUCT:
572  /* Don't need a return value, done by caller. */
573  break;
574 
578  tmp = (void*)(stack - FIRST_ARG_SLOT);
579  tmp += 4 - cif->rtype->size;
580  memcpy((void*)tmp, &ret[0], cif->rtype->size);
581  break;
582 
587  {
588  unsigned int ret2[2];
589  int off;
590 
591  /* Right justify ret[0] and ret[1] */
592  switch (cif->flags)
593  {
594  case FFI_TYPE_SMALL_STRUCT5: off = 3; break;
595  case FFI_TYPE_SMALL_STRUCT6: off = 2; break;
596  case FFI_TYPE_SMALL_STRUCT7: off = 1; break;
597  default: off = 0; break;
598  }
599 
600  memset (ret2, 0, sizeof (ret2));
601  memcpy ((char *)ret2 + off, ret, 8 - off);
602 
603  *(stack - FIRST_ARG_SLOT) = ret2[0];
604  *(stack - FIRST_ARG_SLOT - 1) = ret2[1];
605  }
606  break;
607 
608  case FFI_TYPE_POINTER:
609  case FFI_TYPE_VOID:
610  break;
611 
612  default:
613  debug(0, "assert with cif->flags: %d\n",cif->flags);
614  FFI_ASSERT(0);
615  break;
616  }
617  return FFI_OK;
618 }
619 
620 /* Fill in a closure to refer to the specified fun and user_data.
621  cif specifies the argument and result types for fun.
622  The cif must already be prep'ed. */
623 
624 extern void ffi_closure_pa32(void);
625 
626 ffi_status
627 ffi_prep_closure_loc (ffi_closure* closure,
628  ffi_cif* cif,
629  void (*fun)(ffi_cif*,void*,void**,void*),
630  void *user_data,
631  void *codeloc)
632 {
633  UINT32 *tramp = (UINT32 *)(closure->tramp);
634 #ifdef PA_HPUX
635  UINT32 *tmp;
636 #endif
637 
638  if (cif->abi != FFI_PA32)
639  return FFI_BAD_ABI;
640 
641  /* Make a small trampoline that will branch to our
642  handler function. Use PC-relative addressing. */
643 
644 #ifdef PA_LINUX
645  tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
646  tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
647  tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */
648  tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
649  tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
650  tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */
651  tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
652  tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
653 
654  /* Flush d/icache -- have to flush up 2 two lines because of
655  alignment. */
656  __asm__ volatile(
657  "fdc 0(%0)\n\t"
658  "fdc %1(%0)\n\t"
659  "fic 0(%%sr4, %0)\n\t"
660  "fic %1(%%sr4, %0)\n\t"
661  "sync\n\t"
662  "nop\n\t"
663  "nop\n\t"
664  "nop\n\t"
665  "nop\n\t"
666  "nop\n\t"
667  "nop\n\t"
668  "nop\n"
669  :
670  : "r"((unsigned long)tramp & ~31),
671  "r"(32 /* stride */)
672  : "memory");
673 #endif
674 
675 #ifdef PA_HPUX
676  tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */
677  tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */
678  tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */
679  tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */
680  tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */
681  tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */
682  tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */
683  tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */
684  tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */
685  tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
686 
687  /* Flush d/icache -- have to flush three lines because of alignment. */
688  __asm__ volatile(
689  "copy %1,%0\n\t"
690  "fdc,m %2(%0)\n\t"
691  "fdc,m %2(%0)\n\t"
692  "fdc,m %2(%0)\n\t"
693  "ldsid (%1),%0\n\t"
694  "mtsp %0,%%sr0\n\t"
695  "copy %1,%0\n\t"
696  "fic,m %2(%%sr0,%0)\n\t"
697  "fic,m %2(%%sr0,%0)\n\t"
698  "fic,m %2(%%sr0,%0)\n\t"
699  "sync\n\t"
700  "nop\n\t"
701  "nop\n\t"
702  "nop\n\t"
703  "nop\n\t"
704  "nop\n\t"
705  "nop\n\t"
706  "nop\n"
707  : "=&r" ((unsigned long)tmp)
708  : "r" ((unsigned long)tramp & ~31),
709  "r" (32/* stride */)
710  : "memory");
711 #endif
712 
713  closure->cif = cif;
714  closure->user_data = user_data;
715  closure->fun = fun;
716 
717  return FFI_OK;
718 }
719 #endif
memset
void * memset(void *, int, size_t)
FFI_TYPE_SMALL_STRUCT8
#define FFI_TYPE_SMALL_STRUCT8
Definition: ffitarget.h:84
FFI_ASSERT
#define FFI_ASSERT(x)
Definition: ffi_common.h:72
FFI_TYPE_LONGDOUBLE
#define FFI_TYPE_LONGDOUBLE
Definition: ffi.c:40
FFI_SIZEOF_ARG
#define FFI_SIZEOF_ARG
Definition: ffitarget.h:77
FFI_TYPE_SMALL_STRUCT3
#define FFI_TYPE_SMALL_STRUCT3
Definition: ffitarget.h:79
extended_cif::rvalue
void * rvalue
Definition: ffi_common.h:89
i
uint32_t i
Definition: rb_mjit_min_header-2.7.2.h:5499
long
#define long
Definition: rb_mjit_min_header-2.7.2.h:2921
ffi_common.h
FIRST_ARG_SLOT
#define FIRST_ARG_SLOT
Definition: ffi.c:40
fstd
#define fstd(fpreg, addr)
Definition: ffi.c:49
fldw
#define fldw(addr, fpreg)
Definition: ffi.c:43
unsigned
#define unsigned
Definition: rb_mjit_min_header-2.7.2.h:2915
alloca
#define alloca(size)
Definition: rb_mjit_min_header-2.7.2.h:2525
ptr
struct RIMemo * ptr
Definition: debug.c:65
NULL
#define NULL
Definition: _sdbm.c:101
debug
#define debug(lvl, x...)
Definition: ffi.c:52
FFI_TYPE_SMALL_STRUCT6
#define FFI_TYPE_SMALL_STRUCT6
Definition: ffitarget.h:82
ffi_prep_cif_machdep
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
Definition: ffi.c:758
FFI_TYPE_SMALL_STRUCT7
#define FFI_TYPE_SMALL_STRUCT7
Definition: ffitarget.h:83
extended_cif
Definition: ffi_common.h:87
fldd
#define fldd(addr, fpreg)
Definition: ffi.c:47
ROUND_UP
#define ROUND_UP(v, a)
Definition: ffi.c:37
extended_cif::avalue
void ** avalue
Definition: ffi_common.h:90
FFI_TYPE_SMALL_STRUCT4
#define FFI_TYPE_SMALL_STRUCT4
Definition: ffitarget.h:80
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
__asm__
#define __asm__
Definition: Context.c:12
ffi_call_pa32
void ffi_call_pa32(void(*)(UINT32 *, extended_cif *, unsigned), extended_cif *, unsigned, unsigned, unsigned *, void(*fn)(void))
len
uint8_t len
Definition: escape.c:17
ffi_call
void ffi_call(ffi_cif *cif, void(*fn)(void), void *rvalue, void **avalue)
Definition: ffi.c:813
ffi_prep_closure_loc
ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void(*fun)(ffi_cif *, void *, void **, void *), void *user_data, void *codeloc)
Definition: ffi.c:928
ffi_prep_args_pa32
void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
Definition: ffi.c:142
extended_cif::cif
ffi_cif * cif
Definition: ffi_common.h:88
MIN_STACK_SIZE
#define MIN_STACK_SIZE
Definition: ffi.c:39
fstw
#define fstw(fpreg, addr)
Definition: ffi.c:45
FFI_TYPE_SMALL_STRUCT5
#define FFI_TYPE_SMALL_STRUCT5
Definition: ffitarget.h:81
FFI_TYPE_SMALL_STRUCT2
#define FFI_TYPE_SMALL_STRUCT2
Definition: ffitarget.h:78
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
n
const char size_t n
Definition: rb_mjit_min_header-2.7.2.h:5491