VirtualBox

source: vbox/trunk/src/libs/softfloat-3e/source/s_roundPackToExtF80.c@ 94677

Last change on this file since 94677 was 94677, checked in by vboxsync, 3 years ago

lib/softfloat: Fixed one case of setting the C1 flag during rounding and amended the bias-adjust code to correctly handle the large exponents FSCALE can produce. bugref:9898

  • Property svn:eol-style set to native
File size: 17.0 KB
Line 
1
2/*============================================================================
3
4This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5Package, Release 3e, by John R. Hauser.
6
7Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
8California. All rights reserved.
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13 1. Redistributions of source code must retain the above copyright notice,
14 this list of conditions, and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions, and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19
20 3. Neither the name of the University nor the names of its contributors may
21 be used to endorse or promote products derived from this software without
22 specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35=============================================================================*/
36
37#include <stdbool.h>
38#include <stdint.h>
39#include "platform.h"
40#include "internals.h"
41#include "softfloat.h"
42#include <iprt/types.h> /* VBox: RTFLOAT80U_EXP_BIAS_ADJUST */
43#include <iprt/assert.h>
44
45static extFloat80_t
46 softfloat_roundPackToExtF80Inner(
47 bool sign,
48 int_fast32_t exp,
49 uint_fast64_t sig,
50 uint_fast64_t sigExtra,
51 uint_fast8_t roundingPrecision
52 SOFTFLOAT_STATE_DECL_COMMA
53 )
54{
55 uint_fast8_t roundingMode;
56 bool roundNearEven;
57 uint_fast64_t roundIncrement, roundMask, roundBits;
58 bool isTiny, doIncrement = 0;
59 struct uint64_extra sig64Extra;
60 union { struct extFloat80M s; extFloat80_t f; } uZ;
61 //RTAssertMsg2("softfloat_roundPackToExtF80: exp=%d sig=%RX64 sigExtra=%RX64 rp=%d\n", exp, sig, sigExtra, roundingPrecision);
62
63 /*------------------------------------------------------------------------
64 *------------------------------------------------------------------------*/
65 roundingMode = softfloat_roundingMode;
66 roundNearEven = (roundingMode == softfloat_round_near_even);
67 if ( roundingPrecision == 80 ) goto precision80;
68 if ( roundingPrecision == 64 ) {
69 roundIncrement = UINT64_C( 0x0000000000000400 );
70 roundMask = UINT64_C( 0x00000000000007FF );
71 } else if ( roundingPrecision == 32 ) {
72 roundIncrement = UINT64_C( 0x0000008000000000 );
73 roundMask = UINT64_C( 0x000000FFFFFFFFFF );
74 } else {
75 goto precision80;
76 }
77 sig |= (sigExtra != 0);
78 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
79 roundIncrement =
80 (roundingMode
81 == (sign ? softfloat_round_min : softfloat_round_max))
82 ? roundMask
83 : 0;
84 }
85 roundBits = sig & roundMask;
86 /*------------------------------------------------------------------------
87 *------------------------------------------------------------------------*/
88 if ( 0x7FFD <= (uint32_t) (exp - 1) ) {
89 if ( exp <= 0 ) {
90 /*----------------------------------------------------------------
91 *----------------------------------------------------------------*/
92 isTiny =
93 (softfloat_detectTininess
94 == softfloat_tininess_beforeRounding)
95 || (exp < 0)
96 || (sig <= (uint64_t) (sig + roundIncrement));
97 sig = softfloat_shiftRightJam64(sig, 1 - exp);
98 uint64_t const uOldSig = sig; /* VBox: C1 */
99 roundBits = sig & roundMask;
100 if ( roundBits ) {
101 if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow SOFTFLOAT_STATE_ARG_COMMA );
102 softfloat_exceptionFlags |= softfloat_flag_inexact;
103#ifdef SOFTFLOAT_ROUND_ODD
104 if ( roundingMode == softfloat_round_odd ) {
105 sig |= roundMask + 1;
106 }
107#endif
108 }
109 sig += roundIncrement;
110 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
111 roundIncrement = roundMask + 1;
112 if ( roundNearEven && (roundBits<<1 == roundIncrement) ) {
113 roundMask |= roundIncrement;
114 }
115 sig &= ~roundMask;
116 if ( sig > uOldSig ) { /* VBox: C1 */
117 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
118 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #1\n"); /* VBox: C1 */
119 } /* VBox: C1 */
120 goto packReturn;
121 }
122 if (
123 (0x7FFE < exp)
124 || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig))
125 ) {
126 goto overflow;
127 }
128 }
129 /*------------------------------------------------------------------------
130 *------------------------------------------------------------------------*/
131 { /* VBox: C1 */
132 uint64_t const uOldSig = sig; /* VBox: C1 */
133 if ( roundBits ) {
134 softfloat_exceptionFlags |= softfloat_flag_inexact;
135#ifdef SOFTFLOAT_ROUND_ODD
136 if ( roundingMode == softfloat_round_odd ) {
137 sig = (sig & ~roundMask) | (roundMask + 1);
138 if ( sig > uOldSig ) { /* VBox: C1 */
139 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
140 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #2\n"); /* VBox: C1 */
141 } /* VBox: C1 */
142 goto packReturn;
143 }
144#endif
145 }
146 sig = (uint64_t) (sig + roundIncrement);
147 if ( sig < roundIncrement ) {
148 ++exp;
149 sig = UINT64_C( 0x8000000000000000 );
150 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
151 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #3\n"); /* VBox: C1 */
152 }
153 roundIncrement = roundMask + 1;
154 if ( roundNearEven && (roundBits<<1 == roundIncrement) ) {
155 roundMask |= roundIncrement;
156 }
157 sig &= ~roundMask;
158 if ( sig > uOldSig ) { /* VBox: C1 */
159 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
160 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #4\n"); /* VBox: C1 */
161 } /* VBox: C1 */
162 goto packReturn;
163 } /* VBox: C1 */
164 /*------------------------------------------------------------------------
165 *------------------------------------------------------------------------*/
166 precision80:
167 doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
168 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
169 doIncrement =
170 (roundingMode
171 == (sign ? softfloat_round_min : softfloat_round_max))
172 && sigExtra;
173 }
174 /*------------------------------------------------------------------------
175 *------------------------------------------------------------------------*/
176 if ( 0x7FFD <= (uint32_t) (exp - 1) ) {
177 if ( exp <= 0 ) {
178 /*----------------------------------------------------------------
179 *----------------------------------------------------------------*/
180 isTiny =
181 (softfloat_detectTininess
182 == softfloat_tininess_beforeRounding)
183 || (exp < 0)
184 || ! doIncrement
185 || (sig < UINT64_C( 0xFFFFFFFFFFFFFFFF ));
186//RTAssertMsg2("softfloat_roundPackToExtF80: #2: sig=%#RX64 sigExtra=%#RX64 isTiny=%d exp=%d 1-exp=%d\n", sig, sigExtra, isTiny, exp, 1-exp);
187 sig64Extra =
188 softfloat_shiftRightJam64Extra( sig, sigExtra, 1 - exp );
189 if ( (exp < -63 || sig64Extra.extra != 0) /* VBox: Missing inexact result flag */
190 && ( sig != 0 || sigExtra != 0 ) /*!zero*/ ) { /* VBox: Missing inexact result flag */
191 softfloat_exceptionFlags |= softfloat_flag_inexact; /* VBox: Missing inexact result flag */
192 } /* VBox: Missing inexact result flag */
193 exp = 0;
194 sig = sig64Extra.v;
195 sigExtra = sig64Extra.extra;
196//RTAssertMsg2("softfloat_roundPackToExtF80: #3: sig=%#RX64 sigExtra=%#RX64 isTiny=%d\n", sig, sigExtra, isTiny);
197 if ( sigExtra
198 || ( !(pState->exceptionMask & softfloat_flag_underflow) /* VBox: Unmasked underflow conditions differ */
199 && (sig != 0 || sigExtra != 0) /*zero*/ ) ) { /* VBox: Unmasked underflow conditions differ */
200 if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow SOFTFLOAT_STATE_ARG_COMMA );
201#ifdef SOFTFLOAT_ROUND_ODD
202 if ( roundingMode == softfloat_round_odd ) {
203 sig |= 1;
204 goto packReturn;
205 }
206#endif
207 }
208 doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
209 if (
210 ! roundNearEven
211 && (roundingMode != softfloat_round_near_maxMag)
212 ) {
213 doIncrement =
214 (roundingMode
215 == (sign ? softfloat_round_min : softfloat_round_max))
216 && sigExtra;
217 }
218 if ( doIncrement ) {
219 uint64_t const uOldSig = sig; /* VBox: C1 */
220 ++sig;
221 sig &=
222 ~(uint_fast64_t)
223 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
224 & roundNearEven);
225 if (sig > uOldSig) { /* VBox: C1 */
226 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
227 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #5\n"); /* VBox: C1 */
228 } /* VBox: C1 */
229 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
230 }
231 goto packReturn;
232 }
233 if (
234 (0x7FFE < exp)
235 || ((exp == 0x7FFE) && (sig == UINT64_C( 0xFFFFFFFFFFFFFFFF ))
236 && doIncrement)
237 ) {
238 /*----------------------------------------------------------------
239 *----------------------------------------------------------------*/
240 roundMask = 0;
241 overflow:
242 softfloat_raiseFlags(
243 softfloat_flag_overflow | softfloat_flag_inexact
244 SOFTFLOAT_STATE_ARG_COMMA );
245 if (
246 roundNearEven
247 || (roundingMode == softfloat_round_near_maxMag)
248 || (roundingMode
249 == (sign ? softfloat_round_min : softfloat_round_max))
250 ) {
251 exp = 0x7FFF;
252 sig = UINT64_C( 0x8000000000000000 );
253 softfloat_exceptionFlags |= softfloat_flag_c1; /* Inf means rounding up */ /* VBox: C1 */
254 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #6\n"); /* VBox: C1 */
255 } else {
256 exp = 0x7FFE;
257 sig = ~roundMask;
258 }
259 goto packReturn;
260 }
261 }
262 /*------------------------------------------------------------------------
263 *------------------------------------------------------------------------*/
264 if ( sigExtra ) {
265 softfloat_exceptionFlags |= softfloat_flag_inexact;
266#ifdef SOFTFLOAT_ROUND_ODD
267 if ( roundingMode == softfloat_round_odd ) {
268 sig |= 1;
269 goto packReturn;
270 }
271#endif
272 }
273 if ( doIncrement ) {
274 uint64_t const uOldSig = sig; /* VBox */
275 ++sig;
276 if ( ! sig ) {
277 ++exp;
278 sig = UINT64_C( 0x8000000000000000 );
279 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
280 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #7\n"); /* VBox: C1 */
281 } else {
282 sig &=
283 ~(uint_fast64_t)
284 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
285 & roundNearEven);
286 if ( sig > uOldSig ) { /* VBox: C1 */
287 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
288 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #8\n"); /* VBox: C1 */
289 }
290 }
291 }
292 /*------------------------------------------------------------------------
293 *------------------------------------------------------------------------*/
294 packReturn:
295 uZ.s.signExp = packToExtF80UI64( sign, exp );
296 uZ.s.signif = sig;
297 return uZ.f;
298
299}
300
301/**
302 * VBox: Wrapper for implementing underflow and overflow bias adjustment.
303 */
304extFloat80_t
305 softfloat_roundPackToExtF80(
306 bool sign,
307 int_fast32_t exp,
308 uint_fast64_t sig,
309 uint_fast64_t sigExtra,
310 uint_fast8_t roundingPrecision
311 SOFTFLOAT_STATE_DECL_COMMA
312 )
313{
314 static union extF80M_extF80 const s_aExtF80Zero[2] =
315 {
316 EXTF80M_EXTF80_INIT3_C( 0, 0, 0 ), EXTF80M_EXTF80_INIT3_C( 1, 0, 0 ),
317 };
318 static union extF80M_extF80 const s_aExtF80Infinity[2] =
319 {
320 EXTF80M_EXTF80_INIT3( 0, RT_BIT_64( 63 ), RTFLOAT80U_EXP_MAX ),
321 EXTF80M_EXTF80_INIT3( 1, RT_BIT_64( 63 ), RTFLOAT80U_EXP_MAX ),
322 };
323
324 uint8_t const exceptionFlagsSaved = softfloat_exceptionFlags;
325 softfloat_exceptionFlags = 0;
326 extFloat80_t r80Result = softfloat_roundPackToExtF80Inner( sign, exp, sig, sigExtra, roundingPrecision, pState );
327
328 if ( !(softfloat_exceptionFlags & ~pState->exceptionMask & (softfloat_flag_underflow | softfloat_flag_overflow)) ) {
329 /* likely */
330 }
331 /* On Intel 10980XE the FSCALE instruction can cause really large exponents
332 and the rounding changes when we exceed the bias adjust. */
333 else if (exp >= RTFLOAT80U_EXP_BIAS_ADJUST + RTFLOAT80U_EXP_MAX) {
334 Assert( softfloat_exceptionFlags & softfloat_flag_overflow );
335 softfloat_exceptionFlags |= softfloat_flag_inexact | softfloat_flag_c1;
336 r80Result = s_aExtF80Infinity[sign].f;
337 } else if (exp <= -RTFLOAT80U_EXP_BIAS_ADJUST) {
338 Assert( softfloat_exceptionFlags & softfloat_flag_underflow );
339 softfloat_exceptionFlags &= ~softfloat_flag_c1;
340 softfloat_exceptionFlags |= softfloat_flag_inexact;
341 r80Result = s_aExtF80Zero[sign].f;
342 } else {
343 /* Redo the conversion with the bias applied. */
344 softfloat_exceptionFlags &= softfloat_flag_underflow | softfloat_flag_overflow;
345 if ( softfloat_exceptionFlags & softfloat_flag_underflow ) {
346 exp += RTFLOAT80U_EXP_BIAS_ADJUST;
347 Assert( exp > 0 );
348 } else {
349 exp -= RTFLOAT80U_EXP_BIAS_ADJUST;
350 Assert( exp < RTFLOAT80U_EXP_MAX );
351 }
352 r80Result = softfloat_roundPackToExtF80Inner( sign, exp, sig, sigExtra, roundingPrecision, pState );
353 }
354
355 softfloat_exceptionFlags |= exceptionFlagsSaved;
356 return r80Result;
357}
358
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette