e55a0ba282f3a6c8af54e72b9a9acbbd72a4d6d2
[riscv-isa-sim.git] / softfloat / s_mulAddF32.c
1
2 #include <stdbool.h>
3 #include <stdint.h>
4 #include "platform.h"
5 #include "primitives.h"
6 #include "internals.h"
7 #include "specialize.h"
8 #include "softfloat.h"
9
10 float32_t
11 softfloat_mulAddF32(
12 int op, uint_fast32_t uiA, uint_fast32_t uiB, uint_fast32_t uiC )
13 {
14 bool signA;
15 int_fast16_t expA;
16 uint_fast32_t sigA;
17 bool signB;
18 int_fast16_t expB;
19 uint_fast32_t sigB;
20 bool signC;
21 int_fast16_t expC;
22 uint_fast32_t sigC;
23 bool signProd;
24 uint_fast32_t magBits, uiZ;
25 struct exp16_sig32 normExpSig;
26 int_fast16_t expProd;
27 uint_fast64_t sigProd;
28 bool signZ;
29 int_fast16_t expZ;
30 uint_fast32_t sigZ;
31 int_fast16_t expDiff;
32 uint_fast64_t sigZ64, sigC64;
33 int shiftCount;
34 union ui32_f32 uZ;
35
36 signA = signF32UI( uiA );
37 expA = expF32UI( uiA );
38 sigA = fracF32UI( uiA );
39 signB = signF32UI( uiB );
40 expB = expF32UI( uiB );
41 sigB = fracF32UI( uiB );
42 signC = signF32UI( uiC ) ^ ( op == softfloat_mulAdd_subC );
43 expC = expF32UI( uiC );
44 sigC = fracF32UI( uiC );
45 signProd = signA ^ signB ^ ( op == softfloat_mulAdd_subProd );
46 if ( expA == 0xFF ) {
47 if ( sigA || ( ( expB == 0xFF ) && sigB ) ) goto propagateNaN_ABC;
48 magBits = expB | sigB;
49 goto infProdArg;
50 }
51 if ( expB == 0xFF ) {
52 if ( sigB ) goto propagateNaN_ABC;
53 magBits = expA | sigA;
54 goto infProdArg;
55 }
56 if ( expC == 0xFF ) {
57 if ( sigC ) {
58 uiZ = 0;
59 goto propagateNaN_ZC;
60 }
61 uiZ = uiC;
62 goto uiZ;
63 }
64 if ( ! expA ) {
65 if ( ! sigA ) goto zeroProd;
66 normExpSig = softfloat_normSubnormalF32Sig( sigA );
67 expA = normExpSig.exp;
68 sigA = normExpSig.sig;
69 }
70 if ( ! expB ) {
71 if ( ! sigB ) goto zeroProd;
72 normExpSig = softfloat_normSubnormalF32Sig( sigB );
73 expB = normExpSig.exp;
74 sigB = normExpSig.sig;
75 }
76 expProd = expA + expB - 0x7E;
77 sigA = ( sigA | 0x00800000 )<<7;
78 sigB = ( sigB | 0x00800000 )<<7;
79 sigProd = (uint_fast64_t) sigA * sigB;
80 if ( sigProd < UINT64_C( 0x2000000000000000 ) ) {
81 --expProd;
82 sigProd <<= 1;
83 }
84 signZ = signProd;
85 if ( ! expC ) {
86 if ( ! sigC ) {
87 expZ = expProd - 1;
88 sigZ = softfloat_shortShift64RightJam( sigProd, 31 );
89 goto roundPack;
90 }
91 normExpSig = softfloat_normSubnormalF32Sig( sigC );
92 expC = normExpSig.exp;
93 sigC = normExpSig.sig;
94 }
95 sigC = ( sigC | 0x00800000 )<<6;
96 expDiff = expProd - expC;
97 if ( signProd == signC ) {
98 if ( expDiff <= 0 ) {
99 expZ = expC;
100 sigZ = sigC + softfloat_shift64RightJam( sigProd, 32 - expDiff );
101 } else {
102 expZ = expProd;
103 sigZ64 =
104 sigProd
105 + softfloat_shift64RightJam(
106 (uint_fast64_t) sigC<<32, expDiff );
107 sigZ = softfloat_shortShift64RightJam( sigZ64, 32 );
108 }
109 if ( sigZ < 0x40000000 ) {
110 --expZ;
111 sigZ <<= 1;
112 }
113 } else {
114 /*** OPTIMIZE BETTER? ***/
115 sigC64 = (uint_fast64_t) sigC<<32;
116 if ( expDiff < 0 ) {
117 signZ = signC;
118 expZ = expC;
119 sigZ64 = sigC64 - softfloat_shift64RightJam( sigProd, - expDiff );
120 } else if ( ! expDiff ) {
121 expZ = expProd;
122 sigZ64 = sigProd - sigC64;
123 if ( ! sigZ64 ) goto completeCancellation;
124 if ( sigZ64 & UINT64_C( 0x8000000000000000 ) ) {
125 signZ ^= 1;
126 sigZ64 = - sigZ64;
127 }
128 } else {
129 expZ = expProd;
130 sigZ64 = sigProd - softfloat_shift64RightJam( sigC64, expDiff );
131 }
132 shiftCount = softfloat_countLeadingZeros64( sigZ64 ) - 1;
133 expZ -= shiftCount;
134 shiftCount -= 32;
135 if ( shiftCount < 0 ) {
136 sigZ = softfloat_shortShift64RightJam( sigZ64, - shiftCount );
137 } else {
138 sigZ = (uint_fast32_t) sigZ64<<shiftCount;
139 }
140 }
141 roundPack:
142 return softfloat_roundPackToF32( signZ, expZ, sigZ );
143 propagateNaN_ABC:
144 uiZ = softfloat_propagateNaNF32UI( uiA, uiB );
145 goto propagateNaN_ZC;
146 infProdArg:
147 if ( magBits ) {
148 uiZ = packToF32UI( signProd, 0xFF, 0 );
149 if ( expC != 0xFF ) goto uiZ;
150 if ( sigC ) goto propagateNaN_ZC;
151 if ( signProd == signC ) goto uiZ;
152 }
153 invalid:
154 softfloat_raiseFlags( softfloat_flag_invalid );
155 uiZ = defaultNaNF32UI;
156 propagateNaN_ZC:
157 uiZ = softfloat_propagateNaNF32UI( uiZ, uiC );
158 goto uiZ;
159 zeroProd:
160 uiZ = uiC;
161 if ( ! ( expC | sigC ) && ( signProd != signC ) ) {
162 completeCancellation:
163 uiZ =
164 packToF32UI( softfloat_roundingMode == softfloat_round_min, 0, 0 );
165 }
166 uiZ:
167 uZ.ui = uiZ;
168 return uZ.f;
169
170 }
171