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