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
|
---|
45 | softfloat_mulAddF32(
|
---|
46 | uint_fast32_t uiA, uint_fast32_t uiB, uint_fast32_t uiC, uint_fast8_t op SOFTFLOAT_STATE_DECL_COMMA )
|
---|
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 SOFTFLOAT_STATE_ARG_COMMA );
|
---|
190 | /*------------------------------------------------------------------------
|
---|
191 | *------------------------------------------------------------------------*/
|
---|
192 | propagateNaN_ABC:
|
---|
193 | uiZ = softfloat_propagateNaNF32UI( uiA, uiB SOFTFLOAT_STATE_ARG_COMMA );
|
---|
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 SOFTFLOAT_STATE_ARG_COMMA );
|
---|
205 | uiZ = defaultNaNF32UI;
|
---|
206 | propagateNaN_ZC:
|
---|
207 | uiZ = softfloat_propagateNaNF32UI( uiZ, uiC SOFTFLOAT_STATE_ARG_COMMA );
|
---|
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 |
|
---|