1 
2 /*============================================================================
3 
4 This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
5 Package, Release 3e, by John R. Hauser.
6 
7 Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
8 California.  All rights reserved.
9 
10 Redistribution and use in source and binary forms, with or without
11 modification, 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 
24 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
25 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
27 DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
28 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 ON 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
33 SOFTWARE, 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 
44 float32_t
softfloat_mulAddF32(uint_fast32_t uiA,uint_fast32_t uiB,uint_fast32_t uiC,uint_fast8_t op)45  softfloat_mulAddF32(
46      uint_fast32_t uiA, uint_fast32_t uiB, uint_fast32_t uiC, uint_fast8_t op )
47 {
48     bool signA;
49     int_fast16_t expA;
50     uint_fast32_t sigA;
51     bool signB;
52     int_fast16_t expB;
53     uint_fast32_t sigB;
54     bool signC;
55     int_fast16_t expC;
56     uint_fast32_t sigC;
57     bool signProd;
58     uint_fast32_t magBits, uiZ;
59     struct exp16_sig32 normExpSig;
60     int_fast16_t expProd;
61     uint_fast64_t sigProd;
62     bool signZ;
63     int_fast16_t expZ;
64     uint_fast32_t sigZ;
65     int_fast16_t expDiff;
66     uint_fast64_t sig64Z, sig64C;
67     int_fast8_t shiftDist;
68     union ui32_f32 uZ;
69 
70     /*------------------------------------------------------------------------
71     *------------------------------------------------------------------------*/
72     signA = signF32UI( uiA );
73     expA  = expF32UI( uiA );
74     sigA  = fracF32UI( uiA );
75     signB = signF32UI( uiB );
76     expB  = expF32UI( uiB );
77     sigB  = fracF32UI( uiB );
78     signC = signF32UI( uiC ) ^ (op == softfloat_mulAdd_subC);
79     expC  = expF32UI( uiC );
80     sigC  = fracF32UI( uiC );
81     signProd = signA ^ signB ^ (op == softfloat_mulAdd_subProd);
82     /*------------------------------------------------------------------------
83     *------------------------------------------------------------------------*/
84     if ( expA == 0xFF ) {
85         if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN_ABC;
86         magBits = expB | sigB;
87         goto infProdArg;
88     }
89     if ( expB == 0xFF ) {
90         if ( sigB ) goto propagateNaN_ABC;
91         magBits = expA | sigA;
92         goto infProdArg;
93     }
94     if ( expC == 0xFF ) {
95         if ( sigC ) {
96             uiZ = 0;
97             goto propagateNaN_ZC;
98         }
99         uiZ = uiC;
100         goto uiZ;
101     }
102     /*------------------------------------------------------------------------
103     *------------------------------------------------------------------------*/
104     if ( ! expA ) {
105         if ( ! sigA ) goto zeroProd;
106         normExpSig = softfloat_normSubnormalF32Sig( sigA );
107         expA = normExpSig.exp;
108         sigA = normExpSig.sig;
109     }
110     if ( ! expB ) {
111         if ( ! sigB ) goto zeroProd;
112         normExpSig = softfloat_normSubnormalF32Sig( sigB );
113         expB = normExpSig.exp;
114         sigB = normExpSig.sig;
115     }
116     /*------------------------------------------------------------------------
117     *------------------------------------------------------------------------*/
118     expProd = expA + expB - 0x7E;
119     sigA = (sigA | 0x00800000)<<7;
120     sigB = (sigB | 0x00800000)<<7;
121     sigProd = (uint_fast64_t) sigA * sigB;
122     if ( sigProd < UINT64_C( 0x2000000000000000 ) ) {
123         --expProd;
124         sigProd <<= 1;
125     }
126     signZ = signProd;
127     if ( ! expC ) {
128         if ( ! sigC ) {
129             expZ = expProd - 1;
130             sigZ = softfloat_shortShiftRightJam64( sigProd, 31 );
131             goto roundPack;
132         }
133         normExpSig = softfloat_normSubnormalF32Sig( sigC );
134         expC = normExpSig.exp;
135         sigC = normExpSig.sig;
136     }
137     sigC = (sigC | 0x00800000)<<6;
138     /*------------------------------------------------------------------------
139     *------------------------------------------------------------------------*/
140     expDiff = expProd - expC;
141     if ( signProd == signC ) {
142         /*--------------------------------------------------------------------
143         *--------------------------------------------------------------------*/
144         if ( expDiff <= 0 ) {
145             expZ = expC;
146             sigZ = sigC + softfloat_shiftRightJam64( sigProd, 32 - expDiff );
147         } else {
148             expZ = expProd;
149             sig64Z =
150                 sigProd
151                     + softfloat_shiftRightJam64(
152                           (uint_fast64_t) sigC<<32, expDiff );
153             sigZ = softfloat_shortShiftRightJam64( sig64Z, 32 );
154         }
155         if ( sigZ < 0x40000000 ) {
156             --expZ;
157             sigZ <<= 1;
158         }
159     } else {
160         /*--------------------------------------------------------------------
161         *--------------------------------------------------------------------*/
162         sig64C = (uint_fast64_t) sigC<<32;
163         if ( expDiff < 0 ) {
164             signZ = signC;
165             expZ = expC;
166             sig64Z = sig64C - softfloat_shiftRightJam64( sigProd, -expDiff );
167         } else if ( ! expDiff ) {
168             expZ = expProd;
169             sig64Z = sigProd - sig64C;
170             if ( ! sig64Z ) goto completeCancellation;
171             if ( sig64Z & UINT64_C( 0x8000000000000000 ) ) {
172                 signZ = ! signZ;
173                 sig64Z = -sig64Z;
174             }
175         } else {
176             expZ = expProd;
177             sig64Z = sigProd - softfloat_shiftRightJam64( sig64C, expDiff );
178         }
179         shiftDist = softfloat_countLeadingZeros64( sig64Z ) - 1;
180         expZ -= shiftDist;
181         shiftDist -= 32;
182         if ( shiftDist < 0 ) {
183             sigZ = softfloat_shortShiftRightJam64( sig64Z, -shiftDist );
184         } else {
185             sigZ = (uint_fast32_t) sig64Z<<shiftDist;
186         }
187     }
188  roundPack:
189     return softfloat_roundPackToF32( signZ, expZ, sigZ );
190     /*------------------------------------------------------------------------
191     *------------------------------------------------------------------------*/
192  propagateNaN_ABC:
193     uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
194     goto propagateNaN_ZC;
195     /*------------------------------------------------------------------------
196     *------------------------------------------------------------------------*/
197  infProdArg:
198     if ( magBits ) {
199         uiZ = packToF32UI( signProd, 0xFF, 0 );
200         if ( expC != 0xFF ) goto uiZ;
201         if ( sigC ) goto propagateNaN_ZC;
202         if ( signProd == signC ) goto uiZ;
203     }
204     softfloat_raiseFlags( softfloat_flag_invalid );
205     uiZ = defaultNaNF32UI;
206  propagateNaN_ZC:
207     uiZ = softfloat_propagateNaNF32UI( uiZ, uiC );
208     goto uiZ;
209     /*------------------------------------------------------------------------
210     *------------------------------------------------------------------------*/
211  zeroProd:
212     uiZ = uiC;
213     if ( ! (expC | sigC) && (signProd != signC) ) {
214  completeCancellation:
215         uiZ =
216             packToF32UI(
217                 (softfloat_roundingMode == softfloat_round_min), 0, 0 );
218     }
219  uiZ:
220     uZ.ui = uiZ;
221     return uZ.f;
222 
223 }
224 
225