111
|
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 }
|