xref: /optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_roundToInt.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 #ifdef SOFTFLOAT_FAST_INT64
45 
46 void
47  f128M_roundToInt(
48      const float128_t *aPtr,
49      uint_fast8_t roundingMode,
50      bool exact,
51      float128_t *zPtr
52  )
53 {
54 
55     *zPtr = f128_roundToInt( *aPtr, roundingMode, exact );
56 
57 }
58 
59 #else
60 
61 void
62  f128M_roundToInt(
63      const float128_t *aPtr,
64      uint_fast8_t roundingMode,
65      bool exact,
66      float128_t *zPtr
67  )
68 {
69     const uint32_t *aWPtr;
70     uint32_t *zWPtr;
71     uint32_t ui96;
72     int32_t exp;
73     uint32_t sigExtra;
74     bool sign;
75     uint_fast8_t bitPos;
76     bool roundNear;
77     unsigned int index, lastIndex;
78     bool extra;
79     uint32_t wordA, bit, wordZ;
80     uint_fast8_t carry;
81     uint32_t extrasMask;
82 
83     /*------------------------------------------------------------------------
84     *------------------------------------------------------------------------*/
85     aWPtr = (const uint32_t *) aPtr;
86     zWPtr = (uint32_t *) zPtr;
87     /*------------------------------------------------------------------------
88     *------------------------------------------------------------------------*/
89     ui96 = aWPtr[indexWordHi( 4 )];
90     exp = expF128UI96( ui96 );
91     /*------------------------------------------------------------------------
92     *------------------------------------------------------------------------*/
93     if ( exp < 0x3FFF ) {
94         zWPtr[indexWord( 4, 2 )] = 0;
95         zWPtr[indexWord( 4, 1 )] = 0;
96         zWPtr[indexWord( 4, 0 )] = 0;
97         sigExtra = aWPtr[indexWord( 4, 2 )];
98         if ( ! sigExtra ) {
99             sigExtra = aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )];
100         }
101         if ( ! sigExtra && ! (ui96 & 0x7FFFFFFF) ) goto ui96;
102         if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact;
103         sign = signF128UI96( ui96 );
104         switch ( roundingMode ) {
105          case softfloat_round_near_even:
106             if ( ! fracF128UI96( ui96 ) && ! sigExtra ) break;
107          case softfloat_round_near_maxMag:
108             if ( exp == 0x3FFE ) goto mag1;
109             break;
110          case softfloat_round_min:
111             if ( sign ) goto mag1;
112             break;
113          case softfloat_round_max:
114             if ( ! sign ) goto mag1;
115             break;
116         }
117         ui96 = packToF128UI96( sign, 0, 0 );
118         goto ui96;
119      mag1:
120         ui96 = packToF128UI96( sign, 0x3FFF, 0 );
121         goto ui96;
122     }
123     /*------------------------------------------------------------------------
124     *------------------------------------------------------------------------*/
125     if ( 0x406F <= exp ) {
126         if (
127             (exp == 0x7FFF)
128                 && (fracF128UI96( ui96 )
129                         || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )]
130                                 | aWPtr[indexWord( 4, 0 )]))
131         ) {
132             softfloat_propagateNaNF128M( aWPtr, 0, zWPtr );
133             return;
134         }
135         zWPtr[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )];
136         zWPtr[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )];
137         zWPtr[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )];
138         goto ui96;
139     }
140     /*------------------------------------------------------------------------
141     *------------------------------------------------------------------------*/
142     bitPos = 0x406F - exp;
143     roundNear =
144            (roundingMode == softfloat_round_near_maxMag)
145         || (roundingMode == softfloat_round_near_even);
146     bitPos -= roundNear;
147     index = indexWordLo( 4 );
148     lastIndex = indexWordHi( 4 );
149     extra = 0;
150     for (;;) {
151         wordA = aWPtr[index];
152         if ( bitPos < 32 ) break;
153         if ( wordA ) extra = 1;
154         zWPtr[index] = 0;
155         index += wordIncr;
156         bitPos -= 32;
157     }
158     bit = (uint32_t) 1<<bitPos;
159     if ( roundNear ) {
160         wordZ = wordA + bit;
161         carry = (wordZ < wordA);
162         bit <<= 1;
163         extrasMask = bit - 1;
164         if (
165             (roundingMode == softfloat_round_near_even)
166                 && ! extra && ! (wordZ & extrasMask)
167         ) {
168             if ( ! bit ) {
169                 zWPtr[index] = wordZ;
170                 index += wordIncr;
171                 wordZ = aWPtr[index] + carry;
172                 carry &= ! wordZ;
173                 zWPtr[index] = wordZ & ~1;
174                 goto propagateCarry;
175             }
176             wordZ &= ~bit;
177         }
178     } else {
179         extrasMask = bit - 1;
180         wordZ = wordA;
181         carry = 0;
182         if (
183                (roundingMode != softfloat_round_minMag)
184             && (signF128UI96( ui96 ) ^ (roundingMode == softfloat_round_max))
185         ) {
186             if ( extra || (wordA & extrasMask) ) {
187                 wordZ += bit;
188                 carry = (wordZ < wordA);
189             }
190         }
191     }
192     wordZ &= ~extrasMask;
193     zWPtr[index] = wordZ;
194  propagateCarry:
195     while ( index != lastIndex ) {
196         index += wordIncr;
197         wordZ = aWPtr[index] + carry;
198         zWPtr[index] = wordZ;
199         carry &= ! wordZ;
200     }
201     /*------------------------------------------------------------------------
202     *------------------------------------------------------------------------*/
203     if ( exact && (softfloat_compare128M( aWPtr, zWPtr ) != 0) ) {
204         softfloat_exceptionFlags |= softfloat_flag_inexact;
205     }
206     return;
207     /*------------------------------------------------------------------------
208     *------------------------------------------------------------------------*/
209  ui96:
210     zWPtr[indexWordHi( 4 )] = ui96;
211 
212 }
213 
214 #endif
215 
216