1 /* Copyright (C) 2007 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 2, or (at your option) any later
10 In addition to the permissions in the GNU General Public License, the
11 Free Software Foundation gives you unlimited permission to link the
12 compiled version of this file into combinations with other programs,
13 and to distribute those combinations without any restriction coming
14 from the use of this file. (The General Public License restrictions
15 do apply in other respects; for example, they cover modification of
16 the file, and distribution when not linked into a combine
19 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
20 WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 You should have received a copy of the GNU General Public License
25 along with GCC; see the file COPYING. If not, write to the Free
26 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
29 #include "bid_internal.h"
31 #if DECIMAL_CALL_BY_REFERENCE
33 bid64dq_mul (UINT64
* pres
, UINT64
* px
, UINT128
* py
34 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
37 #if !DECIMAL_GLOBAL_ROUNDING
38 unsigned int rnd_mode
= *prnd_mode
;
42 bid64dq_mul (UINT64 x
, UINT128 y
43 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
46 UINT64 res
= 0xbaddbaddbaddbaddull
;
49 #if DECIMAL_CALL_BY_REFERENCE
50 bid64_to_bid128 (&x1
, &x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
51 bid64qq_mul (&res
, &x1
, py
52 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
55 x1
= bid64_to_bid128 (x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
56 res
= bid64qq_mul (x1
, y
57 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
64 #if DECIMAL_CALL_BY_REFERENCE
66 bid64qd_mul (UINT64
* pres
, UINT128
* px
, UINT64
* py
67 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
70 #if !DECIMAL_GLOBAL_ROUNDING
71 unsigned int rnd_mode
= *prnd_mode
;
75 bid64qd_mul (UINT128 x
, UINT64 y
76 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
79 UINT64 res
= 0xbaddbaddbaddbaddull
;
82 #if DECIMAL_CALL_BY_REFERENCE
83 bid64_to_bid128 (&y1
, &y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
84 bid64qq_mul (&res
, px
, &y1
85 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
88 y1
= bid64_to_bid128 (y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
89 res
= bid64qq_mul (x
, y1
90 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
97 #if DECIMAL_CALL_BY_REFERENCE
99 bid64qq_mul (UINT64
* pres
, UINT128
* px
, UINT128
* py
100 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
102 UINT128 x
= *px
, y
= *py
;
103 #if !DECIMAL_GLOBAL_ROUNDING
104 unsigned int rnd_mode
= *prnd_mode
;
108 bid64qq_mul (UINT128 x
, UINT128 y
109 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
113 UINT128 z
= { {0x0000000000000000ull
, 0x5ffe000000000000ull
}
115 UINT64 res
= 0xbaddbaddbaddbaddull
;
116 UINT64 x_sign
, y_sign
, p_sign
;
117 UINT64 x_exp
, y_exp
, p_exp
;
122 // skip cases where at least one operand is NaN or infinity
123 if (!(((x
.w
[HIGH_128W
] & MASK_NAN
) == MASK_NAN
) ||
124 ((y
.w
[HIGH_128W
] & MASK_NAN
) == MASK_NAN
) ||
125 ((x
.w
[HIGH_128W
] & MASK_ANY_INF
) == MASK_INF
) ||
126 ((y
.w
[HIGH_128W
] & MASK_ANY_INF
) == MASK_INF
))) {
127 // x, y are 0 or f but not inf or NaN => unpack the arguments and check
128 // for non-canonical values
130 x_sign
= x
.w
[HIGH_128W
] & MASK_SIGN
; // 0 for positive, MASK_SIGN for negative
131 C1
.w
[1] = x
.w
[HIGH_128W
] & MASK_COEFF
;
132 C1
.w
[0] = x
.w
[LOW_128W
];
133 // check for non-canonical values - treated as zero
134 if ((x
.w
[HIGH_128W
] & 0x6000000000000000ull
) ==
135 0x6000000000000000ull
) {
136 // G0_G1=11 => non-canonical
137 x_exp
= (x
.w
[HIGH_128W
] << 2) & MASK_EXP
; // biased and shifted left 49 bits
138 C1
.w
[1] = 0; // significand high
139 C1
.w
[0] = 0; // significand low
140 } else { // G0_G1 != 11
141 x_exp
= x
.w
[HIGH_128W
] & MASK_EXP
; // biased and shifted left 49 bits
142 if (C1
.w
[1] > 0x0001ed09bead87c0ull
||
143 (C1
.w
[1] == 0x0001ed09bead87c0ull
&&
144 C1
.w
[0] > 0x378d8e63ffffffffull
)) {
145 // x is non-canonical if coefficient is larger than 10^34 -1
148 } else { // canonical
152 y_sign
= y
.w
[HIGH_128W
] & MASK_SIGN
; // 0 for positive, MASK_SIGN for negative
153 C2
.w
[1] = y
.w
[HIGH_128W
] & MASK_COEFF
;
154 C2
.w
[0] = y
.w
[LOW_128W
];
155 // check for non-canonical values - treated as zero
156 if ((y
.w
[HIGH_128W
] & 0x6000000000000000ull
) ==
157 0x6000000000000000ull
) {
158 // G0_G1=11 => non-canonical
159 y_exp
= (y
.w
[HIGH_128W
] << 2) & MASK_EXP
; // biased and shifted left 49 bits
160 C2
.w
[1] = 0; // significand high
161 C2
.w
[0] = 0; // significand low
162 } else { // G0_G1 != 11
163 y_exp
= y
.w
[HIGH_128W
] & MASK_EXP
; // biased and shifted left 49 bits
164 if (C2
.w
[1] > 0x0001ed09bead87c0ull
||
165 (C2
.w
[1] == 0x0001ed09bead87c0ull
&&
166 C2
.w
[0] > 0x378d8e63ffffffffull
)) {
167 // y is non-canonical if coefficient is larger than 10^34 -1
170 } else { // canonical
174 p_sign
= x_sign
^ y_sign
; // sign of the product
176 true_p_exp
= (x_exp
>> 49) - 6176 + (y_exp
>> 49) - 6176;
177 // true_p_exp, p_exp are used only for 0 * 0, 0 * f, or f * 0
178 if (true_p_exp
< -398)
179 p_exp
= 0; // cannot be less than EXP_MIN
180 else if (true_p_exp
> 369)
181 p_exp
= (UINT64
) (369 + 398) << 53; // cannot be more than EXP_MAX
183 p_exp
= (UINT64
) (true_p_exp
+ 398) << 53;
185 if ((C1
.w
[1] == 0x0 && C1
.w
[0] == 0x0) ||
186 (C2
.w
[1] == 0x0 && C2
.w
[0] == 0x0)) {
189 res
= p_sign
| p_exp
; // preferred exponent in [EXP_MIN, EXP_MAX]
193 // swap x and y - ensure that a NaN in x has 'higher precedence' than one in y
194 #if DECIMAL_CALL_BY_REFERENCE
195 bid64qqq_fma (&res
, &y
, &x
, &z
196 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
199 res
= bid64qqq_fma (y
, x
, z
200 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
207 #if DECIMAL_CALL_BY_REFERENCE
209 bid128dd_mul (UINT128
* pres
, UINT64
* px
, UINT64
* py
210 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
212 UINT64 x
= *px
, y
= *py
;
213 #if !DECIMAL_GLOBAL_ROUNDING
214 unsigned int rnd_mode
= *prnd_mode
;
218 bid128dd_mul (UINT64 x
, UINT64 y
219 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
222 UINT128 res
= { {0xbaddbaddbaddbaddull
, 0xbaddbaddbaddbaddull
}
226 #if DECIMAL_CALL_BY_REFERENCE
227 bid64_to_bid128 (&x1
, &x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
228 bid64_to_bid128 (&y1
, &y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
229 bid128_mul (&res
, &x1
, &y1
230 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
233 x1
= bid64_to_bid128 (x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
234 y1
= bid64_to_bid128 (y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
235 res
= bid128_mul (x1
, y1
236 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
243 #if DECIMAL_CALL_BY_REFERENCE
245 bid128dq_mul (UINT128
* pres
, UINT64
* px
, UINT128
* py
246 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
249 #if !DECIMAL_GLOBAL_ROUNDING
250 unsigned int rnd_mode
= *prnd_mode
;
254 bid128dq_mul (UINT64 x
, UINT128 y
255 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
258 UINT128 res
= { {0xbaddbaddbaddbaddull
, 0xbaddbaddbaddbaddull
}
262 #if DECIMAL_CALL_BY_REFERENCE
263 bid64_to_bid128 (&x1
, &x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
264 bid128_mul (&res
, &x1
, py
265 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
268 x1
= bid64_to_bid128 (x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
269 res
= bid128_mul (x1
, y
270 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
277 #if DECIMAL_CALL_BY_REFERENCE
279 bid128qd_mul (UINT128
* pres
, UINT128
* px
, UINT64
* py
280 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
283 #if !DECIMAL_GLOBAL_ROUNDING
284 unsigned int rnd_mode
= *prnd_mode
;
288 bid128qd_mul (UINT128 x
, UINT64 y
289 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
292 UINT128 res
= { {0xbaddbaddbaddbaddull
, 0xbaddbaddbaddbaddull
}
296 #if DECIMAL_CALL_BY_REFERENCE
297 bid64_to_bid128 (&y1
, &y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
298 bid128_mul (&res
, px
, &y1
299 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
302 y1
= bid64_to_bid128 (y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG
);
303 res
= bid128_mul (x
, y1
304 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
311 // bid128_mul stands for bid128qq_mul
312 #if DECIMAL_CALL_BY_REFERENCE
314 bid128_mul (UINT128
* pres
, UINT128
* px
,
316 py _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
318 UINT128 x
= *px
, y
= *py
;
320 #if !DECIMAL_GLOBAL_ROUNDING
321 unsigned int rnd_mode
= *prnd_mode
;
326 bid128_mul (UINT128 x
,
327 UINT128 y _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
331 UINT128 z
= { {0x0000000000000000ull
, 0x5ffe000000000000ull
}
333 UINT128 res
= { {0xbaddbaddbaddbaddull
, 0xbaddbaddbaddbaddull
}
335 UINT64 x_sign
, y_sign
, p_sign
;
336 UINT64 x_exp
, y_exp
, p_exp
;
342 // skip cases where at least one operand is NaN or infinity
343 if (!(((x
.w
[1] & MASK_NAN
) == MASK_NAN
) ||
344 ((y
.w
[1] & MASK_NAN
) == MASK_NAN
) ||
345 ((x
.w
[1] & MASK_ANY_INF
) == MASK_INF
) ||
346 ((y
.w
[1] & MASK_ANY_INF
) == MASK_INF
))) {
347 // x, y are 0 or f but not inf or NaN => unpack the arguments and check
348 // for non-canonical values
350 x_sign
= x
.w
[1] & MASK_SIGN
; // 0 for positive, MASK_SIGN for negative
351 C1
.w
[1] = x
.w
[1] & MASK_COEFF
;
353 // check for non-canonical values - treated as zero
354 if ((x
.w
[1] & 0x6000000000000000ull
) == 0x6000000000000000ull
) {
355 // G0_G1=11 => non-canonical
356 x_exp
= (x
.w
[1] << 2) & MASK_EXP
; // biased and shifted left 49 bits
357 C1
.w
[1] = 0; // significand high
358 C1
.w
[0] = 0; // significand low
359 } else { // G0_G1 != 11
360 x_exp
= x
.w
[1] & MASK_EXP
; // biased and shifted left 49 bits
361 if (C1
.w
[1] > 0x0001ed09bead87c0ull
||
362 (C1
.w
[1] == 0x0001ed09bead87c0ull
&&
363 C1
.w
[0] > 0x378d8e63ffffffffull
)) {
364 // x is non-canonical if coefficient is larger than 10^34 -1
367 } else { // canonical
371 y_sign
= y
.w
[1] & MASK_SIGN
; // 0 for positive, MASK_SIGN for negative
372 C2
.w
[1] = y
.w
[1] & MASK_COEFF
;
374 // check for non-canonical values - treated as zero
375 if ((y
.w
[1] & 0x6000000000000000ull
) == 0x6000000000000000ull
) {
376 // G0_G1=11 => non-canonical
377 y_exp
= (y
.w
[1] << 2) & MASK_EXP
; // biased and shifted left 49 bits
378 C2
.w
[1] = 0; // significand high
379 C2
.w
[0] = 0; // significand low
380 } else { // G0_G1 != 11
381 y_exp
= y
.w
[1] & MASK_EXP
; // biased and shifted left 49 bits
382 if (C2
.w
[1] > 0x0001ed09bead87c0ull
||
383 (C2
.w
[1] == 0x0001ed09bead87c0ull
&&
384 C2
.w
[0] > 0x378d8e63ffffffffull
)) {
385 // y is non-canonical if coefficient is larger than 10^34 -1
388 } else { // canonical
392 p_sign
= x_sign
^ y_sign
; // sign of the product
394 true_p_exp
= (x_exp
>> 49) - 6176 + (y_exp
>> 49) - 6176;
395 // true_p_exp, p_exp are used only for 0 * 0, 0 * f, or f * 0
396 if (true_p_exp
< -6176)
397 p_exp
= 0; // cannot be less than EXP_MIN
398 else if (true_p_exp
> 6111)
399 p_exp
= (UINT64
) (6111 + 6176) << 49; // cannot be more than EXP_MAX
401 p_exp
= (UINT64
) (true_p_exp
+ 6176) << 49;
403 if ((C1
.w
[1] == 0x0 && C1
.w
[0] == 0x0) ||
404 (C2
.w
[1] == 0x0 && C2
.w
[0] == 0x0)) {
407 res
.w
[1] = p_sign
| p_exp
; // preferred exponent in [EXP_MIN, EXP_MAX]
417 // swap x and y - ensure that a NaN in x has 'higher precedence' than one in y
418 #if DECIMAL_CALL_BY_REFERENCE
419 bid128_fma (&res
, &y
, &x
, &z
420 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
423 res
= bid128_fma (y
, x
, z
424 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG