Mercurial > hg > CbC > CbC_gcc
comparison libffi/src/sh/ffi.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* ----------------------------------------------------------------------- | |
2 ffi.c - Copyright (c) 2002-2008, 2012 Kaz Kojima | |
3 Copyright (c) 2008 Red Hat, Inc. | |
4 | |
5 SuperH Foreign Function Interface | |
6 | |
7 Permission is hereby granted, free of charge, to any person obtaining | |
8 a copy of this software and associated documentation files (the | |
9 ``Software''), to deal in the Software without restriction, including | |
10 without limitation the rights to use, copy, modify, merge, publish, | |
11 distribute, sublicense, and/or sell copies of the Software, and to | |
12 permit persons to whom the Software is furnished to do so, subject to | |
13 the following conditions: | |
14 | |
15 The above copyright notice and this permission notice shall be included | |
16 in all copies or substantial portions of the Software. | |
17 | |
18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, | |
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
25 DEALINGS IN THE SOFTWARE. | |
26 ----------------------------------------------------------------------- */ | |
27 | |
28 #include <ffi.h> | |
29 #include <ffi_common.h> | |
30 | |
31 #include <stdlib.h> | |
32 | |
33 #define NGREGARG 4 | |
34 #if defined(__SH4__) | |
35 #define NFREGARG 8 | |
36 #endif | |
37 | |
38 #if defined(__HITACHI__) | |
39 #define STRUCT_VALUE_ADDRESS_WITH_ARG 1 | |
40 #else | |
41 #define STRUCT_VALUE_ADDRESS_WITH_ARG 0 | |
42 #endif | |
43 | |
44 /* If the structure has essentially an unique element, return its type. */ | |
45 static int | |
46 simple_type (ffi_type *arg) | |
47 { | |
48 if (arg->type != FFI_TYPE_STRUCT) | |
49 return arg->type; | |
50 else if (arg->elements[1]) | |
51 return FFI_TYPE_STRUCT; | |
52 | |
53 return simple_type (arg->elements[0]); | |
54 } | |
55 | |
56 static int | |
57 return_type (ffi_type *arg) | |
58 { | |
59 unsigned short type; | |
60 | |
61 if (arg->type != FFI_TYPE_STRUCT) | |
62 return arg->type; | |
63 | |
64 type = simple_type (arg->elements[0]); | |
65 if (! arg->elements[1]) | |
66 { | |
67 switch (type) | |
68 { | |
69 case FFI_TYPE_SINT8: | |
70 case FFI_TYPE_UINT8: | |
71 case FFI_TYPE_SINT16: | |
72 case FFI_TYPE_UINT16: | |
73 case FFI_TYPE_SINT32: | |
74 case FFI_TYPE_UINT32: | |
75 return FFI_TYPE_INT; | |
76 | |
77 default: | |
78 return type; | |
79 } | |
80 } | |
81 | |
82 /* gcc uses r0/r1 pair for some kind of structures. */ | |
83 if (arg->size <= 2 * sizeof (int)) | |
84 { | |
85 int i = 0; | |
86 ffi_type *e; | |
87 | |
88 while ((e = arg->elements[i++])) | |
89 { | |
90 type = simple_type (e); | |
91 switch (type) | |
92 { | |
93 case FFI_TYPE_SINT32: | |
94 case FFI_TYPE_UINT32: | |
95 case FFI_TYPE_INT: | |
96 case FFI_TYPE_FLOAT: | |
97 return FFI_TYPE_UINT64; | |
98 | |
99 default: | |
100 break; | |
101 } | |
102 } | |
103 } | |
104 | |
105 return FFI_TYPE_STRUCT; | |
106 } | |
107 | |
108 /* ffi_prep_args is called by the assembly routine once stack space | |
109 has been allocated for the function's arguments */ | |
110 | |
111 void ffi_prep_args(char *stack, extended_cif *ecif) | |
112 { | |
113 register unsigned int i; | |
114 register int tmp; | |
115 register unsigned int avn; | |
116 register void **p_argv; | |
117 register char *argp; | |
118 register ffi_type **p_arg; | |
119 int greg, ireg; | |
120 #if defined(__SH4__) | |
121 int freg = 0; | |
122 #endif | |
123 | |
124 tmp = 0; | |
125 argp = stack; | |
126 | |
127 if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT) | |
128 { | |
129 *(void **) argp = ecif->rvalue; | |
130 argp += 4; | |
131 ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0; | |
132 } | |
133 else | |
134 ireg = 0; | |
135 | |
136 /* Set arguments for registers. */ | |
137 greg = ireg; | |
138 avn = ecif->cif->nargs; | |
139 p_argv = ecif->avalue; | |
140 | |
141 for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) | |
142 { | |
143 size_t z; | |
144 | |
145 z = (*p_arg)->size; | |
146 if (z < sizeof(int)) | |
147 { | |
148 if (greg++ >= NGREGARG) | |
149 continue; | |
150 | |
151 z = sizeof(int); | |
152 switch ((*p_arg)->type) | |
153 { | |
154 case FFI_TYPE_SINT8: | |
155 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); | |
156 break; | |
157 | |
158 case FFI_TYPE_UINT8: | |
159 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); | |
160 break; | |
161 | |
162 case FFI_TYPE_SINT16: | |
163 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); | |
164 break; | |
165 | |
166 case FFI_TYPE_UINT16: | |
167 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); | |
168 break; | |
169 | |
170 case FFI_TYPE_STRUCT: | |
171 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); | |
172 break; | |
173 | |
174 default: | |
175 FFI_ASSERT(0); | |
176 } | |
177 argp += z; | |
178 } | |
179 else if (z == sizeof(int)) | |
180 { | |
181 #if defined(__SH4__) | |
182 if ((*p_arg)->type == FFI_TYPE_FLOAT) | |
183 { | |
184 if (freg++ >= NFREGARG) | |
185 continue; | |
186 } | |
187 else | |
188 #endif | |
189 { | |
190 if (greg++ >= NGREGARG) | |
191 continue; | |
192 } | |
193 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); | |
194 argp += z; | |
195 } | |
196 #if defined(__SH4__) | |
197 else if ((*p_arg)->type == FFI_TYPE_DOUBLE) | |
198 { | |
199 if (freg + 1 >= NFREGARG) | |
200 continue; | |
201 freg = (freg + 1) & ~1; | |
202 freg += 2; | |
203 memcpy (argp, *p_argv, z); | |
204 argp += z; | |
205 } | |
206 #endif | |
207 else | |
208 { | |
209 int n = (z + sizeof (int) - 1) / sizeof (int); | |
210 #if defined(__SH4__) | |
211 if (greg + n - 1 >= NGREGARG) | |
212 continue; | |
213 #else | |
214 if (greg >= NGREGARG) | |
215 continue; | |
216 #endif | |
217 greg += n; | |
218 memcpy (argp, *p_argv, z); | |
219 argp += n * sizeof (int); | |
220 } | |
221 } | |
222 | |
223 /* Set arguments on stack. */ | |
224 greg = ireg; | |
225 #if defined(__SH4__) | |
226 freg = 0; | |
227 #endif | |
228 p_argv = ecif->avalue; | |
229 | |
230 for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++) | |
231 { | |
232 size_t z; | |
233 | |
234 z = (*p_arg)->size; | |
235 if (z < sizeof(int)) | |
236 { | |
237 if (greg++ < NGREGARG) | |
238 continue; | |
239 | |
240 z = sizeof(int); | |
241 switch ((*p_arg)->type) | |
242 { | |
243 case FFI_TYPE_SINT8: | |
244 *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); | |
245 break; | |
246 | |
247 case FFI_TYPE_UINT8: | |
248 *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); | |
249 break; | |
250 | |
251 case FFI_TYPE_SINT16: | |
252 *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); | |
253 break; | |
254 | |
255 case FFI_TYPE_UINT16: | |
256 *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); | |
257 break; | |
258 | |
259 case FFI_TYPE_STRUCT: | |
260 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); | |
261 break; | |
262 | |
263 default: | |
264 FFI_ASSERT(0); | |
265 } | |
266 argp += z; | |
267 } | |
268 else if (z == sizeof(int)) | |
269 { | |
270 #if defined(__SH4__) | |
271 if ((*p_arg)->type == FFI_TYPE_FLOAT) | |
272 { | |
273 if (freg++ < NFREGARG) | |
274 continue; | |
275 } | |
276 else | |
277 #endif | |
278 { | |
279 if (greg++ < NGREGARG) | |
280 continue; | |
281 } | |
282 *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); | |
283 argp += z; | |
284 } | |
285 #if defined(__SH4__) | |
286 else if ((*p_arg)->type == FFI_TYPE_DOUBLE) | |
287 { | |
288 if (freg + 1 < NFREGARG) | |
289 { | |
290 freg = (freg + 1) & ~1; | |
291 freg += 2; | |
292 continue; | |
293 } | |
294 memcpy (argp, *p_argv, z); | |
295 argp += z; | |
296 } | |
297 #endif | |
298 else | |
299 { | |
300 int n = (z + sizeof (int) - 1) / sizeof (int); | |
301 if (greg + n - 1 < NGREGARG) | |
302 { | |
303 greg += n; | |
304 continue; | |
305 } | |
306 #if (! defined(__SH4__)) | |
307 else if (greg < NGREGARG) | |
308 { | |
309 greg = NGREGARG; | |
310 continue; | |
311 } | |
312 #endif | |
313 memcpy (argp, *p_argv, z); | |
314 argp += n * sizeof (int); | |
315 } | |
316 } | |
317 | |
318 return; | |
319 } | |
320 | |
321 /* Perform machine dependent cif processing */ | |
322 ffi_status ffi_prep_cif_machdep(ffi_cif *cif) | |
323 { | |
324 int i, j; | |
325 int size, type; | |
326 int n, m; | |
327 int greg; | |
328 #if defined(__SH4__) | |
329 int freg = 0; | |
330 #endif | |
331 | |
332 cif->flags = 0; | |
333 | |
334 greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) && | |
335 STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0; | |
336 | |
337 #if defined(__SH4__) | |
338 for (i = j = 0; i < cif->nargs && j < 12; i++) | |
339 { | |
340 type = (cif->arg_types)[i]->type; | |
341 switch (type) | |
342 { | |
343 case FFI_TYPE_FLOAT: | |
344 if (freg >= NFREGARG) | |
345 continue; | |
346 freg++; | |
347 cif->flags += ((cif->arg_types)[i]->type) << (2 * j); | |
348 j++; | |
349 break; | |
350 | |
351 case FFI_TYPE_DOUBLE: | |
352 if ((freg + 1) >= NFREGARG) | |
353 continue; | |
354 freg = (freg + 1) & ~1; | |
355 freg += 2; | |
356 cif->flags += ((cif->arg_types)[i]->type) << (2 * j); | |
357 j++; | |
358 break; | |
359 | |
360 default: | |
361 size = (cif->arg_types)[i]->size; | |
362 n = (size + sizeof (int) - 1) / sizeof (int); | |
363 if (greg + n - 1 >= NGREGARG) | |
364 continue; | |
365 greg += n; | |
366 for (m = 0; m < n; m++) | |
367 cif->flags += FFI_TYPE_INT << (2 * j++); | |
368 break; | |
369 } | |
370 } | |
371 #else | |
372 for (i = j = 0; i < cif->nargs && j < 4; i++) | |
373 { | |
374 size = (cif->arg_types)[i]->size; | |
375 n = (size + sizeof (int) - 1) / sizeof (int); | |
376 if (greg >= NGREGARG) | |
377 continue; | |
378 else if (greg + n - 1 >= NGREGARG) | |
379 n = NGREGARG - greg; | |
380 greg += n; | |
381 for (m = 0; m < n; m++) | |
382 cif->flags += FFI_TYPE_INT << (2 * j++); | |
383 } | |
384 #endif | |
385 | |
386 /* Set the return type flag */ | |
387 switch (cif->rtype->type) | |
388 { | |
389 case FFI_TYPE_STRUCT: | |
390 cif->flags += (unsigned) (return_type (cif->rtype)) << 24; | |
391 break; | |
392 | |
393 case FFI_TYPE_VOID: | |
394 case FFI_TYPE_FLOAT: | |
395 case FFI_TYPE_DOUBLE: | |
396 case FFI_TYPE_SINT64: | |
397 case FFI_TYPE_UINT64: | |
398 cif->flags += (unsigned) cif->rtype->type << 24; | |
399 break; | |
400 | |
401 default: | |
402 cif->flags += FFI_TYPE_INT << 24; | |
403 break; | |
404 } | |
405 | |
406 return FFI_OK; | |
407 } | |
408 | |
409 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, | |
410 unsigned, unsigned, unsigned *, void (*fn)(void)); | |
411 | |
412 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) | |
413 { | |
414 extended_cif ecif; | |
415 UINT64 trvalue; | |
416 | |
417 ecif.cif = cif; | |
418 ecif.avalue = avalue; | |
419 | |
420 /* If the return value is a struct and we don't have a return */ | |
421 /* value address then we need to make one */ | |
422 | |
423 if (cif->rtype->type == FFI_TYPE_STRUCT | |
424 && return_type (cif->rtype) != FFI_TYPE_STRUCT) | |
425 ecif.rvalue = &trvalue; | |
426 else if ((rvalue == NULL) && | |
427 (cif->rtype->type == FFI_TYPE_STRUCT)) | |
428 { | |
429 ecif.rvalue = alloca(cif->rtype->size); | |
430 } | |
431 else | |
432 ecif.rvalue = rvalue; | |
433 | |
434 switch (cif->abi) | |
435 { | |
436 case FFI_SYSV: | |
437 ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, | |
438 fn); | |
439 break; | |
440 default: | |
441 FFI_ASSERT(0); | |
442 break; | |
443 } | |
444 | |
445 if (rvalue | |
446 && cif->rtype->type == FFI_TYPE_STRUCT | |
447 && return_type (cif->rtype) != FFI_TYPE_STRUCT) | |
448 memcpy (rvalue, &trvalue, cif->rtype->size); | |
449 } | |
450 | |
451 extern void ffi_closure_SYSV (void); | |
452 #if defined(__SH4__) | |
453 extern void __ic_invalidate (void *line); | |
454 #endif | |
455 | |
456 ffi_status | |
457 ffi_prep_closure_loc (ffi_closure* closure, | |
458 ffi_cif* cif, | |
459 void (*fun)(ffi_cif*, void*, void**, void*), | |
460 void *user_data, | |
461 void *codeloc) | |
462 { | |
463 unsigned int *tramp; | |
464 unsigned int insn; | |
465 | |
466 if (cif->abi != FFI_SYSV) | |
467 return FFI_BAD_ABI; | |
468 | |
469 tramp = (unsigned int *) &closure->tramp[0]; | |
470 /* Set T bit if the function returns a struct pointed with R2. */ | |
471 insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT | |
472 ? 0x0018 /* sett */ | |
473 : 0x0008 /* clrt */); | |
474 | |
475 #ifdef __LITTLE_ENDIAN__ | |
476 tramp[0] = 0xd301d102; | |
477 tramp[1] = 0x0000412b | (insn << 16); | |
478 #else | |
479 tramp[0] = 0xd102d301; | |
480 tramp[1] = 0x412b0000 | insn; | |
481 #endif | |
482 *(void **) &tramp[2] = (void *)codeloc; /* ctx */ | |
483 *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */ | |
484 | |
485 closure->cif = cif; | |
486 closure->fun = fun; | |
487 closure->user_data = user_data; | |
488 | |
489 #if defined(__SH4__) | |
490 /* Flush the icache. */ | |
491 __ic_invalidate(codeloc); | |
492 #endif | |
493 | |
494 return FFI_OK; | |
495 } | |
496 | |
497 /* Basically the trampoline invokes ffi_closure_SYSV, and on | |
498 * entry, r3 holds the address of the closure. | |
499 * After storing the registers that could possibly contain | |
500 * parameters to be passed into the stack frame and setting | |
501 * up space for a return value, ffi_closure_SYSV invokes the | |
502 * following helper function to do most of the work. | |
503 */ | |
504 | |
505 #ifdef __LITTLE_ENDIAN__ | |
506 #define OFS_INT8 0 | |
507 #define OFS_INT16 0 | |
508 #else | |
509 #define OFS_INT8 3 | |
510 #define OFS_INT16 2 | |
511 #endif | |
512 | |
513 int | |
514 ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, | |
515 unsigned long *pgr, unsigned long *pfr, | |
516 unsigned long *pst) | |
517 { | |
518 void **avalue; | |
519 ffi_type **p_arg; | |
520 int i, avn; | |
521 int ireg, greg = 0; | |
522 #if defined(__SH4__) | |
523 int freg = 0; | |
524 #endif | |
525 ffi_cif *cif; | |
526 | |
527 cif = closure->cif; | |
528 avalue = alloca(cif->nargs * sizeof(void *)); | |
529 | |
530 /* Copy the caller's structure return value address so that the closure | |
531 returns the data directly to the caller. */ | |
532 if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG) | |
533 { | |
534 rvalue = (void *) *pgr++; | |
535 ireg = 1; | |
536 } | |
537 else | |
538 ireg = 0; | |
539 | |
540 cif = closure->cif; | |
541 greg = ireg; | |
542 avn = cif->nargs; | |
543 | |
544 /* Grab the addresses of the arguments from the stack frame. */ | |
545 for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) | |
546 { | |
547 size_t z; | |
548 | |
549 z = (*p_arg)->size; | |
550 if (z < sizeof(int)) | |
551 { | |
552 if (greg++ >= NGREGARG) | |
553 continue; | |
554 | |
555 z = sizeof(int); | |
556 switch ((*p_arg)->type) | |
557 { | |
558 case FFI_TYPE_SINT8: | |
559 case FFI_TYPE_UINT8: | |
560 avalue[i] = (((char *)pgr) + OFS_INT8); | |
561 break; | |
562 | |
563 case FFI_TYPE_SINT16: | |
564 case FFI_TYPE_UINT16: | |
565 avalue[i] = (((char *)pgr) + OFS_INT16); | |
566 break; | |
567 | |
568 case FFI_TYPE_STRUCT: | |
569 avalue[i] = pgr; | |
570 break; | |
571 | |
572 default: | |
573 FFI_ASSERT(0); | |
574 } | |
575 pgr++; | |
576 } | |
577 else if (z == sizeof(int)) | |
578 { | |
579 #if defined(__SH4__) | |
580 if ((*p_arg)->type == FFI_TYPE_FLOAT) | |
581 { | |
582 if (freg++ >= NFREGARG) | |
583 continue; | |
584 avalue[i] = pfr; | |
585 pfr++; | |
586 } | |
587 else | |
588 #endif | |
589 { | |
590 if (greg++ >= NGREGARG) | |
591 continue; | |
592 avalue[i] = pgr; | |
593 pgr++; | |
594 } | |
595 } | |
596 #if defined(__SH4__) | |
597 else if ((*p_arg)->type == FFI_TYPE_DOUBLE) | |
598 { | |
599 if (freg + 1 >= NFREGARG) | |
600 continue; | |
601 if (freg & 1) | |
602 pfr++; | |
603 freg = (freg + 1) & ~1; | |
604 freg += 2; | |
605 avalue[i] = pfr; | |
606 pfr += 2; | |
607 } | |
608 #endif | |
609 else | |
610 { | |
611 int n = (z + sizeof (int) - 1) / sizeof (int); | |
612 #if defined(__SH4__) | |
613 if (greg + n - 1 >= NGREGARG) | |
614 continue; | |
615 #else | |
616 if (greg >= NGREGARG) | |
617 continue; | |
618 #endif | |
619 greg += n; | |
620 avalue[i] = pgr; | |
621 pgr += n; | |
622 } | |
623 } | |
624 | |
625 greg = ireg; | |
626 #if defined(__SH4__) | |
627 freg = 0; | |
628 #endif | |
629 | |
630 for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) | |
631 { | |
632 size_t z; | |
633 | |
634 z = (*p_arg)->size; | |
635 if (z < sizeof(int)) | |
636 { | |
637 if (greg++ < NGREGARG) | |
638 continue; | |
639 | |
640 z = sizeof(int); | |
641 switch ((*p_arg)->type) | |
642 { | |
643 case FFI_TYPE_SINT8: | |
644 case FFI_TYPE_UINT8: | |
645 avalue[i] = (((char *)pst) + OFS_INT8); | |
646 break; | |
647 | |
648 case FFI_TYPE_SINT16: | |
649 case FFI_TYPE_UINT16: | |
650 avalue[i] = (((char *)pst) + OFS_INT16); | |
651 break; | |
652 | |
653 case FFI_TYPE_STRUCT: | |
654 avalue[i] = pst; | |
655 break; | |
656 | |
657 default: | |
658 FFI_ASSERT(0); | |
659 } | |
660 pst++; | |
661 } | |
662 else if (z == sizeof(int)) | |
663 { | |
664 #if defined(__SH4__) | |
665 if ((*p_arg)->type == FFI_TYPE_FLOAT) | |
666 { | |
667 if (freg++ < NFREGARG) | |
668 continue; | |
669 } | |
670 else | |
671 #endif | |
672 { | |
673 if (greg++ < NGREGARG) | |
674 continue; | |
675 } | |
676 avalue[i] = pst; | |
677 pst++; | |
678 } | |
679 #if defined(__SH4__) | |
680 else if ((*p_arg)->type == FFI_TYPE_DOUBLE) | |
681 { | |
682 if (freg + 1 < NFREGARG) | |
683 { | |
684 freg = (freg + 1) & ~1; | |
685 freg += 2; | |
686 continue; | |
687 } | |
688 avalue[i] = pst; | |
689 pst += 2; | |
690 } | |
691 #endif | |
692 else | |
693 { | |
694 int n = (z + sizeof (int) - 1) / sizeof (int); | |
695 if (greg + n - 1 < NGREGARG) | |
696 { | |
697 greg += n; | |
698 continue; | |
699 } | |
700 #if (! defined(__SH4__)) | |
701 else if (greg < NGREGARG) | |
702 { | |
703 greg += n; | |
704 pst += greg - NGREGARG; | |
705 continue; | |
706 } | |
707 #endif | |
708 avalue[i] = pst; | |
709 pst += n; | |
710 } | |
711 } | |
712 | |
713 (closure->fun) (cif, rvalue, avalue, closure->user_data); | |
714 | |
715 /* Tell ffi_closure_SYSV how to perform return type promotions. */ | |
716 return return_type (cif->rtype); | |
717 } |