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
f128_div(float128_t a,float128_t b)45 float128_t f128_div( float128_t a, float128_t b )
46 {
47 union ui128_f128 uA;
48 uint_fast64_t uiA64, uiA0;
49 bool signA;
50 int_fast32_t expA;
51 struct uint128 sigA;
52 union ui128_f128 uB;
53 uint_fast64_t uiB64, uiB0;
54 bool signB;
55 int_fast32_t expB;
56 struct uint128 sigB;
57 bool signZ;
58 struct exp32_sig128 normExpSig;
59 int_fast32_t expZ;
60 struct uint128 rem;
61 uint_fast32_t recip32;
62 int ix;
63 uint_fast64_t q64;
64 uint_fast32_t q;
65 struct uint128 term;
66 uint_fast32_t qs[3];
67 uint_fast64_t sigZExtra;
68 struct uint128 sigZ, uiZ;
69 union ui128_f128 uZ;
70
71 /*------------------------------------------------------------------------
72 *------------------------------------------------------------------------*/
73 uA.f = a;
74 uiA64 = uA.ui.v64;
75 uiA0 = uA.ui.v0;
76 signA = signF128UI64( uiA64 );
77 expA = expF128UI64( uiA64 );
78 sigA.v64 = fracF128UI64( uiA64 );
79 sigA.v0 = uiA0;
80 uB.f = b;
81 uiB64 = uB.ui.v64;
82 uiB0 = uB.ui.v0;
83 signB = signF128UI64( uiB64 );
84 expB = expF128UI64( uiB64 );
85 sigB.v64 = fracF128UI64( uiB64 );
86 sigB.v0 = uiB0;
87 signZ = signA ^ signB;
88 /*------------------------------------------------------------------------
89 *------------------------------------------------------------------------*/
90 if ( expA == 0x7FFF ) {
91 if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
92 if ( expB == 0x7FFF ) {
93 if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
94 goto invalid;
95 }
96 goto infinity;
97 }
98 if ( expB == 0x7FFF ) {
99 if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
100 goto zero;
101 }
102 /*------------------------------------------------------------------------
103 *------------------------------------------------------------------------*/
104 if ( ! expB ) {
105 if ( ! (sigB.v64 | sigB.v0) ) {
106 if ( ! (expA | sigA.v64 | sigA.v0) ) goto invalid;
107 softfloat_raiseFlags( softfloat_flag_infinite );
108 goto infinity;
109 }
110 normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
111 expB = normExpSig.exp;
112 sigB = normExpSig.sig;
113 }
114 if ( ! expA ) {
115 if ( ! (sigA.v64 | sigA.v0) ) goto zero;
116 normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
117 expA = normExpSig.exp;
118 sigA = normExpSig.sig;
119 }
120 /*------------------------------------------------------------------------
121 *------------------------------------------------------------------------*/
122 expZ = expA - expB + 0x3FFE;
123 sigA.v64 |= UINT64_C( 0x0001000000000000 );
124 sigB.v64 |= UINT64_C( 0x0001000000000000 );
125 rem = sigA;
126 if ( softfloat_lt128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ) ) {
127 --expZ;
128 rem = softfloat_add128( sigA.v64, sigA.v0, sigA.v64, sigA.v0 );
129 }
130 recip32 = softfloat_approxRecip32_1( sigB.v64>>17 );
131 ix = 3;
132 for (;;) {
133 q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32;
134 q = (q64 + 0x80000000)>>32;
135 --ix;
136 if ( ix < 0 ) break;
137 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
138 term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
139 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
140 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
141 --q;
142 rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
143 }
144 qs[ix] = q;
145 }
146 /*------------------------------------------------------------------------
147 *------------------------------------------------------------------------*/
148 if ( ((q + 1) & 7) < 2 ) {
149 rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
150 term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
151 rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
152 if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
153 --q;
154 rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
155 } else if ( softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 ) ) {
156 ++q;
157 rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
158 }
159 if ( rem.v64 | rem.v0 ) q |= 1;
160 }
161 /*------------------------------------------------------------------------
162 *------------------------------------------------------------------------*/
163 sigZExtra = (uint64_t) ((uint_fast64_t) q<<60);
164 term = softfloat_shortShiftLeft128( 0, qs[1], 54 );
165 sigZ =
166 softfloat_add128(
167 (uint_fast64_t) qs[2]<<19, ((uint_fast64_t) qs[0]<<25) + (q>>4),
168 term.v64, term.v0
169 );
170 return
171 softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
172 /*------------------------------------------------------------------------
173 *------------------------------------------------------------------------*/
174 propagateNaN:
175 uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 );
176 goto uiZ;
177 /*------------------------------------------------------------------------
178 *------------------------------------------------------------------------*/
179 invalid:
180 softfloat_raiseFlags( softfloat_flag_invalid );
181 uiZ.v64 = defaultNaNF128UI64;
182 uiZ.v0 = defaultNaNF128UI0;
183 goto uiZ;
184 /*------------------------------------------------------------------------
185 *------------------------------------------------------------------------*/
186 infinity:
187 uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
188 goto uiZ0;
189 /*------------------------------------------------------------------------
190 *------------------------------------------------------------------------*/
191 zero:
192 uiZ.v64 = packToF128UI64( signZ, 0, 0 );
193 uiZ0:
194 uiZ.v0 = 0;
195 uiZ:
196 uZ.ui = uiZ;
197 return uZ.f;
198
199 }
200
201