8000 PowerPC64 ELFv1 fp arg fixes · python/cpython-source-deps@ebf2416 · GitHub
[go: up one dir, main page]

Skip to content 8000

Commit ebf2416

Browse files
amodraatgreen
authored andcommitted
PowerPC64 ELFv1 fp arg fixes
The ELFv1 ABI says: "Single precision floating point values are mapped to the second word in a single doubleword" and also "Floating point registers f1 through f13 are used consecutively to pass up to 13 floating point values, one member aggregates passed by value containing a floating point value, and to pass complex floating point values". libffi wasn't expecting float args in the second word, and wasn't passing one member aggregates in fp registers. This patch fixes those problems, making use of the existing ELFv2 homogeneous aggregate support since a one element fp struct is a special case of an homogeneous aggregate. I've also set a flag when returning pointers that might be used one day. This is just a tidy since the ppc64 assembly support code currently doesn't test FLAG_RETURNS_64BITS for integer types.. * src/powerpc/ffi_linux64.c (discover_homogeneous_aggregate): Compile for ELFv1 too, handling single element aggregates. (ffi_prep_cif_linux64_core): Call discover_homogeneous_aggregate for ELFv1. Set FLAG_RETURNS_64BITS for FFI_TYPE_POINTER return. (ffi_prep_args64): Call discover_homogeneous_aggregate for ELFv1, and handle single element structs containing float or double as if the element wasn't wrapped in a struct. Store floats in second word of doubleword slot when big-endian. (ffi_closure_helper_LINUX64): Similarly.
1 parent a2c6c7a commit ebf2416

File tree

1 file changed

+45
-16
lines changed

1 file changed

+45
-16
lines changed

src/powerpc/ffi_linux64.c

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ ffi_prep_types_linux64 (ffi_abi abi)
6262
#endif
6363

6464

65-
#if _CALL_ELF == 2
6665
static unsigned int
6766
discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
6867
{
@@ -86,8 +85,13 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
8685
return 0;
8786
base_elt = el_elt;
8887
total_elnum += el_elnum;
88+
#if _CALL_ELF == 2
8989
if (total_elnum > 8)
9090
return 0;
91+
#else
92+
if (total_elnum > 1)
93+
return 0;
94+
#endif
9195
el++;
9296
}
9397
*elnum = total_elnum;
@@ -98,7 +102,6 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
98102
return 0;
99103
}
100104
}
101-
#endif
102105

103106

104107
/* Perform machine dependent cif processing */
@@ -109,9 +112,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
109112
unsigned bytes;
110113
unsigned i, fparg_count = 0, intarg_count = 0;
111114
unsigned flags = cif->flags;
112-
#if _CALL_ELF == 2
113115
unsigned int elt, elnum;
114-
#endif
115116

116117
#if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE
117118
/* If compiled without long double support.. */
@@ -157,6 +158,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
157158
/* Fall through. */
158159
case FFI_TYPE_UINT64:
159160
case FFI_TYPE_SINT64:
161+
case FFI_TYPE_POINTER:
160162
flags |= FLAG_RETURNS_64BITS;
161163
break;
162164

@@ -222,7 +224,6 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
222224
intarg_count = FFI_ALIGN (intarg_count, align);
223225
}
224226
intarg_count += ((*ptr)->size + 7) / 8;
225-
#if _CALL_ELF == 2
226227
elt = discover_homogeneous_aggregate (*ptr, &elnum);
227228
if (elt)
228229
{
@@ -231,7 +232,6 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
231232
flags |= FLAG_ARG_NEEDS_PSAVE;
232233
}
233234
else
234-
#endif
235235
{
236236
if (intarg_count > NUM_GPR_ARG_REGISTERS64)
237237
flags |= FLAG_ARG_NEEDS_PSAVE;
@@ -449,9 +449,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
449449
i < nargs;
450450
i++, ptr++, p_argv.v++)
451451
{
452-
#if _CALL_ELF == 2
453452
unsigned int elt, elnum;
454-
#endif
455453

456454
switch ((*ptr)->type)
457455
{
@@ -494,6 +492,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
494492
/* Fall through. */
495493
#endif
496494
case FFI_TYPE_DOUBLE:
495+
do_double:
497496
double_tmp = **p_argv.d;
498497
if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
499498
{
@@ -512,17 +511,30 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
512511
break;
513512

514513
case FFI_TYPE_FLOAT:
514+
do_float:
515515
double_tmp = **p_argv.f;
516516
if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
517517
{
518518
*fpr_base.d++ = double_tmp;
519519
#if _CALL_ELF != 2
520520
if ((flags & FLAG_COMPAT) != 0)
521-
*next_arg.f = (float) double_tmp;
521+
{
522+
# ifndef __LITTLE_ENDIAN__
523+
next_arg.f[1] = (float) double_tmp;
524+
# else
525+
next_arg.f[0] = (float) double_tmp;
526+
# endif
527+
}
522528
#endif
523529
}
524530
else
525-
*next_arg.f = (float) double_tmp;
531+
{
532+
# ifndef __LITTLE_ENDIAN__
533+
next_arg.f[1] = (float) double_tmp;
534+
# else
535+
next_arg.f[0] = (float) double_tmp;
536+
# endif
537+
}
526538
if (++next_arg.ul == gpr_end.ul)
527539
next_arg.ul = rest.ul;
528540
fparg_count++;
@@ -538,10 +550,10 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
538550
if (align > 1)
539551
next_arg.p = FFI_ALIGN (next_arg.p, align);
540552
}
541-
#if _CALL_ELF == 2
542553
elt = discover_homogeneous_aggregate (*ptr, &elnum);
543554
if (elt)
544555
{
556+
#if _CALL_ELF == 2
545557
union {
546558
void *v;
547559
float *f;
@@ -583,9 +595,14 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
583595
fparg_count++;
584596
}
585597
while (--elnum != 0);
598+
#else
599+
if (elt == FFI_TYPE_FLOAT)
600+
goto do_float;
601+
else
602+
goto do_double;
603+
#endif
586604
}
587605
else
588-
#endif
589606
{
590607
words = ((*ptr)->size + 7) / 8;
591608
if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
@@ -796,12 +813,10 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
796813
if (align > 1)
797814
pst = (unsigned long *) FFI_ALIGN ((size_t) pst, align);
798815
}
799-
elt = 0;
800-
#if _CALL_ELF == 2
801816
elt = discover_homogeneous_aggregate (arg_types[i], &elnum);
802-
#endif
803817
if (elt)
804818
{
819+
#if _CALL_ELF == 2
805820
union {
806821
void *v;
807822
unsigned long *ul;
@@ -853,6 +868,12 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
853868
}
854869
while (--elnum != 0);
855870
}
871+
#else
872+
if (elt == FFI_TYPE_FLOAT)
873+
goto do_float;
874+
else
875+
goto do_double;
876+
#endif
856877
}
857878
else
858879
{
@@ -894,6 +915,7 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
894915
/* Fall through. */
895916
#endif
896917
case FFI_TYPE_DOUBLE:
918+
do_double:
897919
/* On the outgoing stack all values are aligned to 8 */
898920
/* there are 13 64bit floating point registers */
899921

@@ -908,6 +930,7 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
908930
break;
909931

910932
case FFI_TYPE_FLOAT:
933+
do_float:
911934
if (pfr < end_pfr && i < nfixedargs)
912935
{
913936
/* Float values are stored as doubles in the
@@ -917,7 +940,13 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
917940
pfr++;
918941
}
919942
else
920-
avalue[i] = pst;
943+
{
944+
#ifndef __LITTLE_ENDIAN__
945+
avalue[i] = (char *) pst + 4;
946+
#else
947+
avalue[i] = pst;
948+
#endif
949+
}
921950
pst++;
922951
break;
923952

0 commit comments

Comments
 (0)
0