1 /* _Float128 ifunc ABI/ifunc generation macros.
2    Copyright (C) 2020-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #ifndef _FLOAT128_IFUNC_H
20 #define _FLOAT128_IFUNC_H 1
21 
22 /* Disable hidden prototypes.  These perform function renames which
23    prevent the ifunc functions from working.  */
24 #undef hidden_proto
25 #define hidden_proto(x)
26 #define NO_MATH_REDIRECT 1
27 
28 /* Include the real math.h to avoid optimizations caused by include/math.h
29    (e.x fabsf128 prototype is masked by an inline definition).*/
30 #define f64xfmaf128 __hide_f64xfmaf128
31 #define f64xsqrtf128 __hide_f64xsqrtf128
32 #include <math/math.h>
33 #undef f64xfmaf128
34 #undef f64xsqrtf128
35 #include <math_private.h>
36 #include <complex.h>
37 #include <first-versions.h>
38 #include <shlib-compat.h>
39 #include "init-arch.h"
40 
41 #include <libm-alias-float128.h>
42 #include <libm-alias-finite.h>
43 #include <math-narrow-alias.h>
44 
45 /* _F128_IFUNC2(func, from, r)
46       Generate an ifunc symbol func ## r from the symbols
47 	from ## {power8, power9} ## r
48 
49       We use the PPC hwcap bit HAS_IEEE128 to select between the two with
50       the assumption all P9 features are available on such targets.  */
51 #define _F128_IFUNC2(func, from, r) \
52 	libc_ifunc (func ## r, (hwcap2 & PPC_FEATURE2_HAS_IEEE128) \
53                                 ? from ## _power9 ## r : from ## _power8 ## r)
54 
55 /* _F128_IFUNC(func, r)
56       Similar to above, except the exported symbol name trivially remaps from
57       func ## {cpu} ## r to func ## r.  */
58 #define _F128_IFUNC(func, r) _F128_IFUNC2(func, func, r)
59 
60 /* MAKE_IMPL_IFUNC2(func, pfx1, pfx2, r)
61      Declare external symbols of type pfx1 ## func ## f128 ## r with the name
62                                       pfx2 ## func ## f128 ## _{cpu} ## r
63      which are exported as implementation specific symbols (i.e backing support
64      for type classification macros).  */
65 #define MAKE_IMPL_IFUNC2(func, pfx1, pfx2, r) \
66 	extern __typeof (pfx1 ## func ## f128 ## r) pfx2 ## func ## f128_power8 ## r; \
67 	extern __typeof (pfx1 ## func ## f128 ## r) pfx2 ## func ## f128_power9 ## r; \
68         _F128_IFUNC2 (__ ## func ## f128, pfx2 ## func ## f128, r);
69 
70 /* GEN_COMPAT_R_e(f)
71      Generate a compatability symbol for finite alias of ieee function.  */
72 #define GEN_COMPAT_R_e(f, r) \
73 	libm_alias_finite (__ieee754_ ## f ## f128 ## r, __ ## f ## f128 ## r)
74 
75 #define GEN_COMPAT_e_acos(f) GEN_COMPAT_R_e(f,)
76 #define GEN_COMPAT_e_acosh(f) GEN_COMPAT_R_e(f,)
77 #define GEN_COMPAT_e_asin(f) GEN_COMPAT_R_e(f,)
78 #define GEN_COMPAT_e_sinh(f) GEN_COMPAT_R_e(f,)
79 #define GEN_COMPAT_e_atan2(f) GEN_COMPAT_R_e(f,)
80 #define GEN_COMPAT_e_atanh(f) GEN_COMPAT_R_e(f,)
81 #define GEN_COMPAT_e_cosh(f) GEN_COMPAT_R_e(f,)
82 #define GEN_COMPAT_e_exp10(f) GEN_COMPAT_R_e(f,)
83 #define GEN_COMPAT_e_exp2(f) GEN_COMPAT_R_e(f,)
84 #define GEN_COMPAT_e_exp(f) GEN_COMPAT_R_e(f,)
85 #define GEN_COMPAT_e_fmod(f) GEN_COMPAT_R_e(f,)
86 #define GEN_COMPAT_e_gamma_r(f) GEN_COMPAT_R_e(f,_r)
87 #define GEN_COMPAT_e_hypot(f) GEN_COMPAT_R_e(f,)
88 #define GEN_COMPAT_e_j0(f) GEN_COMPAT_R_e(f,) GEN_COMPAT_R_e(y0,)
89 #define GEN_COMPAT_e_j1(f) GEN_COMPAT_R_e(f,) GEN_COMPAT_R_e(y1,)
90 #define GEN_COMPAT_e_jn(f) GEN_COMPAT_R_e(f,) GEN_COMPAT_R_e(yn,)
91 #define GEN_COMPAT_e_lgamma_r(f) GEN_COMPAT_R_e(f,_r)
92 #define GEN_COMPAT_e_log10(f) GEN_COMPAT_R_e(f,)
93 #define GEN_COMPAT_e_log2(f) GEN_COMPAT_R_e(f,)
94 #define GEN_COMPAT_e_log(f) GEN_COMPAT_R_e(f,)
95 #define GEN_COMPAT_e_pow(f) GEN_COMPAT_R_e(f,)
96 #define GEN_COMPAT_e_remainder(f) GEN_COMPAT_R_e(f,)
97 #define GEN_COMPAT_e_sqrt(f) GEN_COMPAT_R_e(f,)
98 
99 /* MAKE_IEEE_IFUNC_R(func, pfx, r)
100     Declare an ieee ifunc symbol used internally by libm.  E.g __ieee754_sinf128  */
101 #define MAKE_IEEE_IFUNC_R(func, r) \
102 	extern __typeof (__ieee754_ ## func ## f128 ## r) __ieee754_ ## func ## f128_power8 ## r; \
103 	extern __typeof (__ieee754_ ## func ## f128 ## r) __ieee754_ ## func ## f128_power9 ## r; \
104         _F128_IFUNC2 (__ieee754_ ## func ## f128, __ieee754_ ## func ## f128, r);
105 
106 /* MAKE_IFUNCP_WRAP_R(w, func, r)
107       Export a function which the implementation wraps with prefix w to
108       to func ## r.  */
109 #define MAKE_IFUNCP_WRAP_R(w, func, r) \
110 	extern __typeof (func ## f128 ## r) __ ## func ## f128 ## r; \
111 	MAKE_IMPL_IFUNC2 (func,__,__ ## w, r) \
112 	weak_alias (__ ## func ## f128 ## r, func ## f128 ## r); \
113 	libm_alias_float128_other_r (__ ## func, func, r);
114 
115 /* MAKE_IFUNCP_R(func, r)
116     The default IFUNC generator for all libm _Float128 ABI except
117     when specifically overwritten.  This is a convenience wrapper
118     around MAKE_IFUNCP_R where w is not used.  */
119 #define MAKE_IFUNCP_R(func,r) MAKE_IFUNCP_WRAP_R (,func,r)
120 
121 /* Generic aliasing functions.  */
122 #define DECL_ALIAS(f) MAKE_IFUNCP_R (f,)
123 #define DECL_ALIAS_s(f) MAKE_IFUNCP_R (f,)
124 #define DECL_ALIAS_w(f) MAKE_IFUNCP_R (f,)
125 #define DECL_ALIAS_e(f) MAKE_IEEE_IFUNC_R (f,)
126 #define DECL_ALIAS_k(f)
127 #define DECL_ALIAS_R_w(f) MAKE_IFUNCP_R (f, _r)
128 #define DECL_ALIAS_R_e(f) MAKE_IEEE_IFUNC_R (f,_r)
129 
130 /* No symbols are defined in these helper/wrapper objects. */
131 #define DECL_ALIAS_lgamma_neg(x)
132 #define DECL_ALIAS_lgamma_product(x)
133 #define DECL_ALIAS_gamma_product(x)
134 #define DECL_ALIAS_x2y2m1(x)
135 #define DECL_ALIAS_s_log1p(x)
136 #define DECL_ALIAS_s_scalbln(x)
137 #define DECL_ALIAS_s_scalbn(x)
138 
139 /* Ensure the wrapper functions get exposed via IFUNC, not the
140    wrappee (e.g __w_log1pf128_power8 instead of __log1pf128_power8.  */
141 #define DECL_ALIAS_w_log1p(x) MAKE_IFUNCP_WRAP_R(w_,x,)
142 #define DECL_ALIAS_w_scalbln(x) MAKE_IFUNCP_WRAP_R(w_,x,)
143 
144 /* These are declared in their respective jX objects.  */
145 #define DECL_ALIAS_w_j0(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_R (y0,)
146 #define DECL_ALIAS_w_j1(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_R (y1,)
147 #define DECL_ALIAS_w_jn(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_R (yn,)
148 #define DECL_ALIAS_e_j0(f) MAKE_IEEE_IFUNC_R (f,) MAKE_IEEE_IFUNC_R (y0,)
149 #define DECL_ALIAS_e_j1(f) MAKE_IEEE_IFUNC_R (f,) MAKE_IEEE_IFUNC_R (y1,)
150 #define DECL_ALIAS_e_jn(f) MAKE_IEEE_IFUNC_R (f,) MAKE_IEEE_IFUNC_R (yn,)
151 
152 #define DECL_ALIAS_s_erf(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_R (erfc,)
153 
154 /* scalbnf128 is an alias of ldexpf128.  */
155 #define DECL_ALIAS_s_ldexp(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_WRAP_R (wrap_, scalbn,)
156 
157 /* f64xfmaf128 is an alias of fmaf128.  */
158 #define DECL_ALIAS_s_fma(f) MAKE_IFUNCP_R (f,) libm_alias_float128_narrow (__fma, fma)
159 
160 /* f64xsqrtf128 is an alias of sqrtf128.  */
161 #define DECL_ALIAS_w_sqrt(f) MAKE_IFUNCP_R (f,) libm_alias_float128_narrow (__sqrt, sqrt)
162 
163 /* Declare an IFUNC for a symbol which only exists
164    to provide long double == ieee128 ABI.  */
165 #define DECL_LDOUBLE_ALIAS(func, RTYPE, ARGS) \
166 	extern RTYPE func ARGS; \
167 	extern __typeof (func) func ## _power8; \
168 	extern __typeof (func) func ## _power9; \
169 	_F128_IFUNC ( func,)
170 
171 /* Handle the special case functions which exist only to support
172    ldouble == ieee128.  */
173 #define DECL_ALIAS_w_scalb(x) \
174 	DECL_LDOUBLE_ALIAS (__scalbf128,_Float128, (_Float128, _Float128)) \
175 	libm_alias_float128_other_r_ldbl (__scalb, scalb,)
176 
177 #endif /* ifndef _FLOAT128_IFUNC_H  */
178