1ifeq ($(subdir),math)
2
3#
4# Only enable ifunc _Float128 support if the baseline cpu support
5# is older than power9.
6ifneq (yes,$(libc-submachine-power9))
7do_f128_multiarch = yes
8endif
9
10#
11# This is an ugly, but contained, mechanism to provide hardware optimized
12# _Float128 and ldouble == ieee128 optimized routines for P9 and beyond
13# hardware.  At a very high level, we rely on ASM renames, and rarely
14# macro renames to build two sets of _Float128 ABI, one with _power8 (the
15# baseline powerpc64le cpu) and _power9 (the first powerpc64le cpu to introduce
16# hardware support for _Float128).
17#
18# At a high level, we compile 3 files for each object file.
19#   1.  The baseline soft-float128, unsuffixed objects $(object).$(sfx)
20#       The symbols contained in these files is suffixed by _power8.
21#   2.  The hard-float128, power9, suffixed objects $(object)-power9.$(sfx).
22#       The symbols contained in these files is suffixed by _power9.
23#   3.  The IFUNC wrapper object to export ABI, $(object)-ifunc.$(sfx)
24#       This glues the above together and implements the ABI.
25#
26# 2 & 3 are automatically generated by Makefile rule.  Placing the exported
27# ABI into a separate file allows reuse of existing aliasing macros
28# with minimal hassle.
29#
30#
31# If the float128 ABI is expanded, and a new ifunc wrappers are desired,
32# the following lists how to map new symbols from the shared headers into
33# their local overrides here:
34#
35#   float128_private.h
36#
37#     is used to rename the ldouble == ieee128 object files.  This takes
38#     it a step further and redirects symbols to a local name.  This supports
39#     nearly all files in sysdeps/ieee754/float128, but not all _Float128
40#     objects.  However, this is only meant to be used internally to support
41#     compilation of ldbl-128 into float128.
42#
43#   math-type-macros-float128.h
44#
45#     renames symbols which are generated via shared templated in math/.
46#
47#   math_private.h
48#
49#     provides internal declarations for common macros and functions which
50#     are called from within libm.  Note, float128_private.h duplicates
51#     some of these declarations as these headers are generally not included
52#     in the same translation unit.
53#
54# The above is supported by several header files as described below:
55#
56#   float128-ifunc.h
57#
58#     provides support for generating the IFUNC objects in part 3 above.
59#     This header is only included with wrapper functions.
60#
61#   float128-ifunc-macros.h
62#
63#     disables all first-order float128 aliasing macros used in libm,
64#     and libm wrappers around libc-symbols.h.
65#
66#   float128-ifunc-redirect-macros.h
67#
68#     provides macros which implement the appending of the suffix to
69#     symbols what have been selected.
70#
71#   float128-ifunc-redirects.h
72#
73#     provides ASM redirects for symbols which are redirected in the
74#     private copy of math.h used by glibc, but not declared by math_private.h
75#
76#   float128-ifunc-redirects-mp.h
77#
78#     provides ASM redirects which are used by math_private.h (the -mp suffix)
79#     and the interposer float128_private.h discussed late.
80#
81# Notably, this enforces a slightly different mechanism for machine specific
82# overrides.  Optimizations for all targets must all be reachable from the same
83# file.  See the history to fmaf128 or sqrtf128 to understand how this looks
84# in practice.
85#
86ifeq ($(do_f128_multiarch),yes)
87
88f128-ifunc-calls = s_modff128 s_scalbnf128 s_frexpf128 s_ldexpf128
89gen-libm-f128-ifunc-routines = \
90	e_acosf128 e_acoshf128 e_asinf128 e_atan2f128 e_atanhf128 e_coshf128 \
91	e_expf128 e_fmodf128 e_hypotf128 e_j0f128 e_j1f128 e_jnf128 \
92	e_lgammaf128_r e_logf128 e_log10f128 e_powf128 e_remainderf128 \
93	e_sinhf128 e_sqrtf128 e_gammaf128_r e_ilogbf128 k_tanf128 s_asinhf128 \
94	s_atanf128 s_cbrtf128 s_ceilf128 s_cosf128 s_erff128 s_expm1f128 \
95	s_fabsf128 s_floorf128 s_log1pf128 s_logbf128 \
96	s_rintf128 s_scalblnf128 s_sinf128 s_tanf128 \
97	s_tanhf128 s_truncf128 s_remquof128 e_log2f128 \
98	s_roundf128 s_nearbyintf128 s_sincosf128 s_fmaf128 s_lrintf128 \
99	s_llrintf128 s_lroundf128 s_llroundf128 e_exp10f128 \
100	$(f128-ifunc-calls) $(f128-ifunc-calls:s_%=m_%) x2y2m1f128 \
101	gamma_productf128 lgamma_negf128 lgamma_productf128 s_roundevenf128 \
102	cargf128 conjf128 cimagf128 crealf128 cabsf128 e_scalbf128 s_cacosf128 \
103	s_cacoshf128 s_ccosf128 s_ccoshf128 s_casinf128 s_csinf128 \
104	s_casinhf128 k_casinhf128 s_csinhf128 k_casinhf128 s_csinhf128 \
105	s_catanhf128 s_catanf128 s_ctanf128 s_ctanhf128 s_cexpf128 s_clogf128 \
106	s_cprojf128 s_csqrtf128 s_cpowf128 s_clog10f128 s_fdimf128 \
107	s_fmaxf128 s_fminf128 w_ilogbf128 w_llogbf128 \
108	w_log1pf128 w_scalblnf128 w_acosf128 \
109	w_acoshf128 w_asinf128 w_atan2f128 w_atanhf128 w_coshf128 w_exp10f128 \
110	w_exp2f128 w_fmodf128 w_hypotf128 w_j0f128 w_j1f128 w_jnf128 \
111	w_logf128 w_log10f128 w_log2f128 w_powf128 w_remainderf128 \
112	w_scalbf128 w_sinhf128 w_sqrtf128 w_tgammaf128 w_lgammaf128 \
113	w_lgammaf128_r w_expf128 e_exp2f128 \
114	k_sinf128 k_cosf128 k_sincosf128 e_rem_pio2f128
115
116
117f128-march-routines-p9 = $(addsuffix -power9,$(gen-libm-f128-ifunc-routines))
118f128-march-routines-ifunc = $(addsuffix -ifunc,$(gen-libm-f128-ifunc-routines))
119f128-march-routines = $(f128-march-routines-p9) $(f128-march-routines-ifunc)
120f128-march-cpus = power9
121
122f128-march-calls-p9 = $(addsuffix -power9,$(f128-ifunc-calls))
123f128-march-calls-ifunc = $(addsuffix -ifunc,$(f128-ifunc-calls))
124f128-march-calls = $(f128-march-calls-p9) $(f128-march-calls-ifunc)
125
126calls += $(f128-march-calls)
127libm-routines += $(filter-out $(f128-march-calls), $(f128-march-routines))
128generated += $(f128-march-routines)
129
130CFLAGS-float128-ifunc.c += $(type-float128-CFLAGS) $(no-gnu-attribute-CFLAGS)
131
132# Copy special CFLAGS for some functions
133CFLAGS-s_modff128-power9.c += -fsignaling-nans
134CFLAGS-m_modff128-power9.c += -fsignaling-nans
135
136# Generate ifunc wrapper files and target specific wrappers around
137# each routine above.  Note, m_%.c files are fixed up to include
138# s_%.c files.  This is an artifact of the makefile rules which allow
139# some files to be compiled for libc and libm.
140$(objpfx)gen-float128-ifuncs.stmp: \
141  Makefile $(..)sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
142	$(make-target-directory)
143	for gcall in $(gen-libm-f128-ifunc-routines); do \
144	  ifile="$${gcall}";                             \
145	  if [ $${gcall##m_} != $${gcall} ]; then        \
146	    ifile="s_$${gcall##m_}";                     \
147	  fi;                                            \
148	  for cpu in $(f128-march-cpus); do              \
149	    file=$(objpfx)$${gcall}-$${cpu}.c;           \
150	    {                                            \
151	      echo "#include <$${ifile}.c>";             \
152	    } > $${file};                                \
153	  done;                                          \
154	  name="$${gcall##?_}";                          \
155	  pfx="$${gcall%%_*}";                           \
156	  R="";                                          \
157	  r="";                                          \
158	  if [ $${gcall##m_} != $${gcall} ]; then        \
159	    pfx="s";                                     \
160	  fi;                                            \
161	  if [ $${#pfx} != 1 ]; then                     \
162	    pfx="";                                      \
163	  else                                           \
164	    pfx="_$${pfx}";                              \
165	  fi;                                            \
166	  if [ $${name%%_r} != $${name} ]; then          \
167	    R="_R";                                      \
168	    r="_r";                                      \
169	    name="$${name%%_r}";                         \
170	  fi;                                            \
171	  name="$${name%%f128}";                         \
172	  decl="DECL_ALIAS$${pfx}_$${name}$${r}";        \
173	  compat="GEN_COMPAT$${pfx}_$${name}$${r}";      \
174	  declc="DECL_ALIAS$${R}$${pfx}";                \
175	  {                                              \
176	    echo "#include <float128-ifunc.h>";          \
177	    echo "#ifndef $${decl}";                     \
178	    echo "# define $${decl}(f) $${declc} (f)";   \
179	    echo "#endif";                               \
180	    echo "#ifndef $${compat}";                   \
181	    echo "# define $${compat}(f)";               \
182	    echo "#endif";                               \
183	    echo "$${decl} ($${name});";                 \
184	    echo "$${compat} ($${name});";               \
185	  } > $(objpfx)$${gcall}-ifunc.c;                \
186	done;                                            \
187	echo > $(@)
188
189$(foreach f,$(f128-march-routines),$(objpfx)$(f).c): \
190  $(objpfx)gen-float128-ifuncs.stmp $(objpfx)gen-libm-templates.stmp
191
192enable-f128-ifunc-CFLAGS = -D_F128_ENABLE_IFUNC $(no-gnu-attributes-CFLAGS) $(type-float128-CFLAGS)
193
194# Enable IFUNC on baseline (power8) implementations
195include $(o-iterator)
196define o-iterator-doit
197$(foreach f,$(gen-libm-f128-ifunc-routines),$(objpfx)$(f)$(o)): sysdep-CFLAGS += -D_F128_ENABLE_IFUNC
198endef
199object-suffixes-left := $(all-object-suffixes)
200include $(o-iterator)
201
202# Likewise, but for power9.
203include $(o-iterator)
204define o-iterator-doit
205$(foreach f,$(f128-march-routines-p9),$(objpfx)$(f)$(o)): sysdep-CFLAGS += $$(enable-f128-ifunc-CFLAGS) -mcpu=power9
206endef
207object-suffixes-left := $(all-object-suffixes)
208include $(o-iterator)
209
210endif # do_f128_multiarch
211
212libm-sysdep_routines += e_log-ppc64
213
214ifeq ($(mcpu-power10), yes)
215libm-sysdep_routines += e_log-power10
216CFLAGS-e_log-power10.c += -mcpu=power10
217endif
218
219endif
220