1 /*
2 * License for Berkeley SoftFloat Release 3e
3 *
4 * John R. Hauser
5 * 2018 January 20
6 *
7 * The following applies to the whole of SoftFloat Release 3e as well as to
8 * each source file individually.
9 *
10 * Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the
11 * University of California. All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright notice,
17 * this list of conditions, and the following disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions, and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * 3. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
28 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
30 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
31 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 *
39 * The functions listed in this file are modified versions of the ones
40 * from the Berkeley SoftFloat 3e Library.
41 *
42 * Their implementation correctness has been checked with the Berkeley
43 * TestFloat Release 3e tool for x86_64.
44 */
45
46 #include "rounding.h"
47 #include "bitscan.h"
48 #include "softfloat.h"
49
50 #if defined(BIG_ENDIAN)
51 #define word_incr -1
52 #define index_word(total, n) ((total) - 1 - (n))
53 #define index_word_hi(total) 0
54 #define index_word_lo(total) ((total) - 1)
55 #define index_multiword_hi(total, n) 0
56 #define index_multiword_lo(total, n) ((total) - (n))
57 #define index_multiword_hi_but(total, n) 0
58 #define index_multiword_lo_but(total, n) (n)
59 #else
60 #define word_incr 1
61 #define index_word(total, n) (n)
62 #define index_word_hi(total) ((total) - 1)
63 #define index_word_lo(total) 0
64 #define index_multiword_hi(total, n) ((total) - (n))
65 #define index_multiword_lo(total, n) 0
66 #define index_multiword_hi_but(total, n) (n)
67 #define index_multiword_lo_but(total, n) 0
68 #endif
69
70 typedef union { double f; int64_t i; uint64_t u; } di_type;
71 typedef union { float f; int32_t i; uint32_t u; } fi_type;
72
73 const uint8_t count_leading_zeros8[256] = {
74 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
75 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
76 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
77 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
78 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
79 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
80 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
81 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
82 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
85 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
87 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
88 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
89 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
90 };
91
92 /**
93 * \brief Shifts 'a' right by the number of bits given in 'dist', which must be in
94 * the range 1 to 63. If any nonzero bits are shifted off, they are "jammed"
95 * into the least-significant bit of the shifted value by setting the
96 * least-significant bit to 1. This shifted-and-jammed value is returned.
97 *
98 * From softfloat_shortShiftRightJam64()
99 */
100 static inline
_mesa_short_shift_right_jam64(uint64_t a,uint8_t dist)101 uint64_t _mesa_short_shift_right_jam64(uint64_t a, uint8_t dist)
102 {
103 return a >> dist | ((a & (((uint64_t) 1 << dist) - 1)) != 0);
104 }
105
106 /**
107 * \brief Shifts 'a' right by the number of bits given in 'dist', which must not
108 * be zero. If any nonzero bits are shifted off, they are "jammed" into the
109 * least-significant bit of the shifted value by setting the least-significant
110 * bit to 1. This shifted-and-jammed value is returned.
111 * The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
112 * greater than 64, the result will be either 0 or 1, depending on whether 'a'
113 * is zero or nonzero.
114 *
115 * From softfloat_shiftRightJam64()
116 */
117 static inline
_mesa_shift_right_jam64(uint64_t a,uint32_t dist)118 uint64_t _mesa_shift_right_jam64(uint64_t a, uint32_t dist)
119 {
120 return
121 (dist < 63) ? a >> dist | ((uint64_t) (a << (-dist & 63)) != 0) : (a != 0);
122 }
123
124 /**
125 * \brief Shifts 'a' right by the number of bits given in 'dist', which must not be
126 * zero. If any nonzero bits are shifted off, they are "jammed" into the
127 * least-significant bit of the shifted value by setting the least-significant
128 * bit to 1. This shifted-and-jammed value is returned.
129 * The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
130 * greater than 32, the result will be either 0 or 1, depending on whether 'a'
131 * is zero or nonzero.
132 *
133 * From softfloat_shiftRightJam32()
134 */
135 static inline
_mesa_shift_right_jam32(uint32_t a,uint16_t dist)136 uint32_t _mesa_shift_right_jam32(uint32_t a, uint16_t dist)
137 {
138 return
139 (dist < 31) ? a >> dist | ((uint32_t) (a << (-dist & 31)) != 0) : (a != 0);
140 }
141
142 /**
143 * \brief Extracted from softfloat_roundPackToF64()
144 */
145 static inline
_mesa_roundtozero_f64(int64_t s,int64_t e,int64_t m)146 double _mesa_roundtozero_f64(int64_t s, int64_t e, int64_t m)
147 {
148 di_type result;
149
150 if ((uint64_t) e >= 0x7fd) {
151 if (e < 0) {
152 m = _mesa_shift_right_jam64(m, -e);
153 e = 0;
154 } else if ((e > 0x7fd) || (0x8000000000000000 <= m)) {
155 e = 0x7ff;
156 m = 0;
157 result.u = (s << 63) + (e << 52) + m;
158 result.u -= 1;
159 return result.f;
160 }
161 }
162
163 m >>= 10;
164 if (m == 0)
165 e = 0;
166
167 result.u = (s << 63) + (e << 52) + m;
168 return result.f;
169 }
170
171 /**
172 * \brief Extracted from softfloat_roundPackToF32()
173 */
174 static inline
_mesa_round_f32(int32_t s,int32_t e,int32_t m,bool rtz)175 float _mesa_round_f32(int32_t s, int32_t e, int32_t m, bool rtz)
176 {
177 fi_type result;
178 uint8_t round_increment = rtz ? 0 : 0x40;
179
180 if ((uint32_t) e >= 0xfd) {
181 if (e < 0) {
182 m = _mesa_shift_right_jam32(m, -e);
183 e = 0;
184 } else if ((e > 0xfd) || (0x80000000 <= m + round_increment)) {
185 e = 0xff;
186 m = 0;
187 result.u = (s << 31) + (e << 23) + m;
188 result.u -= !round_increment;
189 return result.f;
190 }
191 }
192
193 uint8_t round_bits;
194 round_bits = m & 0x7f;
195 m = ((uint32_t) m + round_increment) >> 7;
196 m &= ~(uint32_t) (! (round_bits ^ 0x40) & !rtz);
197 if (m == 0)
198 e = 0;
199
200 result.u = (s << 31) + (e << 23) + m;
201 return result.f;
202 }
203
204 /**
205 * \brief Extracted from softfloat_roundPackToF16()
206 */
207 static inline
_mesa_roundtozero_f16(int16_t s,int16_t e,int16_t m)208 uint16_t _mesa_roundtozero_f16(int16_t s, int16_t e, int16_t m)
209 {
210 if ((uint16_t) e >= 0x1d) {
211 if (e < 0) {
212 m = _mesa_shift_right_jam32(m, -e);
213 e = 0;
214 } else if (e > 0x1d) {
215 e = 0x1f;
216 m = 0;
217 return (s << 15) + (e << 10) + m - 1;
218 }
219 }
220
221 m >>= 4;
222 if (m == 0)
223 e = 0;
224
225 return (s << 15) + (e << 10) + m;
226 }
227
228 /**
229 * \brief Shifts the N-bit unsigned integer pointed to by 'a' left by the number of
230 * bits given in 'dist', where N = 'size_words' * 32. The value of 'dist'
231 * must be in the range 1 to 31. Any nonzero bits shifted off are lost. The
232 * shifted N-bit result is stored at the location pointed to by 'm_out'. Each
233 * of 'a' and 'm_out' points to a 'size_words'-long array of 32-bit elements
234 * that concatenate in the platform's normal endian order to form an N-bit
235 * integer.
236 *
237 * From softfloat_shortShiftLeftM()
238 */
239 static inline void
_mesa_short_shift_left_m(uint8_t size_words,const uint32_t * a,uint8_t dist,uint32_t * m_out)240 _mesa_short_shift_left_m(uint8_t size_words, const uint32_t *a, uint8_t dist, uint32_t *m_out)
241 {
242 uint8_t neg_dist;
243 unsigned index, last_index;
244 uint32_t part_word, a_word;
245
246 neg_dist = -dist;
247 index = index_word_hi(size_words);
248 last_index = index_word_lo(size_words);
249 part_word = a[index] << dist;
250 while (index != last_index) {
251 a_word = a[index - word_incr];
252 m_out[index] = part_word | a_word >> (neg_dist & 31);
253 index -= word_incr;
254 part_word = a_word << dist;
255 }
256 m_out[index] = part_word;
257 }
258
259 /**
260 * \brief Shifts the N-bit unsigned integer pointed to by 'a' left by the number of
261 * bits given in 'dist', where N = 'size_words' * 32. The value of 'dist'
262 * must not be zero. Any nonzero bits shifted off are lost. The shifted
263 * N-bit result is stored at the location pointed to by 'm_out'. Each of 'a'
264 * and 'm_out' points to a 'size_words'-long array of 32-bit elements that
265 * concatenate in the platform's normal endian order to form an N-bit
266 * integer. The value of 'dist' can be arbitrarily large. In particular, if
267 * 'dist' is greater than N, the stored result will be 0.
268 *
269 * From softfloat_shiftLeftM()
270 */
271 static inline void
_mesa_shift_left_m(uint8_t size_words,const uint32_t * a,uint32_t dist,uint32_t * m_out)272 _mesa_shift_left_m(uint8_t size_words, const uint32_t *a, uint32_t dist, uint32_t *m_out)
273 {
274 uint32_t word_dist;
275 uint8_t inner_dist;
276 uint8_t i;
277
278 word_dist = dist >> 5;
279 if (word_dist < size_words) {
280 a += index_multiword_lo_but(size_words, word_dist);
281 inner_dist = dist & 31;
282 if (inner_dist) {
283 _mesa_short_shift_left_m(size_words - word_dist, a, inner_dist,
284 m_out + index_multiword_hi_but(size_words, word_dist));
285 if (!word_dist)
286 return;
287 } else {
288 uint32_t *dest = m_out + index_word_hi(size_words);
289 a += index_word_hi(size_words - word_dist);
290 for (i = size_words - word_dist; i; --i) {
291 *dest = *a;
292 a -= word_incr;
293 dest -= word_incr;
294 }
295 }
296 m_out += index_multiword_lo(size_words, word_dist);
297 } else {
298 word_dist = size_words;
299 }
300 do {
301 *m_out++ = 0;
302 --word_dist;
303 } while (word_dist);
304 }
305
306 /**
307 * \brief Shifts the N-bit unsigned integer pointed to by 'a' right by the number of
308 * bits given in 'dist', where N = 'size_words' * 32. The value of 'dist'
309 * must be in the range 1 to 31. Any nonzero bits shifted off are lost. The
310 * shifted N-bit result is stored at the location pointed to by 'm_out'. Each
311 * of 'a' and 'm_out' points to a 'size_words'-long array of 32-bit elements
312 * that concatenate in the platform's normal endian order to form an N-bit
313 * integer.
314 *
315 * From softfloat_shortShiftRightM()
316 */
317 static inline void
_mesa_short_shift_right_m(uint8_t size_words,const uint32_t * a,uint8_t dist,uint32_t * m_out)318 _mesa_short_shift_right_m(uint8_t size_words, const uint32_t *a, uint8_t dist, uint32_t *m_out)
319 {
320 uint8_t neg_dist;
321 unsigned index, last_index;
322 uint32_t part_word, a_word;
323
324 neg_dist = -dist;
325 index = index_word_lo(size_words);
326 last_index = index_word_hi(size_words);
327 part_word = a[index] >> dist;
328 while (index != last_index) {
329 a_word = a[index + word_incr];
330 m_out[index] = a_word << (neg_dist & 31) | part_word;
331 index += word_incr;
332 part_word = a_word >> dist;
333 }
334 m_out[index] = part_word;
335 }
336
337 /**
338 * \brief Shifts the N-bit unsigned integer pointed to by 'a' right by the number of
339 * bits given in 'dist', where N = 'size_words' * 32. The value of 'dist'
340 * must be in the range 1 to 31. If any nonzero bits are shifted off, they
341 * are "jammed" into the least-significant bit of the shifted value by setting
342 * the least-significant bit to 1. This shifted-and-jammed N-bit result is
343 * stored at the location pointed to by 'm_out'. Each of 'a' and 'm_out'
344 * points to a 'size_words'-long array of 32-bit elements that concatenate in
345 * the platform's normal endian order to form an N-bit integer.
346 *
347 *
348 * From softfloat_shortShiftRightJamM()
349 */
350 static inline void
_mesa_short_shift_right_jam_m(uint8_t size_words,const uint32_t * a,uint8_t dist,uint32_t * m_out)351 _mesa_short_shift_right_jam_m(uint8_t size_words, const uint32_t *a, uint8_t dist, uint32_t *m_out)
352 {
353 uint8_t neg_dist;
354 unsigned index, last_index;
355 uint64_t part_word, a_word;
356
357 neg_dist = -dist;
358 index = index_word_lo(size_words);
359 last_index = index_word_hi(size_words);
360 a_word = a[index];
361 part_word = a_word >> dist;
362 if (part_word << dist != a_word )
363 part_word |= 1;
364 while (index != last_index) {
365 a_word = a[index + word_incr];
366 m_out[index] = a_word << (neg_dist & 31) | part_word;
367 index += word_incr;
368 part_word = a_word >> dist;
369 }
370 m_out[index] = part_word;
371 }
372
373 /**
374 * \brief Shifts the N-bit unsigned integer pointed to by 'a' right by the number of
375 * bits given in 'dist', where N = 'size_words' * 32. The value of 'dist'
376 * must not be zero. If any nonzero bits are shifted off, they are "jammed"
377 * into the least-significant bit of the shifted value by setting the
378 * least-significant bit to 1. This shifted-and-jammed N-bit result is stored
379 * at the location pointed to by 'm_out'. Each of 'a' and 'm_out' points to a
380 * 'size_words'-long array of 32-bit elements that concatenate in the
381 * platform's normal endian order to form an N-bit integer. The value of
382 * 'dist' can be arbitrarily large. In particular, if 'dist' is greater than
383 * N, the stored result will be either 0 or 1, depending on whether the
384 * original N bits are all zeros.
385 *
386 * From softfloat_shiftRightJamM()
387 */
388 static inline void
_mesa_shift_right_jam_m(uint8_t size_words,const uint32_t * a,uint32_t dist,uint32_t * m_out)389 _mesa_shift_right_jam_m(uint8_t size_words, const uint32_t *a, uint32_t dist, uint32_t *m_out)
390 {
391 uint32_t word_jam, word_dist, *tmp;
392 uint8_t i, inner_dist;
393
394 word_jam = 0;
395 word_dist = dist >> 5;
396 tmp = NULL;
397 if (word_dist) {
398 if (size_words < word_dist)
399 word_dist = size_words;
400 tmp = (uint32_t *) (a + index_multiword_lo(size_words, word_dist));
401 i = word_dist;
402 do {
403 word_jam = *tmp++;
404 if (word_jam)
405 break;
406 --i;
407 } while (i);
408 tmp = m_out;
409 }
410 if (word_dist < size_words) {
411 a += index_multiword_hi_but(size_words, word_dist);
412 inner_dist = dist & 31;
413 if (inner_dist) {
414 _mesa_short_shift_right_jam_m(size_words - word_dist, a, inner_dist,
415 m_out + index_multiword_lo_but(size_words, word_dist));
416 if (!word_dist) {
417 if (word_jam)
418 m_out[index_word_lo(size_words)] |= 1;
419 return;
420 }
421 } else {
422 a += index_word_lo(size_words - word_dist);
423 tmp = m_out + index_word_lo(size_words);
424 for (i = size_words - word_dist; i; --i) {
425 *tmp = *a;
426 a += word_incr;
427 tmp += word_incr;
428 }
429 }
430 tmp = m_out + index_multiword_hi(size_words, word_dist);
431 }
432 if (tmp) {
433 do {
434 *tmp++ = 0;
435 --word_dist;
436 } while (word_dist);
437 }
438 if (word_jam)
439 m_out[index_word_lo(size_words)] |= 1;
440 }
441
442 /**
443 * \brief Calculate a + b but rounding to zero.
444 *
445 * Notice that this mainly differs from the original Berkeley SoftFloat 3e
446 * implementation in that we don't really treat NaNs, Zeroes nor the
447 * signalling flags. Any NaN is good for us and the sign of the Zero is not
448 * important.
449 *
450 * From f64_add()
451 */
452 double
_mesa_double_add_rtz(double a,double b)453 _mesa_double_add_rtz(double a, double b)
454 {
455 const di_type a_di = {a};
456 uint64_t a_flt_m = a_di.u & 0x0fffffffffffff;
457 uint64_t a_flt_e = (a_di.u >> 52) & 0x7ff;
458 uint64_t a_flt_s = (a_di.u >> 63) & 0x1;
459 const di_type b_di = {b};
460 uint64_t b_flt_m = b_di.u & 0x0fffffffffffff;
461 uint64_t b_flt_e = (b_di.u >> 52) & 0x7ff;
462 uint64_t b_flt_s = (b_di.u >> 63) & 0x1;
463 int64_t s, e, m = 0;
464
465 s = a_flt_s;
466
467 const int64_t exp_diff = a_flt_e - b_flt_e;
468
469 /* Handle special cases */
470
471 if (a_flt_s != b_flt_s) {
472 return _mesa_double_sub_rtz(a, -b);
473 } else if ((a_flt_e == 0) && (a_flt_m == 0)) {
474 /* 'a' is zero, return 'b' */
475 return b;
476 } else if ((b_flt_e == 0) && (b_flt_m == 0)) {
477 /* 'b' is zero, return 'a' */
478 return a;
479 } else if (a_flt_e == 0x7ff && a_flt_m != 0) {
480 /* 'a' is a NaN, return NaN */
481 return a;
482 } else if (b_flt_e == 0x7ff && b_flt_m != 0) {
483 /* 'b' is a NaN, return NaN */
484 return b;
485 } else if (a_flt_e == 0x7ff && a_flt_m == 0) {
486 /* Inf + x = Inf */
487 return a;
488 } else if (b_flt_e == 0x7ff && b_flt_m == 0) {
489 /* x + Inf = Inf */
490 return b;
491 } else if (exp_diff == 0 && a_flt_e == 0) {
492 di_type result_di;
493 result_di.u = a_di.u + b_flt_m;
494 return result_di.f;
495 } else if (exp_diff == 0) {
496 e = a_flt_e;
497 m = 0x0020000000000000 + a_flt_m + b_flt_m;
498 m <<= 9;
499 } else if (exp_diff < 0) {
500 a_flt_m <<= 9;
501 b_flt_m <<= 9;
502 e = b_flt_e;
503
504 if (a_flt_e != 0)
505 a_flt_m += 0x2000000000000000;
506 else
507 a_flt_m <<= 1;
508
509 a_flt_m = _mesa_shift_right_jam64(a_flt_m, -exp_diff);
510 m = 0x2000000000000000 + a_flt_m + b_flt_m;
511 if (m < 0x4000000000000000) {
512 --e;
513 m <<= 1;
514 }
515 } else {
516 a_flt_m <<= 9;
517 b_flt_m <<= 9;
518 e = a_flt_e;
519
520 if (b_flt_e != 0)
521 b_flt_m += 0x2000000000000000;
522 else
523 b_flt_m <<= 1;
524
525 b_flt_m = _mesa_shift_right_jam64(b_flt_m, exp_diff);
526 m = 0x2000000000000000 + a_flt_m + b_flt_m;
527 if (m < 0x4000000000000000) {
528 --e;
529 m <<= 1;
530 }
531 }
532
533 return _mesa_roundtozero_f64(s, e, m);
534 }
535
536 /**
537 * \brief Returns the number of leading 0 bits before the most-significant 1 bit of
538 * 'a'. If 'a' is zero, 64 is returned.
539 */
540 static inline unsigned
_mesa_count_leading_zeros64(uint64_t a)541 _mesa_count_leading_zeros64(uint64_t a)
542 {
543 return 64 - util_last_bit64(a);
544 }
545
546 /**
547 * \brief Returns the number of leading 0 bits before the most-significant 1 bit of
548 * 'a'. If 'a' is zero, 32 is returned.
549 */
550 static inline unsigned
_mesa_count_leading_zeros32(uint32_t a)551 _mesa_count_leading_zeros32(uint32_t a)
552 {
553 return 32 - util_last_bit(a);
554 }
555
556 static inline double
_mesa_norm_round_pack_f64(int64_t s,int64_t e,int64_t m)557 _mesa_norm_round_pack_f64(int64_t s, int64_t e, int64_t m)
558 {
559 int8_t shift_dist;
560
561 shift_dist = _mesa_count_leading_zeros64(m) - 1;
562 e -= shift_dist;
563 if ((10 <= shift_dist) && ((unsigned) e < 0x7fd)) {
564 di_type result;
565 result.u = (s << 63) + ((m ? e : 0) << 52) + (m << (shift_dist - 10));
566 return result.f;
567 } else {
568 return _mesa_roundtozero_f64(s, e, m << shift_dist);
569 }
570 }
571
572 /**
573 * \brief Replaces the N-bit unsigned integer pointed to by 'm_out' by the
574 * 2s-complement of itself, where N = 'size_words' * 32. Argument 'm_out'
575 * points to a 'size_words'-long array of 32-bit elements that concatenate in
576 * the platform's normal endian order to form an N-bit integer.
577 *
578 * From softfloat_negXM()
579 */
580 static inline void
_mesa_neg_x_m(uint8_t size_words,uint32_t * m_out)581 _mesa_neg_x_m(uint8_t size_words, uint32_t *m_out)
582 {
583 unsigned index, last_index;
584 uint8_t carry;
585 uint32_t word;
586
587 index = index_word_lo(size_words);
588 last_index = index_word_hi(size_words);
589 carry = 1;
590 for (;;) {
591 word = ~m_out[index] + carry;
592 m_out[index] = word;
593 if (index == last_index)
594 break;
595 index += word_incr;
596 if (word)
597 carry = 0;
598 }
599 }
600
601 /**
602 * \brief Adds the two N-bit integers pointed to by 'a' and 'b', where N =
603 * 'size_words' * 32. The addition is modulo 2^N, so any carry out is
604 * lost. The N-bit sum is stored at the location pointed to by 'm_out'. Each
605 * of 'a', 'b', and 'm_out' points to a 'size_words'-long array of 32-bit
606 * elements that concatenate in the platform's normal endian order to form an
607 * N-bit integer.
608 *
609 * From softfloat_addM()
610 */
611 static inline void
_mesa_add_m(uint8_t size_words,const uint32_t * a,const uint32_t * b,uint32_t * m_out)612 _mesa_add_m(uint8_t size_words, const uint32_t *a, const uint32_t *b, uint32_t *m_out)
613 {
614 unsigned index, last_index;
615 uint8_t carry;
616 uint32_t a_word, word;
617
618 index = index_word_lo(size_words);
619 last_index = index_word_hi(size_words);
620 carry = 0;
621 for (;;) {
622 a_word = a[index];
623 word = a_word + b[index] + carry;
624 m_out[index] = word;
625 if (index == last_index)
626 break;
627 if (word != a_word)
628 carry = (word < a_word);
629 index += word_incr;
630 }
631 }
632
633 /**
634 * \brief Subtracts the two N-bit integers pointed to by 'a' and 'b', where N =
635 * 'size_words' * 32. The subtraction is modulo 2^N, so any borrow out (carry
636 * out) is lost. The N-bit difference is stored at the location pointed to by
637 * 'm_out'. Each of 'a', 'b', and 'm_out' points to a 'size_words'-long array
638 * of 32-bit elements that concatenate in the platform's normal endian order
639 * to form an N-bit integer.
640 *
641 * From softfloat_subM()
642 */
643 static inline void
_mesa_sub_m(uint8_t size_words,const uint32_t * a,const uint32_t * b,uint32_t * m_out)644 _mesa_sub_m(uint8_t size_words, const uint32_t *a, const uint32_t *b, uint32_t *m_out)
645 {
646 unsigned index, last_index;
647 uint8_t borrow;
648 uint32_t a_word, b_word;
649
650 index = index_word_lo(size_words);
651 last_index = index_word_hi(size_words);
652 borrow = 0;
653 for (;;) {
654 a_word = a[index];
655 b_word = b[index];
656 m_out[index] = a_word - b_word - borrow;
657 if (index == last_index)
658 break;
659 borrow = borrow ? (a_word <= b_word) : (a_word < b_word);
660 index += word_incr;
661 }
662 }
663
664 /* Calculate a - b but rounding to zero.
665 *
666 * Notice that this mainly differs from the original Berkeley SoftFloat 3e
667 * implementation in that we don't really treat NaNs, Zeroes nor the
668 * signalling flags. Any NaN is good for us and the sign of the Zero is not
669 * important.
670 *
671 * From f64_sub()
672 */
673 double
_mesa_double_sub_rtz(double a,double b)674 _mesa_double_sub_rtz(double a, double b)
675 {
676 const di_type a_di = {a};
677 uint64_t a_flt_m = a_di.u & 0x0fffffffffffff;
678 uint64_t a_flt_e = (a_di.u >> 52) & 0x7ff;
679 uint64_t a_flt_s = (a_di.u >> 63) & 0x1;
680 const di_type b_di = {b};
681 uint64_t b_flt_m = b_di.u & 0x0fffffffffffff;
682 uint64_t b_flt_e = (b_di.u >> 52) & 0x7ff;
683 uint64_t b_flt_s = (b_di.u >> 63) & 0x1;
684 int64_t s, e, m = 0;
685 int64_t m_diff = 0;
686 unsigned shift_dist = 0;
687
688 s = a_flt_s;
689
690 const int64_t exp_diff = a_flt_e - b_flt_e;
691
692 /* Handle special cases */
693
694 if (a_flt_s != b_flt_s) {
695 return _mesa_double_add_rtz(a, -b);
696 } else if ((a_flt_e == 0) && (a_flt_m == 0)) {
697 /* 'a' is zero, return '-b' */
698 return -b;
699 } else if ((b_flt_e == 0) && (b_flt_m == 0)) {
700 /* 'b' is zero, return 'a' */
701 return a;
702 } else if (a_flt_e == 0x7ff && a_flt_m != 0) {
703 /* 'a' is a NaN, return NaN */
704 return a;
705 } else if (b_flt_e == 0x7ff && b_flt_m != 0) {
706 /* 'b' is a NaN, return NaN */
707 return b;
708 } else if (a_flt_e == 0x7ff && a_flt_m == 0) {
709 if (b_flt_e == 0x7ff && b_flt_m == 0) {
710 /* Inf - Inf = NaN */
711 di_type result;
712 e = 0x7ff;
713 result.u = (s << 63) + (e << 52) + 0x1;
714 return result.f;
715 }
716 /* Inf - x = Inf */
717 return a;
718 } else if (b_flt_e == 0x7ff && b_flt_m == 0) {
719 /* x - Inf = -Inf */
720 return -b;
721 } else if (exp_diff == 0) {
722 m_diff = a_flt_m - b_flt_m;
723
724 if (m_diff == 0)
725 return 0;
726 if (a_flt_e)
727 --a_flt_e;
728 if (m_diff < 0) {
729 s = !s;
730 m_diff = -m_diff;
731 }
732
733 shift_dist = _mesa_count_leading_zeros64(m_diff) - 11;
734 e = a_flt_e - shift_dist;
735 if (e < 0) {
736 shift_dist = a_flt_e;
737 e = 0;
738 }
739
740 di_type result;
741 result.u = (s << 63) + (e << 52) + (m_diff << shift_dist);
742 return result.f;
743 } else if (exp_diff < 0) {
744 a_flt_m <<= 10;
745 b_flt_m <<= 10;
746 s = !s;
747
748 a_flt_m += (a_flt_e) ? 0x4000000000000000 : a_flt_m;
749 a_flt_m = _mesa_shift_right_jam64(a_flt_m, -exp_diff);
750 b_flt_m |= 0x4000000000000000;
751 e = b_flt_e;
752 m = b_flt_m - a_flt_m;
753 } else {
754 a_flt_m <<= 10;
755 b_flt_m <<= 10;
756
757 b_flt_m += (b_flt_e) ? 0x4000000000000000 : b_flt_m;
758 b_flt_m = _mesa_shift_right_jam64(b_flt_m, exp_diff);
759 a_flt_m |= 0x4000000000000000;
760 e = a_flt_e;
761 m = a_flt_m - b_flt_m;
762 }
763
764 return _mesa_norm_round_pack_f64(s, e - 1, m);
765 }
766
767 static inline void
_mesa_norm_subnormal_mantissa_f64(uint64_t m,uint64_t * exp,uint64_t * m_out)768 _mesa_norm_subnormal_mantissa_f64(uint64_t m, uint64_t *exp, uint64_t *m_out)
769 {
770 int shift_dist;
771
772 shift_dist = _mesa_count_leading_zeros64(m) - 11;
773 *exp = 1 - shift_dist;
774 *m_out = m << shift_dist;
775 }
776
777 static inline void
_mesa_norm_subnormal_mantissa_f32(uint32_t m,uint32_t * exp,uint32_t * m_out)778 _mesa_norm_subnormal_mantissa_f32(uint32_t m, uint32_t *exp, uint32_t *m_out)
779 {
780 int shift_dist;
781
782 shift_dist = _mesa_count_leading_zeros32(m) - 8;
783 *exp = 1 - shift_dist;
784 *m_out = m << shift_dist;
785 }
786
787 /**
788 * \brief Multiplies 'a' and 'b' and stores the 128-bit product at the location
789 * pointed to by 'zPtr'. Argument 'zPtr' points to an array of four 32-bit
790 * elements that concatenate in the platform's normal endian order to form a
791 * 128-bit integer.
792 *
793 * From softfloat_mul64To128M()
794 */
795 static inline void
_mesa_softfloat_mul_f64_to_f128_m(uint64_t a,uint64_t b,uint32_t * m_out)796 _mesa_softfloat_mul_f64_to_f128_m(uint64_t a, uint64_t b, uint32_t *m_out)
797 {
798 uint32_t a32, a0, b32, b0;
799 uint64_t z0, mid1, z64, mid;
800
801 a32 = a >> 32;
802 a0 = a;
803 b32 = b >> 32;
804 b0 = b;
805 z0 = (uint64_t) a0 * b0;
806 mid1 = (uint64_t) a32 * b0;
807 mid = mid1 + (uint64_t) a0 * b32;
808 z64 = (uint64_t) a32 * b32;
809 z64 += (uint64_t) (mid < mid1) << 32 | mid >> 32;
810 mid <<= 32;
811 z0 += mid;
812 m_out[index_word(4, 1)] = z0 >> 32;
813 m_out[index_word(4, 0)] = z0;
814 z64 += (z0 < mid);
815 m_out[index_word(4, 3)] = z64 >> 32;
816 m_out[index_word(4, 2)] = z64;
817 }
818
819 /* Calculate a * b but rounding to zero.
820 *
821 * Notice that this mainly differs from the original Berkeley SoftFloat 3e
822 * implementation in that we don't really treat NaNs, Zeroes nor the
823 * signalling flags. Any NaN is good for us and the sign of the Zero is not
824 * important.
825 *
826 * From f64_mul()
827 */
828 double
_mesa_double_mul_rtz(double a,double b)829 _mesa_double_mul_rtz(double a, double b)
830 {
831 const di_type a_di = {a};
832 uint64_t a_flt_m = a_di.u & 0x0fffffffffffff;
833 uint64_t a_flt_e = (a_di.u >> 52) & 0x7ff;
834 uint64_t a_flt_s = (a_di.u >> 63) & 0x1;
835 const di_type b_di = {b};
836 uint64_t b_flt_m = b_di.u & 0x0fffffffffffff;
837 uint64_t b_flt_e = (b_di.u >> 52) & 0x7ff;
838 uint64_t b_flt_s = (b_di.u >> 63) & 0x1;
839 int64_t s, e, m = 0;
840
841 s = a_flt_s ^ b_flt_s;
842
843 if (a_flt_e == 0x7ff) {
844 if (a_flt_m != 0) {
845 /* 'a' is a NaN, return NaN */
846 return a;
847 } else if (b_flt_e == 0x7ff && b_flt_m != 0) {
848 /* 'b' is a NaN, return NaN */
849 return b;
850 }
851
852 if (!(b_flt_e | b_flt_m)) {
853 /* Inf * 0 = NaN */
854 di_type result;
855 e = 0x7ff;
856 result.u = (s << 63) + (e << 52) + 0x1;
857 return result.f;
858 }
859 /* Inf * x = Inf */
860 di_type result;
861 e = 0x7ff;
862 result.u = (s << 63) + (e << 52) + 0;
863 return result.f;
864 }
865
866 if (b_flt_e == 0x7ff) {
867 if (b_flt_m != 0) {
868 /* 'b' is a NaN, return NaN */
869 return b;
870 }
871 if (!(a_flt_e | a_flt_m)) {
872 /* 0 * Inf = NaN */
873 di_type result;
874 e = 0x7ff;
875 result.u = (s << 63) + (e << 52) + 0x1;
876 return result.f;
877 }
878 /* x * Inf = Inf */
879 di_type result;
880 e = 0x7ff;
881 result.u = (s << 63) + (e << 52) + 0;
882 return result.f;
883 }
884
885 if (a_flt_e == 0) {
886 if (a_flt_m == 0) {
887 /* 'a' is zero. Return zero */
888 di_type result;
889 result.u = (s << 63) + 0;
890 return result.f;
891 }
892 _mesa_norm_subnormal_mantissa_f64(a_flt_m , &a_flt_e, &a_flt_m);
893 }
894 if (b_flt_e == 0) {
895 if (b_flt_m == 0) {
896 /* 'b' is zero. Return zero */
897 di_type result;
898 result.u = (s << 63) + 0;
899 return result.f;
900 }
901 _mesa_norm_subnormal_mantissa_f64(b_flt_m , &b_flt_e, &b_flt_m);
902 }
903
904 e = a_flt_e + b_flt_e - 0x3ff;
905 a_flt_m = (a_flt_m | 0x0010000000000000) << 10;
906 b_flt_m = (b_flt_m | 0x0010000000000000) << 11;
907
908 uint32_t m_128[4];
909 _mesa_softfloat_mul_f64_to_f128_m(a_flt_m, b_flt_m, m_128);
910
911 m = (uint64_t) m_128[index_word(4, 3)] << 32 | m_128[index_word(4, 2)];
912 if (m_128[index_word(4, 1)] || m_128[index_word(4, 0)])
913 m |= 1;
914
915 if (m < 0x4000000000000000) {
916 --e;
917 m <<= 1;
918 }
919
920 return _mesa_roundtozero_f64(s, e, m);
921 }
922
923
924 /**
925 * \brief Calculate a * b + c but rounding to zero.
926 *
927 * Notice that this mainly differs from the original Berkeley SoftFloat 3e
928 * implementation in that we don't really treat NaNs, Zeroes nor the
929 * signalling flags. Any NaN is good for us and the sign of the Zero is not
930 * important.
931 *
932 * From f64_mulAdd()
933 */
934 double
_mesa_double_fma_rtz(double a,double b,double c)935 _mesa_double_fma_rtz(double a, double b, double c)
936 {
937 const di_type a_di = {a};
938 uint64_t a_flt_m = a_di.u & 0x0fffffffffffff;
939 uint64_t a_flt_e = (a_di.u >> 52) & 0x7ff;
940 uint64_t a_flt_s = (a_di.u >> 63) & 0x1;
941 const di_type b_di = {b};
942 uint64_t b_flt_m = b_di.u & 0x0fffffffffffff;
943 uint64_t b_flt_e = (b_di.u >> 52) & 0x7ff;
944 uint64_t b_flt_s = (b_di.u >> 63) & 0x1;
945 const di_type c_di = {c};
946 uint64_t c_flt_m = c_di.u & 0x0fffffffffffff;
947 uint64_t c_flt_e = (c_di.u >> 52) & 0x7ff;
948 uint64_t c_flt_s = (c_di.u >> 63) & 0x1;
949 int64_t s, e, m = 0;
950
951 c_flt_s ^= 0;
952 s = a_flt_s ^ b_flt_s ^ 0;
953
954 if (a_flt_e == 0x7ff) {
955 if (a_flt_m != 0) {
956 /* 'a' is a NaN, return NaN */
957 return a;
958 } else if (b_flt_e == 0x7ff && b_flt_m != 0) {
959 /* 'b' is a NaN, return NaN */
960 return b;
961 } else if (c_flt_e == 0x7ff && c_flt_m != 0) {
962 /* 'c' is a NaN, return NaN */
963 return c;
964 }
965
966 if (!(b_flt_e | b_flt_m)) {
967 /* Inf * 0 + y = NaN */
968 di_type result;
969 e = 0x7ff;
970 result.u = (s << 63) + (e << 52) + 0x1;
971 return result.f;
972 }
973
974 if ((c_flt_e == 0x7ff && c_flt_m == 0) && (s != c_flt_s)) {
975 /* Inf * x - Inf = NaN */
976 di_type result;
977 e = 0x7ff;
978 result.u = (s << 63) + (e << 52) + 0x1;
979 return result.f;
980 }
981
982 /* Inf * x + y = Inf */
983 di_type result;
984 e = 0x7ff;
985 result.u = (s << 63) + (e << 52) + 0;
986 return result.f;
987 }
988
989 if (b_flt_e == 0x7ff) {
990 if (b_flt_m != 0) {
991 /* 'b' is a NaN, return NaN */
992 return b;
993 } else if (c_flt_e == 0x7ff && c_flt_m != 0) {
994 /* 'c' is a NaN, return NaN */
995 return c;
996 }
997
998 if (!(a_flt_e | a_flt_m)) {
999 /* 0 * Inf + y = NaN */
1000 di_type result;
1001 e = 0x7ff;
1002 result.u = (s << 63) + (e << 52) + 0x1;
1003 return result.f;
1004 }
1005
1006 if ((c_flt_e == 0x7ff && c_flt_m == 0) && (s != c_flt_s)) {
1007 /* x * Inf - Inf = NaN */
1008 di_type result;
1009 e = 0x7ff;
1010 result.u = (s << 63) + (e << 52) + 0x1;
1011 return result.f;
1012 }
1013
1014 /* x * Inf + y = Inf */
1015 di_type result;
1016 e = 0x7ff;
1017 result.u = (s << 63) + (e << 52) + 0;
1018 return result.f;
1019 }
1020
1021 if (c_flt_e == 0x7ff) {
1022 if (c_flt_m != 0) {
1023 /* 'c' is a NaN, return NaN */
1024 return c;
1025 }
1026
1027 /* x * y + Inf = Inf */
1028 return c;
1029 }
1030
1031 if (a_flt_e == 0) {
1032 if (a_flt_m == 0) {
1033 /* 'a' is zero, return 'c' */
1034 return c;
1035 }
1036 _mesa_norm_subnormal_mantissa_f64(a_flt_m , &a_flt_e, &a_flt_m);
1037 }
1038
1039 if (b_flt_e == 0) {
1040 if (b_flt_m == 0) {
1041 /* 'b' is zero, return 'c' */
1042 return c;
1043 }
1044 _mesa_norm_subnormal_mantissa_f64(b_flt_m , &b_flt_e, &b_flt_m);
1045 }
1046
1047 e = a_flt_e + b_flt_e - 0x3fe;
1048 a_flt_m = (a_flt_m | 0x0010000000000000) << 10;
1049 b_flt_m = (b_flt_m | 0x0010000000000000) << 11;
1050
1051 uint32_t m_128[4];
1052 _mesa_softfloat_mul_f64_to_f128_m(a_flt_m, b_flt_m, m_128);
1053
1054 m = (uint64_t) m_128[index_word(4, 3)] << 32 | m_128[index_word(4, 2)];
1055
1056 int64_t shift_dist = 0;
1057 if (!(m & 0x4000000000000000)) {
1058 --e;
1059 shift_dist = -1;
1060 }
1061
1062 if (c_flt_e == 0) {
1063 if (c_flt_m == 0) {
1064 /* 'c' is zero, return 'a * b' */
1065 if (shift_dist)
1066 m <<= 1;
1067
1068 if (m_128[index_word(4, 1)] || m_128[index_word(4, 0)])
1069 m |= 1;
1070 return _mesa_roundtozero_f64(s, e - 1, m);
1071 }
1072 _mesa_norm_subnormal_mantissa_f64(c_flt_m , &c_flt_e, &c_flt_m);
1073 }
1074 c_flt_m = (c_flt_m | 0x0010000000000000) << 10;
1075
1076 uint32_t c_flt_m_128[4];
1077 int64_t exp_diff = e - c_flt_e;
1078 if (exp_diff < 0) {
1079 e = c_flt_e;
1080 if ((s == c_flt_s) || (exp_diff < -1)) {
1081 shift_dist -= exp_diff;
1082 if (shift_dist) {
1083 m = _mesa_shift_right_jam64(m, shift_dist);
1084 }
1085 } else {
1086 if (!shift_dist) {
1087 _mesa_short_shift_right_m(4, m_128, 1, m_128);
1088 }
1089 }
1090 } else {
1091 if (shift_dist)
1092 _mesa_add_m(4, m_128, m_128, m_128);
1093 if (!exp_diff) {
1094 m = (uint64_t) m_128[index_word(4, 3)] << 32
1095 | m_128[index_word(4, 2)];
1096 } else {
1097 c_flt_m_128[index_word(4, 3)] = c_flt_m >> 32;
1098 c_flt_m_128[index_word(4, 2)] = c_flt_m;
1099 c_flt_m_128[index_word(4, 1)] = 0;
1100 c_flt_m_128[index_word(4, 0)] = 0;
1101 _mesa_shift_right_jam_m(4, c_flt_m_128, exp_diff, c_flt_m_128);
1102 }
1103 }
1104
1105 if (s == c_flt_s) {
1106 if (exp_diff <= 0) {
1107 m += c_flt_m;
1108 } else {
1109 _mesa_add_m(4, m_128, c_flt_m_128, m_128);
1110 m = (uint64_t) m_128[index_word(4, 3)] << 32
1111 | m_128[index_word(4, 2)];
1112 }
1113 if (m & 0x8000000000000000) {
1114 e++;
1115 m = _mesa_short_shift_right_jam64(m, 1);
1116 }
1117 } else {
1118 if (exp_diff < 0) {
1119 s = c_flt_s;
1120 if (exp_diff < -1) {
1121 m = c_flt_m - m;
1122 if (m_128[index_word(4, 1)] || m_128[index_word(4, 0)]) {
1123 m = (m - 1) | 1;
1124 }
1125 if (!(m & 0x4000000000000000)) {
1126 --e;
1127 m <<= 1;
1128 }
1129 return _mesa_roundtozero_f64(s, e - 1, m);
1130 } else {
1131 c_flt_m_128[index_word(4, 3)] = c_flt_m >> 32;
1132 c_flt_m_128[index_word(4, 2)] = c_flt_m;
1133 c_flt_m_128[index_word(4, 1)] = 0;
1134 c_flt_m_128[index_word(4, 0)] = 0;
1135 _mesa_sub_m(4, c_flt_m_128, m_128, m_128);
1136 }
1137 } else if (!exp_diff) {
1138 m -= c_flt_m;
1139 if (!m && !m_128[index_word(4, 1)] && !m_128[index_word(4, 0)]) {
1140 /* Return zero */
1141 di_type result;
1142 result.u = (s << 63) + 0;
1143 return result.f;
1144 }
1145 m_128[index_word(4, 3)] = m >> 32;
1146 m_128[index_word(4, 2)] = m;
1147 if (m & 0x8000000000000000) {
1148 s = !s;
1149 _mesa_neg_x_m(4, m_128);
1150 }
1151 } else {
1152 _mesa_sub_m(4, m_128, c_flt_m_128, m_128);
1153 if (1 < exp_diff) {
1154 m = (uint64_t) m_128[index_word(4, 3)] << 32
1155 | m_128[index_word(4, 2)];
1156 if (!(m & 0x4000000000000000)) {
1157 --e;
1158 m <<= 1;
1159 }
1160 if (m_128[index_word(4, 1)] || m_128[index_word(4, 0)])
1161 m |= 1;
1162 return _mesa_roundtozero_f64(s, e - 1, m);
1163 }
1164 }
1165
1166 shift_dist = 0;
1167 m = (uint64_t) m_128[index_word(4, 3)] << 32
1168 | m_128[index_word(4, 2)];
1169 if (!m) {
1170 shift_dist = 64;
1171 m = (uint64_t) m_128[index_word(4, 1)] << 32
1172 | m_128[index_word(4, 0)];
1173 }
1174 shift_dist += _mesa_count_leading_zeros64(m) - 1;
1175 if (shift_dist) {
1176 e -= shift_dist;
1177 _mesa_shift_left_m(4, m_128, shift_dist, m_128);
1178 m = (uint64_t) m_128[index_word(4, 3)] << 32
1179 | m_128[index_word(4, 2)];
1180 }
1181 }
1182
1183 if (m_128[index_word(4, 1)] || m_128[index_word(4, 0)])
1184 m |= 1;
1185 return _mesa_roundtozero_f64(s, e - 1, m);
1186 }
1187
1188
1189 /**
1190 * \brief Calculate a * b + c but rounding to zero.
1191 *
1192 * Notice that this mainly differs from the original Berkeley SoftFloat 3e
1193 * implementation in that we don't really treat NaNs, Zeroes nor the
1194 * signalling flags. Any NaN is good for us and the sign of the Zero is not
1195 * important.
1196 *
1197 * From f32_mulAdd()
1198 */
1199 float
_mesa_float_fma_rtz(float a,float b,float c)1200 _mesa_float_fma_rtz(float a, float b, float c)
1201 {
1202 const fi_type a_fi = {a};
1203 uint32_t a_flt_m = a_fi.u & 0x07fffff;
1204 uint32_t a_flt_e = (a_fi.u >> 23) & 0xff;
1205 uint32_t a_flt_s = (a_fi.u >> 31) & 0x1;
1206 const fi_type b_fi = {b};
1207 uint32_t b_flt_m = b_fi.u & 0x07fffff;
1208 uint32_t b_flt_e = (b_fi.u >> 23) & 0xff;
1209 uint32_t b_flt_s = (b_fi.u >> 31) & 0x1;
1210 const fi_type c_fi = {c};
1211 uint32_t c_flt_m = c_fi.u & 0x07fffff;
1212 uint32_t c_flt_e = (c_fi.u >> 23) & 0xff;
1213 uint32_t c_flt_s = (c_fi.u >> 31) & 0x1;
1214 int32_t s, e, m = 0;
1215
1216 c_flt_s ^= 0;
1217 s = a_flt_s ^ b_flt_s ^ 0;
1218
1219 if (a_flt_e == 0xff) {
1220 if (a_flt_m != 0) {
1221 /* 'a' is a NaN, return NaN */
1222 return a;
1223 } else if (b_flt_e == 0xff && b_flt_m != 0) {
1224 /* 'b' is a NaN, return NaN */
1225 return b;
1226 } else if (c_flt_e == 0xff && c_flt_m != 0) {
1227 /* 'c' is a NaN, return NaN */
1228 return c;
1229 }
1230
1231 if (!(b_flt_e | b_flt_m)) {
1232 /* Inf * 0 + y = NaN */
1233 fi_type result;
1234 e = 0xff;
1235 result.u = (s << 31) + (e << 23) + 0x1;
1236 return result.f;
1237 }
1238
1239 if ((c_flt_e == 0xff && c_flt_m == 0) && (s != c_flt_s)) {
1240 /* Inf * x - Inf = NaN */
1241 fi_type result;
1242 e = 0xff;
1243 result.u = (s << 31) + (e << 23) + 0x1;
1244 return result.f;
1245 }
1246
1247 /* Inf * x + y = Inf */
1248 fi_type result;
1249 e = 0xff;
1250 result.u = (s << 31) + (e << 23) + 0;
1251 return result.f;
1252 }
1253
1254 if (b_flt_e == 0xff) {
1255 if (b_flt_m != 0) {
1256 /* 'b' is a NaN, return NaN */
1257 return b;
1258 } else if (c_flt_e == 0xff && c_flt_m != 0) {
1259 /* 'c' is a NaN, return NaN */
1260 return c;
1261 }
1262
1263 if (!(a_flt_e | a_flt_m)) {
1264 /* 0 * Inf + y = NaN */
1265 fi_type result;
1266 e = 0xff;
1267 result.u = (s << 31) + (e << 23) + 0x1;
1268 return result.f;
1269 }
1270
1271 if ((c_flt_e == 0xff && c_flt_m == 0) && (s != c_flt_s)) {
1272 /* x * Inf - Inf = NaN */
1273 fi_type result;
1274 e = 0xff;
1275 result.u = (s << 31) + (e << 23) + 0x1;
1276 return result.f;
1277 }
1278
1279 /* x * Inf + y = Inf */
1280 fi_type result;
1281 e = 0xff;
1282 result.u = (s << 31) + (e << 23) + 0;
1283 return result.f;
1284 }
1285
1286 if (c_flt_e == 0xff) {
1287 if (c_flt_m != 0) {
1288 /* 'c' is a NaN, return NaN */
1289 return c;
1290 }
1291
1292 /* x * y + Inf = Inf */
1293 return c;
1294 }
1295
1296 if (a_flt_e == 0) {
1297 if (a_flt_m == 0) {
1298 /* 'a' is zero, return 'c' */
1299 return c;
1300 }
1301 _mesa_norm_subnormal_mantissa_f32(a_flt_m , &a_flt_e, &a_flt_m);
1302 }
1303
1304 if (b_flt_e == 0) {
1305 if (b_flt_m == 0) {
1306 /* 'b' is zero, return 'c' */
1307 return c;
1308 }
1309 _mesa_norm_subnormal_mantissa_f32(b_flt_m , &b_flt_e, &b_flt_m);
1310 }
1311
1312 e = a_flt_e + b_flt_e - 0x7e;
1313 a_flt_m = (a_flt_m | 0x00800000) << 7;
1314 b_flt_m = (b_flt_m | 0x00800000) << 7;
1315
1316 uint64_t m_64 = (uint64_t) a_flt_m * b_flt_m;
1317 if (m_64 < 0x2000000000000000) {
1318 --e;
1319 m_64 <<= 1;
1320 }
1321
1322 if (c_flt_e == 0) {
1323 if (c_flt_m == 0) {
1324 /* 'c' is zero, return 'a * b' */
1325 m = _mesa_short_shift_right_jam64(m_64, 31);
1326 return _mesa_round_f32(s, e - 1, m, true);
1327 }
1328 _mesa_norm_subnormal_mantissa_f32(c_flt_m , &c_flt_e, &c_flt_m);
1329 }
1330 c_flt_m = (c_flt_m | 0x00800000) << 6;
1331
1332 int16_t exp_diff = e - c_flt_e;
1333 if (s == c_flt_s) {
1334 if (exp_diff <= 0) {
1335 e = c_flt_e;
1336 m = c_flt_m + _mesa_shift_right_jam64(m_64, 32 - exp_diff);
1337 } else {
1338 m_64 += _mesa_shift_right_jam64((uint64_t) c_flt_m << 32, exp_diff);
1339 m = _mesa_short_shift_right_jam64(m_64, 32);
1340 }
1341 if (m < 0x40000000) {
1342 --e;
1343 m <<= 1;
1344 }
1345 } else {
1346 uint64_t c_flt_m_64 = (uint64_t) c_flt_m << 32;
1347 if (exp_diff < 0) {
1348 s = c_flt_s;
1349 e = c_flt_e;
1350 m_64 = c_flt_m_64 - _mesa_shift_right_jam64(m_64, -exp_diff);
1351 } else if (!exp_diff) {
1352 m_64 -= c_flt_m_64;
1353 if (!m_64) {
1354 /* Return zero */
1355 fi_type result;
1356 result.u = (s << 31) + 0;
1357 return result.f;
1358 }
1359 if (m_64 & 0x8000000000000000) {
1360 s = !s;
1361 m_64 = -m_64;
1362 }
1363 } else {
1364 m_64 -= _mesa_shift_right_jam64(c_flt_m_64, exp_diff);
1365 }
1366 int8_t shift_dist = _mesa_count_leading_zeros64(m_64) - 1;
1367 e -= shift_dist;
1368 shift_dist -= 32;
1369 if (shift_dist < 0) {
1370 m = _mesa_short_shift_right_jam64(m_64, -shift_dist);
1371 } else {
1372 m = (uint32_t) m_64 << shift_dist;
1373 }
1374 }
1375
1376 return _mesa_round_f32(s, e, m, true);
1377 }
1378
1379
1380 /**
1381 * \brief Converts from 64bits to 32bits float and rounds according to
1382 * instructed.
1383 *
1384 * From f64_to_f32()
1385 */
1386 float
_mesa_double_to_f32(double val,bool rtz)1387 _mesa_double_to_f32(double val, bool rtz)
1388 {
1389 const di_type di = {val};
1390 uint64_t flt_m = di.u & 0x0fffffffffffff;
1391 uint64_t flt_e = (di.u >> 52) & 0x7ff;
1392 uint64_t flt_s = (di.u >> 63) & 0x1;
1393 int32_t s, e, m = 0;
1394
1395 s = flt_s;
1396
1397 if (flt_e == 0x7ff) {
1398 if (flt_m != 0) {
1399 /* 'val' is a NaN, return NaN */
1400 fi_type result;
1401 e = 0xff;
1402 m = 0x1;
1403 result.u = (s << 31) + (e << 23) + m;
1404 return result.f;
1405 }
1406
1407 /* 'val' is Inf, return Inf */
1408 fi_type result;
1409 e = 0xff;
1410 result.u = (s << 31) + (e << 23) + m;
1411 return result.f;
1412 }
1413
1414 if (!(flt_e | flt_m)) {
1415 /* 'val' is zero, return zero */
1416 fi_type result;
1417 e = 0;
1418 result.u = (s << 31) + (e << 23) + m;
1419 return result.f;
1420 }
1421
1422 m = _mesa_short_shift_right_jam64(flt_m, 22);
1423 if ( ! (flt_e | m) ) {
1424 /* 'val' is denorm, return zero */
1425 fi_type result;
1426 e = 0;
1427 result.u = (s << 31) + (e << 23) + m;
1428 return result.f;
1429 }
1430
1431 return _mesa_round_f32(s, flt_e - 0x381, m | 0x40000000, rtz);
1432 }
1433
1434
1435 /**
1436 * \brief Converts from 32bits to 16bits float and rounds the result to zero.
1437 *
1438 * From f32_to_f16()
1439 */
1440 uint16_t
_mesa_float_to_half_rtz_slow(float val)1441 _mesa_float_to_half_rtz_slow(float val)
1442 {
1443 const fi_type fi = {val};
1444 const uint32_t flt_m = fi.u & 0x7fffff;
1445 const uint32_t flt_e = (fi.u >> 23) & 0xff;
1446 const uint32_t flt_s = (fi.u >> 31) & 0x1;
1447 int16_t s, e, m = 0;
1448
1449 s = flt_s;
1450
1451 if (flt_e == 0xff) {
1452 if (flt_m != 0) {
1453 /* 'val' is a NaN, return NaN */
1454 e = 0x1f;
1455 /* Retain the top bits of a NaN to make sure that the quiet/signaling
1456 * status stays the same.
1457 */
1458 m = flt_m >> 13;
1459 if (!m)
1460 m = 1;
1461 return (s << 15) + (e << 10) + m;
1462 }
1463
1464 /* 'val' is Inf, return Inf */
1465 e = 0x1f;
1466 return (s << 15) + (e << 10) + m;
1467 }
1468
1469 if (!(flt_e | flt_m)) {
1470 /* 'val' is zero, return zero */
1471 e = 0;
1472 return (s << 15) + (e << 10) + m;
1473 }
1474
1475 m = flt_m >> 9 | ((flt_m & 0x1ff) != 0);
1476 if ( ! (flt_e | m) ) {
1477 /* 'val' is denorm, return zero */
1478 e = 0;
1479 return (s << 15) + (e << 10) + m;
1480 }
1481
1482 return _mesa_roundtozero_f16(s, flt_e - 0x71, m | 0x4000);
1483 }
1484