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 extFloat80_t
softfloat_addMagsExtF80(uint_fast16_t uiA64,uint_fast64_t uiA0,uint_fast16_t uiB64,uint_fast64_t uiB0,bool signZ)46  softfloat_addMagsExtF80(
47      uint_fast16_t uiA64,
48      uint_fast64_t uiA0,
49      uint_fast16_t uiB64,
50      uint_fast64_t uiB0,
51      bool signZ
52  )
53 {
54     int_fast32_t expA;
55     uint_fast64_t sigA;
56     int_fast32_t expB;
57     uint_fast64_t sigB;
58     int_fast32_t expDiff;
59     uint_fast16_t uiZ64;
60     uint_fast64_t uiZ0, sigZ, sigZExtra;
61     struct exp32_sig64 normExpSig;
62     int_fast32_t expZ;
63     struct uint64_extra sig64Extra;
64     struct uint128 uiZ;
65     union { struct extFloat80M s; extFloat80_t f; } uZ;
66 
67     /*------------------------------------------------------------------------
68     *------------------------------------------------------------------------*/
69     expA = expExtF80UI64( uiA64 );
70     sigA = uiA0;
71     expB = expExtF80UI64( uiB64 );
72     sigB = uiB0;
73     /*------------------------------------------------------------------------
74     *------------------------------------------------------------------------*/
75     expDiff = expA - expB;
76     if ( ! expDiff ) {
77         if ( expA == 0x7FFF ) {
78             if ( (sigA | sigB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) {
79                 goto propagateNaN;
80             }
81             uiZ64 = uiA64;
82             uiZ0  = uiA0;
83             goto uiZ;
84         }
85         sigZ = sigA + sigB;
86         sigZExtra = 0;
87         if ( ! expA ) {
88             normExpSig = softfloat_normSubnormalExtF80Sig( sigZ );
89             expZ = normExpSig.exp + 1;
90             sigZ = normExpSig.sig;
91             goto roundAndPack;
92         }
93         expZ = expA;
94         goto shiftRight1;
95     }
96     /*------------------------------------------------------------------------
97     *------------------------------------------------------------------------*/
98     if ( expDiff < 0 ) {
99         if ( expB == 0x7FFF ) {
100             if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
101             uiZ64 = packToExtF80UI64( signZ, 0x7FFF );
102             uiZ0  = uiB0;
103             goto uiZ;
104         }
105         expZ = expB;
106         if ( ! expA ) {
107             ++expDiff;
108             sigZExtra = 0;
109             if ( ! expDiff ) goto newlyAligned;
110         }
111         sig64Extra = softfloat_shiftRightJam64Extra( sigA, 0, -expDiff );
112         sigA = sig64Extra.v;
113         sigZExtra = sig64Extra.extra;
114     } else {
115         if ( expA == 0x7FFF ) {
116             if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN;
117             uiZ64 = uiA64;
118             uiZ0  = uiA0;
119             goto uiZ;
120         }
121         expZ = expA;
122         if ( ! expB ) {
123             --expDiff;
124             sigZExtra = 0;
125             if ( ! expDiff ) goto newlyAligned;
126         }
127         sig64Extra = softfloat_shiftRightJam64Extra( sigB, 0, expDiff );
128         sigB = sig64Extra.v;
129         sigZExtra = sig64Extra.extra;
130     }
131  newlyAligned:
132     sigZ = sigA + sigB;
133     if ( sigZ & UINT64_C( 0x8000000000000000 ) ) goto roundAndPack;
134     /*------------------------------------------------------------------------
135     *------------------------------------------------------------------------*/
136  shiftRight1:
137     sig64Extra = softfloat_shortShiftRightJam64Extra( sigZ, sigZExtra, 1 );
138     sigZ = sig64Extra.v | UINT64_C( 0x8000000000000000 );
139     sigZExtra = sig64Extra.extra;
140     ++expZ;
141  roundAndPack:
142     return
143         softfloat_roundPackToExtF80(
144             signZ, expZ, sigZ, sigZExtra, extF80_roundingPrecision );
145     /*------------------------------------------------------------------------
146     *------------------------------------------------------------------------*/
147  propagateNaN:
148     uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 );
149     uiZ64 = uiZ.v64;
150     uiZ0  = uiZ.v0;
151  uiZ:
152     uZ.s.signExp = uiZ64;
153     uZ.s.signif  = uiZ0;
154     return uZ.f;
155 
156 }
157 
158