1 /* Automatic switching between software and hardware IEEE 128-bit 2 floating-point emulation for PowerPC. 3 4 Copyright (C) 2016 Free Software Foundation, Inc. 5 This file is part of the GNU C Library. 6 Contributed by Michael Meissner (meissner@linux.vnet.ibm.com) 7 Code is based on the main soft-fp library written by: 8 Richard Henderson (rth@cygnus.com) and 9 Jakub Jelinek (jj@ultra.linux.cz). 10 11 The GNU C Library is free software; you can redistribute it and/or 12 modify it under the terms of the GNU Lesser General Public 13 License as published by the Free Software Foundation; either 14 version 2.1 of the License, or (at your option) any later version. 15 16 In addition to the permissions in the GNU Lesser General Public 17 License, the Free Software Foundation gives you unlimited 18 permission to link the compiled version of this file into 19 combinations with other programs, and to distribute those 20 combinations without any restriction coming from the use of this 21 file. (The Lesser General Public License restrictions do apply in 22 other respects; for example, they cover modification of the file, 23 and distribution when not linked into a combine executable.) 24 25 The GNU C Library is distributed in the hope that it will be useful, 26 but WITHOUT ANY WARRANTY; without even the implied warranty of 27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 28 Lesser General Public License for more details. 29 30 You should have received a copy of the GNU Lesser General Public 31 License along with the GNU C Library; if not, see 32 <http://www.gnu.org/licenses/>. */ 33 34 #include <soft-fp.h> 35 #include <quad-float128.h> 36 #include <string.h> 37 #include <stdlib.h> 38 #include <ctype.h> 39 40 #ifndef FLOAT128_HW_INSNS 41 #error "float128-ifunc.c needs access to ISA 3.0 instructions and ifunc" 42 #endif 43 44 #ifdef __FLOAT128_HARDWARE__ 45 #error "This module must not be compiled with IEEE 128-bit hardware support" 46 #endif 47 48 #include <sys/auxv.h> 49 50 /* Use the namespace clean version of getauxval. However, not all versions of 51 sys/auxv.h declare it, so declare it here. This code is intended to be 52 temporary until a suitable version of __builtin_cpu_supports is added that 53 allows us to tell quickly if the machine supports IEEE 128-bit hardware. */ 54 extern unsigned long __getauxval (unsigned long); 55 56 static int 57 have_ieee_hw_p (void) 58 { 59 static int ieee_hw_p = -1; 60 61 if (ieee_hw_p < 0) 62 { 63 char *p = (char *) __getauxval (AT_PLATFORM); 64 65 ieee_hw_p = 0; 66 67 /* Don't use atoi/strtol/strncmp/etc. These may require the normal 68 environment to be setup to set errno to 0, and the ifunc resolvers run 69 before the whole glibc environment is initialized. */ 70 if (p && p[0] == 'p' && p[1] == 'o' && p[2] == 'w' && p[3] == 'e' 71 && p[4] == 'r') 72 { 73 long n = 0; 74 char ch; 75 76 p += 5; 77 while ((ch = *p++) >= '0' && (ch <= '9')) 78 n = (n * 10) + (ch - '0'); 79 80 if (n >= 9) 81 ieee_hw_p = 1; 82 } 83 } 84 85 return ieee_hw_p; 86 } 87 88 #define SW_OR_HW(SW, HW) (have_ieee_hw_p () ? HW : SW) 89 90 /* Resolvers. */ 91 92 /* We do not provide ifunc resolvers for __fixkfti, __fixunskfti, __floattikf, 93 and __floatuntikf. There is no ISA 3.0 instruction that converts between 94 128-bit integer types and 128-bit IEEE floating point, or vice versa. So 95 use the emulator functions for these conversions. */ 96 97 static void *__addkf3_resolve (void); 98 static void *__subkf3_resolve (void); 99 static void *__mulkf3_resolve (void); 100 static void *__divkf3_resolve (void); 101 static void *__negkf2_resolve (void); 102 static void *__eqkf2_resolve (void); 103 static void *__nekf2_resolve (void); 104 static void *__gekf2_resolve (void); 105 static void *__gtkf2_resolve (void); 106 static void *__lekf2_resolve (void); 107 static void *__ltkf2_resolve (void); 108 static void *__unordkf2_resolve (void); 109 static void *__extendsfkf2_resolve (void); 110 static void *__extenddfkf2_resolve (void); 111 static void *__trunckfsf2_resolve (void); 112 static void *__trunckfdf2_resolve (void); 113 static void *__fixkfsi_resolve (void); 114 static void *__fixkfdi_resolve (void); 115 static void *__fixunskfsi_resolve (void); 116 static void *__fixunskfdi_resolve (void); 117 static void *__floatsikf_resolve (void); 118 static void *__floatdikf_resolve (void); 119 static void *__floatunsikf_resolve (void); 120 static void *__floatundikf_resolve (void); 121 static void *__extendkftf2_resolve (void); 122 static void *__trunctfkf2_resolve (void); 123 124 static void * 125 __addkf3_resolve (void) 126 { 127 return (void *) SW_OR_HW (__addkf3_sw, __addkf3_hw); 128 } 129 130 static void * 131 __subkf3_resolve (void) 132 { 133 return (void *) SW_OR_HW (__subkf3_sw, __subkf3_hw); 134 } 135 136 static void * 137 __mulkf3_resolve (void) 138 { 139 return (void *) SW_OR_HW (__mulkf3_sw, __mulkf3_hw); 140 } 141 142 static void * 143 __divkf3_resolve (void) 144 { 145 return (void *) SW_OR_HW (__divkf3_sw, __divkf3_hw); 146 } 147 148 static void * 149 __negkf2_resolve (void) 150 { 151 return (void *) SW_OR_HW (__negkf2_sw, __negkf2_hw); 152 } 153 154 static void * 155 __floatsikf_resolve (void) 156 { 157 return (void *) SW_OR_HW (__floatsikf_sw, __floatsikf_hw); 158 } 159 160 static void * 161 __floatdikf_resolve (void) 162 { 163 return (void *) SW_OR_HW (__floatdikf_sw, __floatdikf_hw); 164 } 165 166 static void * 167 __floatunsikf_resolve (void) 168 { 169 return (void *) SW_OR_HW (__floatunsikf_sw, __floatunsikf_hw); 170 } 171 172 static void * 173 __floatundikf_resolve (void) 174 { 175 return (void *) SW_OR_HW (__floatundikf_sw, __floatundikf_hw); 176 } 177 178 static void * 179 __fixkfsi_resolve (void) 180 { 181 return (void *) SW_OR_HW (__fixkfsi_sw, __fixkfsi_hw); 182 } 183 184 static void * 185 __fixkfdi_resolve (void) 186 { 187 return (void *) SW_OR_HW (__fixkfdi_sw, __fixkfdi_hw); 188 } 189 190 static void * 191 __fixunskfsi_resolve (void) 192 { 193 return (void *) SW_OR_HW (__fixunskfsi_sw, __fixunskfsi_hw); 194 } 195 196 static void * 197 __fixunskfdi_resolve (void) 198 { 199 return (void *) SW_OR_HW (__fixunskfdi_sw, __fixunskfdi_hw); 200 } 201 202 static void * 203 __extendsfkf2_resolve (void) 204 { 205 return (void *) SW_OR_HW (__extendsfkf2_sw, __extendsfkf2_hw); 206 } 207 208 static void * 209 __extenddfkf2_resolve (void) 210 { 211 return (void *) SW_OR_HW (__extenddfkf2_sw, __extenddfkf2_hw); 212 } 213 214 static void * 215 __trunckfsf2_resolve (void) 216 { 217 return (void *) SW_OR_HW (__trunckfsf2_sw, __trunckfsf2_hw); 218 } 219 220 static void * 221 __trunckfdf2_resolve (void) 222 { 223 return (void *) SW_OR_HW (__trunckfdf2_sw, __trunckfdf2_hw); 224 } 225 226 static void * 227 __extendkftf2_resolve (void) 228 { 229 return (void *) SW_OR_HW (__extendkftf2_sw, __extendkftf2_hw); 230 } 231 232 static void * 233 __trunctfkf2_resolve (void) 234 { 235 return (void *) SW_OR_HW (__trunctfkf2_sw, __trunctfkf2_hw); 236 } 237 238 static void * 239 __eqkf2_resolve (void) 240 { 241 return (void *) SW_OR_HW (__eqkf2_sw, __eqkf2_hw); 242 } 243 244 static void * 245 __gekf2_resolve (void) 246 { 247 return (void *) SW_OR_HW (__gekf2_sw, __gekf2_hw); 248 } 249 250 static void * 251 __lekf2_resolve (void) 252 { 253 return (void *) SW_OR_HW (__lekf2_sw, __lekf2_hw); 254 } 255 256 static void * 257 __unordkf2_resolve (void) 258 { 259 return (void *) SW_OR_HW (__unordkf2_sw, __unordkf2_hw); 260 } 261 262 /* Resolve __nekf2, __gtkf2, __ltkf2 like __eqkf2, __gekf2, and __lekf2, since 263 the functions return the same values. */ 264 265 static void * 266 __nekf2_resolve (void) 267 { 268 return (void *) SW_OR_HW (__eqkf2_sw, __eqkf2_hw); 269 } 270 271 static void * 272 __gtkf2_resolve (void) 273 { 274 return (void *) SW_OR_HW (__gekf2_sw, __gekf2_hw); 275 } 276 277 static void * 278 __ltkf2_resolve (void) 279 { 280 return (void *) SW_OR_HW (__lekf2_sw, __lekf2_hw); 281 } 282 283 284 285 /* Ifunc definitions. */ 286 TFtype __addkf3 (TFtype, TFtype) 287 __attribute__ ((__ifunc__ ("__addkf3_resolve"))); 288 289 TFtype __subkf3 (TFtype, TFtype) 290 __attribute__ ((__ifunc__ ("__subkf3_resolve"))); 291 292 TFtype __mulkf3 (TFtype, TFtype) 293 __attribute__ ((__ifunc__ ("__mulkf3_resolve"))); 294 295 TFtype __divkf3 (TFtype, TFtype) 296 __attribute__ ((__ifunc__ ("__divkf3_resolve"))); 297 298 TFtype __negkf2 (TFtype) 299 __attribute__ ((__ifunc__ ("__negkf2_resolve"))); 300 301 CMPtype __eqkf2 (TFtype, TFtype) 302 __attribute__ ((__ifunc__ ("__eqkf2_resolve"))); 303 304 CMPtype __nekf2 (TFtype, TFtype) 305 __attribute__ ((__ifunc__ ("__nekf2_resolve"))); 306 307 CMPtype __gekf2 (TFtype, TFtype) 308 __attribute__ ((__ifunc__ ("__gekf2_resolve"))); 309 310 CMPtype __gtkf2 (TFtype, TFtype) 311 __attribute__ ((__ifunc__ ("__gtkf2_resolve"))); 312 313 CMPtype __lekf2 (TFtype, TFtype) 314 __attribute__ ((__ifunc__ ("__lekf2_resolve"))); 315 316 CMPtype __ltkf2 (TFtype, TFtype) 317 __attribute__ ((__ifunc__ ("__ltkf2_resolve"))); 318 319 CMPtype __unordkf2 (TFtype, TFtype) 320 __attribute__ ((__ifunc__ ("__unordkf2_resolve"))); 321 322 TFtype __extendsfkf2 (float) 323 __attribute__ ((__ifunc__ ("__extendsfkf2_resolve"))); 324 325 TFtype __extenddfkf2 (double) 326 __attribute__ ((__ifunc__ ("__extenddfkf2_resolve"))); 327 328 float __trunckfsf2 (TFtype) 329 __attribute__ ((__ifunc__ ("__trunckfsf2_resolve"))); 330 331 double __trunckfdf2 (TFtype) 332 __attribute__ ((__ifunc__ ("__trunckfdf2_resolve"))); 333 334 SItype_ppc __fixkfsi (TFtype) 335 __attribute__ ((__ifunc__ ("__fixkfsi_resolve"))); 336 337 DItype_ppc __fixkfdi (TFtype) 338 __attribute__ ((__ifunc__ ("__fixkfdi_resolve"))); 339 340 USItype_ppc __fixunskfsi (TFtype) 341 __attribute__ ((__ifunc__ ("__fixunskfsi_resolve"))); 342 343 UDItype_ppc __fixunskfdi (TFtype) 344 __attribute__ ((__ifunc__ ("__fixunskfdi_resolve"))); 345 346 TFtype __floatsikf (SItype_ppc) 347 __attribute__ ((__ifunc__ ("__floatsikf_resolve"))); 348 349 TFtype __floatdikf (DItype_ppc) 350 __attribute__ ((__ifunc__ ("__floatdikf_resolve"))); 351 352 TFtype __floatunsikf (USItype_ppc) 353 __attribute__ ((__ifunc__ ("__floatunsikf_resolve"))); 354 355 TFtype __floatundikf (UDItype_ppc) 356 __attribute__ ((__ifunc__ ("__floatundikf_resolve"))); 357 358 IBM128_TYPE __extendkftf2 (TFtype) 359 __attribute__ ((__ifunc__ ("__extendkftf2_resolve"))); 360 361 TFtype __trunctfkf2 (IBM128_TYPE) 362 __attribute__ ((__ifunc__ ("__trunctfkf2_resolve"))); 363