VirtualBox

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

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

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

  • Property svn:eol-style set to native
File size: 15.3 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) && /* zero: */ sig != 0 && sigExtra != 0 ) { /* VBox: Missing inexact result flag */
190 softfloat_exceptionFlags |= softfloat_flag_inexact; /* VBox: Missing inexact result flag */
191 } /* VBox: Missing inexact result flag */
192 exp = 0;
193 sig = sig64Extra.v;
194 sigExtra = sig64Extra.extra;
195//RTAssertMsg2("softfloat_roundPackToExtF80: #2: sig=%#RX64 sigExtra=%#RX64 isTiny=%d\n", sig, sigExtra, isTiny);
196 if ( sigExtra
197 || ( !(pState->exceptionMask & softfloat_flag_underflow) /* VBox: Unmasked underflow conditions differ */
198 && (sig != 0 || sigExtra != 0) /*zero*/ ) ) { /* VBox: Unmasked underflow conditions differ */
199 if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow SOFTFLOAT_STATE_ARG_COMMA );
200#ifdef SOFTFLOAT_ROUND_ODD
201 if ( roundingMode == softfloat_round_odd ) {
202 sig |= 1;
203 goto packReturn;
204 }
205#endif
206 }
207 doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
208 if (
209 ! roundNearEven
210 && (roundingMode != softfloat_round_near_maxMag)
211 ) {
212 doIncrement =
213 (roundingMode
214 == (sign ? softfloat_round_min : softfloat_round_max))
215 && sigExtra;
216 }
217 if ( doIncrement ) {
218 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
219 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #5\n"); /* VBox: C1 */
220 ++sig;
221 sig &=
222 ~(uint_fast64_t)
223 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
224 & roundNearEven);
225 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
226 }
227 goto packReturn;
228 }
229 if (
230 (0x7FFE < exp)
231 || ((exp == 0x7FFE) && (sig == UINT64_C( 0xFFFFFFFFFFFFFFFF ))
232 && doIncrement)
233 ) {
234 /*----------------------------------------------------------------
235 *----------------------------------------------------------------*/
236 roundMask = 0;
237 overflow:
238 softfloat_raiseFlags(
239 softfloat_flag_overflow | softfloat_flag_inexact
240 SOFTFLOAT_STATE_ARG_COMMA );
241 if (
242 roundNearEven
243 || (roundingMode == softfloat_round_near_maxMag)
244 || (roundingMode
245 == (sign ? softfloat_round_min : softfloat_round_max))
246 ) {
247 exp = 0x7FFF;
248 sig = UINT64_C( 0x8000000000000000 );
249 softfloat_exceptionFlags |= softfloat_flag_c1; /* Inf means rounding up */ /* VBox: C1 */
250 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #6\n"); /* VBox: C1 */
251 } else {
252 exp = 0x7FFE;
253 sig = ~roundMask;
254 }
255 goto packReturn;
256 }
257 }
258 /*------------------------------------------------------------------------
259 *------------------------------------------------------------------------*/
260 if ( sigExtra ) {
261 softfloat_exceptionFlags |= softfloat_flag_inexact;
262#ifdef SOFTFLOAT_ROUND_ODD
263 if ( roundingMode == softfloat_round_odd ) {
264 sig |= 1;
265 goto packReturn;
266 }
267#endif
268 }
269 if ( doIncrement ) {
270 uint64_t const uOldSig = sig; /* VBox */
271 ++sig;
272 if ( ! sig ) {
273 ++exp;
274 sig = UINT64_C( 0x8000000000000000 );
275 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
276 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #7\n"); /* VBox: C1 */
277 } else {
278 sig &=
279 ~(uint_fast64_t)
280 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
281 & roundNearEven);
282 if ( sig > uOldSig ) { /* VBox: C1 */
283 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox: C1 */
284 //RTAssertMsg2("softfloat_roundPackToExtF80: C1 #8\n"); /* VBox: C1 */
285 }
286 }
287 }
288 /*------------------------------------------------------------------------
289 *------------------------------------------------------------------------*/
290 packReturn:
291 uZ.s.signExp = packToExtF80UI64( sign, exp );
292 uZ.s.signif = sig;
293 return uZ.f;
294
295}
296
297extFloat80_t
298 softfloat_roundPackToExtF80(
299 bool sign,
300 int_fast32_t exp,
301 uint_fast64_t sig,
302 uint_fast64_t sigExtra,
303 uint_fast8_t roundingPrecision
304 SOFTFLOAT_STATE_DECL_COMMA
305 )
306{
307 uint8_t const exceptionFlagsSaved = softfloat_exceptionFlags;
308 softfloat_exceptionFlags = 0;
309 extFloat80_t r80Result = softfloat_roundPackToExtF80Inner(sign, exp, sig, sigExtra, roundingPrecision, pState);
310
311 if ( !(softfloat_exceptionFlags & ~pState->exceptionMask & (softfloat_flag_underflow | softfloat_flag_overflow)) ) {
312 /* likely */
313 } else {
314 softfloat_exceptionFlags &= softfloat_flag_underflow | softfloat_flag_overflow;
315 if ( softfloat_exceptionFlags & softfloat_flag_underflow ) {
316 exp = (exp + RTFLOAT80U_EXP_BIAS_ADJUST) & RTFLOAT80U_EXP_MAX;
317 } else {
318 exp = (exp - RTFLOAT80U_EXP_BIAS_ADJUST) & RTFLOAT80U_EXP_MAX;
319 }
320 r80Result = softfloat_roundPackToExtF80Inner(sign, exp, sig, sigExtra, roundingPrecision, pState);
321 }
322
323 softfloat_exceptionFlags |= exceptionFlagsSaved;
324 return r80Result;
325}
326
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