| /* Automatic switching between software and hardware IEEE 128-bit |
| floating-point emulation for PowerPC. |
| |
| Copyright (C) 2016-2021 Free Software Foundation, Inc. |
| This file is part of the GNU C Library. |
| Contributed by Michael Meissner (meissner@linux.vnet.ibm.com) |
| Code is based on the main soft-fp library written by: |
| Richard Henderson (rth@cygnus.com) and |
| Jakub Jelinek (jj@ultra.linux.cz). |
| |
| The GNU C Library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 of the License, or (at your option) any later version. |
| |
| In addition to the permissions in the GNU Lesser General Public |
| License, the Free Software Foundation gives you unlimited |
| permission to link the compiled version of this file into |
| combinations with other programs, and to distribute those |
| combinations without any restriction coming from the use of this |
| file. (The Lesser General Public License restrictions do apply in |
| other respects; for example, they cover modification of the file, |
| and distribution when not linked into a combine executable.) |
| |
| The GNU C Library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with the GNU C Library; if not, see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include <soft-fp.h> |
| #include <quad-float128.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <ctype.h> |
| |
| #ifndef FLOAT128_HW_INSNS |
| #error "float128-ifunc.c needs access to ISA 3.0 instructions and ifunc" |
| #endif |
| |
| #ifdef __FLOAT128_HARDWARE__ |
| #error "This module must not be compiled with IEEE 128-bit hardware support" |
| #endif |
| |
| #define SW_OR_HW(SW, HW) (__builtin_cpu_supports ("ieee128") ? HW : SW) |
| #ifdef FLOAT128_HW_INSNS_ISA3_1 |
| #define SW_OR_HW_ISA3_1(SW, HW) (__builtin_cpu_supports ("arch_3_1") ? HW : SW) |
| #endif |
| |
| /* Resolvers. */ |
| static __typeof__ (__addkf3_sw) * |
| __addkf3_resolve (void) |
| { |
| return SW_OR_HW (__addkf3_sw, __addkf3_hw); |
| } |
| |
| static __typeof__ (__subkf3_sw) * |
| __subkf3_resolve (void) |
| { |
| return SW_OR_HW (__subkf3_sw, __subkf3_hw); |
| } |
| |
| static __typeof__ (__mulkf3_sw) * |
| __mulkf3_resolve (void) |
| { |
| return SW_OR_HW (__mulkf3_sw, __mulkf3_hw); |
| } |
| |
| static __typeof__ (__divkf3_sw) * |
| __divkf3_resolve (void) |
| { |
| return SW_OR_HW (__divkf3_sw, __divkf3_hw); |
| } |
| |
| static __typeof__ (__negkf2_sw) * |
| __negkf2_resolve (void) |
| { |
| return SW_OR_HW (__negkf2_sw, __negkf2_hw); |
| } |
| |
| static __typeof__ (__powikf2_sw) * |
| __powikf2_resolve (void) |
| { |
| return SW_OR_HW (__powikf2_sw, __powikf2_hw); |
| } |
| |
| static __typeof__ (__floatsikf_sw) * |
| __floatsikf_resolve (void) |
| { |
| return SW_OR_HW (__floatsikf_sw, __floatsikf_hw); |
| } |
| |
| static __typeof__ (__floatdikf_sw) * |
| __floatdikf_resolve (void) |
| { |
| return SW_OR_HW (__floatdikf_sw, __floatdikf_hw); |
| } |
| |
| #ifdef FLOAT128_HW_INSNS_ISA3_1 |
| static __typeof__ (__floattikf_sw) * |
| __floattikf_resolve (void) |
| { |
| return SW_OR_HW_ISA3_1 (__floattikf_sw, __floattikf_hw); |
| } |
| |
| static __typeof__ (__floatuntikf_sw) * |
| __floatuntikf_resolve (void) |
| { |
| return SW_OR_HW_ISA3_1 (__floatuntikf_sw, __floatuntikf_hw); |
| } |
| #endif |
| |
| static __typeof__ (__floatunsikf_sw) * |
| __floatunsikf_resolve (void) |
| { |
| return SW_OR_HW (__floatunsikf_sw, __floatunsikf_hw); |
| } |
| |
| static __typeof__ (__floatundikf_sw) * |
| __floatundikf_resolve (void) |
| { |
| return SW_OR_HW (__floatundikf_sw, __floatundikf_hw); |
| } |
| |
| #ifdef FLOAT128_HW_INSNS_ISA3_1 |
| static __typeof__ (__fixkfti_sw) * |
| __fixkfti_resolve (void) |
| { |
| return SW_OR_HW_ISA3_1 (__fixkfti_sw, __fixkfti_hw); |
| } |
| |
| static __typeof__ (__fixunskfti_sw) * |
| __fixunskfti_resolve (void) |
| { |
| return SW_OR_HW_ISA3_1 (__fixunskfti_sw, __fixunskfti_hw); |
| } |
| #endif |
| |
| static __typeof__ (__fixkfsi_sw) * |
| __fixkfsi_resolve (void) |
| { |
| return SW_OR_HW (__fixkfsi_sw, __fixkfsi_hw); |
| } |
| |
| static __typeof__ (__fixkfdi_sw) * |
| __fixkfdi_resolve (void) |
| { |
| return SW_OR_HW (__fixkfdi_sw, __fixkfdi_hw); |
| } |
| |
| static __typeof__ (__fixunskfsi_sw) * |
| __fixunskfsi_resolve (void) |
| { |
| return SW_OR_HW (__fixunskfsi_sw, __fixunskfsi_hw); |
| } |
| |
| static __typeof__ (__fixunskfdi_sw) * |
| __fixunskfdi_resolve (void) |
| { |
| return SW_OR_HW (__fixunskfdi_sw, __fixunskfdi_hw); |
| } |
| |
| static __typeof__ (__extendsfkf2_sw) * |
| __extendsfkf2_resolve (void) |
| { |
| return SW_OR_HW (__extendsfkf2_sw, __extendsfkf2_hw); |
| } |
| |
| static __typeof__ (__extenddfkf2_sw) * |
| __extenddfkf2_resolve (void) |
| { |
| return SW_OR_HW (__extenddfkf2_sw, __extenddfkf2_hw); |
| } |
| |
| static __typeof__ (__trunckfsf2_sw) * |
| __trunckfsf2_resolve (void) |
| { |
| return SW_OR_HW (__trunckfsf2_sw, __trunckfsf2_hw); |
| } |
| |
| static __typeof__ (__trunckfdf2_sw) * |
| __trunckfdf2_resolve (void) |
| { |
| return (void *) SW_OR_HW (__trunckfdf2_sw, __trunckfdf2_hw); |
| } |
| |
| static __typeof__ (__extendkftf2_sw) * |
| __extendkftf2_resolve (void) |
| { |
| return SW_OR_HW (__extendkftf2_sw, __extendkftf2_hw); |
| } |
| |
| static __typeof__ (__trunctfkf2_sw) * |
| __trunctfkf2_resolve (void) |
| { |
| return SW_OR_HW (__trunctfkf2_sw, __trunctfkf2_hw); |
| } |
| |
| static __typeof__ (__mulkc3_sw) * |
| __mulkc3_resolve (void) |
| { |
| return SW_OR_HW (__mulkc3_sw, __mulkc3_hw); |
| } |
| |
| static __typeof__ (__divkc3_sw) * |
| __divkc3_resolve (void) |
| { |
| return SW_OR_HW (__divkc3_sw, __divkc3_hw); |
| } |
| |
| static __typeof__ (__eqkf2_sw) * |
| __eqkf2_resolve (void) |
| { |
| return SW_OR_HW (__eqkf2_sw, __eqkf2_hw); |
| } |
| |
| static __typeof__ (__gekf2_sw) * |
| __gekf2_resolve (void) |
| { |
| return SW_OR_HW (__gekf2_sw, __gekf2_hw); |
| } |
| |
| static __typeof__ (__lekf2_sw) * |
| __lekf2_resolve (void) |
| { |
| return SW_OR_HW (__lekf2_sw, __lekf2_hw); |
| } |
| |
| static __typeof__ (__unordkf2_sw) * |
| __unordkf2_resolve (void) |
| { |
| return SW_OR_HW (__unordkf2_sw, __unordkf2_hw); |
| } |
| |
| /* Resolve __nekf2, __gtkf2, __ltkf2 like __eqkf2, __gekf2, and __lekf2, since |
| the functions return the same values. */ |
| |
| static __typeof__ (__eqkf2_sw) * |
| __nekf2_resolve (void) |
| { |
| return SW_OR_HW (__eqkf2_sw, __eqkf2_hw); |
| } |
| |
| static __typeof__ (__eqkf2_sw) * |
| __gtkf2_resolve (void) |
| { |
| return SW_OR_HW (__gekf2_sw, __gekf2_hw); |
| } |
| |
| static __typeof__ (__eqkf2_sw) * |
| __ltkf2_resolve (void) |
| { |
| return SW_OR_HW (__lekf2_sw, __lekf2_hw); |
| } |
| |
| |
| |
| /* Ifunc definitions. */ |
| TFtype __addkf3 (TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__addkf3_resolve"))); |
| |
| TFtype __subkf3 (TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__subkf3_resolve"))); |
| |
| TFtype __mulkf3 (TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__mulkf3_resolve"))); |
| |
| TFtype __divkf3 (TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__divkf3_resolve"))); |
| |
| TFtype __negkf2 (TFtype) |
| __attribute__ ((__ifunc__ ("__negkf2_resolve"))); |
| |
| TFtype __powikf2 (TFtype, SItype_ppc) |
| __attribute__ ((__ifunc__ ("__powikf2_resolve"))); |
| |
| CMPtype __eqkf2 (TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__eqkf2_resolve"))); |
| |
| CMPtype __nekf2 (TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__nekf2_resolve"))); |
| |
| CMPtype __gekf2 (TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__gekf2_resolve"))); |
| |
| CMPtype __gtkf2 (TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__gtkf2_resolve"))); |
| |
| CMPtype __lekf2 (TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__lekf2_resolve"))); |
| |
| CMPtype __ltkf2 (TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__ltkf2_resolve"))); |
| |
| CMPtype __unordkf2 (TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__unordkf2_resolve"))); |
| |
| TFtype __extendsfkf2 (float) |
| __attribute__ ((__ifunc__ ("__extendsfkf2_resolve"))); |
| |
| TFtype __extenddfkf2 (double) |
| __attribute__ ((__ifunc__ ("__extenddfkf2_resolve"))); |
| |
| float __trunckfsf2 (TFtype) |
| __attribute__ ((__ifunc__ ("__trunckfsf2_resolve"))); |
| |
| double __trunckfdf2 (TFtype) |
| __attribute__ ((__ifunc__ ("__trunckfdf2_resolve"))); |
| |
| SItype_ppc __fixkfsi (TFtype) |
| __attribute__ ((__ifunc__ ("__fixkfsi_resolve"))); |
| |
| DItype_ppc __fixkfdi (TFtype) |
| __attribute__ ((__ifunc__ ("__fixkfdi_resolve"))); |
| |
| USItype_ppc __fixunskfsi (TFtype) |
| __attribute__ ((__ifunc__ ("__fixunskfsi_resolve"))); |
| |
| UDItype_ppc __fixunskfdi (TFtype) |
| __attribute__ ((__ifunc__ ("__fixunskfdi_resolve"))); |
| |
| TFtype __floatsikf (SItype_ppc) |
| __attribute__ ((__ifunc__ ("__floatsikf_resolve"))); |
| |
| TFtype __floatdikf (DItype_ppc) |
| __attribute__ ((__ifunc__ ("__floatdikf_resolve"))); |
| |
| #ifdef FLOAT128_HW_INSNS_ISA3_1 |
| TFtype __floattikf (TItype_ppc) |
| __attribute__ ((__ifunc__ ("__floattikf_resolve"))); |
| |
| TFtype __floatuntikf (UTItype_ppc) |
| __attribute__ ((__ifunc__ ("__floatuntikf_resolve"))); |
| |
| TItype_ppc __fixkfti (TFtype) |
| __attribute__ ((__ifunc__ ("__fixkfti_resolve"))); |
| |
| UTItype_ppc __fixunskfti (TFtype) |
| __attribute__ ((__ifunc__ ("__fixunskfti_resolve"))); |
| #endif |
| |
| TFtype __floatunsikf (USItype_ppc) |
| __attribute__ ((__ifunc__ ("__floatunsikf_resolve"))); |
| |
| TFtype __floatundikf (UDItype_ppc) |
| __attribute__ ((__ifunc__ ("__floatundikf_resolve"))); |
| |
| IBM128_TYPE __extendkftf2 (TFtype) |
| __attribute__ ((__ifunc__ ("__extendkftf2_resolve"))); |
| |
| TFtype __trunctfkf2 (IBM128_TYPE) |
| __attribute__ ((__ifunc__ ("__trunctfkf2_resolve"))); |
| |
| TCtype __mulkc3 (TFtype, TFtype, TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__mulkc3_resolve"))); |
| |
| TCtype __divkc3 (TFtype, TFtype, TFtype, TFtype) |
| __attribute__ ((__ifunc__ ("__divkc3_resolve"))); |