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