1 // SPDX-License-Identifier: BSD-3-Clause
2 
3 /*============================================================================
4 
5 This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
6 Package, Release 3a, by John R. Hauser.
7 
8 Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
9 All rights reserved.
10 
11 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions are met:
13 
14  1. Redistributions of source code must retain the above copyright notice,
15     this list of conditions, and the following disclaimer.
16 
17  2. Redistributions in binary form must reproduce the above copyright notice,
18     this list of conditions, and the following disclaimer in the documentation
19     and/or other materials provided with the distribution.
20 
21  3. Neither the name of the University nor the names of its contributors may
22     be used to endorse or promote products derived from this software without
23     specific prior written permission.
24 
25 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
26 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
28 DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
29 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 
36 =============================================================================*/
37 
38 #include <stdbool.h>
39 #include <stdint.h>
40 #include "platform.h"
41 #include "internals.h"
42 #include "specialize.h"
43 #include "softfloat.h"
44 
45 void
softfloat_addF128M(const uint32_t * aWPtr,const uint32_t * bWPtr,uint32_t * zWPtr,bool negateB)46  softfloat_addF128M(
47      const uint32_t *aWPtr,
48      const uint32_t *bWPtr,
49      uint32_t *zWPtr,
50      bool negateB
51  )
52 {
53     uint32_t uiA96;
54     int32_t expA;
55     uint32_t uiB96;
56     int32_t expB;
57     uint32_t uiZ96;
58     bool signZ, signB;
59     const uint32_t *tempPtr;
60     uint32_t sig96A, sig96B;
61     int32_t expDiff;
62     uint_fast8_t
63      (*addCarryMRoutinePtr)(
64          uint_fast8_t,
65          const uint32_t *,
66          const uint32_t *,
67          uint_fast8_t,
68          uint32_t *
69      );
70     uint32_t extSigZ[5], wordSigZ;
71     uint_fast8_t carry;
72     void (*roundPackRoutinePtr)( bool, int32_t, uint32_t *, uint32_t * );
73 
74     /*------------------------------------------------------------------------
75     *------------------------------------------------------------------------*/
76     uiA96 = aWPtr[indexWordHi( 4 )];
77     expA = expF128UI96( uiA96 );
78     uiB96 = bWPtr[indexWordHi( 4 )];
79     expB = expF128UI96( uiB96 );
80     /*------------------------------------------------------------------------
81     *------------------------------------------------------------------------*/
82     if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
83         if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return;
84         uiZ96 = uiA96;
85         if ( expB == 0x7FFF ) {
86             uiZ96 = uiB96 ^ packToF128UI96( negateB, 0, 0 );
87             if ( (expA == 0x7FFF) && (uiZ96 != uiA96) ) {
88                 softfloat_invalidF128M( zWPtr );
89                 return;
90             }
91         }
92         zWPtr[indexWordHi( 4 )] = uiZ96;
93         zWPtr[indexWord( 4, 2 )] = 0;
94         zWPtr[indexWord( 4, 1 )] = 0;
95         zWPtr[indexWord( 4, 0 )] = 0;
96         return;
97     }
98     /*------------------------------------------------------------------------
99     *------------------------------------------------------------------------*/
100     signZ = signF128UI96( uiA96 );
101     signB = signF128UI96( uiB96 ) ^ negateB;
102     negateB = (signZ != signB);
103     if ( (uint32_t) (uiA96<<1) < (uint32_t) (uiB96<<1) ) {
104         signZ = signB;
105         expA = expB;
106         expB = expF128UI96( uiA96 );
107         tempPtr = aWPtr;
108         aWPtr = bWPtr;
109         bWPtr = tempPtr;
110         uiA96 = uiB96;
111         uiB96 = bWPtr[indexWordHi( 4 )];
112     }
113     sig96A = fracF128UI96( uiA96 );
114     sig96B = fracF128UI96( uiB96 );
115     if ( expA ) {
116         --expA;
117         sig96A |= 0x00010000;
118         if ( expB ) {
119             --expB;
120             sig96B |= 0x00010000;
121         }
122     }
123     /*------------------------------------------------------------------------
124     *------------------------------------------------------------------------*/
125     addCarryMRoutinePtr =
126         negateB ? softfloat_addComplCarryM : softfloat_addCarryM;
127     expDiff = expA - expB;
128     if ( expDiff ) {
129         /*--------------------------------------------------------------------
130         *--------------------------------------------------------------------*/
131         extSigZ[indexWordHi( 5 )] = sig96B;
132         extSigZ[indexWord( 5, 3 )] = bWPtr[indexWord( 4, 2 )];
133         extSigZ[indexWord( 5, 2 )] = bWPtr[indexWord( 4, 1 )];
134         extSigZ[indexWord( 5, 1 )] = bWPtr[indexWord( 4, 0 )];
135         extSigZ[indexWord( 5, 0 )] = 0;
136         softfloat_shiftRightJam160M( extSigZ, expDiff, extSigZ );
137         sig96B = extSigZ[indexWordHi( 5 )];
138         carry = 0;
139         if ( negateB ) {
140             sig96B = ~sig96B;
141             wordSigZ = extSigZ[indexWordLo( 5 )];
142             extSigZ[indexWordLo( 5 )] = -wordSigZ;
143             carry = ! wordSigZ;
144         }
145         carry =
146             (*addCarryMRoutinePtr)(
147                 3,
148                 &aWPtr[indexMultiwordLo( 4, 3 )],
149                 &extSigZ[indexMultiword( 5, 3, 1 )],
150                 carry,
151                 &extSigZ[indexMultiword( 5, 3, 1 )]
152             );
153         wordSigZ = sig96A + sig96B + carry;
154     } else {
155         /*--------------------------------------------------------------------
156         *--------------------------------------------------------------------*/
157         extSigZ[indexWordLo( 5 )] = 0;
158         carry =
159             (*addCarryMRoutinePtr)(
160                 3,
161                 &aWPtr[indexMultiwordLo( 4, 3 )],
162                 &bWPtr[indexMultiwordLo( 4, 3 )],
163                 negateB,
164                 &extSigZ[indexMultiword( 5, 3, 1 )]
165             );
166         if ( negateB ) {
167             wordSigZ = sig96A + ~sig96B + carry;
168             if ( wordSigZ & 0x80000000 ) {
169                 signZ = ! signZ;
170                 carry =
171                     softfloat_addComplCarry96M(
172                         &bWPtr[indexMultiwordLo( 4, 3 )],
173                         &aWPtr[indexMultiwordLo( 4, 3 )],
174                         1,
175                         &extSigZ[indexMultiword( 5, 3, 1 )]
176                     );
177                 wordSigZ = sig96B + ~sig96A + carry;
178             } else {
179                 if (
180                     ! wordSigZ && ! extSigZ[indexWord( 5, 3 )]
181                         && ! (  extSigZ[indexWord( 5, 2 )]
182                               | extSigZ[indexWord( 5, 1 )]
183                               | extSigZ[indexWord( 5, 0 )]
184                              )
185                 ) {
186                     signZ = (softfloat_roundingMode == softfloat_round_min);
187                     zWPtr[indexWordHi( 4 )] = packToF128UI96( signZ, 0, 0 );
188                     zWPtr[indexWord( 4, 2 )] = 0;
189                     zWPtr[indexWord( 4, 1 )] = 0;
190                     zWPtr[indexWord( 4, 0 )] = 0;
191                     return;
192                 }
193             }
194         } else {
195             wordSigZ = sig96A + sig96B + carry;
196         }
197     }
198     extSigZ[indexWordHi( 5 )] = wordSigZ;
199     /*------------------------------------------------------------------------
200     *------------------------------------------------------------------------*/
201     roundPackRoutinePtr = softfloat_normRoundPackMToF128M;
202     if ( 0x00010000 <= wordSigZ ) {
203         if ( 0x00020000 <= wordSigZ ) {
204             ++expA;
205             softfloat_shortShiftRightJam160M( extSigZ, 1, extSigZ );
206         }
207         roundPackRoutinePtr = softfloat_roundPackMToF128M;
208     }
209     (*roundPackRoutinePtr)( signZ, expA, extSigZ, zWPtr );
210 
211 }
212 
213