VirtualBox

source: vbox/trunk/src/libs/softfloat-3e/source/s_mulAddF128M.c

Last change on this file was 94558, checked in by vboxsync, 2 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: 14.8 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, 2016 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 "specialize.h"
42#include "softfloat.h"
43
44void
45 softfloat_mulAddF128M(
46 const uint32_t *aWPtr,
47 const uint32_t *bWPtr,
48 const uint32_t *cWPtr,
49 uint32_t *zWPtr,
50 uint_fast8_t op
51 SOFTFLOAT_STATE_DECL_COMMA
52 )
53{
54 uint32_t uiA96;
55 int32_t expA;
56 uint32_t uiB96;
57 int32_t expB;
58 uint32_t uiC96;
59 bool signC;
60 int32_t expC;
61 bool signProd, prodIsInfinite;
62 uint32_t *ptr, uiZ96, sigA[4];
63 uint_fast8_t shiftDist;
64 uint32_t sigX[5];
65 int32_t expProd;
66 uint32_t sigProd[8], wordSig;
67 bool doSub;
68 uint_fast8_t
69 (*addCarryMRoutinePtr)(
70 uint_fast8_t,
71 const uint32_t *,
72 const uint32_t *,
73 uint_fast8_t,
74 uint32_t *
75 );
76 int32_t expDiff;
77 bool signZ;
78 int32_t expZ;
79 uint32_t *extSigPtr;
80 uint_fast8_t carry;
81 void (*roundPackRoutinePtr)( bool, int32_t, uint32_t *, uint32_t * SOFTFLOAT_STATE_DECL_COMMA );
82
83 /*------------------------------------------------------------------------
84 *------------------------------------------------------------------------*/
85 uiA96 = aWPtr[indexWordHi( 4 )];
86 expA = expF128UI96( uiA96 );
87 uiB96 = bWPtr[indexWordHi( 4 )];
88 expB = expF128UI96( uiB96 );
89 uiC96 = cWPtr[indexWordHi( 4 )];
90 signC = signF128UI96( uiC96 ) ^ (op == softfloat_mulAdd_subC);
91 expC = expF128UI96( uiC96 );
92 signProd =
93 signF128UI96( uiA96 ) ^ signF128UI96( uiB96 )
94 ^ (op == softfloat_mulAdd_subProd);
95 /*------------------------------------------------------------------------
96 *------------------------------------------------------------------------*/
97 prodIsInfinite = false;
98 if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
99 if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr SOFTFLOAT_STATE_ARG_COMMA ) ) {
100 goto propagateNaN_ZC;
101 }
102 ptr = (uint32_t *) aWPtr;
103 if ( ! (uint32_t) (uiA96<<1) ) goto possibleInvalidProd;
104 if ( ! (uint32_t) (uiB96<<1) ) {
105 ptr = (uint32_t *) bWPtr;
106 possibleInvalidProd:
107 if (
108 ! (ptr[indexWord( 4, 2 )] | ptr[indexWord( 4, 1 )]
109 | ptr[indexWord( 4, 0 )])
110 ) {
111 goto invalid;
112 }
113 }
114 prodIsInfinite = true;
115 }
116 if ( expC == 0x7FFF ) {
117 if (
118 fracF128UI96( uiC96 )
119 || (cWPtr[indexWord( 4, 2 )] | cWPtr[indexWord( 4, 1 )]
120 | cWPtr[indexWord( 4, 0 )])
121 ) {
122 zWPtr[indexWordHi( 4 )] = 0;
123 goto propagateNaN_ZC;
124 }
125 if ( prodIsInfinite && (signProd != signC) ) goto invalid;
126 goto copyC;
127 }
128 if ( prodIsInfinite ) {
129 uiZ96 = packToF128UI96( signProd, 0x7FFF, 0 );
130 goto uiZ;
131 }
132 /*------------------------------------------------------------------------
133 *------------------------------------------------------------------------*/
134 if ( expA ) {
135 sigA[indexWordHi( 4 )] = fracF128UI96( uiA96 ) | 0x00010000;
136 sigA[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
137 sigA[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
138 sigA[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
139 } else {
140 expA = softfloat_shiftNormSigF128M( aWPtr, 0, sigA );
141 if ( expA == -128 ) goto zeroProd;
142 }
143 if ( expB ) {
144 sigX[indexWordHi( 4 )] = fracF128UI96( uiB96 ) | 0x00010000;
145 sigX[indexWord( 4, 2 )] = bWPtr[indexWord( 4, 2 )];
146 sigX[indexWord( 4, 1 )] = bWPtr[indexWord( 4, 1 )];
147 sigX[indexWord( 4, 0 )] = bWPtr[indexWord( 4, 0 )];
148 } else {
149 expB = softfloat_shiftNormSigF128M( bWPtr, 0, sigX );
150 if ( expB == -128 ) goto zeroProd;
151 }
152 /*------------------------------------------------------------------------
153 *------------------------------------------------------------------------*/
154 expProd = expA + expB - 0x3FF0;
155 softfloat_mul128MTo256M( sigA, sigX, sigProd );
156 /*------------------------------------------------------------------------
157 *------------------------------------------------------------------------*/
158 wordSig = fracF128UI96( uiC96 );
159 if ( expC ) {
160 --expC;
161 wordSig |= 0x00010000;
162 }
163 sigX[indexWordHi( 5 )] = wordSig;
164 sigX[indexWord( 5, 3 )] = cWPtr[indexWord( 4, 2 )];
165 sigX[indexWord( 5, 2 )] = cWPtr[indexWord( 4, 1 )];
166 sigX[indexWord( 5, 1 )] = cWPtr[indexWord( 4, 0 )];
167 /*------------------------------------------------------------------------
168 *------------------------------------------------------------------------*/
169 doSub = (signProd != signC);
170 addCarryMRoutinePtr =
171 doSub ? softfloat_addComplCarryM : softfloat_addCarryM;
172 expDiff = expProd - expC;
173 if ( expDiff <= 0 ) {
174 /*--------------------------------------------------------------------
175 *--------------------------------------------------------------------*/
176 signZ = signC;
177 expZ = expC;
178 if (
179 sigProd[indexWord( 8, 2 )]
180 || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )])
181 ) {
182 sigProd[indexWord( 8, 3 )] |= 1;
183 }
184 extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )];
185 if ( expDiff ) {
186 softfloat_shiftRightJam160M( extSigPtr, -expDiff, extSigPtr );
187 }
188 carry = 0;
189 if ( doSub ) {
190 wordSig = extSigPtr[indexWordLo( 5 )];
191 extSigPtr[indexWordLo( 5 )] = -wordSig;
192 carry = ! wordSig;
193 }
194 (*addCarryMRoutinePtr)(
195 4,
196 &sigX[indexMultiwordHi( 5, 4 )],
197 extSigPtr + indexMultiwordHi( 5, 4 ),
198 carry,
199 extSigPtr + indexMultiwordHi( 5, 4 )
200 );
201 wordSig = extSigPtr[indexWordHi( 5 )];
202 if ( ! expZ ) {
203 if ( wordSig & 0x80000000 ) {
204 signZ = ! signZ;
205 softfloat_negX160M( extSigPtr );
206 wordSig = extSigPtr[indexWordHi( 5 )];
207 }
208 goto checkCancellation;
209 }
210 if ( wordSig < 0x00010000 ) {
211 --expZ;
212 softfloat_add160M( extSigPtr, extSigPtr, extSigPtr );
213 goto roundPack;
214 }
215 goto extSigReady_noCancellation;
216 } else {
217 /*--------------------------------------------------------------------
218 *--------------------------------------------------------------------*/
219 signZ = signProd;
220 expZ = expProd;
221 sigX[indexWordLo( 5 )] = 0;
222 expDiff -= 128;
223 if ( 0 <= expDiff ) {
224 /*----------------------------------------------------------------
225 *----------------------------------------------------------------*/
226 if ( expDiff ) softfloat_shiftRightJam160M( sigX, expDiff, sigX );
227 wordSig = sigX[indexWordLo( 5 )];
228 carry = 0;
229 if ( doSub ) {
230 carry = ! wordSig;
231 wordSig = -wordSig;
232 }
233 carry =
234 (*addCarryMRoutinePtr)(
235 4,
236 &sigProd[indexMultiwordLo( 8, 4 )],
237 &sigX[indexMultiwordHi( 5, 4 )],
238 carry,
239 &sigProd[indexMultiwordLo( 8, 4 )]
240 );
241 sigProd[indexWord( 8, 2 )] |= wordSig;
242 ptr = &sigProd[indexWord( 8, 4 )];
243 } else {
244 /*----------------------------------------------------------------
245 *----------------------------------------------------------------*/
246 shiftDist = expDiff & 31;
247 if ( shiftDist ) {
248 softfloat_shortShiftRight160M( sigX, shiftDist, sigX );
249 }
250 expDiff >>= 5;
251 extSigPtr =
252 &sigProd[indexMultiwordLo( 8, 5 )] - wordIncr
253 + expDiff * -wordIncr;
254 carry =
255 (*addCarryMRoutinePtr)( 5, extSigPtr, sigX, doSub, extSigPtr );
256 if ( expDiff == -4 ) {
257 /*------------------------------------------------------------
258 *------------------------------------------------------------*/
259 wordSig = sigProd[indexWordHi( 8 )];
260 if ( wordSig & 0x80000000 ) {
261 signZ = ! signZ;
262 softfloat_negX256M( sigProd );
263 wordSig = sigProd[indexWordHi( 8 )];
264 }
265 /*------------------------------------------------------------
266 *------------------------------------------------------------*/
267 if ( wordSig ) goto expProdBigger_noWordShift;
268 wordSig = sigProd[indexWord( 8, 6 )];
269 if ( 0x00040000 <= wordSig ) goto expProdBigger_noWordShift;
270 expZ -= 32;
271 extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )] - wordIncr;
272 for (;;) {
273 if ( wordSig ) break;
274 wordSig = extSigPtr[indexWord( 5, 3 )];
275 if ( 0x00040000 <= wordSig ) break;
276 expZ -= 32;
277 extSigPtr -= wordIncr;
278 if ( extSigPtr == &sigProd[indexMultiwordLo( 8, 5 )] ) {
279 goto checkCancellation;
280 }
281 }
282 /*------------------------------------------------------------
283 *------------------------------------------------------------*/
284 ptr = extSigPtr + indexWordLo( 5 );
285 do {
286 ptr -= wordIncr;
287 if ( *ptr ) {
288 extSigPtr[indexWordLo( 5 )] |= 1;
289 break;
290 }
291 } while ( ptr != &sigProd[indexWordLo( 8 )] );
292 wordSig = extSigPtr[indexWordHi( 5 )];
293 goto extSigReady;
294 }
295 ptr = extSigPtr + indexWordHi( 5 ) + wordIncr;
296 }
297 /*--------------------------------------------------------------------
298 *--------------------------------------------------------------------*/
299 if ( carry != doSub ) {
300 if ( doSub ) {
301 do {
302 wordSig = *ptr;
303 *ptr = wordSig - 1;
304 ptr += wordIncr;
305 } while ( ! wordSig );
306 } else {
307 do {
308 wordSig = *ptr + 1;
309 *ptr = wordSig;
310 ptr += wordIncr;
311 } while ( ! wordSig );
312 }
313 }
314 /*--------------------------------------------------------------------
315 *--------------------------------------------------------------------*/
316 expProdBigger_noWordShift:
317 if (
318 sigProd[indexWord( 8, 2 )]
319 || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )])
320 ) {
321 sigProd[indexWord( 8, 3 )] |= 1;
322 }
323 extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )];
324 wordSig = extSigPtr[indexWordHi( 5 )];
325 }
326 extSigReady:
327 roundPackRoutinePtr = softfloat_normRoundPackMToF128M;
328 if ( wordSig < 0x00010000 ) goto doRoundPack;
329 extSigReady_noCancellation:
330 if ( 0x00020000 <= wordSig ) {
331 ++expZ;
332 softfloat_shortShiftRightJam160M( extSigPtr, 1, extSigPtr );
333 }
334 roundPack:
335 roundPackRoutinePtr = softfloat_roundPackMToF128M;
336 doRoundPack:
337 (*roundPackRoutinePtr)( signZ, expZ, extSigPtr, zWPtr SOFTFLOAT_STATE_ARG_COMMA );
338 return;
339 /*------------------------------------------------------------------------
340 *------------------------------------------------------------------------*/
341 invalid:
342 softfloat_invalidF128M( zWPtr SOFTFLOAT_STATE_ARG_COMMA );
343 propagateNaN_ZC:
344 softfloat_propagateNaNF128M( zWPtr, cWPtr, zWPtr SOFTFLOAT_STATE_ARG_COMMA );
345 return;
346 /*------------------------------------------------------------------------
347 *------------------------------------------------------------------------*/
348 zeroProd:
349 if (
350 ! (uint32_t) (uiC96<<1) && (signProd != signC)
351 && ! cWPtr[indexWord( 4, 2 )]
352 && ! (cWPtr[indexWord( 4, 1 )] | cWPtr[indexWord( 4, 0 )])
353 ) {
354 goto completeCancellation;
355 }
356 copyC:
357 zWPtr[indexWordHi( 4 )] = uiC96;
358 zWPtr[indexWord( 4, 2 )] = cWPtr[indexWord( 4, 2 )];
359 zWPtr[indexWord( 4, 1 )] = cWPtr[indexWord( 4, 1 )];
360 zWPtr[indexWord( 4, 0 )] = cWPtr[indexWord( 4, 0 )];
361 return;
362 /*------------------------------------------------------------------------
363 *------------------------------------------------------------------------*/
364 checkCancellation:
365 if (
366 wordSig
367 || (extSigPtr[indexWord( 5, 3 )] | extSigPtr[indexWord( 5, 2 )])
368 || (extSigPtr[indexWord( 5, 1 )] | extSigPtr[indexWord( 5, 0 )])
369 ) {
370 goto extSigReady;
371 }
372 completeCancellation:
373 uiZ96 =
374 packToF128UI96(
375 (softfloat_roundingMode == softfloat_round_min), 0, 0 );
376 uiZ:
377 zWPtr[indexWordHi( 4 )] = uiZ96;
378 zWPtr[indexWord( 4, 2 )] = 0;
379 zWPtr[indexWord( 4, 1 )] = 0;
380 zWPtr[indexWord( 4, 0 )] = 0;
381
382}
383
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use