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