]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/libbid/bid128_mul.c
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / libbid / bid128_mul.c
1 /* Copyright (C) 2007-2020 Free Software Foundation, Inc.
2
3 This file is part of GCC.
4
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
8 version.
9
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
13 for more details.
14
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.
18
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/>. */
23
24 #include "bid_internal.h"
25
26 #if DECIMAL_CALL_BY_REFERENCE
27 void
28 bid64dq_mul (UINT64 * pres, UINT64 * px, UINT128 * py
29 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
30 _EXC_INFO_PARAM) {
31 UINT64 x = *px;
32 #if !DECIMAL_GLOBAL_ROUNDING
33 unsigned int rnd_mode = *prnd_mode;
34 #endif
35 #else
36 UINT64
37 bid64dq_mul (UINT64 x, UINT128 y
38 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
39 _EXC_INFO_PARAM) {
40 #endif
41 UINT64 res = 0xbaddbaddbaddbaddull;
42 UINT128 x1;
43
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
48 _EXC_INFO_ARG);
49 #else
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
53 _EXC_INFO_ARG);
54 #endif
55 BID_RETURN (res);
56 }
57
58
59 #if DECIMAL_CALL_BY_REFERENCE
60 void
61 bid64qd_mul (UINT64 * pres, UINT128 * px, UINT64 * py
62 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
63 _EXC_INFO_PARAM) {
64 UINT64 y = *py;
65 #if !DECIMAL_GLOBAL_ROUNDING
66 unsigned int rnd_mode = *prnd_mode;
67 #endif
68 #else
69 UINT64
70 bid64qd_mul (UINT128 x, UINT64 y
71 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
72 _EXC_INFO_PARAM) {
73 #endif
74 UINT64 res = 0xbaddbaddbaddbaddull;
75 UINT128 y1;
76
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
81 _EXC_INFO_ARG);
82 #else
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
86 _EXC_INFO_ARG);
87 #endif
88 BID_RETURN (res);
89 }
90
91
92 #if DECIMAL_CALL_BY_REFERENCE
93 void
94 bid64qq_mul (UINT64 * pres, UINT128 * px, UINT128 * py
95 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
96 _EXC_INFO_PARAM) {
97 UINT128 x = *px, y = *py;
98 #if !DECIMAL_GLOBAL_ROUNDING
99 unsigned int rnd_mode = *prnd_mode;
100 #endif
101 #else
102 UINT64
103 bid64qq_mul (UINT128 x, UINT128 y
104 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
105 _EXC_INFO_PARAM) {
106 #endif
107
108 UINT128 z = { {0x0000000000000000ull, 0x5ffe000000000000ull}
109 };
110 UINT64 res = 0xbaddbaddbaddbaddull;
111 UINT64 x_sign, y_sign, p_sign;
112 UINT64 x_exp, y_exp, p_exp;
113 int true_p_exp;
114 UINT128 C1, C2;
115
116 BID_SWAP128 (z);
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
124
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
141 C1.w[1] = 0;
142 C1.w[0] = 0;
143 } else { // canonical
144 ;
145 }
146 }
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
163 C2.w[1] = 0;
164 C2.w[0] = 0;
165 } else { // canonical
166 ;
167 }
168 }
169 p_sign = x_sign ^ y_sign; // sign of the product
170
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
177 else
178 p_exp = (UINT64) (true_p_exp + 398) << 53;
179
180 if ((C1.w[1] == 0x0 && C1.w[0] == 0x0) ||
181 (C2.w[1] == 0x0 && C2.w[0] == 0x0)) {
182 // x = 0 or y = 0
183 // the result is 0
184 res = p_sign | p_exp; // preferred exponent in [EXP_MIN, EXP_MAX]
185 BID_RETURN (res)
186 } // else continue
187 }
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
192 _EXC_INFO_ARG);
193 #else
194 res = bid64qqq_fma (y, x, z
195 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
196 _EXC_INFO_ARG);
197 #endif
198 BID_RETURN (res);
199 }
200
201
202 #if DECIMAL_CALL_BY_REFERENCE
203 void
204 bid128dd_mul (UINT128 * pres, UINT64 * px, UINT64 * py
205 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
206 _EXC_INFO_PARAM) {
207 UINT64 x = *px, y = *py;
208 #if !DECIMAL_GLOBAL_ROUNDING
209 unsigned int rnd_mode = *prnd_mode;
210 #endif
211 #else
212 UINT128
213 bid128dd_mul (UINT64 x, UINT64 y
214 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
215 _EXC_INFO_PARAM) {
216 #endif
217 UINT128 res = { {0xbaddbaddbaddbaddull, 0xbaddbaddbaddbaddull}
218 };
219 UINT128 x1, y1;
220
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
226 _EXC_INFO_ARG);
227 #else
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
232 _EXC_INFO_ARG);
233 #endif
234 BID_RETURN (res);
235 }
236
237
238 #if DECIMAL_CALL_BY_REFERENCE
239 void
240 bid128dq_mul (UINT128 * pres, UINT64 * px, UINT128 * py
241 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
242 _EXC_INFO_PARAM) {
243 UINT64 x = *px;
244 #if !DECIMAL_GLOBAL_ROUNDING
245 unsigned int rnd_mode = *prnd_mode;
246 #endif
247 #else
248 UINT128
249 bid128dq_mul (UINT64 x, UINT128 y
250 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
251 _EXC_INFO_PARAM) {
252 #endif
253 UINT128 res = { {0xbaddbaddbaddbaddull, 0xbaddbaddbaddbaddull}
254 };
255 UINT128 x1;
256
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
261 _EXC_INFO_ARG);
262 #else
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
266 _EXC_INFO_ARG);
267 #endif
268 BID_RETURN (res);
269 }
270
271
272 #if DECIMAL_CALL_BY_REFERENCE
273 void
274 bid128qd_mul (UINT128 * pres, UINT128 * px, UINT64 * py
275 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
276 _EXC_INFO_PARAM) {
277 UINT64 y = *py;
278 #if !DECIMAL_GLOBAL_ROUNDING
279 unsigned int rnd_mode = *prnd_mode;
280 #endif
281 #else
282 UINT128
283 bid128qd_mul (UINT128 x, UINT64 y
284 _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
285 _EXC_INFO_PARAM) {
286 #endif
287 UINT128 res = { {0xbaddbaddbaddbaddull, 0xbaddbaddbaddbaddull}
288 };
289 UINT128 y1;
290
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
295 _EXC_INFO_ARG);
296 #else
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
300 _EXC_INFO_ARG);
301 #endif
302 BID_RETURN (res);
303 }
304
305
306 // bid128_mul stands for bid128qq_mul
307 #if DECIMAL_CALL_BY_REFERENCE
308 void
309 bid128_mul (UINT128 * pres, UINT128 * px,
310 UINT128 *
311 py _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
312 _EXC_INFO_PARAM) {
313 UINT128 x = *px, y = *py;
314
315 #if !DECIMAL_GLOBAL_ROUNDING
316 unsigned int rnd_mode = *prnd_mode;
317
318 #endif
319 #else
320 UINT128
321 bid128_mul (UINT128 x,
322 UINT128 y _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
323 _EXC_INFO_PARAM) {
324
325 #endif
326 UINT128 z = { {0x0000000000000000ull, 0x5ffe000000000000ull}
327 };
328 UINT128 res = { {0xbaddbaddbaddbaddull, 0xbaddbaddbaddbaddull}
329 };
330 UINT64 x_sign, y_sign, p_sign;
331 UINT64 x_exp, y_exp, p_exp;
332 int true_p_exp;
333 UINT128 C1, C2;
334
335 BID_SWAP128 (x);
336 BID_SWAP128 (y);
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
344
345 x_sign = x.w[1] & MASK_SIGN; // 0 for positive, MASK_SIGN for negative
346 C1.w[1] = x.w[1] & MASK_COEFF;
347 C1.w[0] = x.w[0];
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
360 C1.w[1] = 0;
361 C1.w[0] = 0;
362 } else { // canonical
363 ;
364 }
365 }
366 y_sign = y.w[1] & MASK_SIGN; // 0 for positive, MASK_SIGN for negative
367 C2.w[1] = y.w[1] & MASK_COEFF;
368 C2.w[0] = y.w[0];
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
381 C2.w[1] = 0;
382 C2.w[0] = 0;
383 } else { // canonical
384 ;
385 }
386 }
387 p_sign = x_sign ^ y_sign; // sign of the product
388
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
395 else
396 p_exp = (UINT64) (true_p_exp + 6176) << 49;
397
398 if ((C1.w[1] == 0x0 && C1.w[0] == 0x0) ||
399 (C2.w[1] == 0x0 && C2.w[0] == 0x0)) {
400 // x = 0 or y = 0
401 // the result is 0
402 res.w[1] = p_sign | p_exp; // preferred exponent in [EXP_MIN, EXP_MAX]
403 res.w[0] = 0x0;
404 BID_SWAP128 (res);
405 BID_RETURN (res)
406 } // else continue
407 }
408
409 BID_SWAP128 (x);
410 BID_SWAP128 (y);
411 BID_SWAP128 (z);
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
416 _EXC_INFO_ARG);
417 #else
418 res = bid128_fma (y, x, z
419 _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
420 _EXC_INFO_ARG);
421 #endif
422 BID_RETURN (res);
423 }