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_addExtF80M(const struct extFloat80M * aSPtr,const struct extFloat80M * bSPtr,struct extFloat80M * zSPtr,bool negateB)46  softfloat_addExtF80M(
47      const struct extFloat80M *aSPtr,
48      const struct extFloat80M *bSPtr,
49      struct extFloat80M *zSPtr,
50      bool negateB
51  )
52 {
53     uint32_t uiA64;
54     int32_t expA;
55     uint32_t uiB64;
56     int32_t expB;
57     uint32_t uiZ64;
58     bool signZ, signB;
59     const struct extFloat80M *tempSPtr;
60     uint64_t sigZ, sigB;
61     void
62      (*roundPackRoutinePtr)(
63          bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * );
64     int32_t expDiff;
65     uint32_t extSigX[3], sigZExtra;
66 
67     /*------------------------------------------------------------------------
68     *------------------------------------------------------------------------*/
69     uiA64 = aSPtr->signExp;
70     expA = expExtF80UI64( uiA64 );
71     uiB64 = bSPtr->signExp;
72     expB = expExtF80UI64( uiB64 );
73     /*------------------------------------------------------------------------
74     *------------------------------------------------------------------------*/
75     if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) {
76         if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return;
77         uiZ64 = uiA64;
78         if ( expB == 0x7FFF ) {
79             uiZ64 = uiB64 ^ packToExtF80UI64( negateB, 0 );
80             if ( (expA == 0x7FFF) && (uiZ64 != uiA64) ) {
81                 softfloat_invalidExtF80M( zSPtr );
82                 return;
83             }
84         }
85         zSPtr->signExp = uiZ64;
86         zSPtr->signif = UINT64_C( 0x8000000000000000 );
87         return;
88     }
89     /*------------------------------------------------------------------------
90     *------------------------------------------------------------------------*/
91     signZ = signExtF80UI64( uiA64 );
92     signB = signExtF80UI64( uiB64 ) ^ negateB;
93     negateB = (signZ != signB);
94     if ( expA < expB ) {
95         signZ = signB;
96         expA = expB;
97         expB = expExtF80UI64( uiA64 );
98         tempSPtr = aSPtr;
99         aSPtr = bSPtr;
100         bSPtr = tempSPtr;
101     }
102     if ( ! expB ) {
103         expB = 1;
104         if ( ! expA ) expA = 1;
105     }
106     sigZ = aSPtr->signif;
107     sigB = bSPtr->signif;
108     /*------------------------------------------------------------------------
109     *------------------------------------------------------------------------*/
110     roundPackRoutinePtr = softfloat_roundPackMToExtF80M;
111     expDiff = expA - expB;
112     if ( expDiff ) {
113         /*--------------------------------------------------------------------
114         *--------------------------------------------------------------------*/
115         extSigX[indexWord( 3, 2 )] = sigB>>32;
116         extSigX[indexWord( 3, 1 )] = sigB;
117         extSigX[indexWord( 3, 0 )] = 0;
118         softfloat_shiftRightJam96M( extSigX, expDiff, extSigX );
119         sigB =
120             (uint64_t) extSigX[indexWord( 3, 2 )]<<32
121                 | extSigX[indexWord( 3, 1 )];
122         if ( negateB ) {
123             sigZ -= sigB;
124             sigZExtra = extSigX[indexWordLo( 3 )];
125             if ( sigZExtra ) {
126                 --sigZ;
127                 sigZExtra = -sigZExtra;
128             }
129             if ( ! (sigZ & UINT64_C( 0x8000000000000000 )) ) {
130                 if ( sigZ & UINT64_C( 0x4000000000000000 ) ) {
131                     --expA;
132                     sigZ = sigZ<<1 | sigZExtra>>31;
133                     sigZExtra <<= 1;
134                 } else {
135                     roundPackRoutinePtr = softfloat_normRoundPackMToExtF80M;
136                 }
137             }
138         } else {
139             sigZ += sigB;
140             if ( sigZ & UINT64_C( 0x8000000000000000 ) ) goto sigZ;
141             sigZExtra = (uint32_t) sigZ<<31 | (extSigX[indexWordLo( 3 )] != 0);
142             goto completeNormAfterAdd;
143         }
144     } else {
145         /*--------------------------------------------------------------------
146         *--------------------------------------------------------------------*/
147         sigZExtra = 0;
148         if ( negateB ) {
149             if ( sigZ < sigB ) {
150                 signZ = ! signZ;
151                 sigZ = sigB - sigZ;
152             } else {
153                 sigZ -= sigB;
154                 if ( ! sigZ ) {
155                     signZ = (softfloat_roundingMode == softfloat_round_min);
156                     zSPtr->signExp = packToExtF80UI64( signZ, 0 );
157                     zSPtr->signif = 0;
158                     return;
159                 }
160             }
161             roundPackRoutinePtr = softfloat_normRoundPackMToExtF80M;
162         } else {
163             sigZ += sigB;
164             if ( sigZ < sigB ) {
165                 sigZExtra = (uint32_t) sigZ<<31;
166  completeNormAfterAdd:
167                 ++expA;
168                 sigZ = UINT64_C( 0x8000000000000000 ) | sigZ>>1;
169             } else {
170                 if ( ! (sigZ & UINT64_C( 0x8000000000000000 )) ) {
171                     roundPackRoutinePtr = softfloat_normRoundPackMToExtF80M;
172                 }
173             }
174         }
175     }
176     extSigX[indexWord( 3, 0 )] = sigZExtra;
177  sigZ:
178     extSigX[indexWord( 3, 2 )] = sigZ>>32;
179     extSigX[indexWord( 3, 1 )] = sigZ;
180     /*------------------------------------------------------------------------
181     *------------------------------------------------------------------------*/
182  roundPack:
183     (*roundPackRoutinePtr)(
184         signZ, expA, extSigX, extF80_roundingPrecision, zSPtr );
185 
186 }
187 
188