1 /* Copyright (C) 2007-2018 Free Software Foundation, Inc.
3 This file is part of GCC.
5 GCC is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 3, or (at your option) any later
10 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 Under Section 7 of GPL version 3, you are granted additional
16 permissions described in the GCC Runtime Library Exception, version
17 3.1, as published by the Free Software Foundation.
19 You should have received a copy of the GNU General Public License and
20 a copy of the GCC Runtime Library Exception along with this program;
21 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
22 <http://www.gnu.org/licenses/>. */
24 #include "bid_internal.h"
26 #if DECIMAL_CALL_BY_REFERENCE
28 bid64dq_mul (UINT64
* pres
, UINT64
* px
, UINT128
* py
29 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
32 #if !DECIMAL_GLOBAL_ROUNDING
33 unsigned int rnd_mode
= *prnd_mode
;
37 bid64dq_mul (UINT64 x
, UINT128 y
38 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
41 UINT64 res
= 0xbaddbaddbaddbaddull
;
44 #if DECIMAL_CALL_BY_REFERENCE
45 bid64_to_bid128 (&x1
, &x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
46 bid64qq_mul (&res
, &x1
, py
47 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
50 x1
= bid64_to_bid128 (x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
51 res
= bid64qq_mul (x1
, y
52 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
59 #if DECIMAL_CALL_BY_REFERENCE
61 bid64qd_mul (UINT64
* pres
, UINT128
* px
, UINT64
* py
62 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
65 #if !DECIMAL_GLOBAL_ROUNDING
66 unsigned int rnd_mode
= *prnd_mode
;
70 bid64qd_mul (UINT128 x
, UINT64 y
71 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
74 UINT64 res
= 0xbaddbaddbaddbaddull
;
77 #if DECIMAL_CALL_BY_REFERENCE
78 bid64_to_bid128 (&y1
, &y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
79 bid64qq_mul (&res
, px
, &y1
80 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
83 y1
= bid64_to_bid128 (y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
84 res
= bid64qq_mul (x
, y1
85 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
92 #if DECIMAL_CALL_BY_REFERENCE
94 bid64qq_mul (UINT64
* pres
, UINT128
* px
, UINT128
* py
95 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
97 UINT128 x
= *px
, y
= *py
;
98 #if !DECIMAL_GLOBAL_ROUNDING
99 unsigned int rnd_mode
= *prnd_mode
;
103 bid64qq_mul (UINT128 x
, UINT128 y
104 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
108 UINT128 z
= { {0x0000000000000000ull
, 0x5ffe000000000000ull
}
110 UINT64 res
= 0xbaddbaddbaddbaddull
;
111 UINT64 x_sign
, y_sign
, p_sign
;
112 UINT64 x_exp
, y_exp
, p_exp
;
117 // skip cases where at least one operand is NaN or infinity
118 if (!(((x
.w
[HIGH_128W
] & MASK_NAN
) == MASK_NAN
) ||
119 ((y
.w
[HIGH_128W
] & MASK_NAN
) == MASK_NAN
) ||
120 ((x
.w
[HIGH_128W
] & MASK_ANY_INF
) == MASK_INF
) ||
121 ((y
.w
[HIGH_128W
] & MASK_ANY_INF
) == MASK_INF
))) {
122 // x, y are 0 or f but not inf or NaN => unpack the arguments and check
123 // for non-canonical values
125 x_sign
= x
.w
[HIGH_128W
] & MASK_SIGN
; // 0 for positive, MASK_SIGN for negative
126 C1
.w
[1] = x
.w
[HIGH_128W
] & MASK_COEFF
;
127 C1
.w
[0] = x
.w
[LOW_128W
];
128 // check for non-canonical values - treated as zero
129 if ((x
.w
[HIGH_128W
] & 0x6000000000000000ull
) ==
130 0x6000000000000000ull
) {
131 // G0_G1=11 => non-canonical
132 x_exp
= (x
.w
[HIGH_128W
] << 2) & MASK_EXP
; // biased and shifted left 49 bits
133 C1
.w
[1] = 0; // significand high
134 C1
.w
[0] = 0; // significand low
135 } else { // G0_G1 != 11
136 x_exp
= x
.w
[HIGH_128W
] & MASK_EXP
; // biased and shifted left 49 bits
137 if (C1
.w
[1] > 0x0001ed09bead87c0ull
||
138 (C1
.w
[1] == 0x0001ed09bead87c0ull
&&
139 C1
.w
[0] > 0x378d8e63ffffffffull
)) {
140 // x is non-canonical if coefficient is larger than 10^34 -1
143 } else { // canonical
147 y_sign
= y
.w
[HIGH_128W
] & MASK_SIGN
; // 0 for positive, MASK_SIGN for negative
148 C2
.w
[1] = y
.w
[HIGH_128W
] & MASK_COEFF
;
149 C2
.w
[0] = y
.w
[LOW_128W
];
150 // check for non-canonical values - treated as zero
151 if ((y
.w
[HIGH_128W
] & 0x6000000000000000ull
) ==
152 0x6000000000000000ull
) {
153 // G0_G1=11 => non-canonical
154 y_exp
= (y
.w
[HIGH_128W
] << 2) & MASK_EXP
; // biased and shifted left 49 bits
155 C2
.w
[1] = 0; // significand high
156 C2
.w
[0] = 0; // significand low
157 } else { // G0_G1 != 11
158 y_exp
= y
.w
[HIGH_128W
] & MASK_EXP
; // biased and shifted left 49 bits
159 if (C2
.w
[1] > 0x0001ed09bead87c0ull
||
160 (C2
.w
[1] == 0x0001ed09bead87c0ull
&&
161 C2
.w
[0] > 0x378d8e63ffffffffull
)) {
162 // y is non-canonical if coefficient is larger than 10^34 -1
165 } else { // canonical
169 p_sign
= x_sign
^ y_sign
; // sign of the product
171 true_p_exp
= (x_exp
>> 49) - 6176 + (y_exp
>> 49) - 6176;
172 // true_p_exp, p_exp are used only for 0 * 0, 0 * f, or f * 0
173 if (true_p_exp
< -398)
174 p_exp
= 0; // cannot be less than EXP_MIN
175 else if (true_p_exp
> 369)
176 p_exp
= (UINT64
) (369 + 398) << 53; // cannot be more than EXP_MAX
178 p_exp
= (UINT64
) (true_p_exp
+ 398) << 53;
180 if ((C1
.w
[1] == 0x0 && C1
.w
[0] == 0x0) ||
181 (C2
.w
[1] == 0x0 && C2
.w
[0] == 0x0)) {
184 res
= p_sign
| p_exp
; // preferred exponent in [EXP_MIN, EXP_MAX]
188 // swap x and y - ensure that a NaN in x has 'higher precedence' than one in y
189 #if DECIMAL_CALL_BY_REFERENCE
190 bid64qqq_fma (&res
, &y
, &x
, &z
191 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
194 res
= bid64qqq_fma (y
, x
, z
195 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
202 #if DECIMAL_CALL_BY_REFERENCE
204 bid128dd_mul (UINT128
* pres
, UINT64
* px
, UINT64
* py
205 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
207 UINT64 x
= *px
, y
= *py
;
208 #if !DECIMAL_GLOBAL_ROUNDING
209 unsigned int rnd_mode
= *prnd_mode
;
213 bid128dd_mul (UINT64 x
, UINT64 y
214 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
217 UINT128 res
= { {0xbaddbaddbaddbaddull
, 0xbaddbaddbaddbaddull
}
221 #if DECIMAL_CALL_BY_REFERENCE
222 bid64_to_bid128 (&x1
, &x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
223 bid64_to_bid128 (&y1
, &y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
224 bid128_mul (&res
, &x1
, &y1
225 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
228 x1
= bid64_to_bid128 (x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
229 y1
= bid64_to_bid128 (y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
230 res
= bid128_mul (x1
, y1
231 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
238 #if DECIMAL_CALL_BY_REFERENCE
240 bid128dq_mul (UINT128
* pres
, UINT64
* px
, UINT128
* py
241 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
244 #if !DECIMAL_GLOBAL_ROUNDING
245 unsigned int rnd_mode
= *prnd_mode
;
249 bid128dq_mul (UINT64 x
, UINT128 y
250 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
253 UINT128 res
= { {0xbaddbaddbaddbaddull
, 0xbaddbaddbaddbaddull
}
257 #if DECIMAL_CALL_BY_REFERENCE
258 bid64_to_bid128 (&x1
, &x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
259 bid128_mul (&res
, &x1
, py
260 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
263 x1
= bid64_to_bid128 (x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
264 res
= bid128_mul (x1
, y
265 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
272 #if DECIMAL_CALL_BY_REFERENCE
274 bid128qd_mul (UINT128
* pres
, UINT128
* px
, UINT64
* py
275 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
278 #if !DECIMAL_GLOBAL_ROUNDING
279 unsigned int rnd_mode
= *prnd_mode
;
283 bid128qd_mul (UINT128 x
, UINT64 y
284 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
287 UINT128 res
= { {0xbaddbaddbaddbaddull
, 0xbaddbaddbaddbaddull
}
291 #if DECIMAL_CALL_BY_REFERENCE
292 bid64_to_bid128 (&y1
, &y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
293 bid128_mul (&res
, px
, &y1
294 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
297 y1
= bid64_to_bid128 (y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
298 res
= bid128_mul (x
, y1
299 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
306 // bid128_mul stands for bid128qq_mul
307 #if DECIMAL_CALL_BY_REFERENCE
309 bid128_mul (UINT128
* pres
, UINT128
* px
,
311 py _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
313 UINT128 x
= *px
, y
= *py
;
315 #if !DECIMAL_GLOBAL_ROUNDING
316 unsigned int rnd_mode
= *prnd_mode
;
321 bid128_mul (UINT128 x
,
322 UINT128 y _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
326 UINT128 z
= { {0x0000000000000000ull
, 0x5ffe000000000000ull
}
328 UINT128 res
= { {0xbaddbaddbaddbaddull
, 0xbaddbaddbaddbaddull
}
330 UINT64 x_sign
, y_sign
, p_sign
;
331 UINT64 x_exp
, y_exp
, p_exp
;
337 // skip cases where at least one operand is NaN or infinity
338 if (!(((x
.w
[1] & MASK_NAN
) == MASK_NAN
) ||
339 ((y
.w
[1] & MASK_NAN
) == MASK_NAN
) ||
340 ((x
.w
[1] & MASK_ANY_INF
) == MASK_INF
) ||
341 ((y
.w
[1] & MASK_ANY_INF
) == MASK_INF
))) {
342 // x, y are 0 or f but not inf or NaN => unpack the arguments and check
343 // for non-canonical values
345 x_sign
= x
.w
[1] & MASK_SIGN
; // 0 for positive, MASK_SIGN for negative
346 C1
.w
[1] = x
.w
[1] & MASK_COEFF
;
348 // check for non-canonical values - treated as zero
349 if ((x
.w
[1] & 0x6000000000000000ull
) == 0x6000000000000000ull
) {
350 // G0_G1=11 => non-canonical
351 x_exp
= (x
.w
[1] << 2) & MASK_EXP
; // biased and shifted left 49 bits
352 C1
.w
[1] = 0; // significand high
353 C1
.w
[0] = 0; // significand low
354 } else { // G0_G1 != 11
355 x_exp
= x
.w
[1] & MASK_EXP
; // biased and shifted left 49 bits
356 if (C1
.w
[1] > 0x0001ed09bead87c0ull
||
357 (C1
.w
[1] == 0x0001ed09bead87c0ull
&&
358 C1
.w
[0] > 0x378d8e63ffffffffull
)) {
359 // x is non-canonical if coefficient is larger than 10^34 -1
362 } else { // canonical
366 y_sign
= y
.w
[1] & MASK_SIGN
; // 0 for positive, MASK_SIGN for negative
367 C2
.w
[1] = y
.w
[1] & MASK_COEFF
;
369 // check for non-canonical values - treated as zero
370 if ((y
.w
[1] & 0x6000000000000000ull
) == 0x6000000000000000ull
) {
371 // G0_G1=11 => non-canonical
372 y_exp
= (y
.w
[1] << 2) & MASK_EXP
; // biased and shifted left 49 bits
373 C2
.w
[1] = 0; // significand high
374 C2
.w
[0] = 0; // significand low
375 } else { // G0_G1 != 11
376 y_exp
= y
.w
[1] & MASK_EXP
; // biased and shifted left 49 bits
377 if (C2
.w
[1] > 0x0001ed09bead87c0ull
||
378 (C2
.w
[1] == 0x0001ed09bead87c0ull
&&
379 C2
.w
[0] > 0x378d8e63ffffffffull
)) {
380 // y is non-canonical if coefficient is larger than 10^34 -1
383 } else { // canonical
387 p_sign
= x_sign
^ y_sign
; // sign of the product
389 true_p_exp
= (x_exp
>> 49) - 6176 + (y_exp
>> 49) - 6176;
390 // true_p_exp, p_exp are used only for 0 * 0, 0 * f, or f * 0
391 if (true_p_exp
< -6176)
392 p_exp
= 0; // cannot be less than EXP_MIN
393 else if (true_p_exp
> 6111)
394 p_exp
= (UINT64
) (6111 + 6176) << 49; // cannot be more than EXP_MAX
396 p_exp
= (UINT64
) (true_p_exp
+ 6176) << 49;
398 if ((C1
.w
[1] == 0x0 && C1
.w
[0] == 0x0) ||
399 (C2
.w
[1] == 0x0 && C2
.w
[0] == 0x0)) {
402 res
.w
[1] = p_sign
| p_exp
; // preferred exponent in [EXP_MIN, EXP_MAX]
412 // swap x and y - ensure that a NaN in x has 'higher precedence' than one in y
413 #if DECIMAL_CALL_BY_REFERENCE
414 bid128_fma (&res
, &y
, &x
, &z
415 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
418 res
= bid128_fma (y
, x
, z
419 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG