1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
Merge from Sourcery G++ 4.4:
2010-02-15 Julian Brown <julian@codesourcery.com>
Issue #7486
gcc/
* config/arm/arm.c (arm_libcall_uses_aapcs_base)
(arm_init_cumulative_args): Use correct ABI for double-precision
helper functions in hard-float mode if only single-precision
arithmetic is supported in hardware.
2010-07-26 Julian Brown <julian@codesourcery.com>
Backport from FSF mainline:
Julian Brown <julian@codesourcery.com>
=== modified file 'gcc/config/arm/arm.c'
--- old/gcc/config/arm/arm.c 2010-08-13 10:30:35 +0000
+++ new/gcc/config/arm/arm.c 2010-08-13 10:43:42 +0000
@@ -3453,6 +3453,28 @@
convert_optab_libfunc (sfix_optab, DImode, SFmode));
add_libcall (libcall_htab,
convert_optab_libfunc (ufix_optab, DImode, SFmode));
+
+ /* Values from double-precision helper functions are returned in core
+ registers if the selected core only supports single-precision
+ arithmetic, even if we are using the hard-float ABI. */
+ if (TARGET_VFP)
+ {
+ add_libcall (libcall_htab, optab_libfunc (add_optab, DFmode));
+ add_libcall (libcall_htab, optab_libfunc (sdiv_optab, DFmode));
+ add_libcall (libcall_htab, optab_libfunc (smul_optab, DFmode));
+ add_libcall (libcall_htab, optab_libfunc (neg_optab, DFmode));
+ add_libcall (libcall_htab, optab_libfunc (sub_optab, DFmode));
+ add_libcall (libcall_htab, optab_libfunc (eq_optab, DFmode));
+ add_libcall (libcall_htab, optab_libfunc (lt_optab, DFmode));
+ add_libcall (libcall_htab, optab_libfunc (le_optab, DFmode));
+ add_libcall (libcall_htab, optab_libfunc (ge_optab, DFmode));
+ add_libcall (libcall_htab, optab_libfunc (gt_optab, DFmode));
+ add_libcall (libcall_htab, optab_libfunc (unord_optab, DFmode));
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (sext_optab, DFmode, SFmode));
+ add_libcall (libcall_htab,
+ convert_optab_libfunc (trunc_optab, SFmode, DFmode));
+ }
}
return libcall && htab_find (libcall_htab, libcall) != NULL;
@@ -4406,6 +4428,31 @@
if (arm_libcall_uses_aapcs_base (libname))
pcum->pcs_variant = ARM_PCS_AAPCS;
+ /* We must pass arguments to double-precision helper functions in core
+ registers if we only have hardware support for single-precision
+ arithmetic, even if we are using the hard-float ABI. */
+ if (TARGET_VFP
+ && (rtx_equal_p (libname, optab_libfunc (add_optab, DFmode))
+ || rtx_equal_p (libname, optab_libfunc (sdiv_optab, DFmode))
+ || rtx_equal_p (libname, optab_libfunc (smul_optab, DFmode))
+ || rtx_equal_p (libname, optab_libfunc (neg_optab, DFmode))
+ || rtx_equal_p (libname, optab_libfunc (sub_optab, DFmode))
+ || rtx_equal_p (libname, optab_libfunc (eq_optab, DFmode))
+ || rtx_equal_p (libname, optab_libfunc (lt_optab, DFmode))
+ || rtx_equal_p (libname, optab_libfunc (le_optab, DFmode))
+ || rtx_equal_p (libname, optab_libfunc (ge_optab, DFmode))
+ || rtx_equal_p (libname, optab_libfunc (gt_optab, DFmode))
+ || rtx_equal_p (libname, optab_libfunc (unord_optab, DFmode))
+ || rtx_equal_p (libname, convert_optab_libfunc (sext_optab,
+ DFmode, SFmode))
+ || rtx_equal_p (libname, convert_optab_libfunc (trunc_optab,
+ SFmode, DFmode))
+ || rtx_equal_p (libname, convert_optab_libfunc (sfix_optab,
+ SImode, DFmode))
+ || rtx_equal_p (libname, convert_optab_libfunc (ufix_optab,
+ SImode, DFmode))))
+ pcum->pcs_variant = ARM_PCS_AAPCS;
+
pcum->aapcs_ncrn = pcum->aapcs_next_ncrn = 0;
pcum->aapcs_reg = NULL_RTX;
pcum->aapcs_partial = 0;
|