VirtualBox

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

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

VMM/IEM,libs/softfloat: Don't use global variables in SoftFloat, pass in a state pointer to (almost) all functions instead. Started on fsqrt instruction implementation. bugref:9898

  • Property svn:eol-style set to native
File size: 10.2 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
43extFloat80_t
44 softfloat_roundPackToExtF80(
45 bool sign,
46 int_fast32_t exp,
47 uint_fast64_t sig,
48 uint_fast64_t sigExtra,
49 uint_fast8_t roundingPrecision
50 SOFTFLOAT_STATE_DECL_COMMA
51 )
52{
53 uint_fast8_t roundingMode;
54 bool roundNearEven;
55 uint_fast64_t roundIncrement, roundMask, roundBits;
56 bool isTiny, doIncrement;
57 struct uint64_extra sig64Extra;
58 union { struct extFloat80M s; extFloat80_t f; } uZ;
59
60 /*------------------------------------------------------------------------
61 *------------------------------------------------------------------------*/
62 roundingMode = softfloat_roundingMode;
63 roundNearEven = (roundingMode == softfloat_round_near_even);
64 if ( roundingPrecision == 80 ) goto precision80;
65 if ( roundingPrecision == 64 ) {
66 roundIncrement = UINT64_C( 0x0000000000000400 );
67 roundMask = UINT64_C( 0x00000000000007FF );
68 } else if ( roundingPrecision == 32 ) {
69 roundIncrement = UINT64_C( 0x0000008000000000 );
70 roundMask = UINT64_C( 0x000000FFFFFFFFFF );
71 } else {
72 goto precision80;
73 }
74 sig |= (sigExtra != 0);
75 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
76 roundIncrement =
77 (roundingMode
78 == (sign ? softfloat_round_min : softfloat_round_max))
79 ? roundMask
80 : 0;
81 }
82 roundBits = sig & roundMask;
83 /*------------------------------------------------------------------------
84 *------------------------------------------------------------------------*/
85 if ( 0x7FFD <= (uint32_t) (exp - 1) ) {
86 if ( exp <= 0 ) {
87 /*----------------------------------------------------------------
88 *----------------------------------------------------------------*/
89 isTiny =
90 (softfloat_detectTininess
91 == softfloat_tininess_beforeRounding)
92 || (exp < 0)
93 || (sig <= (uint64_t) (sig + roundIncrement));
94 sig = softfloat_shiftRightJam64( sig, 1 - exp );
95 roundBits = sig & roundMask;
96 if ( roundBits ) {
97 if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow SOFTFLOAT_STATE_ARG_COMMA );
98 softfloat_exceptionFlags |= softfloat_flag_inexact;
99 if ( roundIncrement ) softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox */
100#ifdef SOFTFLOAT_ROUND_ODD
101 if ( roundingMode == softfloat_round_odd ) {
102 sig |= roundMask + 1;
103 }
104#endif
105 }
106 sig += roundIncrement;
107 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
108 roundIncrement = roundMask + 1;
109 if ( roundNearEven && (roundBits<<1 == roundIncrement) ) {
110 roundMask |= roundIncrement;
111 }
112 sig &= ~roundMask;
113 goto packReturn;
114 }
115 if (
116 (0x7FFE < exp)
117 || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig))
118 ) {
119 goto overflow;
120 }
121 }
122 /*------------------------------------------------------------------------
123 *------------------------------------------------------------------------*/
124 if ( roundBits ) {
125 softfloat_exceptionFlags |= softfloat_flag_inexact;
126 if ( roundIncrement ) softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox */
127#ifdef SOFTFLOAT_ROUND_ODD
128 if ( roundingMode == softfloat_round_odd ) {
129 sig = (sig & ~roundMask) | (roundMask + 1);
130 goto packReturn;
131 }
132#endif
133 }
134 sig = (uint64_t) (sig + roundIncrement);
135 if ( sig < roundIncrement ) {
136 ++exp;
137 sig = UINT64_C( 0x8000000000000000 );
138 }
139 roundIncrement = roundMask + 1;
140 if ( roundNearEven && (roundBits<<1 == roundIncrement) ) {
141 roundMask |= roundIncrement;
142 }
143 sig &= ~roundMask;
144 goto packReturn;
145 /*------------------------------------------------------------------------
146 *------------------------------------------------------------------------*/
147 precision80:
148 doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
149 if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
150 doIncrement =
151 (roundingMode
152 == (sign ? softfloat_round_min : softfloat_round_max))
153 && sigExtra;
154 }
155 /*------------------------------------------------------------------------
156 *------------------------------------------------------------------------*/
157 if ( 0x7FFD <= (uint32_t) (exp - 1) ) {
158 if ( exp <= 0 ) {
159 /*----------------------------------------------------------------
160 *----------------------------------------------------------------*/
161 isTiny =
162 (softfloat_detectTininess
163 == softfloat_tininess_beforeRounding)
164 || (exp < 0)
165 || ! doIncrement
166 || (sig < UINT64_C( 0xFFFFFFFFFFFFFFFF ));
167 sig64Extra =
168 softfloat_shiftRightJam64Extra( sig, sigExtra, 1 - exp );
169 exp = 0;
170 sig = sig64Extra.v;
171 sigExtra = sig64Extra.extra;
172 if ( sigExtra ) {
173 if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow SOFTFLOAT_STATE_ARG_COMMA );
174#ifdef SOFTFLOAT_ROUND_ODD
175 if ( roundingMode == softfloat_round_odd ) {
176 sig |= 1;
177 goto packReturn;
178 }
179#endif
180 }
181 doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
182 if (
183 ! roundNearEven
184 && (roundingMode != softfloat_round_near_maxMag)
185 ) {
186 doIncrement =
187 (roundingMode
188 == (sign ? softfloat_round_min : softfloat_round_max))
189 && sigExtra;
190 }
191 if ( doIncrement ) {
192 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox */
193 ++sig;
194 sig &=
195 ~(uint_fast64_t)
196 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
197 & roundNearEven);
198 exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0);
199 }
200 goto packReturn;
201 }
202 if (
203 (0x7FFE < exp)
204 || ((exp == 0x7FFE) && (sig == UINT64_C( 0xFFFFFFFFFFFFFFFF ))
205 && doIncrement)
206 ) {
207 /*----------------------------------------------------------------
208 *----------------------------------------------------------------*/
209 roundMask = 0;
210 overflow:
211 softfloat_raiseFlags(
212 softfloat_flag_overflow | softfloat_flag_inexact
213 SOFTFLOAT_STATE_ARG_COMMA );
214 if (
215 roundNearEven
216 || (roundingMode == softfloat_round_near_maxMag)
217 || (roundingMode
218 == (sign ? softfloat_round_min : softfloat_round_max))
219 ) {
220 exp = 0x7FFF;
221 sig = UINT64_C( 0x8000000000000000 );
222 } else {
223 exp = 0x7FFE;
224 sig = ~roundMask;
225 }
226 goto packReturn;
227 }
228 }
229 /*------------------------------------------------------------------------
230 *------------------------------------------------------------------------*/
231 if ( sigExtra ) {
232 softfloat_exceptionFlags |= softfloat_flag_inexact;
233#ifdef SOFTFLOAT_ROUND_ODD
234 if ( roundingMode == softfloat_round_odd ) {
235 sig |= 1;
236 goto packReturn;
237 }
238#endif
239 }
240 if ( doIncrement ) {
241 softfloat_exceptionFlags |= softfloat_flag_c1; /* VBox */
242 ++sig;
243 if ( ! sig ) {
244 ++exp;
245 sig = UINT64_C( 0x8000000000000000 );
246 } else {
247 sig &=
248 ~(uint_fast64_t)
249 (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
250 & roundNearEven);
251 }
252 }
253 /*------------------------------------------------------------------------
254 *------------------------------------------------------------------------*/
255 packReturn:
256 uZ.s.signExp = packToExtF80UI64( sign, exp );
257 uZ.s.signif = sig;
258 return uZ.f;
259
260}
261
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