VirtualBox

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

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

lib/softfloat: Corrected not-zero detection when setting the inexact flag again. bugref:9898

  • Property svn:eol-style set to native
File size: 15.5 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 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
220 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #5\n"); /* VBox: C1 */
221 ++sig;
222 sig &=
223 ~(uint_fast64_t)
224 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
225 & roundNearEven);
226 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
227 }
228 goto packReturn;
229 }
230 if (
231 (0x7FFE < exp)
232 || ((exp == 0x7FFE) && (sig == UINT64_C( 0xFFFFFFFFFFFFFFFF ))
233 && doIncrement)
234 ) {
235 /*----------------------------------------------------------------
236 *----------------------------------------------------------------*/
237 roundMask = 0;
238 overflow:
239 softfloat_raiseFlags(
240 softfloat_flag_overflow | softfloat_flag_inexact
241 SOFTFLOAT_STATE_ARG_COMMA );
242 if (
243 roundNearEven
244 || (roundingMode == softfloat_round_near_maxMag)
245 || (roundingMode
246 == (sign ? softfloat_round_min : softfloat_round_max))
247 ) {
248 exp = 0x7FFF;
249 sig = UINT64_C( 0x8000000000000000 );
250 softfloat_exceptionFlags |= softfloat_flag_c1; /* Inf means rounding up */ /* VBox: C1 */
251 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #6\n"); /* VBox: C1 */
252 } else {
253 exp = 0x7FFE;
254 sig = ~roundMask;
255 }
256 goto packReturn;
257 }
258 }
259 /*------------------------------------------------------------------------
260 *------------------------------------------------------------------------*/
261 if ( sigExtra ) {
262 softfloat_exceptionFlags |= softfloat_flag_inexact;
263#ifdef SOFTFLOAT_ROUND_ODD
264 if ( roundingMode == softfloat_round_odd ) {
265 sig |= 1;
266 goto packReturn;
267 }
268#endif
269 }
270 if ( doIncrement ) {
271 uint64_t const uOldSig = sig; /* VBox */
272 ++sig;
273 if ( ! sig ) {
274 ++exp;
275 sig = UINT64_C( 0x8000000000000000 );
276 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
277 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #7\n"); /* VBox: C1 */
278 } else {
279 sig &=
280 ~(uint_fast64_t)
281 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
282 & roundNearEven);
283 if ( sig > uOldSig ) { /* VBox: C1 */
284 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
285 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #8\n"); /* VBox: C1 */
286 }
287 }
288 }
289 /*------------------------------------------------------------------------
290 *------------------------------------------------------------------------*/
291 packReturn:
292 uZ.s.signExp = packToExtF80UI64( sign, exp );
293 uZ.s.signif = sig;
294 return uZ.f;
295
296}
297
298extFloat80_t
299 softfloat_roundPackToExtF80(
300 bool sign,
301 int_fast32_t exp,
302 uint_fast64_t sig,
303 uint_fast64_t sigExtra,
304 uint_fast8_t roundingPrecision
305 SOFTFLOAT_STATE_DECL_COMMA
306 )
307{
308 uint8_t const exceptionFlagsSaved = softfloat_exceptionFlags;
309 softfloat_exceptionFlags = 0;
310 extFloat80_t r80Result = softfloat_roundPackToExtF80Inner(sign, exp, sig, sigExtra, roundingPrecision, pState);
311
312 if ( !(softfloat_exceptionFlags & ~pState->exceptionMask & (softfloat_flag_underflow | softfloat_flag_overflow)) ) {
313 /* likely */
314 } else {
315 softfloat_exceptionFlags &= softfloat_flag_underflow | softfloat_flag_overflow;
316 if ( softfloat_exceptionFlags & softfloat_flag_underflow ) {
317 exp = (exp + RTFLOAT80U_EXP_BIAS_ADJUST) & RTFLOAT80U_EXP_MAX;
318 } else {
319 exp = (exp - RTFLOAT80U_EXP_BIAS_ADJUST) & RTFLOAT80U_EXP_MAX;
320 }
321 r80Result = softfloat_roundPackToExtF80Inner(sign, exp, sig, sigExtra, roundingPrecision, pState);
322 }
323
324 softfloat_exceptionFlags |= exceptionFlagsSaved;
325 return r80Result;
326}
327
Note: See TracBrowser for help on using the repository browser.

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