1/* Copyright (C) 1989-2020 Free Software Foundation, Inc. 2 3This file is part of GCC. 4 5GCC is free software; you can redistribute it and/or modify it under 6the terms of the GNU General Public License as published by the Free 7Software Foundation; either version 3, or (at your option) any later 8version. 9 10GCC is distributed in the hope that it will be useful, but WITHOUT ANY 11WARRANTY; without even the implied warranty of MERCHANTABILITY or 12FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13for more details. 14 15Under Section 7 of GPL version 3, you are granted additional 16permissions described in the GCC Runtime Library Exception, version 173.1, as published by the Free Software Foundation. 18 19You should have received a copy of the GNU General Public License and 20a copy of the GCC Runtime Library Exception along with this program; 21see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22<http://www.gnu.org/licenses/>. */ 23 24/* This is a temporary specialization of code from libgcc/libgcc2.c. */ 25 26#include "soft-fp.h" 27#include "quad-float128.h" 28 29#define COPYSIGN(x,y) __builtin_copysignf128 (x, y) 30#define INFINITY __builtin_inff128 () 31#define isnan __builtin_isnan 32#define isinf __builtin_isinf 33 34#if defined(FLOAT128_HW_INSNS) && !defined(__mulkc3) 35#define __mulkc3 __mulkc3_sw 36#endif 37 38TCtype 39__mulkc3 (TFtype a, TFtype b, TFtype c, TFtype d) 40{ 41 TFtype ac, bd, ad, bc, x, y; 42 TCtype res; 43 44 ac = a * c; 45 bd = b * d; 46 ad = a * d; 47 bc = b * c; 48 49 x = ac - bd; 50 y = ad + bc; 51 52 if (isnan (x) && isnan (y)) 53 { 54 /* Recover infinities that computed as NaN + iNaN. */ 55 _Bool recalc = 0; 56 if (isinf (a) || isinf (b)) 57 { 58 /* z is infinite. "Box" the infinity and change NaNs in 59 the other factor to 0. */ 60 a = COPYSIGN (isinf (a) ? 1 : 0, a); 61 b = COPYSIGN (isinf (b) ? 1 : 0, b); 62 if (isnan (c)) c = COPYSIGN (0, c); 63 if (isnan (d)) d = COPYSIGN (0, d); 64 recalc = 1; 65 } 66 if (isinf (c) || isinf (d)) 67 { 68 /* w is infinite. "Box" the infinity and change NaNs in 69 the other factor to 0. */ 70 c = COPYSIGN (isinf (c) ? 1 : 0, c); 71 d = COPYSIGN (isinf (d) ? 1 : 0, d); 72 if (isnan (a)) a = COPYSIGN (0, a); 73 if (isnan (b)) b = COPYSIGN (0, b); 74 recalc = 1; 75 } 76 if (!recalc 77 && (isinf (ac) || isinf (bd) 78 || isinf (ad) || isinf (bc))) 79 { 80 /* Recover infinities from overflow by changing NaNs to 0. */ 81 if (isnan (a)) a = COPYSIGN (0, a); 82 if (isnan (b)) b = COPYSIGN (0, b); 83 if (isnan (c)) c = COPYSIGN (0, c); 84 if (isnan (d)) d = COPYSIGN (0, d); 85 recalc = 1; 86 } 87 if (recalc) 88 { 89 x = INFINITY * (a * c - b * d); 90 y = INFINITY * (a * d + b * c); 91 } 92 } 93 94 __real__ res = x; 95 __imag__ res = y; 96 return res; 97} 98 99