Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(132565)

Side by Side Diff: Modules/_ctypes/libffi_ios/arm/ffi_armv7.c

Issue 23670: Modifications to support iOS as a development platform
Patch Set: Created 3 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #ifdef __arm__
2
3 /* -----------------------------------------------------------------------
4 ffi.c - Copyright (c) 2011 Timothy Wall
5 Copyright (c) 2011 Plausible Labs Cooperative, Inc.
6 Copyright (c) 2011 Anthony Green
7 Copyright (c) 2011 Free Software Foundation
8 Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
9
10 ARM Foreign Function Interface
11
12 Permission is hereby granted, free of charge, to any person obtaining
13 a copy of this software and associated documentation files (the
14 ``Software''), to deal in the Software without restriction, including
15 without limitation the rights to use, copy, modify, merge, publish,
16 distribute, sublicense, and/or sell copies of the Software, and to
17 permit persons to whom the Software is furnished to do so, subject to
18 the following conditions:
19
20 The above copyright notice and this permission notice shall be included
21 in all copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
24 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 DEALINGS IN THE SOFTWARE.
31 ----------------------------------------------------------------------- */
32
33 #include <fficonfig.h>
34 #include <ffi.h>
35 #include <ffi_common.h>
36 #include <stdlib.h>
37 #include "internal.h"
38
39 #if FFI_EXEC_TRAMPOLINE_TABLE
40
41 #ifdef __MACH__
42 #include <mach/vm_param.h>
43 #endif
44
45 #else
46 extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN;
47 #endif
48
49 /* Forward declares. */
50 static int vfp_type_p (const ffi_type *);
51 static void layout_vfp_args (ffi_cif *);
52
53 static void *
54 ffi_align (ffi_type *ty, void *p)
55 {
56 /* Align if necessary */
57 size_t alignment;
58 #ifdef _WIN32_WCE
59 alignment = 4;
60 #else
61 alignment = ty->alignment;
62 if (alignment < 4)
63 alignment = 4;
64 #endif
65 return (void *) ALIGN (p, alignment);
66 }
67
68 static size_t
69 ffi_put_arg (ffi_type *ty, void *src, void *dst)
70 {
71 size_t z = ty->size;
72
73 switch (ty->type)
74 {
75 case FFI_TYPE_SINT8:
76 *(UINT32 *)dst = *(SINT8 *)src;
77 break;
78 case FFI_TYPE_UINT8:
79 *(UINT32 *)dst = *(UINT8 *)src;
80 break;
81 case FFI_TYPE_SINT16:
82 *(UINT32 *)dst = *(SINT16 *)src;
83 break;
84 case FFI_TYPE_UINT16:
85 *(UINT32 *)dst = *(UINT16 *)src;
86 break;
87
88 case FFI_TYPE_INT:
89 case FFI_TYPE_SINT32:
90 case FFI_TYPE_UINT32:
91 case FFI_TYPE_POINTER:
92 case FFI_TYPE_FLOAT:
93 *(UINT32 *)dst = *(UINT32 *)src;
94 break;
95
96 case FFI_TYPE_SINT64:
97 case FFI_TYPE_UINT64:
98 case FFI_TYPE_DOUBLE:
99 *(UINT64 *)dst = *(UINT64 *)src;
100 break;
101
102 case FFI_TYPE_STRUCT:
103 case FFI_TYPE_COMPLEX:
104 memcpy (dst, src, z);
105 break;
106
107 default:
108 abort();
109 }
110
111 return ALIGN (z, 4);
112 }
113
114 /* ffi_prep_args is called once stack space has been allocated
115 for the function's arguments.
116
117 The vfp_space parameter is the load area for VFP regs, the return
118 value is cif->vfp_used (word bitset of VFP regs used for passing
119 arguments). These are only used for the VFP hard-float ABI.
120 */
121 static void
122 ffi_prep_args_SYSV (ffi_cif *cif, int flags, void *rvalue,
123 void **avalue, char *argp)
124 {
125 ffi_type **arg_types = cif->arg_types;
126 int i, n;
127
128 if (flags == ARM_TYPE_STRUCT)
129 {
130 *(void **) argp = rvalue;
131 argp += 4;
132 }
133
134 for (i = 0, n = cif->nargs; i < n; i++)
135 {
136 ffi_type *ty = arg_types[i];
137 argp = ffi_align (ty, argp);
138 argp += ffi_put_arg (ty, avalue[i], argp);
139 }
140 }
141
142 static void
143 ffi_prep_args_VFP (ffi_cif *cif, int flags, void *rvalue,
144 void **avalue, char *stack, char *vfp_space)
145 {
146 ffi_type **arg_types = cif->arg_types;
147 int i, n, vi = 0;
148 char *argp, *regp, *eo_regp;
149 char stack_used = 0;
150 char done_with_regs = 0;
151
152 /* The first 4 words on the stack are used for values
153 passed in core registers. */
154 regp = stack;
155 eo_regp = argp = regp + 16;
156
157 /* If the function returns an FFI_TYPE_STRUCT in memory,
158 that address is passed in r0 to the function. */
159 if (flags == ARM_TYPE_STRUCT)
160 {
161 *(void **) regp = rvalue;
162 regp += 4;
163 }
164
165 for (i = 0, n = cif->nargs; i < n; i++)
166 {
167 ffi_type *ty = arg_types[i];
168 void *a = avalue[i];
169 int is_vfp_type = vfp_type_p (ty);
170
171 /* Allocated in VFP registers. */
172 if (vi < cif->vfp_nargs && is_vfp_type)
173 {
174 char *vfp_slot = vfp_space + cif->vfp_args[vi++] * 4;
175 ffi_put_arg (ty, a, vfp_slot);
176 continue;
177 }
178 /* Try allocating in core registers. */
179 else if (!done_with_regs && !is_vfp_type)
180 {
181 char *tregp = ffi_align (ty, regp);
182 size_t size = ty->size;
183 size = (size < 4) ? 4 : size; // pad
184 /* Check if there is space left in the aligned register
185 area to place the argument. */
186 if (tregp + size <= eo_regp)
187 {
188 regp = tregp + ffi_put_arg (ty, a, tregp);
189 done_with_regs = (regp == argp);
190 // ensure we did not write into the stack area
191 FFI_ASSERT (regp <= argp);
192 continue;
193 }
194 /* In case there are no arguments in the stack area yet,
195 the argument is passed in the remaining core registers
196 and on the stack. */
197 else if (!stack_used)
198 {
199 stack_used = 1;
200 done_with_regs = 1;
201 argp = tregp + ffi_put_arg (ty, a, tregp);
202 FFI_ASSERT (eo_regp < argp);
203 continue;
204 }
205 }
206 /* Base case, arguments are passed on the stack */
207 stack_used = 1;
208 argp = ffi_align (ty, argp);
209 argp += ffi_put_arg (ty, a, argp);
210 }
211 }
212
213 /* Perform machine dependent cif processing */
214 ffi_status
215 ffi_prep_cif_machdep (ffi_cif *cif)
216 {
217 int flags = 0, cabi = cif->abi;
218 size_t bytes = cif->bytes;
219
220 /* Map out the register placements of VFP register args. The VFP
221 hard-float calling conventions are slightly more sophisticated
222 than the base calling conventions, so we do it here instead of
223 in ffi_prep_args(). */
224 if (cabi == FFI_VFP)
225 layout_vfp_args (cif);
226
227 /* Set the return type flag */
228 switch (cif->rtype->type)
229 {
230 case FFI_TYPE_VOID:
231 flags = ARM_TYPE_VOID;
232 break;
233
234 case FFI_TYPE_INT:
235 case FFI_TYPE_UINT8:
236 case FFI_TYPE_SINT8:
237 case FFI_TYPE_UINT16:
238 case FFI_TYPE_SINT16:
239 case FFI_TYPE_UINT32:
240 case FFI_TYPE_SINT32:
241 case FFI_TYPE_POINTER:
242 flags = ARM_TYPE_INT;
243 break;
244
245 case FFI_TYPE_SINT64:
246 case FFI_TYPE_UINT64:
247 flags = ARM_TYPE_INT64;
248 break;
249
250 case FFI_TYPE_FLOAT:
251 flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_S : ARM_TYPE_INT);
252 break;
253 case FFI_TYPE_DOUBLE:
254 flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_D : ARM_TYPE_INT64);
255 break;
256
257 case FFI_TYPE_STRUCT:
258 case FFI_TYPE_COMPLEX:
259 if (cabi == FFI_VFP)
260 {
261 int h = vfp_type_p (cif->rtype);
262
263 flags = ARM_TYPE_VFP_N;
264 if (h == 0x100 + FFI_TYPE_FLOAT)
265 flags = ARM_TYPE_VFP_S;
266 if (h == 0x100 + FFI_TYPE_DOUBLE)
267 flags = ARM_TYPE_VFP_D;
268 if (h != 0)
269 break;
270 }
271
272 /* A Composite Type not larger than 4 bytes is returned in r0.
273 A Composite Type larger than 4 bytes, or whose size cannot
274 be determined statically ... is stored in memory at an
275 address passed [in r0]. */
276 if (cif->rtype->size <= 4)
277 flags = ARM_TYPE_INT;
278 else
279 {
280 flags = ARM_TYPE_STRUCT;
281 bytes += 4;
282 }
283 break;
284
285 default:
286 abort();
287 }
288
289 /* Round the stack up to a multiple of 8 bytes. This isn't needed
290 everywhere, but it is on some platforms, and it doesn't harm anything
291 when it isn't needed. */
292 bytes = ALIGN (bytes, 8);
293
294 /* Minimum stack space is the 4 register arguments that we pop. */
295 if (bytes < 4*4)
296 bytes = 4*4;
297
298 cif->bytes = bytes;
299 cif->flags = flags;
300
301 return FFI_OK;
302 }
303
304 /* Perform machine dependent cif processing for variadic calls */
305 ffi_status
306 ffi_prep_cif_machdep_var (ffi_cif * cif,
307 unsigned int nfixedargs, unsigned int ntotalargs)
308 {
309 /* VFP variadic calls actually use the SYSV ABI */
310 if (cif->abi == FFI_VFP)
311 cif->abi = FFI_SYSV;
312
313 return ffi_prep_cif_machdep (cif);
314 }
315
316 /* Prototypes for assembly functions, in sysv.S. */
317
318 struct call_frame
319 {
320 void *fp;
321 void *lr;
322 void *rvalue;
323 int flags;
324 void *closure;
325 };
326
327 extern void ffi_call_SYSV (void *stack, struct call_frame *,
328 void (*fn) (void)) FFI_HIDDEN;
329 extern void ffi_call_VFP (void *vfp_space, struct call_frame *,
330 void (*fn) (void), unsigned vfp_used) FFI_HIDDEN;
331
332 static void
333 ffi_call_int (ffi_cif * cif, void (*fn) (void), void *rvalue,
334 void **avalue, void *closure)
335 {
336 int flags = cif->flags;
337 ffi_type *rtype = cif->rtype;
338 size_t bytes, rsize, vfp_size;
339 char *stack, *vfp_space, *new_rvalue;
340 struct call_frame *frame;
341
342 rsize = 0;
343 if (rvalue == NULL)
344 {
345 /* If the return value is a struct and we don't have a return
346 value address then we need to make one. Otherwise the return
347 value is in registers and we can ignore them. */
348 if (flags == ARM_TYPE_STRUCT)
349 rsize = rtype->size;
350 else
351 flags = ARM_TYPE_VOID;
352 }
353 else if (flags == ARM_TYPE_VFP_N)
354 {
355 /* Largest case is double x 4. */
356 rsize = 32;
357 }
358 else if (flags == ARM_TYPE_INT && rtype->type == FFI_TYPE_STRUCT)
359 rsize = 4;
360
361 /* Largest case. */
362 vfp_size = (cif->abi == FFI_VFP && cif->vfp_used ? 8*8: 0);
363
364 bytes = cif->bytes;
365 stack = alloca (vfp_size + bytes + sizeof(struct call_frame) + rsize);
366
367 vfp_space = NULL;
368 if (vfp_size)
369 {
370 vfp_space = stack;
371 stack += vfp_size;
372 }
373
374 frame = (struct call_frame *)(stack + bytes);
375
376 new_rvalue = rvalue;
377 if (rsize)
378 new_rvalue = (void *)(frame + 1);
379
380 frame->rvalue = new_rvalue;
381 frame->flags = flags;
382 frame->closure = closure;
383
384 if (vfp_space)
385 {
386 ffi_prep_args_VFP (cif, flags, new_rvalue, avalue, stack, vfp_space);
387 ffi_call_VFP (vfp_space, frame, fn, cif->vfp_used);
388 }
389 else
390 {
391 ffi_prep_args_SYSV (cif, flags, new_rvalue, avalue, stack);
392 ffi_call_SYSV (stack, frame, fn);
393 }
394
395 if (rvalue && rvalue != new_rvalue)
396 memcpy (rvalue, new_rvalue, rtype->size);
397 }
398
399 void
400 ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
401 {
402 ffi_call_int (cif, fn, rvalue, avalue, NULL);
403 }
404
405 void
406 ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
407 void **avalue, void *closure)
408 {
409 ffi_call_int (cif, fn, rvalue, avalue, closure);
410 }
411
412 static void *
413 ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue,
414 char *argp, void **avalue)
415 {
416 ffi_type **arg_types = cif->arg_types;
417 int i, n;
418
419 if (cif->flags == ARM_TYPE_STRUCT)
420 {
421 rvalue = *(void **) argp;
422 argp += 4;
423 }
424
425 for (i = 0, n = cif->nargs; i < n; i++)
426 {
427 ffi_type *ty = arg_types[i];
428 size_t z = ty->size;
429
430 argp = ffi_align (ty, argp);
431 avalue[i] = (void *) argp;
432 argp += z;
433 }
434
435 return rvalue;
436 }
437
438 static void *
439 ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack,
440 char *vfp_space, void **avalue)
441 {
442 ffi_type **arg_types = cif->arg_types;
443 int i, n, vi = 0;
444 char *argp, *regp, *eo_regp;
445 char done_with_regs = 0;
446 char stack_used = 0;
447
448 regp = stack;
449 eo_regp = argp = regp + 16;
450
451 if (cif->flags == ARM_TYPE_STRUCT)
452 {
453 rvalue = *(void **) regp;
454 regp += 4;
455 }
456
457 for (i = 0, n = cif->nargs; i < n; i++)
458 {
459 ffi_type *ty = arg_types[i];
460 int is_vfp_type = vfp_type_p (ty);
461 size_t z = ty->size;
462
463 if (vi < cif->vfp_nargs && is_vfp_type)
464 {
465 avalue[i] = vfp_space + cif->vfp_args[vi++] * 4;
466 continue;
467 }
468 else if (!done_with_regs && !is_vfp_type)
469 {
470 char *tregp = ffi_align (ty, regp);
471
472 z = (z < 4) ? 4 : z; // pad
473
474 /* If the arguments either fits into the registers or uses registers
475 and stack, while we haven't read other things from the stack */
476 if (tregp + z <= eo_regp || !stack_used)
477 {
478 /* Because we're little endian, this is what it turns into. */
479 avalue[i] = (void *) tregp;
480 regp = tregp + z;
481
482 /* If we read past the last core register, make sure we
483 have not read from the stack before and continue
484 reading after regp. */
485 if (regp > eo_regp)
486 {
487 FFI_ASSERT (!stack_used);
488 argp = regp;
489 }
490 if (regp >= eo_regp)
491 {
492 done_with_regs = 1;
493 stack_used = 1;
494 }
495 continue;
496 }
497 }
498
499 stack_used = 1;
500 argp = ffi_align (ty, argp);
501 avalue[i] = (void *) argp;
502 argp += z;
503 }
504
505 return rvalue;
506 }
507
508 struct closure_frame
509 {
510 char vfp_space[8*8] __attribute__((aligned(8)));
511 char result[8*4];
512 char argp[];
513 };
514
515 int FFI_HIDDEN
516 ffi_closure_inner_SYSV (ffi_cif *cif,
517 void (*fun) (ffi_cif *, void *, void **, void *),
518 void *user_data,
519 struct closure_frame *frame)
520 {
521 void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
522 void *rvalue = ffi_prep_incoming_args_SYSV (cif, frame->result,
523 frame->argp, avalue);
524 fun (cif, rvalue, avalue, user_data);
525 return cif->flags;
526 }
527
528 int FFI_HIDDEN
529 ffi_closure_inner_VFP (ffi_cif *cif,
530 void (*fun) (ffi_cif *, void *, void **, void *),
531 void *user_data,
532 struct closure_frame *frame)
533 {
534 void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
535 void *rvalue = ffi_prep_incoming_args_VFP (cif, frame->result, frame->argp,
536 frame->vfp_space, avalue);
537 fun (cif, rvalue, avalue, user_data);
538 return cif->flags;
539 }
540
541 void ffi_closure_SYSV (void) FFI_HIDDEN;
542 void ffi_closure_VFP (void) FFI_HIDDEN;
543 void ffi_go_closure_SYSV (void) FFI_HIDDEN;
544 void ffi_go_closure_VFP (void) FFI_HIDDEN;
545
546 /* the cif must already be prep'ed */
547
548 ffi_status
549 ffi_prep_closure_loc (ffi_closure * closure,
550 ffi_cif * cif,
551 void (*fun) (ffi_cif *, void *, void **, void *),
552 void *user_data, void *codeloc)
553 {
554 void (*closure_func) (void) = ffi_closure_SYSV;
555
556 if (cif->abi == FFI_VFP)
557 {
558 /* We only need take the vfp path if there are vfp arguments. */
559 if (cif->vfp_used)
560 closure_func = ffi_closure_VFP;
561 }
562 else if (cif->abi != FFI_SYSV)
563 return FFI_BAD_ABI;
564
565 #if FFI_EXEC_TRAMPOLINE_TABLE
566 void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE);
567 config[0] = closure;
568 config[1] = closure_func;
569 #else
570 memcpy (closure->tramp, ffi_arm_trampoline, 8);
571 __clear_cache(closure->tramp, closure->tramp + 8); /* clear data map */
572 __clear_cache(codeloc, codeloc + 8); /* clear insn map */
573 *(void (**)(void))(closure->tramp + 8) = closure_func;
574 #endif
575
576 closure->cif = cif;
577 closure->fun = fun;
578 closure->user_data = user_data;
579
580 return FFI_OK;
581 }
582
583 ffi_status
584 ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
585 void (*fun) (ffi_cif *, void *, void **, void *))
586 {
587 void (*closure_func) (void) = ffi_go_closure_SYSV;
588
589 if (cif->abi == FFI_VFP)
590 {
591 /* We only need take the vfp path if there are vfp arguments. */
592 if (cif->vfp_used)
593 closure_func = ffi_go_closure_VFP;
594 }
595 else if (cif->abi != FFI_SYSV)
596 return FFI_BAD_ABI;
597
598 closure->tramp = closure_func;
599 closure->cif = cif;
600 closure->fun = fun;
601
602 return FFI_OK;
603 }
604
605 /* Below are routines for VFP hard-float support. */
606
607 /* A subroutine of vfp_type_p. Given a structure type, return the type code
608 of the first non-structure element. Recurse for structure elements.
609 Return -1 if the structure is in fact empty, i.e. no nested elements. */
610
611 static int
612 is_hfa0 (const ffi_type *ty)
613 {
614 ffi_type **elements = ty->elements;
615 int i, ret = -1;
616
617 if (elements != NULL)
618 for (i = 0; elements[i]; ++i)
619 {
620 ret = elements[i]->type;
621 if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX)
622 {
623 ret = is_hfa0 (elements[i]);
624 if (ret < 0)
625 continue;
626 }
627 break;
628 }
629
630 return ret;
631 }
632
633 /* A subroutine of vfp_type_p. Given a structure type, return true if all
634 of the non-structure elements are the same as CANDIDATE. */
635
636 static int
637 is_hfa1 (const ffi_type *ty, int candidate)
638 {
639 ffi_type **elements = ty->elements;
640 int i;
641
642 if (elements != NULL)
643 for (i = 0; elements[i]; ++i)
644 {
645 int t = elements[i]->type;
646 if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
647 {
648 if (!is_hfa1 (elements[i], candidate))
649 return 0;
650 }
651 else if (t != candidate)
652 return 0;
653 }
654
655 return 1;
656 }
657
658 /* Determine if TY is an homogenous floating point aggregate (HFA).
659 That is, a structure consisting of 1 to 4 members of all the same type,
660 where that type is a floating point scalar.
661
662 Returns non-zero iff TY is an HFA. The result is an encoded value where
663 bits 0-7 contain the type code, and bits 8-10 contain the element count. */
664
665 static int
666 vfp_type_p (const ffi_type *ty)
667 {
668 ffi_type **elements;
669 int candidate, i;
670 size_t size, ele_count;
671
672 /* Quickest tests first. */
673 candidate = ty->type;
674 switch (ty->type)
675 {
676 default:
677 return 0;
678 case FFI_TYPE_FLOAT:
679 case FFI_TYPE_DOUBLE:
680 ele_count = 1;
681 goto done;
682 case FFI_TYPE_COMPLEX:
683 candidate = ty->elements[0]->type;
684 if (candidate != FFI_TYPE_FLOAT && candidate != FFI_TYPE_DOUBLE)
685 return 0;
686 ele_count = 2;
687 goto done;
688 case FFI_TYPE_STRUCT:
689 break;
690 }
691
692 /* No HFA types are smaller than 4 bytes, or larger than 32 bytes. */
693 size = ty->size;
694 if (size < 4 || size > 32)
695 return 0;
696
697 /* Find the type of the first non-structure member. */
698 elements = ty->elements;
699 candidate = elements[0]->type;
700 if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX)
701 {
702 for (i = 0; ; ++i)
703 {
704 candidate = is_hfa0 (elements[i]);
705 if (candidate >= 0)
706 break;
707 }
708 }
709
710 /* If the first member is not a floating point type, it's not an HFA.
711 Also quickly re-check the size of the structure. */
712 switch (candidate)
713 {
714 case FFI_TYPE_FLOAT:
715 ele_count = size / sizeof(float);
716 if (size != ele_count * sizeof(float))
717 return 0;
718 break;
719 case FFI_TYPE_DOUBLE:
720 ele_count = size / sizeof(double);
721 if (size != ele_count * sizeof(double))
722 return 0;
723 break;
724 default:
725 return 0;
726 }
727 if (ele_count > 4)
728 return 0;
729
730 /* Finally, make sure that all scalar elements are the same type. */
731 for (i = 0; elements[i]; ++i)
732 {
733 int t = elements[i]->type;
734 if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
735 {
736 if (!is_hfa1 (elements[i], candidate))
737 return 0;
738 }
739 else if (t != candidate)
740 return 0;
741 }
742
743 /* All tests succeeded. Encode the result. */
744 done:
745 return (ele_count << 8) | candidate;
746 }
747
748 static int
749 place_vfp_arg (ffi_cif *cif, int h)
750 {
751 unsigned short reg = cif->vfp_reg_free;
752 int align = 1, nregs = h >> 8;
753
754 if ((h & 0xff) == FFI_TYPE_DOUBLE)
755 align = 2, nregs *= 2;
756
757 /* Align register number. */
758 if ((reg & 1) && align == 2)
759 reg++;
760
761 while (reg + nregs <= 16)
762 {
763 int s, new_used = 0;
764 for (s = reg; s < reg + nregs; s++)
765 {
766 new_used |= (1 << s);
767 if (cif->vfp_used & (1 << s))
768 {
769 reg += align;
770 goto next_reg;
771 }
772 }
773 /* Found regs to allocate. */
774 cif->vfp_used |= new_used;
775 cif->vfp_args[cif->vfp_nargs++] = reg;
776
777 /* Update vfp_reg_free. */
778 if (cif->vfp_used & (1 << cif->vfp_reg_free))
779 {
780 reg += nregs;
781 while (cif->vfp_used & (1 << reg))
782 reg += 1;
783 cif->vfp_reg_free = reg;
784 }
785 return 0;
786 next_reg:;
787 }
788 // done, mark all regs as used
789 cif->vfp_reg_free = 16;
790 cif->vfp_used = 0xFFFF;
791 return 1;
792 }
793
794 static void
795 layout_vfp_args (ffi_cif * cif)
796 {
797 int i;
798 /* Init VFP fields */
799 cif->vfp_used = 0;
800 cif->vfp_nargs = 0;
801 cif->vfp_reg_free = 0;
802 memset (cif->vfp_args, -1, 16); /* Init to -1. */
803
804 for (i = 0; i < cif->nargs; i++)
805 {
806 int h = vfp_type_p (cif->arg_types[i]);
807 if (h && place_vfp_arg (cif, h) == 1)
808 break;
809 }
810 }
811
812
813 #endif
OLDNEW
« no previous file with comments | « Modules/_ctypes/libffi_ios/aarch64/sysv_arm64.S ('k') | Modules/_ctypes/libffi_ios/arm/internal.h » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+