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