xref: /openbmc/qemu/fpu/softfloat.c (revision d7754940d78a7d5bfb13531afa9a67f8c57e987e)
18d725facSAndreas Färber /*
28d725facSAndreas Färber  * QEMU float support
38d725facSAndreas Färber  *
416017c48SPeter Maydell  * The code in this source file is derived from release 2a of the SoftFloat
516017c48SPeter Maydell  * IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and
616017c48SPeter Maydell  * some later contributions) are provided under that license, as detailed below.
716017c48SPeter Maydell  * It has subsequently been modified by contributors to the QEMU Project,
816017c48SPeter Maydell  * so some portions are provided under:
916017c48SPeter Maydell  *  the SoftFloat-2a license
1016017c48SPeter Maydell  *  the BSD license
1116017c48SPeter Maydell  *  GPL-v2-or-later
1216017c48SPeter Maydell  *
1316017c48SPeter Maydell  * Any future contributions to this file after December 1st 2014 will be
1416017c48SPeter Maydell  * taken to be licensed under the Softfloat-2a license unless specifically
1516017c48SPeter Maydell  * indicated otherwise.
168d725facSAndreas Färber  */
17158142c2Sbellard 
18a7d1ac78SPeter Maydell /*
19a7d1ac78SPeter Maydell ===============================================================================
20a7d1ac78SPeter Maydell This C source file is part of the SoftFloat IEC/IEEE Floating-point
21a7d1ac78SPeter Maydell Arithmetic Package, Release 2a.
22158142c2Sbellard 
23158142c2Sbellard Written by John R. Hauser.  This work was made possible in part by the
24158142c2Sbellard International Computer Science Institute, located at Suite 600, 1947 Center
25158142c2Sbellard Street, Berkeley, California 94704.  Funding was partially provided by the
26158142c2Sbellard National Science Foundation under grant MIP-9311980.  The original version
27158142c2Sbellard of this code was written as part of a project to build a fixed-point vector
28158142c2Sbellard processor in collaboration with the University of California at Berkeley,
29158142c2Sbellard overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
30a7d1ac78SPeter Maydell is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
31158142c2Sbellard arithmetic/SoftFloat.html'.
32158142c2Sbellard 
33a7d1ac78SPeter Maydell THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
34a7d1ac78SPeter Maydell has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
35a7d1ac78SPeter Maydell TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
36a7d1ac78SPeter Maydell PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
37a7d1ac78SPeter Maydell AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
38158142c2Sbellard 
39158142c2Sbellard Derivative works are acceptable, even for commercial purposes, so long as
40a7d1ac78SPeter Maydell (1) they include prominent notice that the work is derivative, and (2) they
41a7d1ac78SPeter Maydell include prominent notice akin to these four paragraphs for those parts of
42a7d1ac78SPeter Maydell this code that are retained.
43158142c2Sbellard 
44a7d1ac78SPeter Maydell ===============================================================================
45a7d1ac78SPeter Maydell */
46158142c2Sbellard 
4716017c48SPeter Maydell /* BSD licensing:
4816017c48SPeter Maydell  * Copyright (c) 2006, Fabrice Bellard
4916017c48SPeter Maydell  * All rights reserved.
5016017c48SPeter Maydell  *
5116017c48SPeter Maydell  * Redistribution and use in source and binary forms, with or without
5216017c48SPeter Maydell  * modification, are permitted provided that the following conditions are met:
5316017c48SPeter Maydell  *
5416017c48SPeter Maydell  * 1. Redistributions of source code must retain the above copyright notice,
5516017c48SPeter Maydell  * this list of conditions and the following disclaimer.
5616017c48SPeter Maydell  *
5716017c48SPeter Maydell  * 2. Redistributions in binary form must reproduce the above copyright notice,
5816017c48SPeter Maydell  * this list of conditions and the following disclaimer in the documentation
5916017c48SPeter Maydell  * and/or other materials provided with the distribution.
6016017c48SPeter Maydell  *
6116017c48SPeter Maydell  * 3. Neither the name of the copyright holder nor the names of its contributors
6216017c48SPeter Maydell  * may be used to endorse or promote products derived from this software without
6316017c48SPeter Maydell  * specific prior written permission.
6416017c48SPeter Maydell  *
6516017c48SPeter Maydell  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
6616017c48SPeter Maydell  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6716017c48SPeter Maydell  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6816017c48SPeter Maydell  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
6916017c48SPeter Maydell  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
7016017c48SPeter Maydell  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
7116017c48SPeter Maydell  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
7216017c48SPeter Maydell  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
7316017c48SPeter Maydell  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
7416017c48SPeter Maydell  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
7516017c48SPeter Maydell  * THE POSSIBILITY OF SUCH DAMAGE.
7616017c48SPeter Maydell  */
7716017c48SPeter Maydell 
7816017c48SPeter Maydell /* Portions of this work are licensed under the terms of the GNU GPL,
7916017c48SPeter Maydell  * version 2 or later. See the COPYING file in the top-level directory.
8016017c48SPeter Maydell  */
8116017c48SPeter Maydell 
822ac8bd03SPeter Maydell /* softfloat (and in particular the code in softfloat-specialize.h) is
832ac8bd03SPeter Maydell  * target-dependent and needs the TARGET_* macros.
842ac8bd03SPeter Maydell  */
85d38ea87aSPeter Maydell #include "qemu/osdep.h"
86a94b7839SEmilio G. Cota #include <math.h>
876fff2167SAlex Bennée #include "qemu/bitops.h"
886b4c305cSPaolo Bonzini #include "fpu/softfloat.h"
89158142c2Sbellard 
90dc355b76SPeter Maydell /* We only need stdlib for abort() */
91dc355b76SPeter Maydell 
92158142c2Sbellard /*----------------------------------------------------------------------------
93158142c2Sbellard | Primitive arithmetic functions, including multi-word arithmetic, and
94158142c2Sbellard | division and square root approximations.  (Can be specialized to target if
95158142c2Sbellard | desired.)
96158142c2Sbellard *----------------------------------------------------------------------------*/
9788857acaSLaurent Vivier #include "fpu/softfloat-macros.h"
98158142c2Sbellard 
99a94b7839SEmilio G. Cota /*
100a94b7839SEmilio G. Cota  * Hardfloat
101a94b7839SEmilio G. Cota  *
102a94b7839SEmilio G. Cota  * Fast emulation of guest FP instructions is challenging for two reasons.
103a94b7839SEmilio G. Cota  * First, FP instruction semantics are similar but not identical, particularly
104a94b7839SEmilio G. Cota  * when handling NaNs. Second, emulating at reasonable speed the guest FP
105a94b7839SEmilio G. Cota  * exception flags is not trivial: reading the host's flags register with a
106a94b7839SEmilio G. Cota  * feclearexcept & fetestexcept pair is slow [slightly slower than soft-fp],
107a94b7839SEmilio G. Cota  * and trapping on every FP exception is not fast nor pleasant to work with.
108a94b7839SEmilio G. Cota  *
109a94b7839SEmilio G. Cota  * We address these challenges by leveraging the host FPU for a subset of the
110a94b7839SEmilio G. Cota  * operations. To do this we expand on the idea presented in this paper:
111a94b7839SEmilio G. Cota  *
112a94b7839SEmilio G. Cota  * Guo, Yu-Chuan, et al. "Translating the ARM Neon and VFP instructions in a
113a94b7839SEmilio G. Cota  * binary translator." Software: Practice and Experience 46.12 (2016):1591-1615.
114a94b7839SEmilio G. Cota  *
115a94b7839SEmilio G. Cota  * The idea is thus to leverage the host FPU to (1) compute FP operations
116a94b7839SEmilio G. Cota  * and (2) identify whether FP exceptions occurred while avoiding
117a94b7839SEmilio G. Cota  * expensive exception flag register accesses.
118a94b7839SEmilio G. Cota  *
119a94b7839SEmilio G. Cota  * An important optimization shown in the paper is that given that exception
120a94b7839SEmilio G. Cota  * flags are rarely cleared by the guest, we can avoid recomputing some flags.
121a94b7839SEmilio G. Cota  * This is particularly useful for the inexact flag, which is very frequently
122a94b7839SEmilio G. Cota  * raised in floating-point workloads.
123a94b7839SEmilio G. Cota  *
124a94b7839SEmilio G. Cota  * We optimize the code further by deferring to soft-fp whenever FP exception
125a94b7839SEmilio G. Cota  * detection might get hairy. Two examples: (1) when at least one operand is
126a94b7839SEmilio G. Cota  * denormal/inf/NaN; (2) when operands are not guaranteed to lead to a 0 result
127a94b7839SEmilio G. Cota  * and the result is < the minimum normal.
128a94b7839SEmilio G. Cota  */
129a94b7839SEmilio G. Cota #define GEN_INPUT_FLUSH__NOCHECK(name, soft_t)                          \
130a94b7839SEmilio G. Cota     static inline void name(soft_t *a, float_status *s)                 \
131a94b7839SEmilio G. Cota     {                                                                   \
132a94b7839SEmilio G. Cota         if (unlikely(soft_t ## _is_denormal(*a))) {                     \
133a94b7839SEmilio G. Cota             *a = soft_t ## _set_sign(soft_t ## _zero,                   \
134a94b7839SEmilio G. Cota                                      soft_t ## _is_neg(*a));            \
135d82f3b2dSRichard Henderson             float_raise(float_flag_input_denormal, s);                  \
136a94b7839SEmilio G. Cota         }                                                               \
137a94b7839SEmilio G. Cota     }
138a94b7839SEmilio G. Cota 
GEN_INPUT_FLUSH__NOCHECK(float32_input_flush__nocheck,float32)139a94b7839SEmilio G. Cota GEN_INPUT_FLUSH__NOCHECK(float32_input_flush__nocheck, float32)
140a94b7839SEmilio G. Cota GEN_INPUT_FLUSH__NOCHECK(float64_input_flush__nocheck, float64)
141a94b7839SEmilio G. Cota #undef GEN_INPUT_FLUSH__NOCHECK
142a94b7839SEmilio G. Cota 
143a94b7839SEmilio G. Cota #define GEN_INPUT_FLUSH1(name, soft_t)                  \
144a94b7839SEmilio G. Cota     static inline void name(soft_t *a, float_status *s) \
145a94b7839SEmilio G. Cota     {                                                   \
146a94b7839SEmilio G. Cota         if (likely(!s->flush_inputs_to_zero)) {         \
147a94b7839SEmilio G. Cota             return;                                     \
148a94b7839SEmilio G. Cota         }                                               \
149a94b7839SEmilio G. Cota         soft_t ## _input_flush__nocheck(a, s);          \
150a94b7839SEmilio G. Cota     }
151a94b7839SEmilio G. Cota 
152a94b7839SEmilio G. Cota GEN_INPUT_FLUSH1(float32_input_flush1, float32)
153a94b7839SEmilio G. Cota GEN_INPUT_FLUSH1(float64_input_flush1, float64)
154a94b7839SEmilio G. Cota #undef GEN_INPUT_FLUSH1
155a94b7839SEmilio G. Cota 
156a94b7839SEmilio G. Cota #define GEN_INPUT_FLUSH2(name, soft_t)                                  \
157a94b7839SEmilio G. Cota     static inline void name(soft_t *a, soft_t *b, float_status *s)      \
158a94b7839SEmilio G. Cota     {                                                                   \
159a94b7839SEmilio G. Cota         if (likely(!s->flush_inputs_to_zero)) {                         \
160a94b7839SEmilio G. Cota             return;                                                     \
161a94b7839SEmilio G. Cota         }                                                               \
162a94b7839SEmilio G. Cota         soft_t ## _input_flush__nocheck(a, s);                          \
163a94b7839SEmilio G. Cota         soft_t ## _input_flush__nocheck(b, s);                          \
164a94b7839SEmilio G. Cota     }
165a94b7839SEmilio G. Cota 
166a94b7839SEmilio G. Cota GEN_INPUT_FLUSH2(float32_input_flush2, float32)
167a94b7839SEmilio G. Cota GEN_INPUT_FLUSH2(float64_input_flush2, float64)
168a94b7839SEmilio G. Cota #undef GEN_INPUT_FLUSH2
169a94b7839SEmilio G. Cota 
170a94b7839SEmilio G. Cota #define GEN_INPUT_FLUSH3(name, soft_t)                                  \
171a94b7839SEmilio G. Cota     static inline void name(soft_t *a, soft_t *b, soft_t *c, float_status *s) \
172a94b7839SEmilio G. Cota     {                                                                   \
173a94b7839SEmilio G. Cota         if (likely(!s->flush_inputs_to_zero)) {                         \
174a94b7839SEmilio G. Cota             return;                                                     \
175a94b7839SEmilio G. Cota         }                                                               \
176a94b7839SEmilio G. Cota         soft_t ## _input_flush__nocheck(a, s);                          \
177a94b7839SEmilio G. Cota         soft_t ## _input_flush__nocheck(b, s);                          \
178a94b7839SEmilio G. Cota         soft_t ## _input_flush__nocheck(c, s);                          \
179a94b7839SEmilio G. Cota     }
180a94b7839SEmilio G. Cota 
181a94b7839SEmilio G. Cota GEN_INPUT_FLUSH3(float32_input_flush3, float32)
182a94b7839SEmilio G. Cota GEN_INPUT_FLUSH3(float64_input_flush3, float64)
183a94b7839SEmilio G. Cota #undef GEN_INPUT_FLUSH3
184a94b7839SEmilio G. Cota 
185a94b7839SEmilio G. Cota /*
186a94b7839SEmilio G. Cota  * Choose whether to use fpclassify or float32/64_* primitives in the generated
187a94b7839SEmilio G. Cota  * hardfloat functions. Each combination of number of inputs and float size
188a94b7839SEmilio G. Cota  * gets its own value.
189a94b7839SEmilio G. Cota  */
190a94b7839SEmilio G. Cota #if defined(__x86_64__)
191a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_1F32_USE_FP 0
192a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_1F64_USE_FP 1
193a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_2F32_USE_FP 0
194a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_2F64_USE_FP 1
195a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_3F32_USE_FP 0
196a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_3F64_USE_FP 1
197a94b7839SEmilio G. Cota #else
198a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_1F32_USE_FP 0
199a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_1F64_USE_FP 0
200a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_2F32_USE_FP 0
201a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_2F64_USE_FP 0
202a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_3F32_USE_FP 0
203a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_3F64_USE_FP 0
204a94b7839SEmilio G. Cota #endif
205a94b7839SEmilio G. Cota 
206a94b7839SEmilio G. Cota /*
207a94b7839SEmilio G. Cota  * QEMU_HARDFLOAT_USE_ISINF chooses whether to use isinf() over
208a94b7839SEmilio G. Cota  * float{32,64}_is_infinity when !USE_FP.
209a94b7839SEmilio G. Cota  * On x86_64/aarch64, using the former over the latter can yield a ~6% speedup.
210a94b7839SEmilio G. Cota  * On power64 however, using isinf() reduces fp-bench performance by up to 50%.
211a94b7839SEmilio G. Cota  */
212a94b7839SEmilio G. Cota #if defined(__x86_64__) || defined(__aarch64__)
213a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_USE_ISINF   1
214a94b7839SEmilio G. Cota #else
215a94b7839SEmilio G. Cota # define QEMU_HARDFLOAT_USE_ISINF   0
216a94b7839SEmilio G. Cota #endif
217a94b7839SEmilio G. Cota 
218a94b7839SEmilio G. Cota /*
219a94b7839SEmilio G. Cota  * Some targets clear the FP flags before most FP operations. This prevents
220a94b7839SEmilio G. Cota  * the use of hardfloat, since hardfloat relies on the inexact flag being
221a94b7839SEmilio G. Cota  * already set.
222a94b7839SEmilio G. Cota  */
223a94b7839SEmilio G. Cota #if defined(TARGET_PPC) || defined(__FAST_MATH__)
224a94b7839SEmilio G. Cota # if defined(__FAST_MATH__)
225a94b7839SEmilio G. Cota #  warning disabling hardfloat due to -ffast-math: hardfloat requires an exact \
226a94b7839SEmilio G. Cota     IEEE implementation
227a94b7839SEmilio G. Cota # endif
228a94b7839SEmilio G. Cota # define QEMU_NO_HARDFLOAT 1
229a94b7839SEmilio G. Cota # define QEMU_SOFTFLOAT_ATTR QEMU_FLATTEN
230a94b7839SEmilio G. Cota #else
231a94b7839SEmilio G. Cota # define QEMU_NO_HARDFLOAT 0
232a94b7839SEmilio G. Cota # define QEMU_SOFTFLOAT_ATTR QEMU_FLATTEN __attribute__((noinline))
233a94b7839SEmilio G. Cota #endif
234a94b7839SEmilio G. Cota 
235a94b7839SEmilio G. Cota static inline bool can_use_fpu(const float_status *s)
236a94b7839SEmilio G. Cota {
237a94b7839SEmilio G. Cota     if (QEMU_NO_HARDFLOAT) {
238a94b7839SEmilio G. Cota         return false;
239a94b7839SEmilio G. Cota     }
240a94b7839SEmilio G. Cota     return likely(s->float_exception_flags & float_flag_inexact &&
241a94b7839SEmilio G. Cota                   s->float_rounding_mode == float_round_nearest_even);
242a94b7839SEmilio G. Cota }
243a94b7839SEmilio G. Cota 
244a94b7839SEmilio G. Cota /*
245a94b7839SEmilio G. Cota  * Hardfloat generation functions. Each operation can have two flavors:
246a94b7839SEmilio G. Cota  * either using softfloat primitives (e.g. float32_is_zero_or_normal) for
247a94b7839SEmilio G. Cota  * most condition checks, or native ones (e.g. fpclassify).
248a94b7839SEmilio G. Cota  *
249a94b7839SEmilio G. Cota  * The flavor is chosen by the callers. Instead of using macros, we rely on the
250a94b7839SEmilio G. Cota  * compiler to propagate constants and inline everything into the callers.
251a94b7839SEmilio G. Cota  *
252a94b7839SEmilio G. Cota  * We only generate functions for operations with two inputs, since only
253a94b7839SEmilio G. Cota  * these are common enough to justify consolidating them into common code.
254a94b7839SEmilio G. Cota  */
255a94b7839SEmilio G. Cota 
256a94b7839SEmilio G. Cota typedef union {
257a94b7839SEmilio G. Cota     float32 s;
258a94b7839SEmilio G. Cota     float h;
259a94b7839SEmilio G. Cota } union_float32;
260a94b7839SEmilio G. Cota 
261a94b7839SEmilio G. Cota typedef union {
262a94b7839SEmilio G. Cota     float64 s;
263a94b7839SEmilio G. Cota     double h;
264a94b7839SEmilio G. Cota } union_float64;
265a94b7839SEmilio G. Cota 
266a94b7839SEmilio G. Cota typedef bool (*f32_check_fn)(union_float32 a, union_float32 b);
267a94b7839SEmilio G. Cota typedef bool (*f64_check_fn)(union_float64 a, union_float64 b);
268a94b7839SEmilio G. Cota 
269a94b7839SEmilio G. Cota typedef float32 (*soft_f32_op2_fn)(float32 a, float32 b, float_status *s);
270a94b7839SEmilio G. Cota typedef float64 (*soft_f64_op2_fn)(float64 a, float64 b, float_status *s);
271a94b7839SEmilio G. Cota typedef float   (*hard_f32_op2_fn)(float a, float b);
272a94b7839SEmilio G. Cota typedef double  (*hard_f64_op2_fn)(double a, double b);
273a94b7839SEmilio G. Cota 
274a94b7839SEmilio G. Cota /* 2-input is-zero-or-normal */
f32_is_zon2(union_float32 a,union_float32 b)275a94b7839SEmilio G. Cota static inline bool f32_is_zon2(union_float32 a, union_float32 b)
276a94b7839SEmilio G. Cota {
277a94b7839SEmilio G. Cota     if (QEMU_HARDFLOAT_2F32_USE_FP) {
278a94b7839SEmilio G. Cota         /*
279a94b7839SEmilio G. Cota          * Not using a temp variable for consecutive fpclassify calls ends up
280a94b7839SEmilio G. Cota          * generating faster code.
281a94b7839SEmilio G. Cota          */
282a94b7839SEmilio G. Cota         return (fpclassify(a.h) == FP_NORMAL || fpclassify(a.h) == FP_ZERO) &&
283a94b7839SEmilio G. Cota                (fpclassify(b.h) == FP_NORMAL || fpclassify(b.h) == FP_ZERO);
284a94b7839SEmilio G. Cota     }
285a94b7839SEmilio G. Cota     return float32_is_zero_or_normal(a.s) &&
286a94b7839SEmilio G. Cota            float32_is_zero_or_normal(b.s);
287a94b7839SEmilio G. Cota }
288a94b7839SEmilio G. Cota 
f64_is_zon2(union_float64 a,union_float64 b)289a94b7839SEmilio G. Cota static inline bool f64_is_zon2(union_float64 a, union_float64 b)
290a94b7839SEmilio G. Cota {
291a94b7839SEmilio G. Cota     if (QEMU_HARDFLOAT_2F64_USE_FP) {
292a94b7839SEmilio G. Cota         return (fpclassify(a.h) == FP_NORMAL || fpclassify(a.h) == FP_ZERO) &&
293a94b7839SEmilio G. Cota                (fpclassify(b.h) == FP_NORMAL || fpclassify(b.h) == FP_ZERO);
294a94b7839SEmilio G. Cota     }
295a94b7839SEmilio G. Cota     return float64_is_zero_or_normal(a.s) &&
296a94b7839SEmilio G. Cota            float64_is_zero_or_normal(b.s);
297a94b7839SEmilio G. Cota }
298a94b7839SEmilio G. Cota 
299a94b7839SEmilio G. Cota /* 3-input is-zero-or-normal */
300a94b7839SEmilio G. Cota static inline
f32_is_zon3(union_float32 a,union_float32 b,union_float32 c)301a94b7839SEmilio G. Cota bool f32_is_zon3(union_float32 a, union_float32 b, union_float32 c)
302a94b7839SEmilio G. Cota {
303a94b7839SEmilio G. Cota     if (QEMU_HARDFLOAT_3F32_USE_FP) {
304a94b7839SEmilio G. Cota         return (fpclassify(a.h) == FP_NORMAL || fpclassify(a.h) == FP_ZERO) &&
305a94b7839SEmilio G. Cota                (fpclassify(b.h) == FP_NORMAL || fpclassify(b.h) == FP_ZERO) &&
306a94b7839SEmilio G. Cota                (fpclassify(c.h) == FP_NORMAL || fpclassify(c.h) == FP_ZERO);
307a94b7839SEmilio G. Cota     }
308a94b7839SEmilio G. Cota     return float32_is_zero_or_normal(a.s) &&
309a94b7839SEmilio G. Cota            float32_is_zero_or_normal(b.s) &&
310a94b7839SEmilio G. Cota            float32_is_zero_or_normal(c.s);
311a94b7839SEmilio G. Cota }
312a94b7839SEmilio G. Cota 
313a94b7839SEmilio G. Cota static inline
f64_is_zon3(union_float64 a,union_float64 b,union_float64 c)314a94b7839SEmilio G. Cota bool f64_is_zon3(union_float64 a, union_float64 b, union_float64 c)
315a94b7839SEmilio G. Cota {
316a94b7839SEmilio G. Cota     if (QEMU_HARDFLOAT_3F64_USE_FP) {
317a94b7839SEmilio G. Cota         return (fpclassify(a.h) == FP_NORMAL || fpclassify(a.h) == FP_ZERO) &&
318a94b7839SEmilio G. Cota                (fpclassify(b.h) == FP_NORMAL || fpclassify(b.h) == FP_ZERO) &&
319a94b7839SEmilio G. Cota                (fpclassify(c.h) == FP_NORMAL || fpclassify(c.h) == FP_ZERO);
320a94b7839SEmilio G. Cota     }
321a94b7839SEmilio G. Cota     return float64_is_zero_or_normal(a.s) &&
322a94b7839SEmilio G. Cota            float64_is_zero_or_normal(b.s) &&
323a94b7839SEmilio G. Cota            float64_is_zero_or_normal(c.s);
324a94b7839SEmilio G. Cota }
325a94b7839SEmilio G. Cota 
f32_is_inf(union_float32 a)326a94b7839SEmilio G. Cota static inline bool f32_is_inf(union_float32 a)
327a94b7839SEmilio G. Cota {
328a94b7839SEmilio G. Cota     if (QEMU_HARDFLOAT_USE_ISINF) {
329a94b7839SEmilio G. Cota         return isinf(a.h);
330a94b7839SEmilio G. Cota     }
331a94b7839SEmilio G. Cota     return float32_is_infinity(a.s);
332a94b7839SEmilio G. Cota }
333a94b7839SEmilio G. Cota 
f64_is_inf(union_float64 a)334a94b7839SEmilio G. Cota static inline bool f64_is_inf(union_float64 a)
335a94b7839SEmilio G. Cota {
336a94b7839SEmilio G. Cota     if (QEMU_HARDFLOAT_USE_ISINF) {
337a94b7839SEmilio G. Cota         return isinf(a.h);
338a94b7839SEmilio G. Cota     }
339a94b7839SEmilio G. Cota     return float64_is_infinity(a.s);
340a94b7839SEmilio G. Cota }
341a94b7839SEmilio G. Cota 
342a94b7839SEmilio G. Cota static inline float32
float32_gen2(float32 xa,float32 xb,float_status * s,hard_f32_op2_fn hard,soft_f32_op2_fn soft,f32_check_fn pre,f32_check_fn post)343a94b7839SEmilio G. Cota float32_gen2(float32 xa, float32 xb, float_status *s,
344a94b7839SEmilio G. Cota              hard_f32_op2_fn hard, soft_f32_op2_fn soft,
345b240c9c4SRichard Henderson              f32_check_fn pre, f32_check_fn post)
346a94b7839SEmilio G. Cota {
347a94b7839SEmilio G. Cota     union_float32 ua, ub, ur;
348a94b7839SEmilio G. Cota 
349a94b7839SEmilio G. Cota     ua.s = xa;
350a94b7839SEmilio G. Cota     ub.s = xb;
351a94b7839SEmilio G. Cota 
352a94b7839SEmilio G. Cota     if (unlikely(!can_use_fpu(s))) {
353a94b7839SEmilio G. Cota         goto soft;
354a94b7839SEmilio G. Cota     }
355a94b7839SEmilio G. Cota 
356a94b7839SEmilio G. Cota     float32_input_flush2(&ua.s, &ub.s, s);
357a94b7839SEmilio G. Cota     if (unlikely(!pre(ua, ub))) {
358a94b7839SEmilio G. Cota         goto soft;
359a94b7839SEmilio G. Cota     }
360a94b7839SEmilio G. Cota 
361a94b7839SEmilio G. Cota     ur.h = hard(ua.h, ub.h);
362a94b7839SEmilio G. Cota     if (unlikely(f32_is_inf(ur))) {
363d82f3b2dSRichard Henderson         float_raise(float_flag_overflow, s);
364b240c9c4SRichard Henderson     } else if (unlikely(fabsf(ur.h) <= FLT_MIN) && post(ua, ub)) {
365a94b7839SEmilio G. Cota         goto soft;
366a94b7839SEmilio G. Cota     }
367a94b7839SEmilio G. Cota     return ur.s;
368a94b7839SEmilio G. Cota 
369a94b7839SEmilio G. Cota  soft:
370a94b7839SEmilio G. Cota     return soft(ua.s, ub.s, s);
371a94b7839SEmilio G. Cota }
372a94b7839SEmilio G. Cota 
373a94b7839SEmilio G. Cota static inline float64
float64_gen2(float64 xa,float64 xb,float_status * s,hard_f64_op2_fn hard,soft_f64_op2_fn soft,f64_check_fn pre,f64_check_fn post)374a94b7839SEmilio G. Cota float64_gen2(float64 xa, float64 xb, float_status *s,
375a94b7839SEmilio G. Cota              hard_f64_op2_fn hard, soft_f64_op2_fn soft,
376b240c9c4SRichard Henderson              f64_check_fn pre, f64_check_fn post)
377a94b7839SEmilio G. Cota {
378a94b7839SEmilio G. Cota     union_float64 ua, ub, ur;
379a94b7839SEmilio G. Cota 
380a94b7839SEmilio G. Cota     ua.s = xa;
381a94b7839SEmilio G. Cota     ub.s = xb;
382a94b7839SEmilio G. Cota 
383a94b7839SEmilio G. Cota     if (unlikely(!can_use_fpu(s))) {
384a94b7839SEmilio G. Cota         goto soft;
385a94b7839SEmilio G. Cota     }
386a94b7839SEmilio G. Cota 
387a94b7839SEmilio G. Cota     float64_input_flush2(&ua.s, &ub.s, s);
388a94b7839SEmilio G. Cota     if (unlikely(!pre(ua, ub))) {
389a94b7839SEmilio G. Cota         goto soft;
390a94b7839SEmilio G. Cota     }
391a94b7839SEmilio G. Cota 
392a94b7839SEmilio G. Cota     ur.h = hard(ua.h, ub.h);
393a94b7839SEmilio G. Cota     if (unlikely(f64_is_inf(ur))) {
394d82f3b2dSRichard Henderson         float_raise(float_flag_overflow, s);
395b240c9c4SRichard Henderson     } else if (unlikely(fabs(ur.h) <= DBL_MIN) && post(ua, ub)) {
396a94b7839SEmilio G. Cota         goto soft;
397a94b7839SEmilio G. Cota     }
398a94b7839SEmilio G. Cota     return ur.s;
399a94b7839SEmilio G. Cota 
400a94b7839SEmilio G. Cota  soft:
401a94b7839SEmilio G. Cota     return soft(ua.s, ub.s, s);
402a94b7839SEmilio G. Cota }
403a94b7839SEmilio G. Cota 
404a90119b5SAlex Bennée /*
405a90119b5SAlex Bennée  * Classify a floating point number. Everything above float_class_qnan
406a90119b5SAlex Bennée  * is a NaN so cls >= float_class_qnan is any NaN.
407a90119b5SAlex Bennée  */
408a90119b5SAlex Bennée 
409a90119b5SAlex Bennée typedef enum __attribute__ ((__packed__)) {
410a90119b5SAlex Bennée     float_class_unclassified,
411a90119b5SAlex Bennée     float_class_zero,
412a90119b5SAlex Bennée     float_class_normal,
413a90119b5SAlex Bennée     float_class_inf,
414a90119b5SAlex Bennée     float_class_qnan,  /* all NaNs from here */
415a90119b5SAlex Bennée     float_class_snan,
416a90119b5SAlex Bennée } FloatClass;
417a90119b5SAlex Bennée 
418134eda00SRichard Henderson #define float_cmask(bit)  (1u << (bit))
419134eda00SRichard Henderson 
420134eda00SRichard Henderson enum {
421134eda00SRichard Henderson     float_cmask_zero    = float_cmask(float_class_zero),
422134eda00SRichard Henderson     float_cmask_normal  = float_cmask(float_class_normal),
423134eda00SRichard Henderson     float_cmask_inf     = float_cmask(float_class_inf),
424134eda00SRichard Henderson     float_cmask_qnan    = float_cmask(float_class_qnan),
425134eda00SRichard Henderson     float_cmask_snan    = float_cmask(float_class_snan),
426134eda00SRichard Henderson 
427134eda00SRichard Henderson     float_cmask_infzero = float_cmask_zero | float_cmask_inf,
428134eda00SRichard Henderson     float_cmask_anynan  = float_cmask_qnan | float_cmask_snan,
429134eda00SRichard Henderson };
430134eda00SRichard Henderson 
431e1c4667aSRichard Henderson /* Flags for parts_minmax. */
432e1c4667aSRichard Henderson enum {
433e1c4667aSRichard Henderson     /* Set for minimum; clear for maximum. */
434e1c4667aSRichard Henderson     minmax_ismin = 1,
435e1c4667aSRichard Henderson     /* Set for the IEEE 754-2008 minNum() and maxNum() operations. */
436e1c4667aSRichard Henderson     minmax_isnum = 2,
437e1c4667aSRichard Henderson     /* Set for the IEEE 754-2008 minNumMag() and minNumMag() operations. */
438e1c4667aSRichard Henderson     minmax_ismag = 4,
4390e903037SChih-Min Chao     /*
4400e903037SChih-Min Chao      * Set for the IEEE 754-2019 minimumNumber() and maximumNumber()
4410e903037SChih-Min Chao      * operations.
4420e903037SChih-Min Chao      */
4430e903037SChih-Min Chao     minmax_isnumber = 8,
444e1c4667aSRichard Henderson };
445134eda00SRichard Henderson 
446247d1f21SRichard Henderson /* Simple helpers for checking if, or what kind of, NaN we have */
is_nan(FloatClass c)447247d1f21SRichard Henderson static inline __attribute__((unused)) bool is_nan(FloatClass c)
448247d1f21SRichard Henderson {
449247d1f21SRichard Henderson     return unlikely(c >= float_class_qnan);
450247d1f21SRichard Henderson }
451247d1f21SRichard Henderson 
is_snan(FloatClass c)452247d1f21SRichard Henderson static inline __attribute__((unused)) bool is_snan(FloatClass c)
453247d1f21SRichard Henderson {
454247d1f21SRichard Henderson     return c == float_class_snan;
455247d1f21SRichard Henderson }
456247d1f21SRichard Henderson 
is_qnan(FloatClass c)457247d1f21SRichard Henderson static inline __attribute__((unused)) bool is_qnan(FloatClass c)
458247d1f21SRichard Henderson {
459247d1f21SRichard Henderson     return c == float_class_qnan;
460247d1f21SRichard Henderson }
461247d1f21SRichard Henderson 
462a90119b5SAlex Bennée /*
4630018b1f4SRichard Henderson  * Structure holding all of the decomposed parts of a float.
4640018b1f4SRichard Henderson  * The exponent is unbiased and the fraction is normalized.
465a90119b5SAlex Bennée  *
4660018b1f4SRichard Henderson  * The fraction words are stored in big-endian word ordering,
4670018b1f4SRichard Henderson  * so that truncation from a larger format to a smaller format
4680018b1f4SRichard Henderson  * can be done simply by ignoring subsequent elements.
469a90119b5SAlex Bennée  */
470a90119b5SAlex Bennée 
471a90119b5SAlex Bennée typedef struct {
472a90119b5SAlex Bennée     FloatClass cls;
473a90119b5SAlex Bennée     bool sign;
4744109b9eaSRichard Henderson     int32_t exp;
4754109b9eaSRichard Henderson     union {
4764109b9eaSRichard Henderson         /* Routines that know the structure may reference the singular name. */
4774109b9eaSRichard Henderson         uint64_t frac;
4784109b9eaSRichard Henderson         /*
4794109b9eaSRichard Henderson          * Routines expanded with multiple structures reference "hi" and "lo"
4804109b9eaSRichard Henderson          * depending on the operation.  In FloatParts64, "hi" and "lo" are
4814109b9eaSRichard Henderson          * both the same word and aliased here.
4824109b9eaSRichard Henderson          */
4834109b9eaSRichard Henderson         uint64_t frac_hi;
4844109b9eaSRichard Henderson         uint64_t frac_lo;
4854109b9eaSRichard Henderson     };
486f8155c1dSRichard Henderson } FloatParts64;
487a90119b5SAlex Bennée 
4880018b1f4SRichard Henderson typedef struct {
4890018b1f4SRichard Henderson     FloatClass cls;
4900018b1f4SRichard Henderson     bool sign;
4910018b1f4SRichard Henderson     int32_t exp;
4920018b1f4SRichard Henderson     uint64_t frac_hi;
4930018b1f4SRichard Henderson     uint64_t frac_lo;
4940018b1f4SRichard Henderson } FloatParts128;
4950018b1f4SRichard Henderson 
496aca84527SRichard Henderson typedef struct {
497aca84527SRichard Henderson     FloatClass cls;
498aca84527SRichard Henderson     bool sign;
499aca84527SRichard Henderson     int32_t exp;
500aca84527SRichard Henderson     uint64_t frac_hi;
501aca84527SRichard Henderson     uint64_t frac_hm;  /* high-middle */
502aca84527SRichard Henderson     uint64_t frac_lm;  /* low-middle */
503aca84527SRichard Henderson     uint64_t frac_lo;
504aca84527SRichard Henderson } FloatParts256;
505aca84527SRichard Henderson 
5060018b1f4SRichard Henderson /* These apply to the most significant word of each FloatPartsN. */
507e99c4373SRichard Henderson #define DECOMPOSED_BINARY_POINT    63
508a90119b5SAlex Bennée #define DECOMPOSED_IMPLICIT_BIT    (1ull << DECOMPOSED_BINARY_POINT)
509a90119b5SAlex Bennée 
510a90119b5SAlex Bennée /* Structure holding all of the relevant parameters for a format.
511a90119b5SAlex Bennée  *   exp_size: the size of the exponent field
512a90119b5SAlex Bennée  *   exp_bias: the offset applied to the exponent field
513a90119b5SAlex Bennée  *   exp_max: the maximum normalised exponent
514a90119b5SAlex Bennée  *   frac_size: the size of the fraction field
515a90119b5SAlex Bennée  *   frac_shift: shift to normalise the fraction with DECOMPOSED_BINARY_POINT
516a90119b5SAlex Bennée  * The following are computed based the size of fraction
517d6e1f0cdSRichard Henderson  *   round_mask: bits below lsb which must be rounded
518ca3a3d5aSAlex Bennée  * The following optional modifiers are available:
519ca3a3d5aSAlex Bennée  *   arm_althp: handle ARM Alternative Half Precision
520*72246065SRichard Henderson  *   m68k_denormal: explicit integer bit for extended precision may be 1
521a90119b5SAlex Bennée  */
522a90119b5SAlex Bennée typedef struct {
523a90119b5SAlex Bennée     int exp_size;
524a90119b5SAlex Bennée     int exp_bias;
525c40da5c6SLucas Mateus Castro (alqotel)     int exp_re_bias;
526a90119b5SAlex Bennée     int exp_max;
527a90119b5SAlex Bennée     int frac_size;
528a90119b5SAlex Bennée     int frac_shift;
529ca3a3d5aSAlex Bennée     bool arm_althp;
530*72246065SRichard Henderson     bool m68k_denormal;
531d6e1f0cdSRichard Henderson     uint64_t round_mask;
532a90119b5SAlex Bennée } FloatFmt;
533a90119b5SAlex Bennée 
534a90119b5SAlex Bennée /* Expand fields based on the size of exponent and fraction */
535c1b6299bSRichard Henderson #define FLOAT_PARAMS_(E)                                \
536a90119b5SAlex Bennée     .exp_size       = E,                                \
537a90119b5SAlex Bennée     .exp_bias       = ((1 << E) - 1) >> 1,              \
538c40da5c6SLucas Mateus Castro (alqotel)     .exp_re_bias    = (1 << (E - 1)) + (1 << (E - 2)),  \
539c1b6299bSRichard Henderson     .exp_max        = (1 << E) - 1
540d6e1f0cdSRichard Henderson 
541d6e1f0cdSRichard Henderson #define FLOAT_PARAMS(E, F)                              \
542c1b6299bSRichard Henderson     FLOAT_PARAMS_(E),                                   \
543c1b6299bSRichard Henderson     .frac_size      = F,                                \
5440018b1f4SRichard Henderson     .frac_shift     = (-F - 1) & 63,                    \
545d6e1f0cdSRichard Henderson     .round_mask     = (1ull << ((-F - 1) & 63)) - 1
546a90119b5SAlex Bennée 
547a90119b5SAlex Bennée static const FloatFmt float16_params = {
548a90119b5SAlex Bennée     FLOAT_PARAMS(5, 10)
549a90119b5SAlex Bennée };
550a90119b5SAlex Bennée 
5516fed16b2SAlex Bennée static const FloatFmt float16_params_ahp = {
5526fed16b2SAlex Bennée     FLOAT_PARAMS(5, 10),
5536fed16b2SAlex Bennée     .arm_althp = true
5546fed16b2SAlex Bennée };
5556fed16b2SAlex Bennée 
5568282310dSLIU Zhiwei static const FloatFmt bfloat16_params = {
5578282310dSLIU Zhiwei     FLOAT_PARAMS(8, 7)
5588282310dSLIU Zhiwei };
5598282310dSLIU Zhiwei 
560a90119b5SAlex Bennée static const FloatFmt float32_params = {
561a90119b5SAlex Bennée     FLOAT_PARAMS(8, 23)
562a90119b5SAlex Bennée };
563a90119b5SAlex Bennée 
564a90119b5SAlex Bennée static const FloatFmt float64_params = {
565a90119b5SAlex Bennée     FLOAT_PARAMS(11, 52)
566a90119b5SAlex Bennée };
567a90119b5SAlex Bennée 
5680018b1f4SRichard Henderson static const FloatFmt float128_params = {
5690018b1f4SRichard Henderson     FLOAT_PARAMS(15, 112)
5700018b1f4SRichard Henderson };
5710018b1f4SRichard Henderson 
572c1b6299bSRichard Henderson #define FLOATX80_PARAMS(R)              \
573c1b6299bSRichard Henderson     FLOAT_PARAMS_(15),                  \
574c1b6299bSRichard Henderson     .frac_size = R == 64 ? 63 : R,      \
575c1b6299bSRichard Henderson     .frac_shift = 0,                    \
576c1b6299bSRichard Henderson     .round_mask = R == 64 ? -1 : (1ull << ((-R - 1) & 63)) - 1
577c1b6299bSRichard Henderson 
578c1b6299bSRichard Henderson static const FloatFmt floatx80_params[3] = {
579c1b6299bSRichard Henderson     [floatx80_precision_s] = { FLOATX80_PARAMS(23) },
580c1b6299bSRichard Henderson     [floatx80_precision_d] = { FLOATX80_PARAMS(52) },
581*72246065SRichard Henderson     [floatx80_precision_x] = {
582*72246065SRichard Henderson         FLOATX80_PARAMS(64),
583*72246065SRichard Henderson #ifdef TARGET_M68K
584*72246065SRichard Henderson         .m68k_denormal = true,
585*72246065SRichard Henderson #endif
586*72246065SRichard Henderson     },
587c1b6299bSRichard Henderson };
588c1b6299bSRichard Henderson 
5896fff2167SAlex Bennée /* Unpack a float to parts, but do not canonicalize.  */
unpack_raw64(FloatParts64 * r,const FloatFmt * fmt,uint64_t raw)590d8fdd172SRichard Henderson static void unpack_raw64(FloatParts64 *r, const FloatFmt *fmt, uint64_t raw)
5916fff2167SAlex Bennée {
592d8fdd172SRichard Henderson     const int f_size = fmt->frac_size;
593d8fdd172SRichard Henderson     const int e_size = fmt->exp_size;
5946fff2167SAlex Bennée 
595d8fdd172SRichard Henderson     *r = (FloatParts64) {
5966fff2167SAlex Bennée         .cls = float_class_unclassified,
597d8fdd172SRichard Henderson         .sign = extract64(raw, f_size + e_size, 1),
598d8fdd172SRichard Henderson         .exp = extract64(raw, f_size, e_size),
599d8fdd172SRichard Henderson         .frac = extract64(raw, 0, f_size)
6006fff2167SAlex Bennée     };
6016fff2167SAlex Bennée }
6026fff2167SAlex Bennée 
float16_unpack_raw(FloatParts64 * p,float16 f)6031d3daf95SAlex Bennée static void QEMU_FLATTEN float16_unpack_raw(FloatParts64 *p, float16 f)
6046fff2167SAlex Bennée {
6053dddb203SRichard Henderson     unpack_raw64(p, &float16_params, f);
6066fff2167SAlex Bennée }
6076fff2167SAlex Bennée 
bfloat16_unpack_raw(FloatParts64 * p,bfloat16 f)6081d3daf95SAlex Bennée static void QEMU_FLATTEN bfloat16_unpack_raw(FloatParts64 *p, bfloat16 f)
6098282310dSLIU Zhiwei {
6103dddb203SRichard Henderson     unpack_raw64(p, &bfloat16_params, f);
6118282310dSLIU Zhiwei }
6128282310dSLIU Zhiwei 
float32_unpack_raw(FloatParts64 * p,float32 f)6131d3daf95SAlex Bennée static void QEMU_FLATTEN float32_unpack_raw(FloatParts64 *p, float32 f)
6146fff2167SAlex Bennée {
6153dddb203SRichard Henderson     unpack_raw64(p, &float32_params, f);
6166fff2167SAlex Bennée }
6176fff2167SAlex Bennée 
float64_unpack_raw(FloatParts64 * p,float64 f)6181d3daf95SAlex Bennée static void QEMU_FLATTEN float64_unpack_raw(FloatParts64 *p, float64 f)
6196fff2167SAlex Bennée {
6203dddb203SRichard Henderson     unpack_raw64(p, &float64_params, f);
6216fff2167SAlex Bennée }
6226fff2167SAlex Bennée 
floatx80_unpack_raw(FloatParts128 * p,floatx80 f)6231d3daf95SAlex Bennée static void QEMU_FLATTEN floatx80_unpack_raw(FloatParts128 *p, floatx80 f)
624c1b6299bSRichard Henderson {
625c1b6299bSRichard Henderson     *p = (FloatParts128) {
626c1b6299bSRichard Henderson         .cls = float_class_unclassified,
627c1b6299bSRichard Henderson         .sign = extract32(f.high, 15, 1),
628c1b6299bSRichard Henderson         .exp = extract32(f.high, 0, 15),
629c1b6299bSRichard Henderson         .frac_hi = f.low
630c1b6299bSRichard Henderson     };
631c1b6299bSRichard Henderson }
632c1b6299bSRichard Henderson 
float128_unpack_raw(FloatParts128 * p,float128 f)6331d3daf95SAlex Bennée static void QEMU_FLATTEN float128_unpack_raw(FloatParts128 *p, float128 f)
6340018b1f4SRichard Henderson {
6350018b1f4SRichard Henderson     const int f_size = float128_params.frac_size - 64;
6360018b1f4SRichard Henderson     const int e_size = float128_params.exp_size;
6370018b1f4SRichard Henderson 
6380018b1f4SRichard Henderson     *p = (FloatParts128) {
6390018b1f4SRichard Henderson         .cls = float_class_unclassified,
6400018b1f4SRichard Henderson         .sign = extract64(f.high, f_size + e_size, 1),
6410018b1f4SRichard Henderson         .exp = extract64(f.high, f_size, e_size),
6420018b1f4SRichard Henderson         .frac_hi = extract64(f.high, 0, f_size),
6430018b1f4SRichard Henderson         .frac_lo = f.low,
6440018b1f4SRichard Henderson     };
6450018b1f4SRichard Henderson }
6460018b1f4SRichard Henderson 
6476fff2167SAlex Bennée /* Pack a float from parts, but do not canonicalize.  */
pack_raw64(const FloatParts64 * p,const FloatFmt * fmt)6489e4af58cSRichard Henderson static uint64_t pack_raw64(const FloatParts64 *p, const FloatFmt *fmt)
6496fff2167SAlex Bennée {
6509e4af58cSRichard Henderson     const int f_size = fmt->frac_size;
6519e4af58cSRichard Henderson     const int e_size = fmt->exp_size;
6529e4af58cSRichard Henderson     uint64_t ret;
6539e4af58cSRichard Henderson 
6549e4af58cSRichard Henderson     ret = (uint64_t)p->sign << (f_size + e_size);
6559e4af58cSRichard Henderson     ret = deposit64(ret, f_size, e_size, p->exp);
6569e4af58cSRichard Henderson     ret = deposit64(ret, 0, f_size, p->frac);
6579e4af58cSRichard Henderson     return ret;
6586fff2167SAlex Bennée }
6596fff2167SAlex Bennée 
float16_pack_raw(const FloatParts64 * p)6601d3daf95SAlex Bennée static float16 QEMU_FLATTEN float16_pack_raw(const FloatParts64 *p)
6616fff2167SAlex Bennée {
66271fd178eSRichard Henderson     return make_float16(pack_raw64(p, &float16_params));
6636fff2167SAlex Bennée }
6646fff2167SAlex Bennée 
bfloat16_pack_raw(const FloatParts64 * p)6651d3daf95SAlex Bennée static bfloat16 QEMU_FLATTEN bfloat16_pack_raw(const FloatParts64 *p)
6668282310dSLIU Zhiwei {
66771fd178eSRichard Henderson     return pack_raw64(p, &bfloat16_params);
6688282310dSLIU Zhiwei }
6698282310dSLIU Zhiwei 
float32_pack_raw(const FloatParts64 * p)6701d3daf95SAlex Bennée static float32 QEMU_FLATTEN float32_pack_raw(const FloatParts64 *p)
6716fff2167SAlex Bennée {
67271fd178eSRichard Henderson     return make_float32(pack_raw64(p, &float32_params));
6736fff2167SAlex Bennée }
6746fff2167SAlex Bennée 
float64_pack_raw(const FloatParts64 * p)6751d3daf95SAlex Bennée static float64 QEMU_FLATTEN float64_pack_raw(const FloatParts64 *p)
6766fff2167SAlex Bennée {
67771fd178eSRichard Henderson     return make_float64(pack_raw64(p, &float64_params));
6786fff2167SAlex Bennée }
6796fff2167SAlex Bennée 
float128_pack_raw(const FloatParts128 * p)6801d3daf95SAlex Bennée static float128 QEMU_FLATTEN float128_pack_raw(const FloatParts128 *p)
6810018b1f4SRichard Henderson {
6820018b1f4SRichard Henderson     const int f_size = float128_params.frac_size - 64;
6830018b1f4SRichard Henderson     const int e_size = float128_params.exp_size;
6840018b1f4SRichard Henderson     uint64_t hi;
6850018b1f4SRichard Henderson 
6860018b1f4SRichard Henderson     hi = (uint64_t)p->sign << (f_size + e_size);
6870018b1f4SRichard Henderson     hi = deposit64(hi, f_size, e_size, p->exp);
6880018b1f4SRichard Henderson     hi = deposit64(hi, 0, f_size, p->frac_hi);
6890018b1f4SRichard Henderson     return make_float128(hi, p->frac_lo);
6900018b1f4SRichard Henderson }
6910018b1f4SRichard Henderson 
6920664335aSRichard Henderson /*----------------------------------------------------------------------------
6930664335aSRichard Henderson | Functions and definitions to determine:  (1) whether tininess for underflow
6940664335aSRichard Henderson | is detected before or after rounding by default, (2) what (if anything)
6950664335aSRichard Henderson | happens when exceptions are raised, (3) how signaling NaNs are distinguished
6960664335aSRichard Henderson | from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
6970664335aSRichard Henderson | are propagated from function inputs to output.  These details are target-
6980664335aSRichard Henderson | specific.
6990664335aSRichard Henderson *----------------------------------------------------------------------------*/
700139c1837SPaolo Bonzini #include "softfloat-specialize.c.inc"
7010664335aSRichard Henderson 
7020018b1f4SRichard Henderson #define PARTS_GENERIC_64_128(NAME, P) \
7036c06aca0SRichard Henderson     _Generic((P), FloatParts64 *: parts64_##NAME, \
7046c06aca0SRichard Henderson                   FloatParts128 *: parts128_##NAME)
7050018b1f4SRichard Henderson 
706dedd123cSRichard Henderson #define PARTS_GENERIC_64_128_256(NAME, P) \
7076c06aca0SRichard Henderson     _Generic((P), FloatParts64 *: parts64_##NAME, \
7086c06aca0SRichard Henderson                   FloatParts128 *: parts128_##NAME, \
7096c06aca0SRichard Henderson                   FloatParts256 *: parts256_##NAME)
710dedd123cSRichard Henderson 
711e9034ea8SRichard Henderson #define parts_default_nan(P, S)    PARTS_GENERIC_64_128(default_nan, P)(P, S)
7120018b1f4SRichard Henderson #define parts_silence_nan(P, S)    PARTS_GENERIC_64_128(silence_nan, P)(P, S)
7130018b1f4SRichard Henderson 
7147c45bad8SRichard Henderson static void parts64_return_nan(FloatParts64 *a, float_status *s);
7157c45bad8SRichard Henderson static void parts128_return_nan(FloatParts128 *a, float_status *s);
7167c45bad8SRichard Henderson 
7177c45bad8SRichard Henderson #define parts_return_nan(P, S)     PARTS_GENERIC_64_128(return_nan, P)(P, S)
7180018b1f4SRichard Henderson 
71922c355f4SRichard Henderson static FloatParts64 *parts64_pick_nan(FloatParts64 *a, FloatParts64 *b,
72022c355f4SRichard Henderson                                       float_status *s);
72122c355f4SRichard Henderson static FloatParts128 *parts128_pick_nan(FloatParts128 *a, FloatParts128 *b,
72222c355f4SRichard Henderson                                         float_status *s);
72322c355f4SRichard Henderson 
72422c355f4SRichard Henderson #define parts_pick_nan(A, B, S)    PARTS_GENERIC_64_128(pick_nan, A)(A, B, S)
72522c355f4SRichard Henderson 
726979582d0SRichard Henderson static FloatParts64 *parts64_pick_nan_muladd(FloatParts64 *a, FloatParts64 *b,
727979582d0SRichard Henderson                                              FloatParts64 *c, float_status *s,
728979582d0SRichard Henderson                                              int ab_mask, int abc_mask);
729979582d0SRichard Henderson static FloatParts128 *parts128_pick_nan_muladd(FloatParts128 *a,
730979582d0SRichard Henderson                                                FloatParts128 *b,
731979582d0SRichard Henderson                                                FloatParts128 *c,
732979582d0SRichard Henderson                                                float_status *s,
733979582d0SRichard Henderson                                                int ab_mask, int abc_mask);
734979582d0SRichard Henderson 
735979582d0SRichard Henderson #define parts_pick_nan_muladd(A, B, C, S, ABM, ABCM) \
736979582d0SRichard Henderson     PARTS_GENERIC_64_128(pick_nan_muladd, A)(A, B, C, S, ABM, ABCM)
737979582d0SRichard Henderson 
738d46975bcSRichard Henderson static void parts64_canonicalize(FloatParts64 *p, float_status *status,
739d46975bcSRichard Henderson                                  const FloatFmt *fmt);
740d46975bcSRichard Henderson static void parts128_canonicalize(FloatParts128 *p, float_status *status,
741d46975bcSRichard Henderson                                   const FloatFmt *fmt);
742d46975bcSRichard Henderson 
743d46975bcSRichard Henderson #define parts_canonicalize(A, S, F) \
744d46975bcSRichard Henderson     PARTS_GENERIC_64_128(canonicalize, A)(A, S, F)
745d46975bcSRichard Henderson 
74625fdedf0SRichard Henderson static void parts64_uncanon_normal(FloatParts64 *p, float_status *status,
74725fdedf0SRichard Henderson                                    const FloatFmt *fmt);
74825fdedf0SRichard Henderson static void parts128_uncanon_normal(FloatParts128 *p, float_status *status,
74925fdedf0SRichard Henderson                                     const FloatFmt *fmt);
75025fdedf0SRichard Henderson 
75125fdedf0SRichard Henderson #define parts_uncanon_normal(A, S, F) \
75225fdedf0SRichard Henderson     PARTS_GENERIC_64_128(uncanon_normal, A)(A, S, F)
75325fdedf0SRichard Henderson 
754ee6959f2SRichard Henderson static void parts64_uncanon(FloatParts64 *p, float_status *status,
755ee6959f2SRichard Henderson                             const FloatFmt *fmt);
756ee6959f2SRichard Henderson static void parts128_uncanon(FloatParts128 *p, float_status *status,
757ee6959f2SRichard Henderson                              const FloatFmt *fmt);
758ee6959f2SRichard Henderson 
759ee6959f2SRichard Henderson #define parts_uncanon(A, S, F) \
760ee6959f2SRichard Henderson     PARTS_GENERIC_64_128(uncanon, A)(A, S, F)
761ee6959f2SRichard Henderson 
762da10a907SRichard Henderson static void parts64_add_normal(FloatParts64 *a, FloatParts64 *b);
763da10a907SRichard Henderson static void parts128_add_normal(FloatParts128 *a, FloatParts128 *b);
764dedd123cSRichard Henderson static void parts256_add_normal(FloatParts256 *a, FloatParts256 *b);
765da10a907SRichard Henderson 
766da10a907SRichard Henderson #define parts_add_normal(A, B) \
767dedd123cSRichard Henderson     PARTS_GENERIC_64_128_256(add_normal, A)(A, B)
768da10a907SRichard Henderson 
769da10a907SRichard Henderson static bool parts64_sub_normal(FloatParts64 *a, FloatParts64 *b);
770da10a907SRichard Henderson static bool parts128_sub_normal(FloatParts128 *a, FloatParts128 *b);
771dedd123cSRichard Henderson static bool parts256_sub_normal(FloatParts256 *a, FloatParts256 *b);
772da10a907SRichard Henderson 
773da10a907SRichard Henderson #define parts_sub_normal(A, B) \
774dedd123cSRichard Henderson     PARTS_GENERIC_64_128_256(sub_normal, A)(A, B)
775da10a907SRichard Henderson 
776da10a907SRichard Henderson static FloatParts64 *parts64_addsub(FloatParts64 *a, FloatParts64 *b,
777da10a907SRichard Henderson                                     float_status *s, bool subtract);
778da10a907SRichard Henderson static FloatParts128 *parts128_addsub(FloatParts128 *a, FloatParts128 *b,
779da10a907SRichard Henderson                                       float_status *s, bool subtract);
780da10a907SRichard Henderson 
781da10a907SRichard Henderson #define parts_addsub(A, B, S, Z) \
782da10a907SRichard Henderson     PARTS_GENERIC_64_128(addsub, A)(A, B, S, Z)
783da10a907SRichard Henderson 
784aca84527SRichard Henderson static FloatParts64 *parts64_mul(FloatParts64 *a, FloatParts64 *b,
785aca84527SRichard Henderson                                  float_status *s);
786aca84527SRichard Henderson static FloatParts128 *parts128_mul(FloatParts128 *a, FloatParts128 *b,
787aca84527SRichard Henderson                                    float_status *s);
788aca84527SRichard Henderson 
789aca84527SRichard Henderson #define parts_mul(A, B, S) \
790aca84527SRichard Henderson     PARTS_GENERIC_64_128(mul, A)(A, B, S)
791aca84527SRichard Henderson 
792dedd123cSRichard Henderson static FloatParts64 *parts64_muladd(FloatParts64 *a, FloatParts64 *b,
793dedd123cSRichard Henderson                                     FloatParts64 *c, int flags,
794dedd123cSRichard Henderson                                     float_status *s);
795dedd123cSRichard Henderson static FloatParts128 *parts128_muladd(FloatParts128 *a, FloatParts128 *b,
796dedd123cSRichard Henderson                                       FloatParts128 *c, int flags,
797dedd123cSRichard Henderson                                       float_status *s);
798dedd123cSRichard Henderson 
799dedd123cSRichard Henderson #define parts_muladd(A, B, C, Z, S) \
800dedd123cSRichard Henderson     PARTS_GENERIC_64_128(muladd, A)(A, B, C, Z, S)
801dedd123cSRichard Henderson 
802ec961b81SRichard Henderson static FloatParts64 *parts64_div(FloatParts64 *a, FloatParts64 *b,
803ec961b81SRichard Henderson                                  float_status *s);
804ec961b81SRichard Henderson static FloatParts128 *parts128_div(FloatParts128 *a, FloatParts128 *b,
805ec961b81SRichard Henderson                                    float_status *s);
806ec961b81SRichard Henderson 
807ec961b81SRichard Henderson #define parts_div(A, B, S) \
808ec961b81SRichard Henderson     PARTS_GENERIC_64_128(div, A)(A, B, S)
809ec961b81SRichard Henderson 
810feaf2e9cSRichard Henderson static FloatParts64 *parts64_modrem(FloatParts64 *a, FloatParts64 *b,
811feaf2e9cSRichard Henderson                                     uint64_t *mod_quot, float_status *s);
812feaf2e9cSRichard Henderson static FloatParts128 *parts128_modrem(FloatParts128 *a, FloatParts128 *b,
813feaf2e9cSRichard Henderson                                       uint64_t *mod_quot, float_status *s);
814feaf2e9cSRichard Henderson 
815feaf2e9cSRichard Henderson #define parts_modrem(A, B, Q, S) \
816feaf2e9cSRichard Henderson     PARTS_GENERIC_64_128(modrem, A)(A, B, Q, S)
817feaf2e9cSRichard Henderson 
8189261b245SRichard Henderson static void parts64_sqrt(FloatParts64 *a, float_status *s, const FloatFmt *f);
8199261b245SRichard Henderson static void parts128_sqrt(FloatParts128 *a, float_status *s, const FloatFmt *f);
8209261b245SRichard Henderson 
8219261b245SRichard Henderson #define parts_sqrt(A, S, F) \
8229261b245SRichard Henderson     PARTS_GENERIC_64_128(sqrt, A)(A, S, F)
8239261b245SRichard Henderson 
824afc34931SRichard Henderson static bool parts64_round_to_int_normal(FloatParts64 *a, FloatRoundMode rm,
825afc34931SRichard Henderson                                         int scale, int frac_size);
826afc34931SRichard Henderson static bool parts128_round_to_int_normal(FloatParts128 *a, FloatRoundMode r,
827afc34931SRichard Henderson                                          int scale, int frac_size);
828afc34931SRichard Henderson 
829afc34931SRichard Henderson #define parts_round_to_int_normal(A, R, C, F) \
830afc34931SRichard Henderson     PARTS_GENERIC_64_128(round_to_int_normal, A)(A, R, C, F)
831afc34931SRichard Henderson 
832afc34931SRichard Henderson static void parts64_round_to_int(FloatParts64 *a, FloatRoundMode rm,
833afc34931SRichard Henderson                                  int scale, float_status *s,
834afc34931SRichard Henderson                                  const FloatFmt *fmt);
835afc34931SRichard Henderson static void parts128_round_to_int(FloatParts128 *a, FloatRoundMode r,
836afc34931SRichard Henderson                                   int scale, float_status *s,
837afc34931SRichard Henderson                                   const FloatFmt *fmt);
838afc34931SRichard Henderson 
839afc34931SRichard Henderson #define parts_round_to_int(A, R, C, S, F) \
840afc34931SRichard Henderson     PARTS_GENERIC_64_128(round_to_int, A)(A, R, C, S, F)
841afc34931SRichard Henderson 
842463b3f0dSRichard Henderson static int64_t parts64_float_to_sint(FloatParts64 *p, FloatRoundMode rmode,
843463b3f0dSRichard Henderson                                      int scale, int64_t min, int64_t max,
844463b3f0dSRichard Henderson                                      float_status *s);
845463b3f0dSRichard Henderson static int64_t parts128_float_to_sint(FloatParts128 *p, FloatRoundMode rmode,
846463b3f0dSRichard Henderson                                      int scale, int64_t min, int64_t max,
847463b3f0dSRichard Henderson                                      float_status *s);
848463b3f0dSRichard Henderson 
849463b3f0dSRichard Henderson #define parts_float_to_sint(P, R, Z, MN, MX, S) \
850463b3f0dSRichard Henderson     PARTS_GENERIC_64_128(float_to_sint, P)(P, R, Z, MN, MX, S)
851463b3f0dSRichard Henderson 
8524ab4aef0SRichard Henderson static uint64_t parts64_float_to_uint(FloatParts64 *p, FloatRoundMode rmode,
8534ab4aef0SRichard Henderson                                       int scale, uint64_t max,
8544ab4aef0SRichard Henderson                                       float_status *s);
8554ab4aef0SRichard Henderson static uint64_t parts128_float_to_uint(FloatParts128 *p, FloatRoundMode rmode,
8564ab4aef0SRichard Henderson                                        int scale, uint64_t max,
8574ab4aef0SRichard Henderson                                        float_status *s);
8584ab4aef0SRichard Henderson 
8594ab4aef0SRichard Henderson #define parts_float_to_uint(P, R, Z, M, S) \
8604ab4aef0SRichard Henderson     PARTS_GENERIC_64_128(float_to_uint, P)(P, R, Z, M, S)
8614ab4aef0SRichard Henderson 
862e2041f4dSRichard Henderson static int64_t parts64_float_to_sint_modulo(FloatParts64 *p,
863e2041f4dSRichard Henderson                                             FloatRoundMode rmode,
864e2041f4dSRichard Henderson                                             int bitsm1, float_status *s);
865e2041f4dSRichard Henderson static int64_t parts128_float_to_sint_modulo(FloatParts128 *p,
866e2041f4dSRichard Henderson                                              FloatRoundMode rmode,
867e2041f4dSRichard Henderson                                              int bitsm1, float_status *s);
868e2041f4dSRichard Henderson 
869e2041f4dSRichard Henderson #define parts_float_to_sint_modulo(P, R, M, S) \
870e2041f4dSRichard Henderson     PARTS_GENERIC_64_128(float_to_sint_modulo, P)(P, R, M, S)
871e2041f4dSRichard Henderson 
872e3689519SRichard Henderson static void parts64_sint_to_float(FloatParts64 *p, int64_t a,
873e3689519SRichard Henderson                                   int scale, float_status *s);
874e3689519SRichard Henderson static void parts128_sint_to_float(FloatParts128 *p, int64_t a,
875e3689519SRichard Henderson                                    int scale, float_status *s);
876e3689519SRichard Henderson 
877e2041f4dSRichard Henderson #define parts_float_to_sint(P, R, Z, MN, MX, S) \
878e2041f4dSRichard Henderson     PARTS_GENERIC_64_128(float_to_sint, P)(P, R, Z, MN, MX, S)
879e2041f4dSRichard Henderson 
880e3689519SRichard Henderson #define parts_sint_to_float(P, I, Z, S) \
881e3689519SRichard Henderson     PARTS_GENERIC_64_128(sint_to_float, P)(P, I, Z, S)
882e3689519SRichard Henderson 
88337c954a1SRichard Henderson static void parts64_uint_to_float(FloatParts64 *p, uint64_t a,
88437c954a1SRichard Henderson                                   int scale, float_status *s);
88537c954a1SRichard Henderson static void parts128_uint_to_float(FloatParts128 *p, uint64_t a,
88637c954a1SRichard Henderson                                    int scale, float_status *s);
88737c954a1SRichard Henderson 
88837c954a1SRichard Henderson #define parts_uint_to_float(P, I, Z, S) \
88937c954a1SRichard Henderson     PARTS_GENERIC_64_128(uint_to_float, P)(P, I, Z, S)
89037c954a1SRichard Henderson 
891e1c4667aSRichard Henderson static FloatParts64 *parts64_minmax(FloatParts64 *a, FloatParts64 *b,
892e1c4667aSRichard Henderson                                     float_status *s, int flags);
893e1c4667aSRichard Henderson static FloatParts128 *parts128_minmax(FloatParts128 *a, FloatParts128 *b,
894e1c4667aSRichard Henderson                                       float_status *s, int flags);
895e1c4667aSRichard Henderson 
896e1c4667aSRichard Henderson #define parts_minmax(A, B, S, F) \
897e1c4667aSRichard Henderson     PARTS_GENERIC_64_128(minmax, A)(A, B, S, F)
898e1c4667aSRichard Henderson 
899b880867fSRichard Henderson static FloatRelation parts64_compare(FloatParts64 *a, FloatParts64 *b,
9006eb169b8SRichard Henderson                                      float_status *s, bool q);
901b880867fSRichard Henderson static FloatRelation parts128_compare(FloatParts128 *a, FloatParts128 *b,
9026eb169b8SRichard Henderson                                       float_status *s, bool q);
9036eb169b8SRichard Henderson 
9046eb169b8SRichard Henderson #define parts_compare(A, B, S, Q) \
9056eb169b8SRichard Henderson     PARTS_GENERIC_64_128(compare, A)(A, B, S, Q)
9066eb169b8SRichard Henderson 
90739626b0cSRichard Henderson static void parts64_scalbn(FloatParts64 *a, int n, float_status *s);
90839626b0cSRichard Henderson static void parts128_scalbn(FloatParts128 *a, int n, float_status *s);
90939626b0cSRichard Henderson 
91039626b0cSRichard Henderson #define parts_scalbn(A, N, S) \
91139626b0cSRichard Henderson     PARTS_GENERIC_64_128(scalbn, A)(A, N, S)
91239626b0cSRichard Henderson 
9132fa3546cSRichard Henderson static void parts64_log2(FloatParts64 *a, float_status *s, const FloatFmt *f);
9142fa3546cSRichard Henderson static void parts128_log2(FloatParts128 *a, float_status *s, const FloatFmt *f);
9152fa3546cSRichard Henderson 
9162fa3546cSRichard Henderson #define parts_log2(A, S, F) \
9172fa3546cSRichard Henderson     PARTS_GENERIC_64_128(log2, A)(A, S, F)
9182fa3546cSRichard Henderson 
9190018b1f4SRichard Henderson /*
9200018b1f4SRichard Henderson  * Helper functions for softfloat-parts.c.inc, per-size operations.
9210018b1f4SRichard Henderson  */
9220018b1f4SRichard Henderson 
92322c355f4SRichard Henderson #define FRAC_GENERIC_64_128(NAME, P) \
9246c06aca0SRichard Henderson     _Generic((P), FloatParts64 *: frac64_##NAME, \
9256c06aca0SRichard Henderson                   FloatParts128 *: frac128_##NAME)
92622c355f4SRichard Henderson 
927dedd123cSRichard Henderson #define FRAC_GENERIC_64_128_256(NAME, P) \
9286c06aca0SRichard Henderson     _Generic((P), FloatParts64 *: frac64_##NAME, \
9296c06aca0SRichard Henderson                   FloatParts128 *: frac128_##NAME, \
9306c06aca0SRichard Henderson                   FloatParts256 *: frac256_##NAME)
931dedd123cSRichard Henderson 
frac64_add(FloatParts64 * r,FloatParts64 * a,FloatParts64 * b)932da10a907SRichard Henderson static bool frac64_add(FloatParts64 *r, FloatParts64 *a, FloatParts64 *b)
933da10a907SRichard Henderson {
934da10a907SRichard Henderson     return uadd64_overflow(a->frac, b->frac, &r->frac);
935da10a907SRichard Henderson }
936da10a907SRichard Henderson 
frac128_add(FloatParts128 * r,FloatParts128 * a,FloatParts128 * b)937da10a907SRichard Henderson static bool frac128_add(FloatParts128 *r, FloatParts128 *a, FloatParts128 *b)
938da10a907SRichard Henderson {
939da10a907SRichard Henderson     bool c = 0;
940da10a907SRichard Henderson     r->frac_lo = uadd64_carry(a->frac_lo, b->frac_lo, &c);
941da10a907SRichard Henderson     r->frac_hi = uadd64_carry(a->frac_hi, b->frac_hi, &c);
942da10a907SRichard Henderson     return c;
943da10a907SRichard Henderson }
944da10a907SRichard Henderson 
frac256_add(FloatParts256 * r,FloatParts256 * a,FloatParts256 * b)945dedd123cSRichard Henderson static bool frac256_add(FloatParts256 *r, FloatParts256 *a, FloatParts256 *b)
946dedd123cSRichard Henderson {
947dedd123cSRichard Henderson     bool c = 0;
948dedd123cSRichard Henderson     r->frac_lo = uadd64_carry(a->frac_lo, b->frac_lo, &c);
949dedd123cSRichard Henderson     r->frac_lm = uadd64_carry(a->frac_lm, b->frac_lm, &c);
950dedd123cSRichard Henderson     r->frac_hm = uadd64_carry(a->frac_hm, b->frac_hm, &c);
951dedd123cSRichard Henderson     r->frac_hi = uadd64_carry(a->frac_hi, b->frac_hi, &c);
952dedd123cSRichard Henderson     return c;
953dedd123cSRichard Henderson }
954dedd123cSRichard Henderson 
955dedd123cSRichard Henderson #define frac_add(R, A, B)  FRAC_GENERIC_64_128_256(add, R)(R, A, B)
956da10a907SRichard Henderson 
frac64_addi(FloatParts64 * r,FloatParts64 * a,uint64_t c)957ee6959f2SRichard Henderson static bool frac64_addi(FloatParts64 *r, FloatParts64 *a, uint64_t c)
958ee6959f2SRichard Henderson {
959ee6959f2SRichard Henderson     return uadd64_overflow(a->frac, c, &r->frac);
960ee6959f2SRichard Henderson }
961ee6959f2SRichard Henderson 
frac128_addi(FloatParts128 * r,FloatParts128 * a,uint64_t c)962ee6959f2SRichard Henderson static bool frac128_addi(FloatParts128 *r, FloatParts128 *a, uint64_t c)
963ee6959f2SRichard Henderson {
964ee6959f2SRichard Henderson     c = uadd64_overflow(a->frac_lo, c, &r->frac_lo);
965ee6959f2SRichard Henderson     return uadd64_overflow(a->frac_hi, c, &r->frac_hi);
966ee6959f2SRichard Henderson }
967ee6959f2SRichard Henderson 
968ee6959f2SRichard Henderson #define frac_addi(R, A, C)  FRAC_GENERIC_64_128(addi, R)(R, A, C)
969ee6959f2SRichard Henderson 
frac64_allones(FloatParts64 * a)970ee6959f2SRichard Henderson static void frac64_allones(FloatParts64 *a)
971ee6959f2SRichard Henderson {
972ee6959f2SRichard Henderson     a->frac = -1;
973ee6959f2SRichard Henderson }
974ee6959f2SRichard Henderson 
frac128_allones(FloatParts128 * a)975ee6959f2SRichard Henderson static void frac128_allones(FloatParts128 *a)
976ee6959f2SRichard Henderson {
977ee6959f2SRichard Henderson     a->frac_hi = a->frac_lo = -1;
978ee6959f2SRichard Henderson }
979ee6959f2SRichard Henderson 
980ee6959f2SRichard Henderson #define frac_allones(A)  FRAC_GENERIC_64_128(allones, A)(A)
981ee6959f2SRichard Henderson 
frac64_cmp(FloatParts64 * a,FloatParts64 * b)982dee3fcfbSRichard Henderson static FloatRelation frac64_cmp(FloatParts64 *a, FloatParts64 *b)
98322c355f4SRichard Henderson {
984dee3fcfbSRichard Henderson     return (a->frac == b->frac ? float_relation_equal
985dee3fcfbSRichard Henderson             : a->frac < b->frac ? float_relation_less
986dee3fcfbSRichard Henderson             : float_relation_greater);
98722c355f4SRichard Henderson }
98822c355f4SRichard Henderson 
frac128_cmp(FloatParts128 * a,FloatParts128 * b)989dee3fcfbSRichard Henderson static FloatRelation frac128_cmp(FloatParts128 *a, FloatParts128 *b)
99022c355f4SRichard Henderson {
99122c355f4SRichard Henderson     uint64_t ta = a->frac_hi, tb = b->frac_hi;
99222c355f4SRichard Henderson     if (ta == tb) {
99322c355f4SRichard Henderson         ta = a->frac_lo, tb = b->frac_lo;
99422c355f4SRichard Henderson         if (ta == tb) {
995dee3fcfbSRichard Henderson             return float_relation_equal;
99622c355f4SRichard Henderson         }
99722c355f4SRichard Henderson     }
998dee3fcfbSRichard Henderson     return ta < tb ? float_relation_less : float_relation_greater;
99922c355f4SRichard Henderson }
100022c355f4SRichard Henderson 
100122c355f4SRichard Henderson #define frac_cmp(A, B)  FRAC_GENERIC_64_128(cmp, A)(A, B)
100222c355f4SRichard Henderson 
frac64_clear(FloatParts64 * a)1003d46975bcSRichard Henderson static void frac64_clear(FloatParts64 *a)
1004d46975bcSRichard Henderson {
1005d46975bcSRichard Henderson     a->frac = 0;
1006d46975bcSRichard Henderson }
1007d46975bcSRichard Henderson 
frac128_clear(FloatParts128 * a)1008d46975bcSRichard Henderson static void frac128_clear(FloatParts128 *a)
1009d46975bcSRichard Henderson {
1010d46975bcSRichard Henderson     a->frac_hi = a->frac_lo = 0;
1011d46975bcSRichard Henderson }
1012d46975bcSRichard Henderson 
1013d46975bcSRichard Henderson #define frac_clear(A)  FRAC_GENERIC_64_128(clear, A)(A)
1014d46975bcSRichard Henderson 
frac64_div(FloatParts64 * a,FloatParts64 * b)1015ec961b81SRichard Henderson static bool frac64_div(FloatParts64 *a, FloatParts64 *b)
1016ec961b81SRichard Henderson {
1017ec961b81SRichard Henderson     uint64_t n1, n0, r, q;
1018ec961b81SRichard Henderson     bool ret;
1019ec961b81SRichard Henderson 
1020ec961b81SRichard Henderson     /*
1021ec961b81SRichard Henderson      * We want a 2*N / N-bit division to produce exactly an N-bit
1022ec961b81SRichard Henderson      * result, so that we do not lose any precision and so that we
1023ec961b81SRichard Henderson      * do not have to renormalize afterward.  If A.frac < B.frac,
1024ec961b81SRichard Henderson      * then division would produce an (N-1)-bit result; shift A left
1025ec961b81SRichard Henderson      * by one to produce the an N-bit result, and return true to
1026ec961b81SRichard Henderson      * decrement the exponent to match.
1027ec961b81SRichard Henderson      *
1028ec961b81SRichard Henderson      * The udiv_qrnnd algorithm that we're using requires normalization,
1029ec961b81SRichard Henderson      * i.e. the msb of the denominator must be set, which is already true.
1030ec961b81SRichard Henderson      */
1031ec961b81SRichard Henderson     ret = a->frac < b->frac;
1032ec961b81SRichard Henderson     if (ret) {
1033ec961b81SRichard Henderson         n0 = a->frac;
1034ec961b81SRichard Henderson         n1 = 0;
1035ec961b81SRichard Henderson     } else {
1036ec961b81SRichard Henderson         n0 = a->frac >> 1;
1037ec961b81SRichard Henderson         n1 = a->frac << 63;
1038ec961b81SRichard Henderson     }
1039ec961b81SRichard Henderson     q = udiv_qrnnd(&r, n0, n1, b->frac);
1040ec961b81SRichard Henderson 
1041ec961b81SRichard Henderson     /* Set lsb if there is a remainder, to set inexact. */
1042ec961b81SRichard Henderson     a->frac = q | (r != 0);
1043ec961b81SRichard Henderson 
1044ec961b81SRichard Henderson     return ret;
1045ec961b81SRichard Henderson }
1046ec961b81SRichard Henderson 
frac128_div(FloatParts128 * a,FloatParts128 * b)1047ec961b81SRichard Henderson static bool frac128_div(FloatParts128 *a, FloatParts128 *b)
1048ec961b81SRichard Henderson {
1049ec961b81SRichard Henderson     uint64_t q0, q1, a0, a1, b0, b1;
1050ec961b81SRichard Henderson     uint64_t r0, r1, r2, r3, t0, t1, t2, t3;
1051ec961b81SRichard Henderson     bool ret = false;
1052ec961b81SRichard Henderson 
1053ec961b81SRichard Henderson     a0 = a->frac_hi, a1 = a->frac_lo;
1054ec961b81SRichard Henderson     b0 = b->frac_hi, b1 = b->frac_lo;
1055ec961b81SRichard Henderson 
1056ec961b81SRichard Henderson     ret = lt128(a0, a1, b0, b1);
1057ec961b81SRichard Henderson     if (!ret) {
1058ec961b81SRichard Henderson         a1 = shr_double(a0, a1, 1);
1059ec961b81SRichard Henderson         a0 = a0 >> 1;
1060ec961b81SRichard Henderson     }
1061ec961b81SRichard Henderson 
1062ec961b81SRichard Henderson     /* Use 128/64 -> 64 division as estimate for 192/128 -> 128 division. */
1063ec961b81SRichard Henderson     q0 = estimateDiv128To64(a0, a1, b0);
1064ec961b81SRichard Henderson 
1065ec961b81SRichard Henderson     /*
1066ec961b81SRichard Henderson      * Estimate is high because B1 was not included (unless B1 == 0).
1067ec961b81SRichard Henderson      * Reduce quotient and increase remainder until remainder is non-negative.
1068ec961b81SRichard Henderson      * This loop will execute 0 to 2 times.
1069ec961b81SRichard Henderson      */
1070ec961b81SRichard Henderson     mul128By64To192(b0, b1, q0, &t0, &t1, &t2);
1071ec961b81SRichard Henderson     sub192(a0, a1, 0, t0, t1, t2, &r0, &r1, &r2);
1072ec961b81SRichard Henderson     while (r0 != 0) {
1073ec961b81SRichard Henderson         q0--;
1074ec961b81SRichard Henderson         add192(r0, r1, r2, 0, b0, b1, &r0, &r1, &r2);
1075ec961b81SRichard Henderson     }
1076ec961b81SRichard Henderson 
1077ec961b81SRichard Henderson     /* Repeat using the remainder, producing a second word of quotient. */
1078ec961b81SRichard Henderson     q1 = estimateDiv128To64(r1, r2, b0);
1079ec961b81SRichard Henderson     mul128By64To192(b0, b1, q1, &t1, &t2, &t3);
1080ec961b81SRichard Henderson     sub192(r1, r2, 0, t1, t2, t3, &r1, &r2, &r3);
1081ec961b81SRichard Henderson     while (r1 != 0) {
1082ec961b81SRichard Henderson         q1--;
1083ec961b81SRichard Henderson         add192(r1, r2, r3, 0, b0, b1, &r1, &r2, &r3);
1084ec961b81SRichard Henderson     }
1085ec961b81SRichard Henderson 
1086ec961b81SRichard Henderson     /* Any remainder indicates inexact; set sticky bit. */
1087ec961b81SRichard Henderson     q1 |= (r2 | r3) != 0;
1088ec961b81SRichard Henderson 
1089ec961b81SRichard Henderson     a->frac_hi = q0;
1090ec961b81SRichard Henderson     a->frac_lo = q1;
1091ec961b81SRichard Henderson     return ret;
1092ec961b81SRichard Henderson }
1093ec961b81SRichard Henderson 
1094ec961b81SRichard Henderson #define frac_div(A, B)  FRAC_GENERIC_64_128(div, A)(A, B)
1095ec961b81SRichard Henderson 
frac64_eqz(FloatParts64 * a)1096d46975bcSRichard Henderson static bool frac64_eqz(FloatParts64 *a)
1097d46975bcSRichard Henderson {
1098d46975bcSRichard Henderson     return a->frac == 0;
1099d46975bcSRichard Henderson }
1100d46975bcSRichard Henderson 
frac128_eqz(FloatParts128 * a)1101d46975bcSRichard Henderson static bool frac128_eqz(FloatParts128 *a)
1102d46975bcSRichard Henderson {
1103d46975bcSRichard Henderson     return (a->frac_hi | a->frac_lo) == 0;
1104d46975bcSRichard Henderson }
1105d46975bcSRichard Henderson 
1106d46975bcSRichard Henderson #define frac_eqz(A)  FRAC_GENERIC_64_128(eqz, A)(A)
1107d46975bcSRichard Henderson 
frac64_mulw(FloatParts128 * r,FloatParts64 * a,FloatParts64 * b)1108aca84527SRichard Henderson static void frac64_mulw(FloatParts128 *r, FloatParts64 *a, FloatParts64 *b)
1109aca84527SRichard Henderson {
1110aca84527SRichard Henderson     mulu64(&r->frac_lo, &r->frac_hi, a->frac, b->frac);
1111aca84527SRichard Henderson }
1112aca84527SRichard Henderson 
frac128_mulw(FloatParts256 * r,FloatParts128 * a,FloatParts128 * b)1113aca84527SRichard Henderson static void frac128_mulw(FloatParts256 *r, FloatParts128 *a, FloatParts128 *b)
1114aca84527SRichard Henderson {
1115aca84527SRichard Henderson     mul128To256(a->frac_hi, a->frac_lo, b->frac_hi, b->frac_lo,
1116aca84527SRichard Henderson                 &r->frac_hi, &r->frac_hm, &r->frac_lm, &r->frac_lo);
1117aca84527SRichard Henderson }
1118aca84527SRichard Henderson 
1119aca84527SRichard Henderson #define frac_mulw(R, A, B)  FRAC_GENERIC_64_128(mulw, A)(R, A, B)
1120aca84527SRichard Henderson 
frac64_neg(FloatParts64 * a)1121da10a907SRichard Henderson static void frac64_neg(FloatParts64 *a)
1122da10a907SRichard Henderson {
1123da10a907SRichard Henderson     a->frac = -a->frac;
1124da10a907SRichard Henderson }
1125da10a907SRichard Henderson 
frac128_neg(FloatParts128 * a)1126da10a907SRichard Henderson static void frac128_neg(FloatParts128 *a)
1127da10a907SRichard Henderson {
1128da10a907SRichard Henderson     bool c = 0;
1129da10a907SRichard Henderson     a->frac_lo = usub64_borrow(0, a->frac_lo, &c);
1130da10a907SRichard Henderson     a->frac_hi = usub64_borrow(0, a->frac_hi, &c);
1131da10a907SRichard Henderson }
1132da10a907SRichard Henderson 
frac256_neg(FloatParts256 * a)1133dedd123cSRichard Henderson static void frac256_neg(FloatParts256 *a)
1134dedd123cSRichard Henderson {
1135dedd123cSRichard Henderson     bool c = 0;
1136dedd123cSRichard Henderson     a->frac_lo = usub64_borrow(0, a->frac_lo, &c);
1137dedd123cSRichard Henderson     a->frac_lm = usub64_borrow(0, a->frac_lm, &c);
1138dedd123cSRichard Henderson     a->frac_hm = usub64_borrow(0, a->frac_hm, &c);
1139dedd123cSRichard Henderson     a->frac_hi = usub64_borrow(0, a->frac_hi, &c);
1140dedd123cSRichard Henderson }
1141dedd123cSRichard Henderson 
1142dedd123cSRichard Henderson #define frac_neg(A)  FRAC_GENERIC_64_128_256(neg, A)(A)
1143da10a907SRichard Henderson 
frac64_normalize(FloatParts64 * a)1144d46975bcSRichard Henderson static int frac64_normalize(FloatParts64 *a)
1145d46975bcSRichard Henderson {
1146d46975bcSRichard Henderson     if (a->frac) {
1147d46975bcSRichard Henderson         int shift = clz64(a->frac);
1148d46975bcSRichard Henderson         a->frac <<= shift;
1149d46975bcSRichard Henderson         return shift;
1150d46975bcSRichard Henderson     }
1151d46975bcSRichard Henderson     return 64;
1152d46975bcSRichard Henderson }
1153d46975bcSRichard Henderson 
frac128_normalize(FloatParts128 * a)1154d46975bcSRichard Henderson static int frac128_normalize(FloatParts128 *a)
1155d46975bcSRichard Henderson {
1156d46975bcSRichard Henderson     if (a->frac_hi) {
1157d46975bcSRichard Henderson         int shl = clz64(a->frac_hi);
1158463e45dcSRichard Henderson         a->frac_hi = shl_double(a->frac_hi, a->frac_lo, shl);
1159463e45dcSRichard Henderson         a->frac_lo <<= shl;
1160d46975bcSRichard Henderson         return shl;
1161d46975bcSRichard Henderson     } else if (a->frac_lo) {
1162d46975bcSRichard Henderson         int shl = clz64(a->frac_lo);
1163463e45dcSRichard Henderson         a->frac_hi = a->frac_lo << shl;
1164d46975bcSRichard Henderson         a->frac_lo = 0;
1165d46975bcSRichard Henderson         return shl + 64;
1166d46975bcSRichard Henderson     }
1167d46975bcSRichard Henderson     return 128;
1168d46975bcSRichard Henderson }
1169d46975bcSRichard Henderson 
frac256_normalize(FloatParts256 * a)1170dedd123cSRichard Henderson static int frac256_normalize(FloatParts256 *a)
1171dedd123cSRichard Henderson {
1172dedd123cSRichard Henderson     uint64_t a0 = a->frac_hi, a1 = a->frac_hm;
1173dedd123cSRichard Henderson     uint64_t a2 = a->frac_lm, a3 = a->frac_lo;
1174463e45dcSRichard Henderson     int ret, shl;
1175dedd123cSRichard Henderson 
1176dedd123cSRichard Henderson     if (likely(a0)) {
1177dedd123cSRichard Henderson         shl = clz64(a0);
1178dedd123cSRichard Henderson         if (shl == 0) {
1179dedd123cSRichard Henderson             return 0;
1180dedd123cSRichard Henderson         }
1181dedd123cSRichard Henderson         ret = shl;
1182dedd123cSRichard Henderson     } else {
1183dedd123cSRichard Henderson         if (a1) {
1184dedd123cSRichard Henderson             ret = 64;
1185dedd123cSRichard Henderson             a0 = a1, a1 = a2, a2 = a3, a3 = 0;
1186dedd123cSRichard Henderson         } else if (a2) {
1187dedd123cSRichard Henderson             ret = 128;
1188dedd123cSRichard Henderson             a0 = a2, a1 = a3, a2 = 0, a3 = 0;
1189dedd123cSRichard Henderson         } else if (a3) {
1190dedd123cSRichard Henderson             ret = 192;
1191dedd123cSRichard Henderson             a0 = a3, a1 = 0, a2 = 0, a3 = 0;
1192dedd123cSRichard Henderson         } else {
1193dedd123cSRichard Henderson             ret = 256;
1194dedd123cSRichard Henderson             a0 = 0, a1 = 0, a2 = 0, a3 = 0;
1195dedd123cSRichard Henderson             goto done;
1196dedd123cSRichard Henderson         }
1197dedd123cSRichard Henderson         shl = clz64(a0);
1198dedd123cSRichard Henderson         if (shl == 0) {
1199dedd123cSRichard Henderson             goto done;
1200dedd123cSRichard Henderson         }
1201dedd123cSRichard Henderson         ret += shl;
1202dedd123cSRichard Henderson     }
1203dedd123cSRichard Henderson 
1204463e45dcSRichard Henderson     a0 = shl_double(a0, a1, shl);
1205463e45dcSRichard Henderson     a1 = shl_double(a1, a2, shl);
1206463e45dcSRichard Henderson     a2 = shl_double(a2, a3, shl);
1207463e45dcSRichard Henderson     a3 <<= shl;
1208dedd123cSRichard Henderson 
1209dedd123cSRichard Henderson  done:
1210dedd123cSRichard Henderson     a->frac_hi = a0;
1211dedd123cSRichard Henderson     a->frac_hm = a1;
1212dedd123cSRichard Henderson     a->frac_lm = a2;
1213dedd123cSRichard Henderson     a->frac_lo = a3;
1214dedd123cSRichard Henderson     return ret;
1215dedd123cSRichard Henderson }
1216dedd123cSRichard Henderson 
1217dedd123cSRichard Henderson #define frac_normalize(A)  FRAC_GENERIC_64_128_256(normalize, A)(A)
1218d46975bcSRichard Henderson 
frac64_modrem(FloatParts64 * a,FloatParts64 * b,uint64_t * mod_quot)1219feaf2e9cSRichard Henderson static void frac64_modrem(FloatParts64 *a, FloatParts64 *b, uint64_t *mod_quot)
1220feaf2e9cSRichard Henderson {
1221feaf2e9cSRichard Henderson     uint64_t a0, a1, b0, t0, t1, q, quot;
1222feaf2e9cSRichard Henderson     int exp_diff = a->exp - b->exp;
1223feaf2e9cSRichard Henderson     int shift;
1224feaf2e9cSRichard Henderson 
1225feaf2e9cSRichard Henderson     a0 = a->frac;
1226feaf2e9cSRichard Henderson     a1 = 0;
1227feaf2e9cSRichard Henderson 
1228feaf2e9cSRichard Henderson     if (exp_diff < -1) {
1229feaf2e9cSRichard Henderson         if (mod_quot) {
1230feaf2e9cSRichard Henderson             *mod_quot = 0;
1231feaf2e9cSRichard Henderson         }
1232feaf2e9cSRichard Henderson         return;
1233feaf2e9cSRichard Henderson     }
1234feaf2e9cSRichard Henderson     if (exp_diff == -1) {
1235feaf2e9cSRichard Henderson         a0 >>= 1;
1236feaf2e9cSRichard Henderson         exp_diff = 0;
1237feaf2e9cSRichard Henderson     }
1238feaf2e9cSRichard Henderson 
1239feaf2e9cSRichard Henderson     b0 = b->frac;
1240feaf2e9cSRichard Henderson     quot = q = b0 <= a0;
1241feaf2e9cSRichard Henderson     if (q) {
1242feaf2e9cSRichard Henderson         a0 -= b0;
1243feaf2e9cSRichard Henderson     }
1244feaf2e9cSRichard Henderson 
1245feaf2e9cSRichard Henderson     exp_diff -= 64;
1246feaf2e9cSRichard Henderson     while (exp_diff > 0) {
1247feaf2e9cSRichard Henderson         q = estimateDiv128To64(a0, a1, b0);
1248feaf2e9cSRichard Henderson         q = q > 2 ? q - 2 : 0;
1249feaf2e9cSRichard Henderson         mul64To128(b0, q, &t0, &t1);
1250feaf2e9cSRichard Henderson         sub128(a0, a1, t0, t1, &a0, &a1);
1251feaf2e9cSRichard Henderson         shortShift128Left(a0, a1, 62, &a0, &a1);
1252feaf2e9cSRichard Henderson         exp_diff -= 62;
1253feaf2e9cSRichard Henderson         quot = (quot << 62) + q;
1254feaf2e9cSRichard Henderson     }
1255feaf2e9cSRichard Henderson 
1256feaf2e9cSRichard Henderson     exp_diff += 64;
1257feaf2e9cSRichard Henderson     if (exp_diff > 0) {
1258feaf2e9cSRichard Henderson         q = estimateDiv128To64(a0, a1, b0);
1259feaf2e9cSRichard Henderson         q = q > 2 ? (q - 2) >> (64 - exp_diff) : 0;
1260feaf2e9cSRichard Henderson         mul64To128(b0, q << (64 - exp_diff), &t0, &t1);
1261feaf2e9cSRichard Henderson         sub128(a0, a1, t0, t1, &a0, &a1);
1262feaf2e9cSRichard Henderson         shortShift128Left(0, b0, 64 - exp_diff, &t0, &t1);
1263feaf2e9cSRichard Henderson         while (le128(t0, t1, a0, a1)) {
1264feaf2e9cSRichard Henderson             ++q;
1265feaf2e9cSRichard Henderson             sub128(a0, a1, t0, t1, &a0, &a1);
1266feaf2e9cSRichard Henderson         }
1267feaf2e9cSRichard Henderson         quot = (exp_diff < 64 ? quot << exp_diff : 0) + q;
1268feaf2e9cSRichard Henderson     } else {
1269feaf2e9cSRichard Henderson         t0 = b0;
1270feaf2e9cSRichard Henderson         t1 = 0;
1271feaf2e9cSRichard Henderson     }
1272feaf2e9cSRichard Henderson 
1273feaf2e9cSRichard Henderson     if (mod_quot) {
1274feaf2e9cSRichard Henderson         *mod_quot = quot;
1275feaf2e9cSRichard Henderson     } else {
1276feaf2e9cSRichard Henderson         sub128(t0, t1, a0, a1, &t0, &t1);
1277feaf2e9cSRichard Henderson         if (lt128(t0, t1, a0, a1) ||
1278feaf2e9cSRichard Henderson             (eq128(t0, t1, a0, a1) && (q & 1))) {
1279feaf2e9cSRichard Henderson             a0 = t0;
1280feaf2e9cSRichard Henderson             a1 = t1;
1281feaf2e9cSRichard Henderson             a->sign = !a->sign;
1282feaf2e9cSRichard Henderson         }
1283feaf2e9cSRichard Henderson     }
1284feaf2e9cSRichard Henderson 
1285feaf2e9cSRichard Henderson     if (likely(a0)) {
1286feaf2e9cSRichard Henderson         shift = clz64(a0);
1287feaf2e9cSRichard Henderson         shortShift128Left(a0, a1, shift, &a0, &a1);
1288feaf2e9cSRichard Henderson     } else if (likely(a1)) {
1289feaf2e9cSRichard Henderson         shift = clz64(a1);
1290feaf2e9cSRichard Henderson         a0 = a1 << shift;
1291feaf2e9cSRichard Henderson         a1 = 0;
1292feaf2e9cSRichard Henderson         shift += 64;
1293feaf2e9cSRichard Henderson     } else {
1294feaf2e9cSRichard Henderson         a->cls = float_class_zero;
1295feaf2e9cSRichard Henderson         return;
1296feaf2e9cSRichard Henderson     }
1297feaf2e9cSRichard Henderson 
1298feaf2e9cSRichard Henderson     a->exp = b->exp + exp_diff - shift;
1299feaf2e9cSRichard Henderson     a->frac = a0 | (a1 != 0);
1300feaf2e9cSRichard Henderson }
1301feaf2e9cSRichard Henderson 
frac128_modrem(FloatParts128 * a,FloatParts128 * b,uint64_t * mod_quot)1302feaf2e9cSRichard Henderson static void frac128_modrem(FloatParts128 *a, FloatParts128 *b,
1303feaf2e9cSRichard Henderson                            uint64_t *mod_quot)
1304feaf2e9cSRichard Henderson {
1305feaf2e9cSRichard Henderson     uint64_t a0, a1, a2, b0, b1, t0, t1, t2, q, quot;
1306feaf2e9cSRichard Henderson     int exp_diff = a->exp - b->exp;
1307feaf2e9cSRichard Henderson     int shift;
1308feaf2e9cSRichard Henderson 
1309feaf2e9cSRichard Henderson     a0 = a->frac_hi;
1310feaf2e9cSRichard Henderson     a1 = a->frac_lo;
1311feaf2e9cSRichard Henderson     a2 = 0;
1312feaf2e9cSRichard Henderson 
1313feaf2e9cSRichard Henderson     if (exp_diff < -1) {
1314feaf2e9cSRichard Henderson         if (mod_quot) {
1315feaf2e9cSRichard Henderson             *mod_quot = 0;
1316feaf2e9cSRichard Henderson         }
1317feaf2e9cSRichard Henderson         return;
1318feaf2e9cSRichard Henderson     }
1319feaf2e9cSRichard Henderson     if (exp_diff == -1) {
1320feaf2e9cSRichard Henderson         shift128Right(a0, a1, 1, &a0, &a1);
1321feaf2e9cSRichard Henderson         exp_diff = 0;
1322feaf2e9cSRichard Henderson     }
1323feaf2e9cSRichard Henderson 
1324feaf2e9cSRichard Henderson     b0 = b->frac_hi;
1325feaf2e9cSRichard Henderson     b1 = b->frac_lo;
1326feaf2e9cSRichard Henderson 
1327feaf2e9cSRichard Henderson     quot = q = le128(b0, b1, a0, a1);
1328feaf2e9cSRichard Henderson     if (q) {
1329feaf2e9cSRichard Henderson         sub128(a0, a1, b0, b1, &a0, &a1);
1330feaf2e9cSRichard Henderson     }
1331feaf2e9cSRichard Henderson 
1332feaf2e9cSRichard Henderson     exp_diff -= 64;
1333feaf2e9cSRichard Henderson     while (exp_diff > 0) {
1334feaf2e9cSRichard Henderson         q = estimateDiv128To64(a0, a1, b0);
1335feaf2e9cSRichard Henderson         q = q > 4 ? q - 4 : 0;
1336feaf2e9cSRichard Henderson         mul128By64To192(b0, b1, q, &t0, &t1, &t2);
1337feaf2e9cSRichard Henderson         sub192(a0, a1, a2, t0, t1, t2, &a0, &a1, &a2);
1338feaf2e9cSRichard Henderson         shortShift192Left(a0, a1, a2, 61, &a0, &a1, &a2);
1339feaf2e9cSRichard Henderson         exp_diff -= 61;
1340feaf2e9cSRichard Henderson         quot = (quot << 61) + q;
1341feaf2e9cSRichard Henderson     }
1342feaf2e9cSRichard Henderson 
1343feaf2e9cSRichard Henderson     exp_diff += 64;
1344feaf2e9cSRichard Henderson     if (exp_diff > 0) {
1345feaf2e9cSRichard Henderson         q = estimateDiv128To64(a0, a1, b0);
1346feaf2e9cSRichard Henderson         q = q > 4 ? (q - 4) >> (64 - exp_diff) : 0;
1347feaf2e9cSRichard Henderson         mul128By64To192(b0, b1, q << (64 - exp_diff), &t0, &t1, &t2);
1348feaf2e9cSRichard Henderson         sub192(a0, a1, a2, t0, t1, t2, &a0, &a1, &a2);
1349feaf2e9cSRichard Henderson         shortShift192Left(0, b0, b1, 64 - exp_diff, &t0, &t1, &t2);
1350feaf2e9cSRichard Henderson         while (le192(t0, t1, t2, a0, a1, a2)) {
1351feaf2e9cSRichard Henderson             ++q;
1352feaf2e9cSRichard Henderson             sub192(a0, a1, a2, t0, t1, t2, &a0, &a1, &a2);
1353feaf2e9cSRichard Henderson         }
1354feaf2e9cSRichard Henderson         quot = (exp_diff < 64 ? quot << exp_diff : 0) + q;
1355feaf2e9cSRichard Henderson     } else {
1356feaf2e9cSRichard Henderson         t0 = b0;
1357feaf2e9cSRichard Henderson         t1 = b1;
1358feaf2e9cSRichard Henderson         t2 = 0;
1359feaf2e9cSRichard Henderson     }
1360feaf2e9cSRichard Henderson 
1361feaf2e9cSRichard Henderson     if (mod_quot) {
1362feaf2e9cSRichard Henderson         *mod_quot = quot;
1363feaf2e9cSRichard Henderson     } else {
1364feaf2e9cSRichard Henderson         sub192(t0, t1, t2, a0, a1, a2, &t0, &t1, &t2);
1365feaf2e9cSRichard Henderson         if (lt192(t0, t1, t2, a0, a1, a2) ||
1366feaf2e9cSRichard Henderson             (eq192(t0, t1, t2, a0, a1, a2) && (q & 1))) {
1367feaf2e9cSRichard Henderson             a0 = t0;
1368feaf2e9cSRichard Henderson             a1 = t1;
1369feaf2e9cSRichard Henderson             a2 = t2;
1370feaf2e9cSRichard Henderson             a->sign = !a->sign;
1371feaf2e9cSRichard Henderson         }
1372feaf2e9cSRichard Henderson     }
1373feaf2e9cSRichard Henderson 
1374feaf2e9cSRichard Henderson     if (likely(a0)) {
1375feaf2e9cSRichard Henderson         shift = clz64(a0);
1376feaf2e9cSRichard Henderson         shortShift192Left(a0, a1, a2, shift, &a0, &a1, &a2);
1377feaf2e9cSRichard Henderson     } else if (likely(a1)) {
1378feaf2e9cSRichard Henderson         shift = clz64(a1);
1379feaf2e9cSRichard Henderson         shortShift128Left(a1, a2, shift, &a0, &a1);
1380feaf2e9cSRichard Henderson         a2 = 0;
1381feaf2e9cSRichard Henderson         shift += 64;
1382feaf2e9cSRichard Henderson     } else if (likely(a2)) {
1383feaf2e9cSRichard Henderson         shift = clz64(a2);
1384feaf2e9cSRichard Henderson         a0 = a2 << shift;
1385feaf2e9cSRichard Henderson         a1 = a2 = 0;
1386feaf2e9cSRichard Henderson         shift += 128;
1387feaf2e9cSRichard Henderson     } else {
1388feaf2e9cSRichard Henderson         a->cls = float_class_zero;
1389feaf2e9cSRichard Henderson         return;
1390feaf2e9cSRichard Henderson     }
1391feaf2e9cSRichard Henderson 
1392feaf2e9cSRichard Henderson     a->exp = b->exp + exp_diff - shift;
1393feaf2e9cSRichard Henderson     a->frac_hi = a0;
1394feaf2e9cSRichard Henderson     a->frac_lo = a1 | (a2 != 0);
1395feaf2e9cSRichard Henderson }
1396feaf2e9cSRichard Henderson 
1397feaf2e9cSRichard Henderson #define frac_modrem(A, B, Q)  FRAC_GENERIC_64_128(modrem, A)(A, B, Q)
1398feaf2e9cSRichard Henderson 
frac64_shl(FloatParts64 * a,int c)1399d46975bcSRichard Henderson static void frac64_shl(FloatParts64 *a, int c)
1400d46975bcSRichard Henderson {
1401d46975bcSRichard Henderson     a->frac <<= c;
1402d46975bcSRichard Henderson }
1403d46975bcSRichard Henderson 
frac128_shl(FloatParts128 * a,int c)14040018b1f4SRichard Henderson static void frac128_shl(FloatParts128 *a, int c)
14050018b1f4SRichard Henderson {
1406463e45dcSRichard Henderson     uint64_t a0 = a->frac_hi, a1 = a->frac_lo;
1407463e45dcSRichard Henderson 
1408463e45dcSRichard Henderson     if (c & 64) {
1409463e45dcSRichard Henderson         a0 = a1, a1 = 0;
1410463e45dcSRichard Henderson     }
1411463e45dcSRichard Henderson 
1412463e45dcSRichard Henderson     c &= 63;
1413463e45dcSRichard Henderson     if (c) {
1414463e45dcSRichard Henderson         a0 = shl_double(a0, a1, c);
1415463e45dcSRichard Henderson         a1 = a1 << c;
1416463e45dcSRichard Henderson     }
1417463e45dcSRichard Henderson 
1418463e45dcSRichard Henderson     a->frac_hi = a0;
1419463e45dcSRichard Henderson     a->frac_lo = a1;
14200018b1f4SRichard Henderson }
14210018b1f4SRichard Henderson 
1422d46975bcSRichard Henderson #define frac_shl(A, C)  FRAC_GENERIC_64_128(shl, A)(A, C)
1423d46975bcSRichard Henderson 
frac64_shr(FloatParts64 * a,int c)1424d46975bcSRichard Henderson static void frac64_shr(FloatParts64 *a, int c)
1425d46975bcSRichard Henderson {
1426d46975bcSRichard Henderson     a->frac >>= c;
1427d46975bcSRichard Henderson }
14280018b1f4SRichard Henderson 
frac128_shr(FloatParts128 * a,int c)14290018b1f4SRichard Henderson static void frac128_shr(FloatParts128 *a, int c)
14300018b1f4SRichard Henderson {
1431463e45dcSRichard Henderson     uint64_t a0 = a->frac_hi, a1 = a->frac_lo;
1432463e45dcSRichard Henderson 
1433463e45dcSRichard Henderson     if (c & 64) {
1434463e45dcSRichard Henderson         a1 = a0, a0 = 0;
1435463e45dcSRichard Henderson     }
1436463e45dcSRichard Henderson 
1437463e45dcSRichard Henderson     c &= 63;
1438463e45dcSRichard Henderson     if (c) {
1439463e45dcSRichard Henderson         a1 = shr_double(a0, a1, c);
1440463e45dcSRichard Henderson         a0 = a0 >> c;
1441463e45dcSRichard Henderson     }
1442463e45dcSRichard Henderson 
1443463e45dcSRichard Henderson     a->frac_hi = a0;
1444463e45dcSRichard Henderson     a->frac_lo = a1;
14450018b1f4SRichard Henderson }
14460018b1f4SRichard Henderson 
1447d46975bcSRichard Henderson #define frac_shr(A, C)  FRAC_GENERIC_64_128(shr, A)(A, C)
14480fc07cadSRichard Henderson 
frac64_shrjam(FloatParts64 * a,int c)1449ee6959f2SRichard Henderson static void frac64_shrjam(FloatParts64 *a, int c)
14506fff2167SAlex Bennée {
1451463e45dcSRichard Henderson     uint64_t a0 = a->frac;
1452463e45dcSRichard Henderson 
1453463e45dcSRichard Henderson     if (likely(c != 0)) {
1454463e45dcSRichard Henderson         if (likely(c < 64)) {
1455463e45dcSRichard Henderson             a0 = (a0 >> c) | (shr_double(a0, 0, c) != 0);
1456463e45dcSRichard Henderson         } else {
1457463e45dcSRichard Henderson             a0 = a0 != 0;
1458463e45dcSRichard Henderson         }
1459463e45dcSRichard Henderson         a->frac = a0;
1460463e45dcSRichard Henderson     }
14616fff2167SAlex Bennée }
14626fff2167SAlex Bennée 
frac128_shrjam(FloatParts128 * a,int c)1463ee6959f2SRichard Henderson static void frac128_shrjam(FloatParts128 *a, int c)
1464ee6959f2SRichard Henderson {
1465463e45dcSRichard Henderson     uint64_t a0 = a->frac_hi, a1 = a->frac_lo;
1466463e45dcSRichard Henderson     uint64_t sticky = 0;
1467463e45dcSRichard Henderson 
1468463e45dcSRichard Henderson     if (unlikely(c == 0)) {
1469463e45dcSRichard Henderson         return;
1470463e45dcSRichard Henderson     } else if (likely(c < 64)) {
1471463e45dcSRichard Henderson         /* nothing */
1472463e45dcSRichard Henderson     } else if (likely(c < 128)) {
1473463e45dcSRichard Henderson         sticky = a1;
1474463e45dcSRichard Henderson         a1 = a0;
1475463e45dcSRichard Henderson         a0 = 0;
1476463e45dcSRichard Henderson         c &= 63;
1477463e45dcSRichard Henderson         if (c == 0) {
1478463e45dcSRichard Henderson             goto done;
1479463e45dcSRichard Henderson         }
1480463e45dcSRichard Henderson     } else {
1481463e45dcSRichard Henderson         sticky = a0 | a1;
1482463e45dcSRichard Henderson         a0 = a1 = 0;
1483463e45dcSRichard Henderson         goto done;
1484463e45dcSRichard Henderson     }
1485463e45dcSRichard Henderson 
1486463e45dcSRichard Henderson     sticky |= shr_double(a1, 0, c);
1487463e45dcSRichard Henderson     a1 = shr_double(a0, a1, c);
1488463e45dcSRichard Henderson     a0 = a0 >> c;
1489463e45dcSRichard Henderson 
1490463e45dcSRichard Henderson  done:
1491463e45dcSRichard Henderson     a->frac_lo = a1 | (sticky != 0);
1492463e45dcSRichard Henderson     a->frac_hi = a0;
1493e99c4373SRichard Henderson }
14946fff2167SAlex Bennée 
frac256_shrjam(FloatParts256 * a,int c)1495dedd123cSRichard Henderson static void frac256_shrjam(FloatParts256 *a, int c)
1496dedd123cSRichard Henderson {
1497dedd123cSRichard Henderson     uint64_t a0 = a->frac_hi, a1 = a->frac_hm;
1498dedd123cSRichard Henderson     uint64_t a2 = a->frac_lm, a3 = a->frac_lo;
1499dedd123cSRichard Henderson     uint64_t sticky = 0;
1500dedd123cSRichard Henderson 
1501dedd123cSRichard Henderson     if (unlikely(c == 0)) {
1502dedd123cSRichard Henderson         return;
1503dedd123cSRichard Henderson     } else if (likely(c < 64)) {
1504dedd123cSRichard Henderson         /* nothing */
1505dedd123cSRichard Henderson     } else if (likely(c < 256)) {
1506dedd123cSRichard Henderson         if (unlikely(c & 128)) {
1507dedd123cSRichard Henderson             sticky |= a2 | a3;
1508dedd123cSRichard Henderson             a3 = a1, a2 = a0, a1 = 0, a0 = 0;
1509dedd123cSRichard Henderson         }
1510dedd123cSRichard Henderson         if (unlikely(c & 64)) {
1511dedd123cSRichard Henderson             sticky |= a3;
1512dedd123cSRichard Henderson             a3 = a2, a2 = a1, a1 = a0, a0 = 0;
1513dedd123cSRichard Henderson         }
1514dedd123cSRichard Henderson         c &= 63;
1515dedd123cSRichard Henderson         if (c == 0) {
1516dedd123cSRichard Henderson             goto done;
1517dedd123cSRichard Henderson         }
1518dedd123cSRichard Henderson     } else {
1519dedd123cSRichard Henderson         sticky = a0 | a1 | a2 | a3;
1520dedd123cSRichard Henderson         a0 = a1 = a2 = a3 = 0;
1521dedd123cSRichard Henderson         goto done;
1522dedd123cSRichard Henderson     }
1523dedd123cSRichard Henderson 
1524463e45dcSRichard Henderson     sticky |= shr_double(a3, 0, c);
1525463e45dcSRichard Henderson     a3 = shr_double(a2, a3, c);
1526463e45dcSRichard Henderson     a2 = shr_double(a1, a2, c);
1527463e45dcSRichard Henderson     a1 = shr_double(a0, a1, c);
1528463e45dcSRichard Henderson     a0 = a0 >> c;
1529dedd123cSRichard Henderson 
1530dedd123cSRichard Henderson  done:
1531dedd123cSRichard Henderson     a->frac_lo = a3 | (sticky != 0);
1532dedd123cSRichard Henderson     a->frac_lm = a2;
1533dedd123cSRichard Henderson     a->frac_hm = a1;
1534dedd123cSRichard Henderson     a->frac_hi = a0;
1535dedd123cSRichard Henderson }
1536dedd123cSRichard Henderson 
1537dedd123cSRichard Henderson #define frac_shrjam(A, C)  FRAC_GENERIC_64_128_256(shrjam, A)(A, C)
1538d446830aSAlex Bennée 
frac64_sub(FloatParts64 * r,FloatParts64 * a,FloatParts64 * b)1539da10a907SRichard Henderson static bool frac64_sub(FloatParts64 *r, FloatParts64 *a, FloatParts64 *b)
1540da10a907SRichard Henderson {
1541da10a907SRichard Henderson     return usub64_overflow(a->frac, b->frac, &r->frac);
1542da10a907SRichard Henderson }
15437c45bad8SRichard Henderson 
frac128_sub(FloatParts128 * r,FloatParts128 * a,FloatParts128 * b)1544da10a907SRichard Henderson static bool frac128_sub(FloatParts128 *r, FloatParts128 *a, FloatParts128 *b)
1545da10a907SRichard Henderson {
1546da10a907SRichard Henderson     bool c = 0;
1547da10a907SRichard Henderson     r->frac_lo = usub64_borrow(a->frac_lo, b->frac_lo, &c);
1548da10a907SRichard Henderson     r->frac_hi = usub64_borrow(a->frac_hi, b->frac_hi, &c);
1549da10a907SRichard Henderson     return c;
1550da10a907SRichard Henderson }
1551da10a907SRichard Henderson 
frac256_sub(FloatParts256 * r,FloatParts256 * a,FloatParts256 * b)1552dedd123cSRichard Henderson static bool frac256_sub(FloatParts256 *r, FloatParts256 *a, FloatParts256 *b)
1553dedd123cSRichard Henderson {
1554dedd123cSRichard Henderson     bool c = 0;
1555dedd123cSRichard Henderson     r->frac_lo = usub64_borrow(a->frac_lo, b->frac_lo, &c);
1556dedd123cSRichard Henderson     r->frac_lm = usub64_borrow(a->frac_lm, b->frac_lm, &c);
1557dedd123cSRichard Henderson     r->frac_hm = usub64_borrow(a->frac_hm, b->frac_hm, &c);
1558dedd123cSRichard Henderson     r->frac_hi = usub64_borrow(a->frac_hi, b->frac_hi, &c);
1559dedd123cSRichard Henderson     return c;
1560dedd123cSRichard Henderson }
1561dedd123cSRichard Henderson 
1562dedd123cSRichard Henderson #define frac_sub(R, A, B)  FRAC_GENERIC_64_128_256(sub, R)(R, A, B)
1563da10a907SRichard Henderson 
frac64_truncjam(FloatParts64 * r,FloatParts128 * a)1564aca84527SRichard Henderson static void frac64_truncjam(FloatParts64 *r, FloatParts128 *a)
1565aca84527SRichard Henderson {
1566aca84527SRichard Henderson     r->frac = a->frac_hi | (a->frac_lo != 0);
1567aca84527SRichard Henderson }
1568aca84527SRichard Henderson 
frac128_truncjam(FloatParts128 * r,FloatParts256 * a)1569aca84527SRichard Henderson static void frac128_truncjam(FloatParts128 *r, FloatParts256 *a)
1570aca84527SRichard Henderson {
1571aca84527SRichard Henderson     r->frac_hi = a->frac_hi;
1572aca84527SRichard Henderson     r->frac_lo = a->frac_hm | ((a->frac_lm | a->frac_lo) != 0);
1573aca84527SRichard Henderson }
1574aca84527SRichard Henderson 
1575aca84527SRichard Henderson #define frac_truncjam(R, A)  FRAC_GENERIC_64_128(truncjam, R)(R, A)
1576aca84527SRichard Henderson 
frac64_widen(FloatParts128 * r,FloatParts64 * a)1577dedd123cSRichard Henderson static void frac64_widen(FloatParts128 *r, FloatParts64 *a)
1578dedd123cSRichard Henderson {
1579dedd123cSRichard Henderson     r->frac_hi = a->frac;
1580dedd123cSRichard Henderson     r->frac_lo = 0;
1581dedd123cSRichard Henderson }
1582dedd123cSRichard Henderson 
frac128_widen(FloatParts256 * r,FloatParts128 * a)1583dedd123cSRichard Henderson static void frac128_widen(FloatParts256 *r, FloatParts128 *a)
1584dedd123cSRichard Henderson {
1585dedd123cSRichard Henderson     r->frac_hi = a->frac_hi;
1586dedd123cSRichard Henderson     r->frac_hm = a->frac_lo;
1587dedd123cSRichard Henderson     r->frac_lm = 0;
1588dedd123cSRichard Henderson     r->frac_lo = 0;
1589dedd123cSRichard Henderson }
1590dedd123cSRichard Henderson 
1591dedd123cSRichard Henderson #define frac_widen(A, B)  FRAC_GENERIC_64_128(widen, B)(A, B)
1592dedd123cSRichard Henderson 
15939261b245SRichard Henderson /*
15949261b245SRichard Henderson  * Reciprocal sqrt table.  1 bit of exponent, 6-bits of mantessa.
15959261b245SRichard Henderson  * From https://git.musl-libc.org/cgit/musl/tree/src/math/sqrt_data.c
15969261b245SRichard Henderson  * and thus MIT licenced.
15979261b245SRichard Henderson  */
15989261b245SRichard Henderson static const uint16_t rsqrt_tab[128] = {
15999261b245SRichard Henderson     0xb451, 0xb2f0, 0xb196, 0xb044, 0xaef9, 0xadb6, 0xac79, 0xab43,
16009261b245SRichard Henderson     0xaa14, 0xa8eb, 0xa7c8, 0xa6aa, 0xa592, 0xa480, 0xa373, 0xa26b,
16019261b245SRichard Henderson     0xa168, 0xa06a, 0x9f70, 0x9e7b, 0x9d8a, 0x9c9d, 0x9bb5, 0x9ad1,
16029261b245SRichard Henderson     0x99f0, 0x9913, 0x983a, 0x9765, 0x9693, 0x95c4, 0x94f8, 0x9430,
16039261b245SRichard Henderson     0x936b, 0x92a9, 0x91ea, 0x912e, 0x9075, 0x8fbe, 0x8f0a, 0x8e59,
16049261b245SRichard Henderson     0x8daa, 0x8cfe, 0x8c54, 0x8bac, 0x8b07, 0x8a64, 0x89c4, 0x8925,
16059261b245SRichard Henderson     0x8889, 0x87ee, 0x8756, 0x86c0, 0x862b, 0x8599, 0x8508, 0x8479,
16069261b245SRichard Henderson     0x83ec, 0x8361, 0x82d8, 0x8250, 0x81c9, 0x8145, 0x80c2, 0x8040,
16079261b245SRichard Henderson     0xff02, 0xfd0e, 0xfb25, 0xf947, 0xf773, 0xf5aa, 0xf3ea, 0xf234,
16089261b245SRichard Henderson     0xf087, 0xeee3, 0xed47, 0xebb3, 0xea27, 0xe8a3, 0xe727, 0xe5b2,
16099261b245SRichard Henderson     0xe443, 0xe2dc, 0xe17a, 0xe020, 0xdecb, 0xdd7d, 0xdc34, 0xdaf1,
16109261b245SRichard Henderson     0xd9b3, 0xd87b, 0xd748, 0xd61a, 0xd4f1, 0xd3cd, 0xd2ad, 0xd192,
16119261b245SRichard Henderson     0xd07b, 0xcf69, 0xce5b, 0xcd51, 0xcc4a, 0xcb48, 0xca4a, 0xc94f,
16129261b245SRichard Henderson     0xc858, 0xc764, 0xc674, 0xc587, 0xc49d, 0xc3b7, 0xc2d4, 0xc1f4,
16139261b245SRichard Henderson     0xc116, 0xc03c, 0xbf65, 0xbe90, 0xbdbe, 0xbcef, 0xbc23, 0xbb59,
16149261b245SRichard Henderson     0xba91, 0xb9cc, 0xb90a, 0xb84a, 0xb78c, 0xb6d0, 0xb617, 0xb560,
16159261b245SRichard Henderson };
16169261b245SRichard Henderson 
1617da10a907SRichard Henderson #define partsN(NAME)   glue(glue(glue(parts,N),_),NAME)
1618da10a907SRichard Henderson #define FloatPartsN    glue(FloatParts,N)
1619aca84527SRichard Henderson #define FloatPartsW    glue(FloatParts,W)
1620da10a907SRichard Henderson 
1621da10a907SRichard Henderson #define N 64
1622aca84527SRichard Henderson #define W 128
1623da10a907SRichard Henderson 
1624da10a907SRichard Henderson #include "softfloat-parts-addsub.c.inc"
16257c45bad8SRichard Henderson #include "softfloat-parts.c.inc"
16267c45bad8SRichard Henderson 
1627da10a907SRichard Henderson #undef  N
1628aca84527SRichard Henderson #undef  W
1629da10a907SRichard Henderson #define N 128
1630aca84527SRichard Henderson #define W 256
16317c45bad8SRichard Henderson 
1632da10a907SRichard Henderson #include "softfloat-parts-addsub.c.inc"
16337c45bad8SRichard Henderson #include "softfloat-parts.c.inc"
16347c45bad8SRichard Henderson 
1635da10a907SRichard Henderson #undef  N
1636aca84527SRichard Henderson #undef  W
1637dedd123cSRichard Henderson #define N            256
1638dedd123cSRichard Henderson 
1639dedd123cSRichard Henderson #include "softfloat-parts-addsub.c.inc"
1640dedd123cSRichard Henderson 
1641dedd123cSRichard Henderson #undef  N
1642dedd123cSRichard Henderson #undef  W
16437c45bad8SRichard Henderson #undef  partsN
16447c45bad8SRichard Henderson #undef  FloatPartsN
1645aca84527SRichard Henderson #undef  FloatPartsW
16467c45bad8SRichard Henderson 
16476fff2167SAlex Bennée /*
1648aaffb7bfSRichard Henderson  * Pack/unpack routines with a specific FloatFmt.
1649aaffb7bfSRichard Henderson  */
1650aaffb7bfSRichard Henderson 
float16a_unpack_canonical(FloatParts64 * p,float16 f,float_status * s,const FloatFmt * params)165198e256fcSRichard Henderson static void float16a_unpack_canonical(FloatParts64 *p, float16 f,
165298e256fcSRichard Henderson                                       float_status *s, const FloatFmt *params)
1653aaffb7bfSRichard Henderson {
165498e256fcSRichard Henderson     float16_unpack_raw(p, f);
1655d46975bcSRichard Henderson     parts_canonicalize(p, s, params);
1656aaffb7bfSRichard Henderson }
1657aaffb7bfSRichard Henderson 
float16_unpack_canonical(FloatParts64 * p,float16 f,float_status * s)165898e256fcSRichard Henderson static void float16_unpack_canonical(FloatParts64 *p, float16 f,
165998e256fcSRichard Henderson                                      float_status *s)
1660aaffb7bfSRichard Henderson {
166198e256fcSRichard Henderson     float16a_unpack_canonical(p, f, s, &float16_params);
1662aaffb7bfSRichard Henderson }
1663aaffb7bfSRichard Henderson 
bfloat16_unpack_canonical(FloatParts64 * p,bfloat16 f,float_status * s)166498e256fcSRichard Henderson static void bfloat16_unpack_canonical(FloatParts64 *p, bfloat16 f,
166598e256fcSRichard Henderson                                       float_status *s)
1666aaffb7bfSRichard Henderson {
166798e256fcSRichard Henderson     bfloat16_unpack_raw(p, f);
1668d46975bcSRichard Henderson     parts_canonicalize(p, s, &bfloat16_params);
1669aaffb7bfSRichard Henderson }
1670aaffb7bfSRichard Henderson 
float16a_round_pack_canonical(FloatParts64 * p,float_status * s,const FloatFmt * params)1671e293e927SRichard Henderson static float16 float16a_round_pack_canonical(FloatParts64 *p,
1672e293e927SRichard Henderson                                              float_status *s,
1673aaffb7bfSRichard Henderson                                              const FloatFmt *params)
1674aaffb7bfSRichard Henderson {
1675ee6959f2SRichard Henderson     parts_uncanon(p, s, params);
1676e293e927SRichard Henderson     return float16_pack_raw(p);
1677aaffb7bfSRichard Henderson }
1678aaffb7bfSRichard Henderson 
float16_round_pack_canonical(FloatParts64 * p,float_status * s)1679e293e927SRichard Henderson static float16 float16_round_pack_canonical(FloatParts64 *p,
1680e293e927SRichard Henderson                                             float_status *s)
1681aaffb7bfSRichard Henderson {
1682aaffb7bfSRichard Henderson     return float16a_round_pack_canonical(p, s, &float16_params);
1683aaffb7bfSRichard Henderson }
1684aaffb7bfSRichard Henderson 
bfloat16_round_pack_canonical(FloatParts64 * p,float_status * s)1685e293e927SRichard Henderson static bfloat16 bfloat16_round_pack_canonical(FloatParts64 *p,
1686e293e927SRichard Henderson                                               float_status *s)
1687aaffb7bfSRichard Henderson {
1688ee6959f2SRichard Henderson     parts_uncanon(p, s, &bfloat16_params);
1689e293e927SRichard Henderson     return bfloat16_pack_raw(p);
1690aaffb7bfSRichard Henderson }
1691aaffb7bfSRichard Henderson 
float32_unpack_canonical(FloatParts64 * p,float32 f,float_status * s)169298e256fcSRichard Henderson static void float32_unpack_canonical(FloatParts64 *p, float32 f,
169398e256fcSRichard Henderson                                      float_status *s)
1694aaffb7bfSRichard Henderson {
169598e256fcSRichard Henderson     float32_unpack_raw(p, f);
1696d46975bcSRichard Henderson     parts_canonicalize(p, s, &float32_params);
1697aaffb7bfSRichard Henderson }
1698aaffb7bfSRichard Henderson 
float32_round_pack_canonical(FloatParts64 * p,float_status * s)1699e293e927SRichard Henderson static float32 float32_round_pack_canonical(FloatParts64 *p,
1700e293e927SRichard Henderson                                             float_status *s)
1701aaffb7bfSRichard Henderson {
1702ee6959f2SRichard Henderson     parts_uncanon(p, s, &float32_params);
1703e293e927SRichard Henderson     return float32_pack_raw(p);
1704aaffb7bfSRichard Henderson }
1705aaffb7bfSRichard Henderson 
float64_unpack_canonical(FloatParts64 * p,float64 f,float_status * s)170698e256fcSRichard Henderson static void float64_unpack_canonical(FloatParts64 *p, float64 f,
170798e256fcSRichard Henderson                                      float_status *s)
1708aaffb7bfSRichard Henderson {
170998e256fcSRichard Henderson     float64_unpack_raw(p, f);
1710d46975bcSRichard Henderson     parts_canonicalize(p, s, &float64_params);
1711aaffb7bfSRichard Henderson }
1712aaffb7bfSRichard Henderson 
float64_round_pack_canonical(FloatParts64 * p,float_status * s)1713e293e927SRichard Henderson static float64 float64_round_pack_canonical(FloatParts64 *p,
1714e293e927SRichard Henderson                                             float_status *s)
1715aaffb7bfSRichard Henderson {
1716ee6959f2SRichard Henderson     parts_uncanon(p, s, &float64_params);
1717e293e927SRichard Henderson     return float64_pack_raw(p);
1718aaffb7bfSRichard Henderson }
1719aaffb7bfSRichard Henderson 
float64r32_round_pack_canonical(FloatParts64 * p,float_status * s)172042636fb9SRichard Henderson static float64 float64r32_round_pack_canonical(FloatParts64 *p,
172142636fb9SRichard Henderson                                                float_status *s)
172242636fb9SRichard Henderson {
172342636fb9SRichard Henderson     parts_uncanon(p, s, &float32_params);
172442636fb9SRichard Henderson 
172542636fb9SRichard Henderson     /*
172642636fb9SRichard Henderson      * In parts_uncanon, we placed the fraction for float32 at the lsb.
172742636fb9SRichard Henderson      * We need to adjust the fraction higher so that the least N bits are
172842636fb9SRichard Henderson      * zero, and the fraction is adjacent to the float64 implicit bit.
172942636fb9SRichard Henderson      */
173042636fb9SRichard Henderson     switch (p->cls) {
173142636fb9SRichard Henderson     case float_class_normal:
173242636fb9SRichard Henderson         if (unlikely(p->exp == 0)) {
173342636fb9SRichard Henderson             /*
173442636fb9SRichard Henderson              * The result is denormal for float32, but can be represented
173542636fb9SRichard Henderson              * in normalized form for float64.  Adjust, per canonicalize.
173642636fb9SRichard Henderson              */
173742636fb9SRichard Henderson             int shift = frac_normalize(p);
173842636fb9SRichard Henderson             p->exp = (float32_params.frac_shift -
173942636fb9SRichard Henderson                       float32_params.exp_bias - shift + 1 +
174042636fb9SRichard Henderson                       float64_params.exp_bias);
174142636fb9SRichard Henderson             frac_shr(p, float64_params.frac_shift);
174242636fb9SRichard Henderson         } else {
174342636fb9SRichard Henderson             frac_shl(p, float32_params.frac_shift - float64_params.frac_shift);
174442636fb9SRichard Henderson             p->exp += float64_params.exp_bias - float32_params.exp_bias;
174542636fb9SRichard Henderson         }
174642636fb9SRichard Henderson         break;
174742636fb9SRichard Henderson     case float_class_snan:
174842636fb9SRichard Henderson     case float_class_qnan:
174942636fb9SRichard Henderson         frac_shl(p, float32_params.frac_shift - float64_params.frac_shift);
175042636fb9SRichard Henderson         p->exp = float64_params.exp_max;
175142636fb9SRichard Henderson         break;
175242636fb9SRichard Henderson     case float_class_inf:
175342636fb9SRichard Henderson         p->exp = float64_params.exp_max;
175442636fb9SRichard Henderson         break;
175542636fb9SRichard Henderson     case float_class_zero:
175642636fb9SRichard Henderson         break;
175742636fb9SRichard Henderson     default:
175842636fb9SRichard Henderson         g_assert_not_reached();
175942636fb9SRichard Henderson     }
176042636fb9SRichard Henderson 
176142636fb9SRichard Henderson     return float64_pack_raw(p);
176242636fb9SRichard Henderson }
176342636fb9SRichard Henderson 
float128_unpack_canonical(FloatParts128 * p,float128 f,float_status * s)17643ff49e56SRichard Henderson static void float128_unpack_canonical(FloatParts128 *p, float128 f,
17653ff49e56SRichard Henderson                                       float_status *s)
17663ff49e56SRichard Henderson {
17673ff49e56SRichard Henderson     float128_unpack_raw(p, f);
17683ff49e56SRichard Henderson     parts_canonicalize(p, s, &float128_params);
17693ff49e56SRichard Henderson }
17703ff49e56SRichard Henderson 
float128_round_pack_canonical(FloatParts128 * p,float_status * s)17713ff49e56SRichard Henderson static float128 float128_round_pack_canonical(FloatParts128 *p,
17723ff49e56SRichard Henderson                                               float_status *s)
17733ff49e56SRichard Henderson {
17743ff49e56SRichard Henderson     parts_uncanon(p, s, &float128_params);
17753ff49e56SRichard Henderson     return float128_pack_raw(p);
17763ff49e56SRichard Henderson }
17773ff49e56SRichard Henderson 
1778c1b6299bSRichard Henderson /* Returns false if the encoding is invalid. */
floatx80_unpack_canonical(FloatParts128 * p,floatx80 f,float_status * s)1779c1b6299bSRichard Henderson static bool floatx80_unpack_canonical(FloatParts128 *p, floatx80 f,
1780c1b6299bSRichard Henderson                                       float_status *s)
1781c1b6299bSRichard Henderson {
1782c1b6299bSRichard Henderson     /* Ensure rounding precision is set before beginning. */
1783c1b6299bSRichard Henderson     switch (s->floatx80_rounding_precision) {
1784c1b6299bSRichard Henderson     case floatx80_precision_x:
1785c1b6299bSRichard Henderson     case floatx80_precision_d:
1786c1b6299bSRichard Henderson     case floatx80_precision_s:
1787c1b6299bSRichard Henderson         break;
1788c1b6299bSRichard Henderson     default:
1789c1b6299bSRichard Henderson         g_assert_not_reached();
1790c1b6299bSRichard Henderson     }
1791c1b6299bSRichard Henderson 
1792c1b6299bSRichard Henderson     if (unlikely(floatx80_invalid_encoding(f))) {
1793c1b6299bSRichard Henderson         float_raise(float_flag_invalid, s);
1794c1b6299bSRichard Henderson         return false;
1795c1b6299bSRichard Henderson     }
1796c1b6299bSRichard Henderson 
1797c1b6299bSRichard Henderson     floatx80_unpack_raw(p, f);
1798c1b6299bSRichard Henderson 
1799c1b6299bSRichard Henderson     if (likely(p->exp != floatx80_params[floatx80_precision_x].exp_max)) {
1800c1b6299bSRichard Henderson         parts_canonicalize(p, s, &floatx80_params[floatx80_precision_x]);
1801c1b6299bSRichard Henderson     } else {
1802c1b6299bSRichard Henderson         /* The explicit integer bit is ignored, after invalid checks. */
1803c1b6299bSRichard Henderson         p->frac_hi &= MAKE_64BIT_MASK(0, 63);
1804c1b6299bSRichard Henderson         p->cls = (p->frac_hi == 0 ? float_class_inf
1805c1b6299bSRichard Henderson                   : parts_is_snan_frac(p->frac_hi, s)
1806c1b6299bSRichard Henderson                   ? float_class_snan : float_class_qnan);
1807c1b6299bSRichard Henderson     }
1808c1b6299bSRichard Henderson     return true;
1809c1b6299bSRichard Henderson }
1810c1b6299bSRichard Henderson 
floatx80_round_pack_canonical(FloatParts128 * p,float_status * s)1811c1b6299bSRichard Henderson static floatx80 floatx80_round_pack_canonical(FloatParts128 *p,
1812c1b6299bSRichard Henderson                                               float_status *s)
1813c1b6299bSRichard Henderson {
1814c1b6299bSRichard Henderson     const FloatFmt *fmt = &floatx80_params[s->floatx80_rounding_precision];
1815c1b6299bSRichard Henderson     uint64_t frac;
1816c1b6299bSRichard Henderson     int exp;
1817c1b6299bSRichard Henderson 
1818c1b6299bSRichard Henderson     switch (p->cls) {
1819c1b6299bSRichard Henderson     case float_class_normal:
1820c1b6299bSRichard Henderson         if (s->floatx80_rounding_precision == floatx80_precision_x) {
1821c1b6299bSRichard Henderson             parts_uncanon_normal(p, s, fmt);
1822c1b6299bSRichard Henderson             frac = p->frac_hi;
1823c1b6299bSRichard Henderson             exp = p->exp;
1824c1b6299bSRichard Henderson         } else {
1825c1b6299bSRichard Henderson             FloatParts64 p64;
1826c1b6299bSRichard Henderson 
1827c1b6299bSRichard Henderson             p64.sign = p->sign;
1828c1b6299bSRichard Henderson             p64.exp = p->exp;
1829c1b6299bSRichard Henderson             frac_truncjam(&p64, p);
1830c1b6299bSRichard Henderson             parts_uncanon_normal(&p64, s, fmt);
1831c1b6299bSRichard Henderson             frac = p64.frac;
1832c1b6299bSRichard Henderson             exp = p64.exp;
1833c1b6299bSRichard Henderson         }
1834c1b6299bSRichard Henderson         if (exp != fmt->exp_max) {
1835c1b6299bSRichard Henderson             break;
1836c1b6299bSRichard Henderson         }
1837c1b6299bSRichard Henderson         /* rounded to inf -- fall through to set frac correctly */
1838c1b6299bSRichard Henderson 
1839c1b6299bSRichard Henderson     case float_class_inf:
1840c1b6299bSRichard Henderson         /* x86 and m68k differ in the setting of the integer bit. */
1841c1b6299bSRichard Henderson         frac = floatx80_infinity_low;
1842c1b6299bSRichard Henderson         exp = fmt->exp_max;
1843c1b6299bSRichard Henderson         break;
1844c1b6299bSRichard Henderson 
1845c1b6299bSRichard Henderson     case float_class_zero:
1846c1b6299bSRichard Henderson         frac = 0;
1847c1b6299bSRichard Henderson         exp = 0;
1848c1b6299bSRichard Henderson         break;
1849c1b6299bSRichard Henderson 
1850c1b6299bSRichard Henderson     case float_class_snan:
1851c1b6299bSRichard Henderson     case float_class_qnan:
1852c1b6299bSRichard Henderson         /* NaNs have the integer bit set. */
1853c1b6299bSRichard Henderson         frac = p->frac_hi | (1ull << 63);
1854c1b6299bSRichard Henderson         exp = fmt->exp_max;
1855c1b6299bSRichard Henderson         break;
1856c1b6299bSRichard Henderson 
1857c1b6299bSRichard Henderson     default:
1858c1b6299bSRichard Henderson         g_assert_not_reached();
1859c1b6299bSRichard Henderson     }
1860c1b6299bSRichard Henderson 
1861c1b6299bSRichard Henderson     return packFloatx80(p->sign, exp, frac);
1862c1b6299bSRichard Henderson }
1863c1b6299bSRichard Henderson 
1864aaffb7bfSRichard Henderson /*
1865da10a907SRichard Henderson  * Addition and subtraction
18666fff2167SAlex Bennée  */
18676fff2167SAlex Bennée 
1868da10a907SRichard Henderson static float16 QEMU_FLATTEN
float16_addsub(float16 a,float16 b,float_status * status,bool subtract)1869da10a907SRichard Henderson float16_addsub(float16 a, float16 b, float_status *status, bool subtract)
18706fff2167SAlex Bennée {
1871da10a907SRichard Henderson     FloatParts64 pa, pb, *pr;
187298e256fcSRichard Henderson 
187398e256fcSRichard Henderson     float16_unpack_canonical(&pa, a, status);
187498e256fcSRichard Henderson     float16_unpack_canonical(&pb, b, status);
1875da10a907SRichard Henderson     pr = parts_addsub(&pa, &pb, status, subtract);
18766fff2167SAlex Bennée 
1877da10a907SRichard Henderson     return float16_round_pack_canonical(pr, status);
18786fff2167SAlex Bennée }
18796fff2167SAlex Bennée 
float16_add(float16 a,float16 b,float_status * status)1880da10a907SRichard Henderson float16 float16_add(float16 a, float16 b, float_status *status)
18816fff2167SAlex Bennée {
1882da10a907SRichard Henderson     return float16_addsub(a, b, status, false);
1883da10a907SRichard Henderson }
188498e256fcSRichard Henderson 
float16_sub(float16 a,float16 b,float_status * status)1885da10a907SRichard Henderson float16 float16_sub(float16 a, float16 b, float_status *status)
1886da10a907SRichard Henderson {
1887da10a907SRichard Henderson     return float16_addsub(a, b, status, true);
18886fff2167SAlex Bennée }
18896fff2167SAlex Bennée 
18901b615d48SEmilio G. Cota static float32 QEMU_SOFTFLOAT_ATTR
soft_f32_addsub(float32 a,float32 b,float_status * status,bool subtract)1891da10a907SRichard Henderson soft_f32_addsub(float32 a, float32 b, float_status *status, bool subtract)
18926fff2167SAlex Bennée {
1893da10a907SRichard Henderson     FloatParts64 pa, pb, *pr;
189498e256fcSRichard Henderson 
189598e256fcSRichard Henderson     float32_unpack_canonical(&pa, a, status);
189698e256fcSRichard Henderson     float32_unpack_canonical(&pb, b, status);
1897da10a907SRichard Henderson     pr = parts_addsub(&pa, &pb, status, subtract);
18986fff2167SAlex Bennée 
1899da10a907SRichard Henderson     return float32_round_pack_canonical(pr, status);
19006fff2167SAlex Bennée }
19016fff2167SAlex Bennée 
soft_f32_add(float32 a,float32 b,float_status * status)1902da10a907SRichard Henderson static float32 soft_f32_add(float32 a, float32 b, float_status *status)
19031b615d48SEmilio G. Cota {
1904da10a907SRichard Henderson     return soft_f32_addsub(a, b, status, false);
19051b615d48SEmilio G. Cota }
19061b615d48SEmilio G. Cota 
soft_f32_sub(float32 a,float32 b,float_status * status)1907da10a907SRichard Henderson static float32 soft_f32_sub(float32 a, float32 b, float_status *status)
19081b615d48SEmilio G. Cota {
1909da10a907SRichard Henderson     return soft_f32_addsub(a, b, status, true);
19101b615d48SEmilio G. Cota }
19111b615d48SEmilio G. Cota 
19121b615d48SEmilio G. Cota static float64 QEMU_SOFTFLOAT_ATTR
soft_f64_addsub(float64 a,float64 b,float_status * status,bool subtract)1913da10a907SRichard Henderson soft_f64_addsub(float64 a, float64 b, float_status *status, bool subtract)
19146fff2167SAlex Bennée {
1915da10a907SRichard Henderson     FloatParts64 pa, pb, *pr;
191698e256fcSRichard Henderson 
191798e256fcSRichard Henderson     float64_unpack_canonical(&pa, a, status);
191898e256fcSRichard Henderson     float64_unpack_canonical(&pb, b, status);
1919da10a907SRichard Henderson     pr = parts_addsub(&pa, &pb, status, subtract);
19206fff2167SAlex Bennée 
1921da10a907SRichard Henderson     return float64_round_pack_canonical(pr, status);
19226fff2167SAlex Bennée }
19236fff2167SAlex Bennée 
soft_f64_add(float64 a,float64 b,float_status * status)1924da10a907SRichard Henderson static float64 soft_f64_add(float64 a, float64 b, float_status *status)
19251b615d48SEmilio G. Cota {
1926da10a907SRichard Henderson     return soft_f64_addsub(a, b, status, false);
19271b615d48SEmilio G. Cota }
19281b615d48SEmilio G. Cota 
soft_f64_sub(float64 a,float64 b,float_status * status)1929da10a907SRichard Henderson static float64 soft_f64_sub(float64 a, float64 b, float_status *status)
19301b615d48SEmilio G. Cota {
1931da10a907SRichard Henderson     return soft_f64_addsub(a, b, status, true);
19321b615d48SEmilio G. Cota }
19331b615d48SEmilio G. Cota 
hard_f32_add(float a,float b)19341b615d48SEmilio G. Cota static float hard_f32_add(float a, float b)
19351b615d48SEmilio G. Cota {
19361b615d48SEmilio G. Cota     return a + b;
19371b615d48SEmilio G. Cota }
19381b615d48SEmilio G. Cota 
hard_f32_sub(float a,float b)19391b615d48SEmilio G. Cota static float hard_f32_sub(float a, float b)
19401b615d48SEmilio G. Cota {
19411b615d48SEmilio G. Cota     return a - b;
19421b615d48SEmilio G. Cota }
19431b615d48SEmilio G. Cota 
hard_f64_add(double a,double b)19441b615d48SEmilio G. Cota static double hard_f64_add(double a, double b)
19451b615d48SEmilio G. Cota {
19461b615d48SEmilio G. Cota     return a + b;
19471b615d48SEmilio G. Cota }
19481b615d48SEmilio G. Cota 
hard_f64_sub(double a,double b)19491b615d48SEmilio G. Cota static double hard_f64_sub(double a, double b)
19501b615d48SEmilio G. Cota {
19511b615d48SEmilio G. Cota     return a - b;
19521b615d48SEmilio G. Cota }
19531b615d48SEmilio G. Cota 
f32_addsubmul_post(union_float32 a,union_float32 b)1954b240c9c4SRichard Henderson static bool f32_addsubmul_post(union_float32 a, union_float32 b)
19551b615d48SEmilio G. Cota {
19561b615d48SEmilio G. Cota     if (QEMU_HARDFLOAT_2F32_USE_FP) {
19571b615d48SEmilio G. Cota         return !(fpclassify(a.h) == FP_ZERO && fpclassify(b.h) == FP_ZERO);
19581b615d48SEmilio G. Cota     }
19591b615d48SEmilio G. Cota     return !(float32_is_zero(a.s) && float32_is_zero(b.s));
19601b615d48SEmilio G. Cota }
19611b615d48SEmilio G. Cota 
f64_addsubmul_post(union_float64 a,union_float64 b)1962b240c9c4SRichard Henderson static bool f64_addsubmul_post(union_float64 a, union_float64 b)
19631b615d48SEmilio G. Cota {
19641b615d48SEmilio G. Cota     if (QEMU_HARDFLOAT_2F64_USE_FP) {
19651b615d48SEmilio G. Cota         return !(fpclassify(a.h) == FP_ZERO && fpclassify(b.h) == FP_ZERO);
19661b615d48SEmilio G. Cota     } else {
19671b615d48SEmilio G. Cota         return !(float64_is_zero(a.s) && float64_is_zero(b.s));
19681b615d48SEmilio G. Cota     }
19691b615d48SEmilio G. Cota }
19701b615d48SEmilio G. Cota 
float32_addsub(float32 a,float32 b,float_status * s,hard_f32_op2_fn hard,soft_f32_op2_fn soft)19711b615d48SEmilio G. Cota static float32 float32_addsub(float32 a, float32 b, float_status *s,
19721b615d48SEmilio G. Cota                               hard_f32_op2_fn hard, soft_f32_op2_fn soft)
19731b615d48SEmilio G. Cota {
19741b615d48SEmilio G. Cota     return float32_gen2(a, b, s, hard, soft,
1975b240c9c4SRichard Henderson                         f32_is_zon2, f32_addsubmul_post);
19761b615d48SEmilio G. Cota }
19771b615d48SEmilio G. Cota 
float64_addsub(float64 a,float64 b,float_status * s,hard_f64_op2_fn hard,soft_f64_op2_fn soft)19781b615d48SEmilio G. Cota static float64 float64_addsub(float64 a, float64 b, float_status *s,
19791b615d48SEmilio G. Cota                               hard_f64_op2_fn hard, soft_f64_op2_fn soft)
19801b615d48SEmilio G. Cota {
19811b615d48SEmilio G. Cota     return float64_gen2(a, b, s, hard, soft,
1982b240c9c4SRichard Henderson                         f64_is_zon2, f64_addsubmul_post);
19831b615d48SEmilio G. Cota }
19841b615d48SEmilio G. Cota 
19851b615d48SEmilio G. Cota float32 QEMU_FLATTEN
float32_add(float32 a,float32 b,float_status * s)19861b615d48SEmilio G. Cota float32_add(float32 a, float32 b, float_status *s)
19871b615d48SEmilio G. Cota {
19881b615d48SEmilio G. Cota     return float32_addsub(a, b, s, hard_f32_add, soft_f32_add);
19891b615d48SEmilio G. Cota }
19901b615d48SEmilio G. Cota 
19911b615d48SEmilio G. Cota float32 QEMU_FLATTEN
float32_sub(float32 a,float32 b,float_status * s)19921b615d48SEmilio G. Cota float32_sub(float32 a, float32 b, float_status *s)
19931b615d48SEmilio G. Cota {
19941b615d48SEmilio G. Cota     return float32_addsub(a, b, s, hard_f32_sub, soft_f32_sub);
19951b615d48SEmilio G. Cota }
19961b615d48SEmilio G. Cota 
19971b615d48SEmilio G. Cota float64 QEMU_FLATTEN
float64_add(float64 a,float64 b,float_status * s)19981b615d48SEmilio G. Cota float64_add(float64 a, float64 b, float_status *s)
19991b615d48SEmilio G. Cota {
20001b615d48SEmilio G. Cota     return float64_addsub(a, b, s, hard_f64_add, soft_f64_add);
20011b615d48SEmilio G. Cota }
20021b615d48SEmilio G. Cota 
20031b615d48SEmilio G. Cota float64 QEMU_FLATTEN
float64_sub(float64 a,float64 b,float_status * s)20041b615d48SEmilio G. Cota float64_sub(float64 a, float64 b, float_status *s)
20051b615d48SEmilio G. Cota {
20061b615d48SEmilio G. Cota     return float64_addsub(a, b, s, hard_f64_sub, soft_f64_sub);
20071b615d48SEmilio G. Cota }
20081b615d48SEmilio G. Cota 
float64r32_addsub(float64 a,float64 b,float_status * status,bool subtract)200942636fb9SRichard Henderson static float64 float64r32_addsub(float64 a, float64 b, float_status *status,
201042636fb9SRichard Henderson                                  bool subtract)
201142636fb9SRichard Henderson {
201242636fb9SRichard Henderson     FloatParts64 pa, pb, *pr;
201342636fb9SRichard Henderson 
201442636fb9SRichard Henderson     float64_unpack_canonical(&pa, a, status);
201542636fb9SRichard Henderson     float64_unpack_canonical(&pb, b, status);
201642636fb9SRichard Henderson     pr = parts_addsub(&pa, &pb, status, subtract);
201742636fb9SRichard Henderson 
201842636fb9SRichard Henderson     return float64r32_round_pack_canonical(pr, status);
201942636fb9SRichard Henderson }
202042636fb9SRichard Henderson 
float64r32_add(float64 a,float64 b,float_status * status)202142636fb9SRichard Henderson float64 float64r32_add(float64 a, float64 b, float_status *status)
202242636fb9SRichard Henderson {
202342636fb9SRichard Henderson     return float64r32_addsub(a, b, status, false);
202442636fb9SRichard Henderson }
202542636fb9SRichard Henderson 
float64r32_sub(float64 a,float64 b,float_status * status)202642636fb9SRichard Henderson float64 float64r32_sub(float64 a, float64 b, float_status *status)
202742636fb9SRichard Henderson {
202842636fb9SRichard Henderson     return float64r32_addsub(a, b, status, true);
202942636fb9SRichard Henderson }
203042636fb9SRichard Henderson 
2031da10a907SRichard Henderson static bfloat16 QEMU_FLATTEN
bfloat16_addsub(bfloat16 a,bfloat16 b,float_status * status,bool subtract)2032da10a907SRichard Henderson bfloat16_addsub(bfloat16 a, bfloat16 b, float_status *status, bool subtract)
20338282310dSLIU Zhiwei {
2034da10a907SRichard Henderson     FloatParts64 pa, pb, *pr;
203598e256fcSRichard Henderson 
203698e256fcSRichard Henderson     bfloat16_unpack_canonical(&pa, a, status);
203798e256fcSRichard Henderson     bfloat16_unpack_canonical(&pb, b, status);
2038da10a907SRichard Henderson     pr = parts_addsub(&pa, &pb, status, subtract);
20398282310dSLIU Zhiwei 
2040da10a907SRichard Henderson     return bfloat16_round_pack_canonical(pr, status);
20418282310dSLIU Zhiwei }
20428282310dSLIU Zhiwei 
bfloat16_add(bfloat16 a,bfloat16 b,float_status * status)2043da10a907SRichard Henderson bfloat16 bfloat16_add(bfloat16 a, bfloat16 b, float_status *status)
20448282310dSLIU Zhiwei {
2045da10a907SRichard Henderson     return bfloat16_addsub(a, b, status, false);
2046da10a907SRichard Henderson }
204798e256fcSRichard Henderson 
bfloat16_sub(bfloat16 a,bfloat16 b,float_status * status)2048da10a907SRichard Henderson bfloat16 bfloat16_sub(bfloat16 a, bfloat16 b, float_status *status)
2049da10a907SRichard Henderson {
2050da10a907SRichard Henderson     return bfloat16_addsub(a, b, status, true);
20518282310dSLIU Zhiwei }
20528282310dSLIU Zhiwei 
20533ff49e56SRichard Henderson static float128 QEMU_FLATTEN
float128_addsub(float128 a,float128 b,float_status * status,bool subtract)20543ff49e56SRichard Henderson float128_addsub(float128 a, float128 b, float_status *status, bool subtract)
20553ff49e56SRichard Henderson {
20563ff49e56SRichard Henderson     FloatParts128 pa, pb, *pr;
20573ff49e56SRichard Henderson 
20583ff49e56SRichard Henderson     float128_unpack_canonical(&pa, a, status);
20593ff49e56SRichard Henderson     float128_unpack_canonical(&pb, b, status);
20603ff49e56SRichard Henderson     pr = parts_addsub(&pa, &pb, status, subtract);
20613ff49e56SRichard Henderson 
20623ff49e56SRichard Henderson     return float128_round_pack_canonical(pr, status);
20633ff49e56SRichard Henderson }
20643ff49e56SRichard Henderson 
float128_add(float128 a,float128 b,float_status * status)20653ff49e56SRichard Henderson float128 float128_add(float128 a, float128 b, float_status *status)
20663ff49e56SRichard Henderson {
20673ff49e56SRichard Henderson     return float128_addsub(a, b, status, false);
20683ff49e56SRichard Henderson }
20693ff49e56SRichard Henderson 
float128_sub(float128 a,float128 b,float_status * status)20703ff49e56SRichard Henderson float128 float128_sub(float128 a, float128 b, float_status *status)
20713ff49e56SRichard Henderson {
20723ff49e56SRichard Henderson     return float128_addsub(a, b, status, true);
20733ff49e56SRichard Henderson }
20743ff49e56SRichard Henderson 
2075c1b6299bSRichard Henderson static floatx80 QEMU_FLATTEN
floatx80_addsub(floatx80 a,floatx80 b,float_status * status,bool subtract)2076c1b6299bSRichard Henderson floatx80_addsub(floatx80 a, floatx80 b, float_status *status, bool subtract)
2077c1b6299bSRichard Henderson {
2078c1b6299bSRichard Henderson     FloatParts128 pa, pb, *pr;
2079c1b6299bSRichard Henderson 
2080c1b6299bSRichard Henderson     if (!floatx80_unpack_canonical(&pa, a, status) ||
2081c1b6299bSRichard Henderson         !floatx80_unpack_canonical(&pb, b, status)) {
2082c1b6299bSRichard Henderson         return floatx80_default_nan(status);
2083c1b6299bSRichard Henderson     }
2084c1b6299bSRichard Henderson 
2085c1b6299bSRichard Henderson     pr = parts_addsub(&pa, &pb, status, subtract);
2086c1b6299bSRichard Henderson     return floatx80_round_pack_canonical(pr, status);
2087c1b6299bSRichard Henderson }
2088c1b6299bSRichard Henderson 
floatx80_add(floatx80 a,floatx80 b,float_status * status)2089c1b6299bSRichard Henderson floatx80 floatx80_add(floatx80 a, floatx80 b, float_status *status)
2090c1b6299bSRichard Henderson {
2091c1b6299bSRichard Henderson     return floatx80_addsub(a, b, status, false);
2092c1b6299bSRichard Henderson }
2093c1b6299bSRichard Henderson 
floatx80_sub(floatx80 a,floatx80 b,float_status * status)2094c1b6299bSRichard Henderson floatx80 floatx80_sub(floatx80 a, floatx80 b, float_status *status)
2095c1b6299bSRichard Henderson {
2096c1b6299bSRichard Henderson     return floatx80_addsub(a, b, status, true);
2097c1b6299bSRichard Henderson }
2098c1b6299bSRichard Henderson 
20998282310dSLIU Zhiwei /*
2100aca84527SRichard Henderson  * Multiplication
210174d707e2SAlex Bennée  */
210274d707e2SAlex Bennée 
float16_mul(float16 a,float16 b,float_status * status)210397ff87c0SThomas Huth float16 QEMU_FLATTEN float16_mul(float16 a, float16 b, float_status *status)
210474d707e2SAlex Bennée {
2105aca84527SRichard Henderson     FloatParts64 pa, pb, *pr;
210698e256fcSRichard Henderson 
210798e256fcSRichard Henderson     float16_unpack_canonical(&pa, a, status);
210898e256fcSRichard Henderson     float16_unpack_canonical(&pb, b, status);
2109aca84527SRichard Henderson     pr = parts_mul(&pa, &pb, status);
211074d707e2SAlex Bennée 
2111aca84527SRichard Henderson     return float16_round_pack_canonical(pr, status);
211274d707e2SAlex Bennée }
211374d707e2SAlex Bennée 
21142dfabc86SEmilio G. Cota static float32 QEMU_SOFTFLOAT_ATTR
soft_f32_mul(float32 a,float32 b,float_status * status)21152dfabc86SEmilio G. Cota soft_f32_mul(float32 a, float32 b, float_status *status)
211674d707e2SAlex Bennée {
2117aca84527SRichard Henderson     FloatParts64 pa, pb, *pr;
211898e256fcSRichard Henderson 
211998e256fcSRichard Henderson     float32_unpack_canonical(&pa, a, status);
212098e256fcSRichard Henderson     float32_unpack_canonical(&pb, b, status);
2121aca84527SRichard Henderson     pr = parts_mul(&pa, &pb, status);
212274d707e2SAlex Bennée 
2123aca84527SRichard Henderson     return float32_round_pack_canonical(pr, status);
212474d707e2SAlex Bennée }
212574d707e2SAlex Bennée 
21262dfabc86SEmilio G. Cota static float64 QEMU_SOFTFLOAT_ATTR
soft_f64_mul(float64 a,float64 b,float_status * status)21272dfabc86SEmilio G. Cota soft_f64_mul(float64 a, float64 b, float_status *status)
212874d707e2SAlex Bennée {
2129aca84527SRichard Henderson     FloatParts64 pa, pb, *pr;
213098e256fcSRichard Henderson 
213198e256fcSRichard Henderson     float64_unpack_canonical(&pa, a, status);
213298e256fcSRichard Henderson     float64_unpack_canonical(&pb, b, status);
2133aca84527SRichard Henderson     pr = parts_mul(&pa, &pb, status);
213474d707e2SAlex Bennée 
2135aca84527SRichard Henderson     return float64_round_pack_canonical(pr, status);
213674d707e2SAlex Bennée }
213774d707e2SAlex Bennée 
hard_f32_mul(float a,float b)21382dfabc86SEmilio G. Cota static float hard_f32_mul(float a, float b)
21392dfabc86SEmilio G. Cota {
21402dfabc86SEmilio G. Cota     return a * b;
21412dfabc86SEmilio G. Cota }
21422dfabc86SEmilio G. Cota 
hard_f64_mul(double a,double b)21432dfabc86SEmilio G. Cota static double hard_f64_mul(double a, double b)
21442dfabc86SEmilio G. Cota {
21452dfabc86SEmilio G. Cota     return a * b;
21462dfabc86SEmilio G. Cota }
21472dfabc86SEmilio G. Cota 
21482dfabc86SEmilio G. Cota float32 QEMU_FLATTEN
float32_mul(float32 a,float32 b,float_status * s)21492dfabc86SEmilio G. Cota float32_mul(float32 a, float32 b, float_status *s)
21502dfabc86SEmilio G. Cota {
21512dfabc86SEmilio G. Cota     return float32_gen2(a, b, s, hard_f32_mul, soft_f32_mul,
2152b240c9c4SRichard Henderson                         f32_is_zon2, f32_addsubmul_post);
21532dfabc86SEmilio G. Cota }
21542dfabc86SEmilio G. Cota 
21552dfabc86SEmilio G. Cota float64 QEMU_FLATTEN
float64_mul(float64 a,float64 b,float_status * s)21562dfabc86SEmilio G. Cota float64_mul(float64 a, float64 b, float_status *s)
21572dfabc86SEmilio G. Cota {
21582dfabc86SEmilio G. Cota     return float64_gen2(a, b, s, hard_f64_mul, soft_f64_mul,
2159b240c9c4SRichard Henderson                         f64_is_zon2, f64_addsubmul_post);
21602dfabc86SEmilio G. Cota }
21612dfabc86SEmilio G. Cota 
float64r32_mul(float64 a,float64 b,float_status * status)216242636fb9SRichard Henderson float64 float64r32_mul(float64 a, float64 b, float_status *status)
216342636fb9SRichard Henderson {
216442636fb9SRichard Henderson     FloatParts64 pa, pb, *pr;
216542636fb9SRichard Henderson 
216642636fb9SRichard Henderson     float64_unpack_canonical(&pa, a, status);
216742636fb9SRichard Henderson     float64_unpack_canonical(&pb, b, status);
216842636fb9SRichard Henderson     pr = parts_mul(&pa, &pb, status);
216942636fb9SRichard Henderson 
217042636fb9SRichard Henderson     return float64r32_round_pack_canonical(pr, status);
217142636fb9SRichard Henderson }
217242636fb9SRichard Henderson 
2173aca84527SRichard Henderson bfloat16 QEMU_FLATTEN
bfloat16_mul(bfloat16 a,bfloat16 b,float_status * status)2174aca84527SRichard Henderson bfloat16_mul(bfloat16 a, bfloat16 b, float_status *status)
21758282310dSLIU Zhiwei {
2176aca84527SRichard Henderson     FloatParts64 pa, pb, *pr;
217798e256fcSRichard Henderson 
217898e256fcSRichard Henderson     bfloat16_unpack_canonical(&pa, a, status);
217998e256fcSRichard Henderson     bfloat16_unpack_canonical(&pb, b, status);
2180aca84527SRichard Henderson     pr = parts_mul(&pa, &pb, status);
21818282310dSLIU Zhiwei 
2182aca84527SRichard Henderson     return bfloat16_round_pack_canonical(pr, status);
2183aca84527SRichard Henderson }
2184aca84527SRichard Henderson 
2185aca84527SRichard Henderson float128 QEMU_FLATTEN
float128_mul(float128 a,float128 b,float_status * status)2186aca84527SRichard Henderson float128_mul(float128 a, float128 b, float_status *status)
2187aca84527SRichard Henderson {
2188aca84527SRichard Henderson     FloatParts128 pa, pb, *pr;
2189aca84527SRichard Henderson 
2190aca84527SRichard Henderson     float128_unpack_canonical(&pa, a, status);
2191aca84527SRichard Henderson     float128_unpack_canonical(&pb, b, status);
2192aca84527SRichard Henderson     pr = parts_mul(&pa, &pb, status);
2193aca84527SRichard Henderson 
2194aca84527SRichard Henderson     return float128_round_pack_canonical(pr, status);
21958282310dSLIU Zhiwei }
21968282310dSLIU Zhiwei 
2197153f664aSRichard Henderson floatx80 QEMU_FLATTEN
floatx80_mul(floatx80 a,floatx80 b,float_status * status)2198153f664aSRichard Henderson floatx80_mul(floatx80 a, floatx80 b, float_status *status)
2199153f664aSRichard Henderson {
2200153f664aSRichard Henderson     FloatParts128 pa, pb, *pr;
2201153f664aSRichard Henderson 
2202153f664aSRichard Henderson     if (!floatx80_unpack_canonical(&pa, a, status) ||
2203153f664aSRichard Henderson         !floatx80_unpack_canonical(&pb, b, status)) {
2204153f664aSRichard Henderson         return floatx80_default_nan(status);
2205153f664aSRichard Henderson     }
2206153f664aSRichard Henderson 
2207153f664aSRichard Henderson     pr = parts_mul(&pa, &pb, status);
2208153f664aSRichard Henderson     return floatx80_round_pack_canonical(pr, status);
2209153f664aSRichard Henderson }
2210153f664aSRichard Henderson 
22118282310dSLIU Zhiwei /*
2212dedd123cSRichard Henderson  * Fused multiply-add
2213d446830aSAlex Bennée  */
2214d446830aSAlex Bennée 
float16_muladd(float16 a,float16 b,float16 c,int flags,float_status * status)221597ff87c0SThomas Huth float16 QEMU_FLATTEN float16_muladd(float16 a, float16 b, float16 c,
2216d446830aSAlex Bennée                                     int flags, float_status *status)
2217d446830aSAlex Bennée {
2218dedd123cSRichard Henderson     FloatParts64 pa, pb, pc, *pr;
221998e256fcSRichard Henderson 
222098e256fcSRichard Henderson     float16_unpack_canonical(&pa, a, status);
222198e256fcSRichard Henderson     float16_unpack_canonical(&pb, b, status);
222298e256fcSRichard Henderson     float16_unpack_canonical(&pc, c, status);
2223dedd123cSRichard Henderson     pr = parts_muladd(&pa, &pb, &pc, flags, status);
2224d446830aSAlex Bennée 
2225dedd123cSRichard Henderson     return float16_round_pack_canonical(pr, status);
2226d446830aSAlex Bennée }
2227d446830aSAlex Bennée 
2228ccf770baSEmilio G. Cota static float32 QEMU_SOFTFLOAT_ATTR
soft_f32_muladd(float32 a,float32 b,float32 c,int flags,float_status * status)2229ccf770baSEmilio G. Cota soft_f32_muladd(float32 a, float32 b, float32 c, int flags,
2230ccf770baSEmilio G. Cota                 float_status *status)
2231d446830aSAlex Bennée {
2232dedd123cSRichard Henderson     FloatParts64 pa, pb, pc, *pr;
223398e256fcSRichard Henderson 
223498e256fcSRichard Henderson     float32_unpack_canonical(&pa, a, status);
223598e256fcSRichard Henderson     float32_unpack_canonical(&pb, b, status);
223698e256fcSRichard Henderson     float32_unpack_canonical(&pc, c, status);
2237dedd123cSRichard Henderson     pr = parts_muladd(&pa, &pb, &pc, flags, status);
2238d446830aSAlex Bennée 
2239dedd123cSRichard Henderson     return float32_round_pack_canonical(pr, status);
2240d446830aSAlex Bennée }
2241d446830aSAlex Bennée 
2242ccf770baSEmilio G. Cota static float64 QEMU_SOFTFLOAT_ATTR
soft_f64_muladd(float64 a,float64 b,float64 c,int flags,float_status * status)2243ccf770baSEmilio G. Cota soft_f64_muladd(float64 a, float64 b, float64 c, int flags,
2244ccf770baSEmilio G. Cota                 float_status *status)
2245d446830aSAlex Bennée {
2246dedd123cSRichard Henderson     FloatParts64 pa, pb, pc, *pr;
224798e256fcSRichard Henderson 
224898e256fcSRichard Henderson     float64_unpack_canonical(&pa, a, status);
224998e256fcSRichard Henderson     float64_unpack_canonical(&pb, b, status);
225098e256fcSRichard Henderson     float64_unpack_canonical(&pc, c, status);
2251dedd123cSRichard Henderson     pr = parts_muladd(&pa, &pb, &pc, flags, status);
2252d446830aSAlex Bennée 
2253dedd123cSRichard Henderson     return float64_round_pack_canonical(pr, status);
2254d446830aSAlex Bennée }
2255d446830aSAlex Bennée 
2256f6b3b108SEmilio G. Cota static bool force_soft_fma;
2257f6b3b108SEmilio G. Cota 
2258ccf770baSEmilio G. Cota float32 QEMU_FLATTEN
float32_muladd(float32 xa,float32 xb,float32 xc,int flags,float_status * s)2259ccf770baSEmilio G. Cota float32_muladd(float32 xa, float32 xb, float32 xc, int flags, float_status *s)
2260ccf770baSEmilio G. Cota {
2261ccf770baSEmilio G. Cota     union_float32 ua, ub, uc, ur;
2262ccf770baSEmilio G. Cota 
2263ccf770baSEmilio G. Cota     ua.s = xa;
2264ccf770baSEmilio G. Cota     ub.s = xb;
2265ccf770baSEmilio G. Cota     uc.s = xc;
2266ccf770baSEmilio G. Cota 
2267ccf770baSEmilio G. Cota     if (unlikely(!can_use_fpu(s))) {
2268ccf770baSEmilio G. Cota         goto soft;
2269ccf770baSEmilio G. Cota     }
2270ccf770baSEmilio G. Cota     if (unlikely(flags & float_muladd_halve_result)) {
2271ccf770baSEmilio G. Cota         goto soft;
2272ccf770baSEmilio G. Cota     }
2273ccf770baSEmilio G. Cota 
2274ccf770baSEmilio G. Cota     float32_input_flush3(&ua.s, &ub.s, &uc.s, s);
2275ccf770baSEmilio G. Cota     if (unlikely(!f32_is_zon3(ua, ub, uc))) {
2276ccf770baSEmilio G. Cota         goto soft;
2277ccf770baSEmilio G. Cota     }
2278f6b3b108SEmilio G. Cota 
2279f6b3b108SEmilio G. Cota     if (unlikely(force_soft_fma)) {
2280f6b3b108SEmilio G. Cota         goto soft;
2281f6b3b108SEmilio G. Cota     }
2282f6b3b108SEmilio G. Cota 
2283ccf770baSEmilio G. Cota     /*
2284ccf770baSEmilio G. Cota      * When (a || b) == 0, there's no need to check for under/over flow,
2285ccf770baSEmilio G. Cota      * since we know the addend is (normal || 0) and the product is 0.
2286ccf770baSEmilio G. Cota      */
2287ccf770baSEmilio G. Cota     if (float32_is_zero(ua.s) || float32_is_zero(ub.s)) {
2288ccf770baSEmilio G. Cota         union_float32 up;
2289ccf770baSEmilio G. Cota         bool prod_sign;
2290ccf770baSEmilio G. Cota 
2291ccf770baSEmilio G. Cota         prod_sign = float32_is_neg(ua.s) ^ float32_is_neg(ub.s);
2292ccf770baSEmilio G. Cota         prod_sign ^= !!(flags & float_muladd_negate_product);
2293ccf770baSEmilio G. Cota         up.s = float32_set_sign(float32_zero, prod_sign);
2294ccf770baSEmilio G. Cota 
2295ccf770baSEmilio G. Cota         if (flags & float_muladd_negate_c) {
2296ccf770baSEmilio G. Cota             uc.h = -uc.h;
2297ccf770baSEmilio G. Cota         }
2298ccf770baSEmilio G. Cota         ur.h = up.h + uc.h;
2299ccf770baSEmilio G. Cota     } else {
2300896f51fbSKito Cheng         union_float32 ua_orig = ua;
2301896f51fbSKito Cheng         union_float32 uc_orig = uc;
2302896f51fbSKito Cheng 
2303ccf770baSEmilio G. Cota         if (flags & float_muladd_negate_product) {
2304ccf770baSEmilio G. Cota             ua.h = -ua.h;
2305ccf770baSEmilio G. Cota         }
2306ccf770baSEmilio G. Cota         if (flags & float_muladd_negate_c) {
2307ccf770baSEmilio G. Cota             uc.h = -uc.h;
2308ccf770baSEmilio G. Cota         }
2309ccf770baSEmilio G. Cota 
2310ccf770baSEmilio G. Cota         ur.h = fmaf(ua.h, ub.h, uc.h);
2311ccf770baSEmilio G. Cota 
2312ccf770baSEmilio G. Cota         if (unlikely(f32_is_inf(ur))) {
2313d82f3b2dSRichard Henderson             float_raise(float_flag_overflow, s);
2314ccf770baSEmilio G. Cota         } else if (unlikely(fabsf(ur.h) <= FLT_MIN)) {
2315896f51fbSKito Cheng             ua = ua_orig;
2316896f51fbSKito Cheng             uc = uc_orig;
2317ccf770baSEmilio G. Cota             goto soft;
2318ccf770baSEmilio G. Cota         }
2319ccf770baSEmilio G. Cota     }
2320ccf770baSEmilio G. Cota     if (flags & float_muladd_negate_result) {
2321ccf770baSEmilio G. Cota         return float32_chs(ur.s);
2322ccf770baSEmilio G. Cota     }
2323ccf770baSEmilio G. Cota     return ur.s;
2324ccf770baSEmilio G. Cota 
2325ccf770baSEmilio G. Cota  soft:
2326ccf770baSEmilio G. Cota     return soft_f32_muladd(ua.s, ub.s, uc.s, flags, s);
2327ccf770baSEmilio G. Cota }
2328ccf770baSEmilio G. Cota 
2329ccf770baSEmilio G. Cota float64 QEMU_FLATTEN
float64_muladd(float64 xa,float64 xb,float64 xc,int flags,float_status * s)2330ccf770baSEmilio G. Cota float64_muladd(float64 xa, float64 xb, float64 xc, int flags, float_status *s)
2331ccf770baSEmilio G. Cota {
2332ccf770baSEmilio G. Cota     union_float64 ua, ub, uc, ur;
2333ccf770baSEmilio G. Cota 
2334ccf770baSEmilio G. Cota     ua.s = xa;
2335ccf770baSEmilio G. Cota     ub.s = xb;
2336ccf770baSEmilio G. Cota     uc.s = xc;
2337ccf770baSEmilio G. Cota 
2338ccf770baSEmilio G. Cota     if (unlikely(!can_use_fpu(s))) {
2339ccf770baSEmilio G. Cota         goto soft;
2340ccf770baSEmilio G. Cota     }
2341ccf770baSEmilio G. Cota     if (unlikely(flags & float_muladd_halve_result)) {
2342ccf770baSEmilio G. Cota         goto soft;
2343ccf770baSEmilio G. Cota     }
2344ccf770baSEmilio G. Cota 
2345ccf770baSEmilio G. Cota     float64_input_flush3(&ua.s, &ub.s, &uc.s, s);
2346ccf770baSEmilio G. Cota     if (unlikely(!f64_is_zon3(ua, ub, uc))) {
2347ccf770baSEmilio G. Cota         goto soft;
2348ccf770baSEmilio G. Cota     }
2349f6b3b108SEmilio G. Cota 
2350f6b3b108SEmilio G. Cota     if (unlikely(force_soft_fma)) {
2351f6b3b108SEmilio G. Cota         goto soft;
2352f6b3b108SEmilio G. Cota     }
2353f6b3b108SEmilio G. Cota 
2354ccf770baSEmilio G. Cota     /*
2355ccf770baSEmilio G. Cota      * When (a || b) == 0, there's no need to check for under/over flow,
2356ccf770baSEmilio G. Cota      * since we know the addend is (normal || 0) and the product is 0.
2357ccf770baSEmilio G. Cota      */
2358ccf770baSEmilio G. Cota     if (float64_is_zero(ua.s) || float64_is_zero(ub.s)) {
2359ccf770baSEmilio G. Cota         union_float64 up;
2360ccf770baSEmilio G. Cota         bool prod_sign;
2361ccf770baSEmilio G. Cota 
2362ccf770baSEmilio G. Cota         prod_sign = float64_is_neg(ua.s) ^ float64_is_neg(ub.s);
2363ccf770baSEmilio G. Cota         prod_sign ^= !!(flags & float_muladd_negate_product);
2364ccf770baSEmilio G. Cota         up.s = float64_set_sign(float64_zero, prod_sign);
2365ccf770baSEmilio G. Cota 
2366ccf770baSEmilio G. Cota         if (flags & float_muladd_negate_c) {
2367ccf770baSEmilio G. Cota             uc.h = -uc.h;
2368ccf770baSEmilio G. Cota         }
2369ccf770baSEmilio G. Cota         ur.h = up.h + uc.h;
2370ccf770baSEmilio G. Cota     } else {
2371896f51fbSKito Cheng         union_float64 ua_orig = ua;
2372896f51fbSKito Cheng         union_float64 uc_orig = uc;
2373896f51fbSKito Cheng 
2374ccf770baSEmilio G. Cota         if (flags & float_muladd_negate_product) {
2375ccf770baSEmilio G. Cota             ua.h = -ua.h;
2376ccf770baSEmilio G. Cota         }
2377ccf770baSEmilio G. Cota         if (flags & float_muladd_negate_c) {
2378ccf770baSEmilio G. Cota             uc.h = -uc.h;
2379ccf770baSEmilio G. Cota         }
2380ccf770baSEmilio G. Cota 
2381ccf770baSEmilio G. Cota         ur.h = fma(ua.h, ub.h, uc.h);
2382ccf770baSEmilio G. Cota 
2383ccf770baSEmilio G. Cota         if (unlikely(f64_is_inf(ur))) {
2384d82f3b2dSRichard Henderson             float_raise(float_flag_overflow, s);
2385ccf770baSEmilio G. Cota         } else if (unlikely(fabs(ur.h) <= FLT_MIN)) {
2386896f51fbSKito Cheng             ua = ua_orig;
2387896f51fbSKito Cheng             uc = uc_orig;
2388ccf770baSEmilio G. Cota             goto soft;
2389ccf770baSEmilio G. Cota         }
2390ccf770baSEmilio G. Cota     }
2391ccf770baSEmilio G. Cota     if (flags & float_muladd_negate_result) {
2392ccf770baSEmilio G. Cota         return float64_chs(ur.s);
2393ccf770baSEmilio G. Cota     }
2394ccf770baSEmilio G. Cota     return ur.s;
2395ccf770baSEmilio G. Cota 
2396ccf770baSEmilio G. Cota  soft:
2397ccf770baSEmilio G. Cota     return soft_f64_muladd(ua.s, ub.s, uc.s, flags, s);
2398ccf770baSEmilio G. Cota }
2399ccf770baSEmilio G. Cota 
float64r32_muladd(float64 a,float64 b,float64 c,int flags,float_status * status)240042636fb9SRichard Henderson float64 float64r32_muladd(float64 a, float64 b, float64 c,
240142636fb9SRichard Henderson                           int flags, float_status *status)
240242636fb9SRichard Henderson {
240342636fb9SRichard Henderson     FloatParts64 pa, pb, pc, *pr;
240442636fb9SRichard Henderson 
240542636fb9SRichard Henderson     float64_unpack_canonical(&pa, a, status);
240642636fb9SRichard Henderson     float64_unpack_canonical(&pb, b, status);
240742636fb9SRichard Henderson     float64_unpack_canonical(&pc, c, status);
240842636fb9SRichard Henderson     pr = parts_muladd(&pa, &pb, &pc, flags, status);
240942636fb9SRichard Henderson 
241042636fb9SRichard Henderson     return float64r32_round_pack_canonical(pr, status);
241142636fb9SRichard Henderson }
241242636fb9SRichard Henderson 
bfloat16_muladd(bfloat16 a,bfloat16 b,bfloat16 c,int flags,float_status * status)24138282310dSLIU Zhiwei bfloat16 QEMU_FLATTEN bfloat16_muladd(bfloat16 a, bfloat16 b, bfloat16 c,
24148282310dSLIU Zhiwei                                       int flags, float_status *status)
24158282310dSLIU Zhiwei {
2416dedd123cSRichard Henderson     FloatParts64 pa, pb, pc, *pr;
241798e256fcSRichard Henderson 
241898e256fcSRichard Henderson     bfloat16_unpack_canonical(&pa, a, status);
241998e256fcSRichard Henderson     bfloat16_unpack_canonical(&pb, b, status);
242098e256fcSRichard Henderson     bfloat16_unpack_canonical(&pc, c, status);
2421dedd123cSRichard Henderson     pr = parts_muladd(&pa, &pb, &pc, flags, status);
24228282310dSLIU Zhiwei 
2423dedd123cSRichard Henderson     return bfloat16_round_pack_canonical(pr, status);
2424dedd123cSRichard Henderson }
2425dedd123cSRichard Henderson 
float128_muladd(float128 a,float128 b,float128 c,int flags,float_status * status)2426dedd123cSRichard Henderson float128 QEMU_FLATTEN float128_muladd(float128 a, float128 b, float128 c,
2427dedd123cSRichard Henderson                                       int flags, float_status *status)
2428dedd123cSRichard Henderson {
2429dedd123cSRichard Henderson     FloatParts128 pa, pb, pc, *pr;
2430dedd123cSRichard Henderson 
2431dedd123cSRichard Henderson     float128_unpack_canonical(&pa, a, status);
2432dedd123cSRichard Henderson     float128_unpack_canonical(&pb, b, status);
2433dedd123cSRichard Henderson     float128_unpack_canonical(&pc, c, status);
2434dedd123cSRichard Henderson     pr = parts_muladd(&pa, &pb, &pc, flags, status);
2435dedd123cSRichard Henderson 
2436dedd123cSRichard Henderson     return float128_round_pack_canonical(pr, status);
24378282310dSLIU Zhiwei }
24388282310dSLIU Zhiwei 
24398282310dSLIU Zhiwei /*
2440ec961b81SRichard Henderson  * Division
2441cf07323dSAlex Bennée  */
2442cf07323dSAlex Bennée 
float16_div(float16 a,float16 b,float_status * status)2443cf07323dSAlex Bennée float16 float16_div(float16 a, float16 b, float_status *status)
2444cf07323dSAlex Bennée {
2445ec961b81SRichard Henderson     FloatParts64 pa, pb, *pr;
244698e256fcSRichard Henderson 
244798e256fcSRichard Henderson     float16_unpack_canonical(&pa, a, status);
244898e256fcSRichard Henderson     float16_unpack_canonical(&pb, b, status);
2449ec961b81SRichard Henderson     pr = parts_div(&pa, &pb, status);
2450cf07323dSAlex Bennée 
2451ec961b81SRichard Henderson     return float16_round_pack_canonical(pr, status);
2452cf07323dSAlex Bennée }
2453cf07323dSAlex Bennée 
24544a629561SEmilio G. Cota static float32 QEMU_SOFTFLOAT_ATTR
soft_f32_div(float32 a,float32 b,float_status * status)24554a629561SEmilio G. Cota soft_f32_div(float32 a, float32 b, float_status *status)
2456cf07323dSAlex Bennée {
2457ec961b81SRichard Henderson     FloatParts64 pa, pb, *pr;
245898e256fcSRichard Henderson 
245998e256fcSRichard Henderson     float32_unpack_canonical(&pa, a, status);
246098e256fcSRichard Henderson     float32_unpack_canonical(&pb, b, status);
2461ec961b81SRichard Henderson     pr = parts_div(&pa, &pb, status);
2462cf07323dSAlex Bennée 
2463ec961b81SRichard Henderson     return float32_round_pack_canonical(pr, status);
2464cf07323dSAlex Bennée }
2465cf07323dSAlex Bennée 
24664a629561SEmilio G. Cota static float64 QEMU_SOFTFLOAT_ATTR
soft_f64_div(float64 a,float64 b,float_status * status)24674a629561SEmilio G. Cota soft_f64_div(float64 a, float64 b, float_status *status)
2468cf07323dSAlex Bennée {
2469ec961b81SRichard Henderson     FloatParts64 pa, pb, *pr;
247098e256fcSRichard Henderson 
247198e256fcSRichard Henderson     float64_unpack_canonical(&pa, a, status);
247298e256fcSRichard Henderson     float64_unpack_canonical(&pb, b, status);
2473ec961b81SRichard Henderson     pr = parts_div(&pa, &pb, status);
2474cf07323dSAlex Bennée 
2475ec961b81SRichard Henderson     return float64_round_pack_canonical(pr, status);
2476cf07323dSAlex Bennée }
2477cf07323dSAlex Bennée 
hard_f32_div(float a,float b)24784a629561SEmilio G. Cota static float hard_f32_div(float a, float b)
24794a629561SEmilio G. Cota {
24804a629561SEmilio G. Cota     return a / b;
24814a629561SEmilio G. Cota }
24824a629561SEmilio G. Cota 
hard_f64_div(double a,double b)24834a629561SEmilio G. Cota static double hard_f64_div(double a, double b)
24844a629561SEmilio G. Cota {
24854a629561SEmilio G. Cota     return a / b;
24864a629561SEmilio G. Cota }
24874a629561SEmilio G. Cota 
f32_div_pre(union_float32 a,union_float32 b)24884a629561SEmilio G. Cota static bool f32_div_pre(union_float32 a, union_float32 b)
24894a629561SEmilio G. Cota {
24904a629561SEmilio G. Cota     if (QEMU_HARDFLOAT_2F32_USE_FP) {
24914a629561SEmilio G. Cota         return (fpclassify(a.h) == FP_NORMAL || fpclassify(a.h) == FP_ZERO) &&
24924a629561SEmilio G. Cota                fpclassify(b.h) == FP_NORMAL;
24934a629561SEmilio G. Cota     }
24944a629561SEmilio G. Cota     return float32_is_zero_or_normal(a.s) && float32_is_normal(b.s);
24954a629561SEmilio G. Cota }
24964a629561SEmilio G. Cota 
f64_div_pre(union_float64 a,union_float64 b)24974a629561SEmilio G. Cota static bool f64_div_pre(union_float64 a, union_float64 b)
24984a629561SEmilio G. Cota {
24994a629561SEmilio G. Cota     if (QEMU_HARDFLOAT_2F64_USE_FP) {
25004a629561SEmilio G. Cota         return (fpclassify(a.h) == FP_NORMAL || fpclassify(a.h) == FP_ZERO) &&
25014a629561SEmilio G. Cota                fpclassify(b.h) == FP_NORMAL;
25024a629561SEmilio G. Cota     }
25034a629561SEmilio G. Cota     return float64_is_zero_or_normal(a.s) && float64_is_normal(b.s);
25044a629561SEmilio G. Cota }
25054a629561SEmilio G. Cota 
f32_div_post(union_float32 a,union_float32 b)25064a629561SEmilio G. Cota static bool f32_div_post(union_float32 a, union_float32 b)
25074a629561SEmilio G. Cota {
25084a629561SEmilio G. Cota     if (QEMU_HARDFLOAT_2F32_USE_FP) {
25094a629561SEmilio G. Cota         return fpclassify(a.h) != FP_ZERO;
25104a629561SEmilio G. Cota     }
25114a629561SEmilio G. Cota     return !float32_is_zero(a.s);
25124a629561SEmilio G. Cota }
25134a629561SEmilio G. Cota 
f64_div_post(union_float64 a,union_float64 b)25144a629561SEmilio G. Cota static bool f64_div_post(union_float64 a, union_float64 b)
25154a629561SEmilio G. Cota {
25164a629561SEmilio G. Cota     if (QEMU_HARDFLOAT_2F64_USE_FP) {
25174a629561SEmilio G. Cota         return fpclassify(a.h) != FP_ZERO;
25184a629561SEmilio G. Cota     }
25194a629561SEmilio G. Cota     return !float64_is_zero(a.s);
25204a629561SEmilio G. Cota }
25214a629561SEmilio G. Cota 
25224a629561SEmilio G. Cota float32 QEMU_FLATTEN
float32_div(float32 a,float32 b,float_status * s)25234a629561SEmilio G. Cota float32_div(float32 a, float32 b, float_status *s)
25244a629561SEmilio G. Cota {
25254a629561SEmilio G. Cota     return float32_gen2(a, b, s, hard_f32_div, soft_f32_div,
2526b240c9c4SRichard Henderson                         f32_div_pre, f32_div_post);
25274a629561SEmilio G. Cota }
25284a629561SEmilio G. Cota 
25294a629561SEmilio G. Cota float64 QEMU_FLATTEN
float64_div(float64 a,float64 b,float_status * s)25304a629561SEmilio G. Cota float64_div(float64 a, float64 b, float_status *s)
25314a629561SEmilio G. Cota {
25324a629561SEmilio G. Cota     return float64_gen2(a, b, s, hard_f64_div, soft_f64_div,
2533b240c9c4SRichard Henderson                         f64_div_pre, f64_div_post);
25344a629561SEmilio G. Cota }
25354a629561SEmilio G. Cota 
float64r32_div(float64 a,float64 b,float_status * status)253642636fb9SRichard Henderson float64 float64r32_div(float64 a, float64 b, float_status *status)
253742636fb9SRichard Henderson {
253842636fb9SRichard Henderson     FloatParts64 pa, pb, *pr;
253942636fb9SRichard Henderson 
254042636fb9SRichard Henderson     float64_unpack_canonical(&pa, a, status);
254142636fb9SRichard Henderson     float64_unpack_canonical(&pb, b, status);
254242636fb9SRichard Henderson     pr = parts_div(&pa, &pb, status);
254342636fb9SRichard Henderson 
254442636fb9SRichard Henderson     return float64r32_round_pack_canonical(pr, status);
254542636fb9SRichard Henderson }
254642636fb9SRichard Henderson 
2547ec961b81SRichard Henderson bfloat16 QEMU_FLATTEN
bfloat16_div(bfloat16 a,bfloat16 b,float_status * status)2548ec961b81SRichard Henderson bfloat16_div(bfloat16 a, bfloat16 b, float_status *status)
25498282310dSLIU Zhiwei {
2550ec961b81SRichard Henderson     FloatParts64 pa, pb, *pr;
255198e256fcSRichard Henderson 
255298e256fcSRichard Henderson     bfloat16_unpack_canonical(&pa, a, status);
255398e256fcSRichard Henderson     bfloat16_unpack_canonical(&pb, b, status);
2554ec961b81SRichard Henderson     pr = parts_div(&pa, &pb, status);
25558282310dSLIU Zhiwei 
2556ec961b81SRichard Henderson     return bfloat16_round_pack_canonical(pr, status);
2557ec961b81SRichard Henderson }
2558ec961b81SRichard Henderson 
2559ec961b81SRichard Henderson float128 QEMU_FLATTEN
float128_div(float128 a,float128 b,float_status * status)2560ec961b81SRichard Henderson float128_div(float128 a, float128 b, float_status *status)
2561ec961b81SRichard Henderson {
2562ec961b81SRichard Henderson     FloatParts128 pa, pb, *pr;
2563ec961b81SRichard Henderson 
2564ec961b81SRichard Henderson     float128_unpack_canonical(&pa, a, status);
2565ec961b81SRichard Henderson     float128_unpack_canonical(&pb, b, status);
2566ec961b81SRichard Henderson     pr = parts_div(&pa, &pb, status);
2567ec961b81SRichard Henderson 
2568ec961b81SRichard Henderson     return float128_round_pack_canonical(pr, status);
25698282310dSLIU Zhiwei }
25708282310dSLIU Zhiwei 
floatx80_div(floatx80 a,floatx80 b,float_status * status)257138db99e2SRichard Henderson floatx80 floatx80_div(floatx80 a, floatx80 b, float_status *status)
257238db99e2SRichard Henderson {
257338db99e2SRichard Henderson     FloatParts128 pa, pb, *pr;
257438db99e2SRichard Henderson 
257538db99e2SRichard Henderson     if (!floatx80_unpack_canonical(&pa, a, status) ||
257638db99e2SRichard Henderson         !floatx80_unpack_canonical(&pb, b, status)) {
257738db99e2SRichard Henderson         return floatx80_default_nan(status);
257838db99e2SRichard Henderson     }
257938db99e2SRichard Henderson 
258038db99e2SRichard Henderson     pr = parts_div(&pa, &pb, status);
258138db99e2SRichard Henderson     return floatx80_round_pack_canonical(pr, status);
258238db99e2SRichard Henderson }
258338db99e2SRichard Henderson 
25848282310dSLIU Zhiwei /*
2585feaf2e9cSRichard Henderson  * Remainder
2586feaf2e9cSRichard Henderson  */
2587feaf2e9cSRichard Henderson 
float32_rem(float32 a,float32 b,float_status * status)2588feaf2e9cSRichard Henderson float32 float32_rem(float32 a, float32 b, float_status *status)
2589feaf2e9cSRichard Henderson {
2590feaf2e9cSRichard Henderson     FloatParts64 pa, pb, *pr;
2591feaf2e9cSRichard Henderson 
2592feaf2e9cSRichard Henderson     float32_unpack_canonical(&pa, a, status);
2593feaf2e9cSRichard Henderson     float32_unpack_canonical(&pb, b, status);
2594feaf2e9cSRichard Henderson     pr = parts_modrem(&pa, &pb, NULL, status);
2595feaf2e9cSRichard Henderson 
2596feaf2e9cSRichard Henderson     return float32_round_pack_canonical(pr, status);
2597feaf2e9cSRichard Henderson }
2598feaf2e9cSRichard Henderson 
float64_rem(float64 a,float64 b,float_status * status)2599feaf2e9cSRichard Henderson float64 float64_rem(float64 a, float64 b, float_status *status)
2600feaf2e9cSRichard Henderson {
2601feaf2e9cSRichard Henderson     FloatParts64 pa, pb, *pr;
2602feaf2e9cSRichard Henderson 
2603feaf2e9cSRichard Henderson     float64_unpack_canonical(&pa, a, status);
2604feaf2e9cSRichard Henderson     float64_unpack_canonical(&pb, b, status);
2605feaf2e9cSRichard Henderson     pr = parts_modrem(&pa, &pb, NULL, status);
2606feaf2e9cSRichard Henderson 
2607feaf2e9cSRichard Henderson     return float64_round_pack_canonical(pr, status);
2608feaf2e9cSRichard Henderson }
2609feaf2e9cSRichard Henderson 
float128_rem(float128 a,float128 b,float_status * status)2610feaf2e9cSRichard Henderson float128 float128_rem(float128 a, float128 b, float_status *status)
2611feaf2e9cSRichard Henderson {
2612feaf2e9cSRichard Henderson     FloatParts128 pa, pb, *pr;
2613feaf2e9cSRichard Henderson 
2614feaf2e9cSRichard Henderson     float128_unpack_canonical(&pa, a, status);
2615feaf2e9cSRichard Henderson     float128_unpack_canonical(&pb, b, status);
2616feaf2e9cSRichard Henderson     pr = parts_modrem(&pa, &pb, NULL, status);
2617feaf2e9cSRichard Henderson 
2618feaf2e9cSRichard Henderson     return float128_round_pack_canonical(pr, status);
2619feaf2e9cSRichard Henderson }
2620feaf2e9cSRichard Henderson 
2621feaf2e9cSRichard Henderson /*
2622feaf2e9cSRichard Henderson  * Returns the remainder of the extended double-precision floating-point value
2623feaf2e9cSRichard Henderson  * `a' with respect to the corresponding value `b'.
2624feaf2e9cSRichard Henderson  * If 'mod' is false, the operation is performed according to the IEC/IEEE
2625feaf2e9cSRichard Henderson  * Standard for Binary Floating-Point Arithmetic.  If 'mod' is true, return
2626feaf2e9cSRichard Henderson  * the remainder based on truncating the quotient toward zero instead and
2627feaf2e9cSRichard Henderson  * *quotient is set to the low 64 bits of the absolute value of the integer
2628feaf2e9cSRichard Henderson  * quotient.
2629feaf2e9cSRichard Henderson  */
floatx80_modrem(floatx80 a,floatx80 b,bool mod,uint64_t * quotient,float_status * status)2630feaf2e9cSRichard Henderson floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod,
2631feaf2e9cSRichard Henderson                          uint64_t *quotient, float_status *status)
2632feaf2e9cSRichard Henderson {
2633feaf2e9cSRichard Henderson     FloatParts128 pa, pb, *pr;
2634feaf2e9cSRichard Henderson 
2635feaf2e9cSRichard Henderson     *quotient = 0;
2636feaf2e9cSRichard Henderson     if (!floatx80_unpack_canonical(&pa, a, status) ||
2637feaf2e9cSRichard Henderson         !floatx80_unpack_canonical(&pb, b, status)) {
2638feaf2e9cSRichard Henderson         return floatx80_default_nan(status);
2639feaf2e9cSRichard Henderson     }
2640feaf2e9cSRichard Henderson     pr = parts_modrem(&pa, &pb, mod ? quotient : NULL, status);
2641feaf2e9cSRichard Henderson 
2642feaf2e9cSRichard Henderson     return floatx80_round_pack_canonical(pr, status);
2643feaf2e9cSRichard Henderson }
2644feaf2e9cSRichard Henderson 
floatx80_rem(floatx80 a,floatx80 b,float_status * status)2645feaf2e9cSRichard Henderson floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status)
2646feaf2e9cSRichard Henderson {
2647feaf2e9cSRichard Henderson     uint64_t quotient;
2648feaf2e9cSRichard Henderson     return floatx80_modrem(a, b, false, &quotient, status);
2649feaf2e9cSRichard Henderson }
2650feaf2e9cSRichard Henderson 
floatx80_mod(floatx80 a,floatx80 b,float_status * status)2651feaf2e9cSRichard Henderson floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status)
2652feaf2e9cSRichard Henderson {
2653feaf2e9cSRichard Henderson     uint64_t quotient;
2654feaf2e9cSRichard Henderson     return floatx80_modrem(a, b, true, &quotient, status);
2655feaf2e9cSRichard Henderson }
2656feaf2e9cSRichard Henderson 
2657feaf2e9cSRichard Henderson /*
26586fed16b2SAlex Bennée  * Float to Float conversions
26596fed16b2SAlex Bennée  *
26606fed16b2SAlex Bennée  * Returns the result of converting one float format to another. The
26616fed16b2SAlex Bennée  * conversion is performed according to the IEC/IEEE Standard for
26626fed16b2SAlex Bennée  * Binary Floating-Point Arithmetic.
26636fed16b2SAlex Bennée  *
2664c3f1875eSRichard Henderson  * Usually this only needs to take care of raising invalid exceptions
2665c3f1875eSRichard Henderson  * and handling the conversion on NaNs.
26666fed16b2SAlex Bennée  */
26676fed16b2SAlex Bennée 
parts_float_to_ahp(FloatParts64 * a,float_status * s)2668c3f1875eSRichard Henderson static void parts_float_to_ahp(FloatParts64 *a, float_status *s)
26696fed16b2SAlex Bennée {
2670c3f1875eSRichard Henderson     switch (a->cls) {
26716fed16b2SAlex Bennée     case float_class_snan:
2672e706d445SRichard Henderson         float_raise(float_flag_invalid_snan, s);
2673e706d445SRichard Henderson         /* fall through */
2674e706d445SRichard Henderson     case float_class_qnan:
2675c3f1875eSRichard Henderson         /*
2676c3f1875eSRichard Henderson          * There is no NaN in the destination format.  Raise Invalid
26776fed16b2SAlex Bennée          * and return a zero with the sign of the input NaN.
26786fed16b2SAlex Bennée          */
2679d82f3b2dSRichard Henderson         float_raise(float_flag_invalid, s);
2680c3f1875eSRichard Henderson         a->cls = float_class_zero;
26816fed16b2SAlex Bennée         break;
26826fed16b2SAlex Bennée 
26836fed16b2SAlex Bennée     case float_class_inf:
2684c3f1875eSRichard Henderson         /*
2685c3f1875eSRichard Henderson          * There is no Inf in the destination format.  Raise Invalid
26866fed16b2SAlex Bennée          * and return the maximum normal with the correct sign.
26876fed16b2SAlex Bennée          */
2688d82f3b2dSRichard Henderson         float_raise(float_flag_invalid, s);
2689c3f1875eSRichard Henderson         a->cls = float_class_normal;
2690c3f1875eSRichard Henderson         a->exp = float16_params_ahp.exp_max;
2691c3f1875eSRichard Henderson         a->frac = MAKE_64BIT_MASK(float16_params_ahp.frac_shift,
2692c3f1875eSRichard Henderson                                   float16_params_ahp.frac_size + 1);
2693c3f1875eSRichard Henderson         break;
2694c3f1875eSRichard Henderson 
2695c3f1875eSRichard Henderson     case float_class_normal:
2696c3f1875eSRichard Henderson     case float_class_zero:
26976fed16b2SAlex Bennée         break;
26986fed16b2SAlex Bennée 
26996fed16b2SAlex Bennée     default:
2700c3f1875eSRichard Henderson         g_assert_not_reached();
27016fed16b2SAlex Bennée     }
27026fed16b2SAlex Bennée }
2703c3f1875eSRichard Henderson 
parts64_float_to_float(FloatParts64 * a,float_status * s)2704c3f1875eSRichard Henderson static void parts64_float_to_float(FloatParts64 *a, float_status *s)
2705c3f1875eSRichard Henderson {
2706c3f1875eSRichard Henderson     if (is_nan(a->cls)) {
2707c3f1875eSRichard Henderson         parts_return_nan(a, s);
27086fed16b2SAlex Bennée     }
2709c3f1875eSRichard Henderson }
2710c3f1875eSRichard Henderson 
parts128_float_to_float(FloatParts128 * a,float_status * s)2711c3f1875eSRichard Henderson static void parts128_float_to_float(FloatParts128 *a, float_status *s)
2712c3f1875eSRichard Henderson {
2713c3f1875eSRichard Henderson     if (is_nan(a->cls)) {
2714c3f1875eSRichard Henderson         parts_return_nan(a, s);
2715c3f1875eSRichard Henderson     }
2716c3f1875eSRichard Henderson }
2717c3f1875eSRichard Henderson 
2718c3f1875eSRichard Henderson #define parts_float_to_float(P, S) \
2719c3f1875eSRichard Henderson     PARTS_GENERIC_64_128(float_to_float, P)(P, S)
27206fed16b2SAlex Bennée 
parts_float_to_float_narrow(FloatParts64 * a,FloatParts128 * b,float_status * s)27219882ccafSRichard Henderson static void parts_float_to_float_narrow(FloatParts64 *a, FloatParts128 *b,
27229882ccafSRichard Henderson                                         float_status *s)
27239882ccafSRichard Henderson {
27249882ccafSRichard Henderson     a->cls = b->cls;
27259882ccafSRichard Henderson     a->sign = b->sign;
27269882ccafSRichard Henderson     a->exp = b->exp;
27279882ccafSRichard Henderson 
27289882ccafSRichard Henderson     if (a->cls == float_class_normal) {
27299882ccafSRichard Henderson         frac_truncjam(a, b);
27309882ccafSRichard Henderson     } else if (is_nan(a->cls)) {
27319882ccafSRichard Henderson         /* Discard the low bits of the NaN. */
27329882ccafSRichard Henderson         a->frac = b->frac_hi;
27339882ccafSRichard Henderson         parts_return_nan(a, s);
27349882ccafSRichard Henderson     }
27359882ccafSRichard Henderson }
27369882ccafSRichard Henderson 
parts_float_to_float_widen(FloatParts128 * a,FloatParts64 * b,float_status * s)27379882ccafSRichard Henderson static void parts_float_to_float_widen(FloatParts128 *a, FloatParts64 *b,
27389882ccafSRichard Henderson                                        float_status *s)
27399882ccafSRichard Henderson {
27409882ccafSRichard Henderson     a->cls = b->cls;
27419882ccafSRichard Henderson     a->sign = b->sign;
27429882ccafSRichard Henderson     a->exp = b->exp;
27439882ccafSRichard Henderson     frac_widen(a, b);
27449882ccafSRichard Henderson 
27459882ccafSRichard Henderson     if (is_nan(a->cls)) {
27469882ccafSRichard Henderson         parts_return_nan(a, s);
27479882ccafSRichard Henderson     }
27489882ccafSRichard Henderson }
27499882ccafSRichard Henderson 
float16_to_float32(float16 a,bool ieee,float_status * s)27506fed16b2SAlex Bennée float32 float16_to_float32(float16 a, bool ieee, float_status *s)
27516fed16b2SAlex Bennée {
27526fed16b2SAlex Bennée     const FloatFmt *fmt16 = ieee ? &float16_params : &float16_params_ahp;
2753c3f1875eSRichard Henderson     FloatParts64 p;
275498e256fcSRichard Henderson 
2755c3f1875eSRichard Henderson     float16a_unpack_canonical(&p, a, s, fmt16);
2756c3f1875eSRichard Henderson     parts_float_to_float(&p, s);
2757c3f1875eSRichard Henderson     return float32_round_pack_canonical(&p, s);
27586fed16b2SAlex Bennée }
27596fed16b2SAlex Bennée 
float16_to_float64(float16 a,bool ieee,float_status * s)27606fed16b2SAlex Bennée float64 float16_to_float64(float16 a, bool ieee, float_status *s)
27616fed16b2SAlex Bennée {
27626fed16b2SAlex Bennée     const FloatFmt *fmt16 = ieee ? &float16_params : &float16_params_ahp;
2763c3f1875eSRichard Henderson     FloatParts64 p;
276498e256fcSRichard Henderson 
2765c3f1875eSRichard Henderson     float16a_unpack_canonical(&p, a, s, fmt16);
2766c3f1875eSRichard Henderson     parts_float_to_float(&p, s);
2767c3f1875eSRichard Henderson     return float64_round_pack_canonical(&p, s);
27686fed16b2SAlex Bennée }
27696fed16b2SAlex Bennée 
float32_to_float16(float32 a,bool ieee,float_status * s)27706fed16b2SAlex Bennée float16 float32_to_float16(float32 a, bool ieee, float_status *s)
27716fed16b2SAlex Bennée {
2772c3f1875eSRichard Henderson     FloatParts64 p;
2773c3f1875eSRichard Henderson     const FloatFmt *fmt;
277498e256fcSRichard Henderson 
2775c3f1875eSRichard Henderson     float32_unpack_canonical(&p, a, s);
2776c3f1875eSRichard Henderson     if (ieee) {
2777c3f1875eSRichard Henderson         parts_float_to_float(&p, s);
2778c3f1875eSRichard Henderson         fmt = &float16_params;
2779c3f1875eSRichard Henderson     } else {
2780c3f1875eSRichard Henderson         parts_float_to_ahp(&p, s);
2781c3f1875eSRichard Henderson         fmt = &float16_params_ahp;
2782c3f1875eSRichard Henderson     }
2783c3f1875eSRichard Henderson     return float16a_round_pack_canonical(&p, s, fmt);
27846fed16b2SAlex Bennée }
27856fed16b2SAlex Bennée 
278621381dcfSMatus Kysel static float64 QEMU_SOFTFLOAT_ATTR
soft_float32_to_float64(float32 a,float_status * s)278721381dcfSMatus Kysel soft_float32_to_float64(float32 a, float_status *s)
27886fed16b2SAlex Bennée {
2789c3f1875eSRichard Henderson     FloatParts64 p;
279098e256fcSRichard Henderson 
2791c3f1875eSRichard Henderson     float32_unpack_canonical(&p, a, s);
2792c3f1875eSRichard Henderson     parts_float_to_float(&p, s);
2793c3f1875eSRichard Henderson     return float64_round_pack_canonical(&p, s);
27946fed16b2SAlex Bennée }
27956fed16b2SAlex Bennée 
float32_to_float64(float32 a,float_status * s)279621381dcfSMatus Kysel float64 float32_to_float64(float32 a, float_status *s)
279721381dcfSMatus Kysel {
279821381dcfSMatus Kysel     if (likely(float32_is_normal(a))) {
279921381dcfSMatus Kysel         /* Widening conversion can never produce inexact results.  */
280021381dcfSMatus Kysel         union_float32 uf;
280121381dcfSMatus Kysel         union_float64 ud;
280221381dcfSMatus Kysel         uf.s = a;
280321381dcfSMatus Kysel         ud.h = uf.h;
280421381dcfSMatus Kysel         return ud.s;
280521381dcfSMatus Kysel     } else if (float32_is_zero(a)) {
280621381dcfSMatus Kysel         return float64_set_sign(float64_zero, float32_is_neg(a));
280721381dcfSMatus Kysel     } else {
280821381dcfSMatus Kysel         return soft_float32_to_float64(a, s);
280921381dcfSMatus Kysel     }
281021381dcfSMatus Kysel }
281121381dcfSMatus Kysel 
float64_to_float16(float64 a,bool ieee,float_status * s)28126fed16b2SAlex Bennée float16 float64_to_float16(float64 a, bool ieee, float_status *s)
28136fed16b2SAlex Bennée {
2814c3f1875eSRichard Henderson     FloatParts64 p;
2815c3f1875eSRichard Henderson     const FloatFmt *fmt;
281698e256fcSRichard Henderson 
2817c3f1875eSRichard Henderson     float64_unpack_canonical(&p, a, s);
2818c3f1875eSRichard Henderson     if (ieee) {
2819c3f1875eSRichard Henderson         parts_float_to_float(&p, s);
2820c3f1875eSRichard Henderson         fmt = &float16_params;
2821c3f1875eSRichard Henderson     } else {
2822c3f1875eSRichard Henderson         parts_float_to_ahp(&p, s);
2823c3f1875eSRichard Henderson         fmt = &float16_params_ahp;
2824c3f1875eSRichard Henderson     }
2825c3f1875eSRichard Henderson     return float16a_round_pack_canonical(&p, s, fmt);
28266fed16b2SAlex Bennée }
28276fed16b2SAlex Bennée 
float64_to_float32(float64 a,float_status * s)28286fed16b2SAlex Bennée float32 float64_to_float32(float64 a, float_status *s)
28296fed16b2SAlex Bennée {
2830c3f1875eSRichard Henderson     FloatParts64 p;
283198e256fcSRichard Henderson 
2832c3f1875eSRichard Henderson     float64_unpack_canonical(&p, a, s);
2833c3f1875eSRichard Henderson     parts_float_to_float(&p, s);
2834c3f1875eSRichard Henderson     return float32_round_pack_canonical(&p, s);
28356fed16b2SAlex Bennée }
28366fed16b2SAlex Bennée 
bfloat16_to_float32(bfloat16 a,float_status * s)283734f0c0a9SLIU Zhiwei float32 bfloat16_to_float32(bfloat16 a, float_status *s)
283834f0c0a9SLIU Zhiwei {
2839c3f1875eSRichard Henderson     FloatParts64 p;
284098e256fcSRichard Henderson 
2841c3f1875eSRichard Henderson     bfloat16_unpack_canonical(&p, a, s);
2842c3f1875eSRichard Henderson     parts_float_to_float(&p, s);
2843c3f1875eSRichard Henderson     return float32_round_pack_canonical(&p, s);
284434f0c0a9SLIU Zhiwei }
284534f0c0a9SLIU Zhiwei 
bfloat16_to_float64(bfloat16 a,float_status * s)284634f0c0a9SLIU Zhiwei float64 bfloat16_to_float64(bfloat16 a, float_status *s)
284734f0c0a9SLIU Zhiwei {
2848c3f1875eSRichard Henderson     FloatParts64 p;
284998e256fcSRichard Henderson 
2850c3f1875eSRichard Henderson     bfloat16_unpack_canonical(&p, a, s);
2851c3f1875eSRichard Henderson     parts_float_to_float(&p, s);
2852c3f1875eSRichard Henderson     return float64_round_pack_canonical(&p, s);
285334f0c0a9SLIU Zhiwei }
285434f0c0a9SLIU Zhiwei 
float32_to_bfloat16(float32 a,float_status * s)285534f0c0a9SLIU Zhiwei bfloat16 float32_to_bfloat16(float32 a, float_status *s)
285634f0c0a9SLIU Zhiwei {
2857c3f1875eSRichard Henderson     FloatParts64 p;
285898e256fcSRichard Henderson 
2859c3f1875eSRichard Henderson     float32_unpack_canonical(&p, a, s);
2860c3f1875eSRichard Henderson     parts_float_to_float(&p, s);
2861c3f1875eSRichard Henderson     return bfloat16_round_pack_canonical(&p, s);
286234f0c0a9SLIU Zhiwei }
286334f0c0a9SLIU Zhiwei 
float64_to_bfloat16(float64 a,float_status * s)286434f0c0a9SLIU Zhiwei bfloat16 float64_to_bfloat16(float64 a, float_status *s)
286534f0c0a9SLIU Zhiwei {
2866c3f1875eSRichard Henderson     FloatParts64 p;
286798e256fcSRichard Henderson 
2868c3f1875eSRichard Henderson     float64_unpack_canonical(&p, a, s);
2869c3f1875eSRichard Henderson     parts_float_to_float(&p, s);
2870c3f1875eSRichard Henderson     return bfloat16_round_pack_canonical(&p, s);
287134f0c0a9SLIU Zhiwei }
287234f0c0a9SLIU Zhiwei 
float128_to_float32(float128 a,float_status * s)28739882ccafSRichard Henderson float32 float128_to_float32(float128 a, float_status *s)
28749882ccafSRichard Henderson {
28759882ccafSRichard Henderson     FloatParts64 p64;
28769882ccafSRichard Henderson     FloatParts128 p128;
28779882ccafSRichard Henderson 
28789882ccafSRichard Henderson     float128_unpack_canonical(&p128, a, s);
28799882ccafSRichard Henderson     parts_float_to_float_narrow(&p64, &p128, s);
28809882ccafSRichard Henderson     return float32_round_pack_canonical(&p64, s);
28819882ccafSRichard Henderson }
28829882ccafSRichard Henderson 
float128_to_float64(float128 a,float_status * s)28839882ccafSRichard Henderson float64 float128_to_float64(float128 a, float_status *s)
28849882ccafSRichard Henderson {
28859882ccafSRichard Henderson     FloatParts64 p64;
28869882ccafSRichard Henderson     FloatParts128 p128;
28879882ccafSRichard Henderson 
28889882ccafSRichard Henderson     float128_unpack_canonical(&p128, a, s);
28899882ccafSRichard Henderson     parts_float_to_float_narrow(&p64, &p128, s);
28909882ccafSRichard Henderson     return float64_round_pack_canonical(&p64, s);
28919882ccafSRichard Henderson }
28929882ccafSRichard Henderson 
float32_to_float128(float32 a,float_status * s)28939882ccafSRichard Henderson float128 float32_to_float128(float32 a, float_status *s)
28949882ccafSRichard Henderson {
28959882ccafSRichard Henderson     FloatParts64 p64;
28969882ccafSRichard Henderson     FloatParts128 p128;
28979882ccafSRichard Henderson 
28989882ccafSRichard Henderson     float32_unpack_canonical(&p64, a, s);
28999882ccafSRichard Henderson     parts_float_to_float_widen(&p128, &p64, s);
29009882ccafSRichard Henderson     return float128_round_pack_canonical(&p128, s);
29019882ccafSRichard Henderson }
29029882ccafSRichard Henderson 
float64_to_float128(float64 a,float_status * s)29039882ccafSRichard Henderson float128 float64_to_float128(float64 a, float_status *s)
29049882ccafSRichard Henderson {
29059882ccafSRichard Henderson     FloatParts64 p64;
29069882ccafSRichard Henderson     FloatParts128 p128;
29079882ccafSRichard Henderson 
29089882ccafSRichard Henderson     float64_unpack_canonical(&p64, a, s);
29099882ccafSRichard Henderson     parts_float_to_float_widen(&p128, &p64, s);
29109882ccafSRichard Henderson     return float128_round_pack_canonical(&p128, s);
29119882ccafSRichard Henderson }
29129882ccafSRichard Henderson 
floatx80_to_float32(floatx80 a,float_status * s)29138ae5719cSRichard Henderson float32 floatx80_to_float32(floatx80 a, float_status *s)
29148ae5719cSRichard Henderson {
29158ae5719cSRichard Henderson     FloatParts64 p64;
29168ae5719cSRichard Henderson     FloatParts128 p128;
29178ae5719cSRichard Henderson 
29188ae5719cSRichard Henderson     if (floatx80_unpack_canonical(&p128, a, s)) {
29198ae5719cSRichard Henderson         parts_float_to_float_narrow(&p64, &p128, s);
29208ae5719cSRichard Henderson     } else {
29218ae5719cSRichard Henderson         parts_default_nan(&p64, s);
29228ae5719cSRichard Henderson     }
29238ae5719cSRichard Henderson     return float32_round_pack_canonical(&p64, s);
29248ae5719cSRichard Henderson }
29258ae5719cSRichard Henderson 
floatx80_to_float64(floatx80 a,float_status * s)29268ae5719cSRichard Henderson float64 floatx80_to_float64(floatx80 a, float_status *s)
29278ae5719cSRichard Henderson {
29288ae5719cSRichard Henderson     FloatParts64 p64;
29298ae5719cSRichard Henderson     FloatParts128 p128;
29308ae5719cSRichard Henderson 
29318ae5719cSRichard Henderson     if (floatx80_unpack_canonical(&p128, a, s)) {
29328ae5719cSRichard Henderson         parts_float_to_float_narrow(&p64, &p128, s);
29338ae5719cSRichard Henderson     } else {
29348ae5719cSRichard Henderson         parts_default_nan(&p64, s);
29358ae5719cSRichard Henderson     }
29368ae5719cSRichard Henderson     return float64_round_pack_canonical(&p64, s);
29378ae5719cSRichard Henderson }
29388ae5719cSRichard Henderson 
floatx80_to_float128(floatx80 a,float_status * s)29398ae5719cSRichard Henderson float128 floatx80_to_float128(floatx80 a, float_status *s)
29408ae5719cSRichard Henderson {
29418ae5719cSRichard Henderson     FloatParts128 p;
29428ae5719cSRichard Henderson 
29438ae5719cSRichard Henderson     if (floatx80_unpack_canonical(&p, a, s)) {
29448ae5719cSRichard Henderson         parts_float_to_float(&p, s);
29458ae5719cSRichard Henderson     } else {
29468ae5719cSRichard Henderson         parts_default_nan(&p, s);
29478ae5719cSRichard Henderson     }
29488ae5719cSRichard Henderson     return float128_round_pack_canonical(&p, s);
29498ae5719cSRichard Henderson }
29508ae5719cSRichard Henderson 
float32_to_floatx80(float32 a,float_status * s)29518ae5719cSRichard Henderson floatx80 float32_to_floatx80(float32 a, float_status *s)
29528ae5719cSRichard Henderson {
29538ae5719cSRichard Henderson     FloatParts64 p64;
29548ae5719cSRichard Henderson     FloatParts128 p128;
29558ae5719cSRichard Henderson 
29568ae5719cSRichard Henderson     float32_unpack_canonical(&p64, a, s);
29578ae5719cSRichard Henderson     parts_float_to_float_widen(&p128, &p64, s);
29588ae5719cSRichard Henderson     return floatx80_round_pack_canonical(&p128, s);
29598ae5719cSRichard Henderson }
29608ae5719cSRichard Henderson 
float64_to_floatx80(float64 a,float_status * s)29618ae5719cSRichard Henderson floatx80 float64_to_floatx80(float64 a, float_status *s)
29628ae5719cSRichard Henderson {
29638ae5719cSRichard Henderson     FloatParts64 p64;
29648ae5719cSRichard Henderson     FloatParts128 p128;
29658ae5719cSRichard Henderson 
29668ae5719cSRichard Henderson     float64_unpack_canonical(&p64, a, s);
29678ae5719cSRichard Henderson     parts_float_to_float_widen(&p128, &p64, s);
29688ae5719cSRichard Henderson     return floatx80_round_pack_canonical(&p128, s);
29698ae5719cSRichard Henderson }
29708ae5719cSRichard Henderson 
float128_to_floatx80(float128 a,float_status * s)29718ae5719cSRichard Henderson floatx80 float128_to_floatx80(float128 a, float_status *s)
29728ae5719cSRichard Henderson {
29738ae5719cSRichard Henderson     FloatParts128 p;
29748ae5719cSRichard Henderson 
29758ae5719cSRichard Henderson     float128_unpack_canonical(&p, a, s);
29768ae5719cSRichard Henderson     parts_float_to_float(&p, s);
29778ae5719cSRichard Henderson     return floatx80_round_pack_canonical(&p, s);
29788ae5719cSRichard Henderson }
29798ae5719cSRichard Henderson 
29806fed16b2SAlex Bennée /*
2981afc34931SRichard Henderson  * Round to integral value
2982dbe4d53aSAlex Bennée  */
2983dbe4d53aSAlex Bennée 
float16_round_to_int(float16 a,float_status * s)2984dbe4d53aSAlex Bennée float16 float16_round_to_int(float16 a, float_status *s)
2985dbe4d53aSAlex Bennée {
2986afc34931SRichard Henderson     FloatParts64 p;
298798e256fcSRichard Henderson 
2988afc34931SRichard Henderson     float16_unpack_canonical(&p, a, s);
2989afc34931SRichard Henderson     parts_round_to_int(&p, s->float_rounding_mode, 0, s, &float16_params);
2990afc34931SRichard Henderson     return float16_round_pack_canonical(&p, s);
2991dbe4d53aSAlex Bennée }
2992dbe4d53aSAlex Bennée 
float32_round_to_int(float32 a,float_status * s)2993dbe4d53aSAlex Bennée float32 float32_round_to_int(float32 a, float_status *s)
2994dbe4d53aSAlex Bennée {
2995afc34931SRichard Henderson     FloatParts64 p;
299698e256fcSRichard Henderson 
2997afc34931SRichard Henderson     float32_unpack_canonical(&p, a, s);
2998afc34931SRichard Henderson     parts_round_to_int(&p, s->float_rounding_mode, 0, s, &float32_params);
2999afc34931SRichard Henderson     return float32_round_pack_canonical(&p, s);
3000dbe4d53aSAlex Bennée }
3001dbe4d53aSAlex Bennée 
float64_round_to_int(float64 a,float_status * s)3002dbe4d53aSAlex Bennée float64 float64_round_to_int(float64 a, float_status *s)
3003dbe4d53aSAlex Bennée {
3004afc34931SRichard Henderson     FloatParts64 p;
300598e256fcSRichard Henderson 
3006afc34931SRichard Henderson     float64_unpack_canonical(&p, a, s);
3007afc34931SRichard Henderson     parts_round_to_int(&p, s->float_rounding_mode, 0, s, &float64_params);
3008afc34931SRichard Henderson     return float64_round_pack_canonical(&p, s);
3009dbe4d53aSAlex Bennée }
3010dbe4d53aSAlex Bennée 
bfloat16_round_to_int(bfloat16 a,float_status * s)301134f0c0a9SLIU Zhiwei bfloat16 bfloat16_round_to_int(bfloat16 a, float_status *s)
301234f0c0a9SLIU Zhiwei {
3013afc34931SRichard Henderson     FloatParts64 p;
301498e256fcSRichard Henderson 
3015afc34931SRichard Henderson     bfloat16_unpack_canonical(&p, a, s);
3016afc34931SRichard Henderson     parts_round_to_int(&p, s->float_rounding_mode, 0, s, &bfloat16_params);
3017afc34931SRichard Henderson     return bfloat16_round_pack_canonical(&p, s);
3018afc34931SRichard Henderson }
3019afc34931SRichard Henderson 
float128_round_to_int(float128 a,float_status * s)3020afc34931SRichard Henderson float128 float128_round_to_int(float128 a, float_status *s)
3021afc34931SRichard Henderson {
3022afc34931SRichard Henderson     FloatParts128 p;
3023afc34931SRichard Henderson 
3024afc34931SRichard Henderson     float128_unpack_canonical(&p, a, s);
3025afc34931SRichard Henderson     parts_round_to_int(&p, s->float_rounding_mode, 0, s, &float128_params);
3026afc34931SRichard Henderson     return float128_round_pack_canonical(&p, s);
302734f0c0a9SLIU Zhiwei }
302834f0c0a9SLIU Zhiwei 
floatx80_round_to_int(floatx80 a,float_status * status)3029f9a95a78SRichard Henderson floatx80 floatx80_round_to_int(floatx80 a, float_status *status)
3030f9a95a78SRichard Henderson {
3031f9a95a78SRichard Henderson     FloatParts128 p;
3032f9a95a78SRichard Henderson 
3033f9a95a78SRichard Henderson     if (!floatx80_unpack_canonical(&p, a, status)) {
3034f9a95a78SRichard Henderson         return floatx80_default_nan(status);
3035f9a95a78SRichard Henderson     }
3036f9a95a78SRichard Henderson 
3037f9a95a78SRichard Henderson     parts_round_to_int(&p, status->float_rounding_mode, 0, status,
3038f9a95a78SRichard Henderson                        &floatx80_params[status->floatx80_rounding_precision]);
3039f9a95a78SRichard Henderson     return floatx80_round_pack_canonical(&p, status);
3040f9a95a78SRichard Henderson }
3041f9a95a78SRichard Henderson 
304234f0c0a9SLIU Zhiwei /*
3043463b3f0dSRichard Henderson  * Floating-point to signed integer conversions
3044ab52f973SAlex Bennée  */
3045ab52f973SAlex Bennée 
float16_to_int8_scalbn(float16 a,FloatRoundMode rmode,int scale,float_status * s)30460d93d8ecSFrank Chang int8_t float16_to_int8_scalbn(float16 a, FloatRoundMode rmode, int scale,
30470d93d8ecSFrank Chang                               float_status *s)
30480d93d8ecSFrank Chang {
304998e256fcSRichard Henderson     FloatParts64 p;
305098e256fcSRichard Henderson 
305198e256fcSRichard Henderson     float16_unpack_canonical(&p, a, s);
3052463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT8_MIN, INT8_MAX, s);
30530d93d8ecSFrank Chang }
30540d93d8ecSFrank Chang 
float16_to_int16_scalbn(float16 a,FloatRoundMode rmode,int scale,float_status * s)30553dede407SRichard Henderson int16_t float16_to_int16_scalbn(float16 a, FloatRoundMode rmode, int scale,
30562f6c74beSRichard Henderson                                 float_status *s)
30572f6c74beSRichard Henderson {
305898e256fcSRichard Henderson     FloatParts64 p;
305998e256fcSRichard Henderson 
306098e256fcSRichard Henderson     float16_unpack_canonical(&p, a, s);
3061463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT16_MIN, INT16_MAX, s);
3062ab52f973SAlex Bennée }
3063ab52f973SAlex Bennée 
float16_to_int32_scalbn(float16 a,FloatRoundMode rmode,int scale,float_status * s)30643dede407SRichard Henderson int32_t float16_to_int32_scalbn(float16 a, FloatRoundMode rmode, int scale,
30652f6c74beSRichard Henderson                                 float_status *s)
30662f6c74beSRichard Henderson {
306798e256fcSRichard Henderson     FloatParts64 p;
306898e256fcSRichard Henderson 
306998e256fcSRichard Henderson     float16_unpack_canonical(&p, a, s);
3070463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT32_MIN, INT32_MAX, s);
30712f6c74beSRichard Henderson }
3072ab52f973SAlex Bennée 
float16_to_int64_scalbn(float16 a,FloatRoundMode rmode,int scale,float_status * s)30733dede407SRichard Henderson int64_t float16_to_int64_scalbn(float16 a, FloatRoundMode rmode, int scale,
30742f6c74beSRichard Henderson                                 float_status *s)
30752f6c74beSRichard Henderson {
307698e256fcSRichard Henderson     FloatParts64 p;
307798e256fcSRichard Henderson 
307898e256fcSRichard Henderson     float16_unpack_canonical(&p, a, s);
3079463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT64_MIN, INT64_MAX, s);
30802f6c74beSRichard Henderson }
3081ab52f973SAlex Bennée 
float32_to_int16_scalbn(float32 a,FloatRoundMode rmode,int scale,float_status * s)30823dede407SRichard Henderson int16_t float32_to_int16_scalbn(float32 a, FloatRoundMode rmode, int scale,
30832f6c74beSRichard Henderson                                 float_status *s)
30842f6c74beSRichard Henderson {
308598e256fcSRichard Henderson     FloatParts64 p;
308698e256fcSRichard Henderson 
308798e256fcSRichard Henderson     float32_unpack_canonical(&p, a, s);
3088463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT16_MIN, INT16_MAX, s);
30892f6c74beSRichard Henderson }
3090ab52f973SAlex Bennée 
float32_to_int32_scalbn(float32 a,FloatRoundMode rmode,int scale,float_status * s)30913dede407SRichard Henderson int32_t float32_to_int32_scalbn(float32 a, FloatRoundMode rmode, int scale,
30922f6c74beSRichard Henderson                                 float_status *s)
30932f6c74beSRichard Henderson {
309498e256fcSRichard Henderson     FloatParts64 p;
309598e256fcSRichard Henderson 
309698e256fcSRichard Henderson     float32_unpack_canonical(&p, a, s);
3097463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT32_MIN, INT32_MAX, s);
30982f6c74beSRichard Henderson }
30992f6c74beSRichard Henderson 
float32_to_int64_scalbn(float32 a,FloatRoundMode rmode,int scale,float_status * s)31003dede407SRichard Henderson int64_t float32_to_int64_scalbn(float32 a, FloatRoundMode rmode, int scale,
31012f6c74beSRichard Henderson                                 float_status *s)
31022f6c74beSRichard Henderson {
310398e256fcSRichard Henderson     FloatParts64 p;
310498e256fcSRichard Henderson 
310598e256fcSRichard Henderson     float32_unpack_canonical(&p, a, s);
3106463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT64_MIN, INT64_MAX, s);
31072f6c74beSRichard Henderson }
31082f6c74beSRichard Henderson 
float64_to_int16_scalbn(float64 a,FloatRoundMode rmode,int scale,float_status * s)31093dede407SRichard Henderson int16_t float64_to_int16_scalbn(float64 a, FloatRoundMode rmode, int scale,
31102f6c74beSRichard Henderson                                 float_status *s)
31112f6c74beSRichard Henderson {
311298e256fcSRichard Henderson     FloatParts64 p;
311398e256fcSRichard Henderson 
311498e256fcSRichard Henderson     float64_unpack_canonical(&p, a, s);
3115463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT16_MIN, INT16_MAX, s);
31162f6c74beSRichard Henderson }
31172f6c74beSRichard Henderson 
float64_to_int32_scalbn(float64 a,FloatRoundMode rmode,int scale,float_status * s)31183dede407SRichard Henderson int32_t float64_to_int32_scalbn(float64 a, FloatRoundMode rmode, int scale,
31192f6c74beSRichard Henderson                                 float_status *s)
31202f6c74beSRichard Henderson {
312198e256fcSRichard Henderson     FloatParts64 p;
312298e256fcSRichard Henderson 
312398e256fcSRichard Henderson     float64_unpack_canonical(&p, a, s);
3124463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT32_MIN, INT32_MAX, s);
31252f6c74beSRichard Henderson }
31262f6c74beSRichard Henderson 
float64_to_int64_scalbn(float64 a,FloatRoundMode rmode,int scale,float_status * s)31273dede407SRichard Henderson int64_t float64_to_int64_scalbn(float64 a, FloatRoundMode rmode, int scale,
31282f6c74beSRichard Henderson                                 float_status *s)
31292f6c74beSRichard Henderson {
313098e256fcSRichard Henderson     FloatParts64 p;
313198e256fcSRichard Henderson 
313298e256fcSRichard Henderson     float64_unpack_canonical(&p, a, s);
3133463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT64_MIN, INT64_MAX, s);
3134463b3f0dSRichard Henderson }
3135463b3f0dSRichard Henderson 
bfloat16_to_int8_scalbn(bfloat16 a,FloatRoundMode rmode,int scale,float_status * s)313600f9ef8fSLIU Zhiwei int8_t bfloat16_to_int8_scalbn(bfloat16 a, FloatRoundMode rmode, int scale,
313700f9ef8fSLIU Zhiwei                                float_status *s)
313800f9ef8fSLIU Zhiwei {
313900f9ef8fSLIU Zhiwei     FloatParts64 p;
314000f9ef8fSLIU Zhiwei 
314100f9ef8fSLIU Zhiwei     bfloat16_unpack_canonical(&p, a, s);
314200f9ef8fSLIU Zhiwei     return parts_float_to_sint(&p, rmode, scale, INT8_MIN, INT8_MAX, s);
314300f9ef8fSLIU Zhiwei }
314400f9ef8fSLIU Zhiwei 
bfloat16_to_int16_scalbn(bfloat16 a,FloatRoundMode rmode,int scale,float_status * s)3145463b3f0dSRichard Henderson int16_t bfloat16_to_int16_scalbn(bfloat16 a, FloatRoundMode rmode, int scale,
3146463b3f0dSRichard Henderson                                  float_status *s)
3147463b3f0dSRichard Henderson {
3148463b3f0dSRichard Henderson     FloatParts64 p;
3149463b3f0dSRichard Henderson 
3150463b3f0dSRichard Henderson     bfloat16_unpack_canonical(&p, a, s);
3151463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT16_MIN, INT16_MAX, s);
3152463b3f0dSRichard Henderson }
3153463b3f0dSRichard Henderson 
bfloat16_to_int32_scalbn(bfloat16 a,FloatRoundMode rmode,int scale,float_status * s)3154463b3f0dSRichard Henderson int32_t bfloat16_to_int32_scalbn(bfloat16 a, FloatRoundMode rmode, int scale,
3155463b3f0dSRichard Henderson                                  float_status *s)
3156463b3f0dSRichard Henderson {
3157463b3f0dSRichard Henderson     FloatParts64 p;
3158463b3f0dSRichard Henderson 
3159463b3f0dSRichard Henderson     bfloat16_unpack_canonical(&p, a, s);
3160463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT32_MIN, INT32_MAX, s);
3161463b3f0dSRichard Henderson }
3162463b3f0dSRichard Henderson 
bfloat16_to_int64_scalbn(bfloat16 a,FloatRoundMode rmode,int scale,float_status * s)3163463b3f0dSRichard Henderson int64_t bfloat16_to_int64_scalbn(bfloat16 a, FloatRoundMode rmode, int scale,
3164463b3f0dSRichard Henderson                                  float_status *s)
3165463b3f0dSRichard Henderson {
3166463b3f0dSRichard Henderson     FloatParts64 p;
3167463b3f0dSRichard Henderson 
3168463b3f0dSRichard Henderson     bfloat16_unpack_canonical(&p, a, s);
3169463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT64_MIN, INT64_MAX, s);
3170463b3f0dSRichard Henderson }
3171463b3f0dSRichard Henderson 
float128_to_int32_scalbn(float128 a,FloatRoundMode rmode,int scale,float_status * s)3172463b3f0dSRichard Henderson static int32_t float128_to_int32_scalbn(float128 a, FloatRoundMode rmode,
3173463b3f0dSRichard Henderson                                         int scale, float_status *s)
3174463b3f0dSRichard Henderson {
3175463b3f0dSRichard Henderson     FloatParts128 p;
3176463b3f0dSRichard Henderson 
3177463b3f0dSRichard Henderson     float128_unpack_canonical(&p, a, s);
3178463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT32_MIN, INT32_MAX, s);
3179463b3f0dSRichard Henderson }
3180463b3f0dSRichard Henderson 
float128_to_int64_scalbn(float128 a,FloatRoundMode rmode,int scale,float_status * s)3181463b3f0dSRichard Henderson static int64_t float128_to_int64_scalbn(float128 a, FloatRoundMode rmode,
3182463b3f0dSRichard Henderson                                         int scale, float_status *s)
3183463b3f0dSRichard Henderson {
3184463b3f0dSRichard Henderson     FloatParts128 p;
3185463b3f0dSRichard Henderson 
3186463b3f0dSRichard Henderson     float128_unpack_canonical(&p, a, s);
3187463b3f0dSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT64_MIN, INT64_MAX, s);
31882f6c74beSRichard Henderson }
31892f6c74beSRichard Henderson 
float128_to_int128_scalbn(float128 a,FloatRoundMode rmode,int scale,float_status * s)3190bea59230SMatheus Ferst static Int128 float128_to_int128_scalbn(float128 a, FloatRoundMode rmode,
3191bea59230SMatheus Ferst                                         int scale, float_status *s)
3192bea59230SMatheus Ferst {
3193bea59230SMatheus Ferst     int flags = 0;
3194bea59230SMatheus Ferst     Int128 r;
3195bea59230SMatheus Ferst     FloatParts128 p;
3196bea59230SMatheus Ferst 
3197bea59230SMatheus Ferst     float128_unpack_canonical(&p, a, s);
3198bea59230SMatheus Ferst 
3199bea59230SMatheus Ferst     switch (p.cls) {
3200bea59230SMatheus Ferst     case float_class_snan:
3201bea59230SMatheus Ferst         flags |= float_flag_invalid_snan;
3202bea59230SMatheus Ferst         /* fall through */
3203bea59230SMatheus Ferst     case float_class_qnan:
3204bea59230SMatheus Ferst         flags |= float_flag_invalid;
3205bea59230SMatheus Ferst         r = UINT128_MAX;
3206bea59230SMatheus Ferst         break;
3207bea59230SMatheus Ferst 
3208bea59230SMatheus Ferst     case float_class_inf:
3209bea59230SMatheus Ferst         flags = float_flag_invalid | float_flag_invalid_cvti;
3210bea59230SMatheus Ferst         r = p.sign ? INT128_MIN : INT128_MAX;
3211bea59230SMatheus Ferst         break;
3212bea59230SMatheus Ferst 
3213bea59230SMatheus Ferst     case float_class_zero:
3214bea59230SMatheus Ferst         return int128_zero();
3215bea59230SMatheus Ferst 
3216bea59230SMatheus Ferst     case float_class_normal:
3217bea59230SMatheus Ferst         if (parts_round_to_int_normal(&p, rmode, scale, 128 - 2)) {
3218bea59230SMatheus Ferst             flags = float_flag_inexact;
3219bea59230SMatheus Ferst         }
3220bea59230SMatheus Ferst 
3221bea59230SMatheus Ferst         if (p.exp < 127) {
3222bea59230SMatheus Ferst             int shift = 127 - p.exp;
3223bea59230SMatheus Ferst             r = int128_urshift(int128_make128(p.frac_lo, p.frac_hi), shift);
3224bea59230SMatheus Ferst             if (p.sign) {
3225bea59230SMatheus Ferst                 r = int128_neg(r);
3226bea59230SMatheus Ferst             }
3227bea59230SMatheus Ferst         } else if (p.exp == 127 && p.sign && p.frac_lo == 0 &&
3228bea59230SMatheus Ferst                    p.frac_hi == DECOMPOSED_IMPLICIT_BIT) {
3229bea59230SMatheus Ferst             r = INT128_MIN;
3230bea59230SMatheus Ferst         } else {
3231bea59230SMatheus Ferst             flags = float_flag_invalid | float_flag_invalid_cvti;
3232bea59230SMatheus Ferst             r = p.sign ? INT128_MIN : INT128_MAX;
3233bea59230SMatheus Ferst         }
3234bea59230SMatheus Ferst         break;
3235bea59230SMatheus Ferst 
3236bea59230SMatheus Ferst     default:
3237bea59230SMatheus Ferst         g_assert_not_reached();
3238bea59230SMatheus Ferst     }
3239bea59230SMatheus Ferst 
3240bea59230SMatheus Ferst     float_raise(flags, s);
3241bea59230SMatheus Ferst     return r;
3242bea59230SMatheus Ferst }
3243bea59230SMatheus Ferst 
floatx80_to_int32_scalbn(floatx80 a,FloatRoundMode rmode,int scale,float_status * s)3244a1fc527bSRichard Henderson static int32_t floatx80_to_int32_scalbn(floatx80 a, FloatRoundMode rmode,
3245a1fc527bSRichard Henderson                                         int scale, float_status *s)
3246a1fc527bSRichard Henderson {
3247a1fc527bSRichard Henderson     FloatParts128 p;
3248a1fc527bSRichard Henderson 
3249a1fc527bSRichard Henderson     if (!floatx80_unpack_canonical(&p, a, s)) {
3250a1fc527bSRichard Henderson         parts_default_nan(&p, s);
3251a1fc527bSRichard Henderson     }
3252a1fc527bSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT32_MIN, INT32_MAX, s);
3253a1fc527bSRichard Henderson }
3254a1fc527bSRichard Henderson 
floatx80_to_int64_scalbn(floatx80 a,FloatRoundMode rmode,int scale,float_status * s)3255a1fc527bSRichard Henderson static int64_t floatx80_to_int64_scalbn(floatx80 a, FloatRoundMode rmode,
3256a1fc527bSRichard Henderson                                         int scale, float_status *s)
3257a1fc527bSRichard Henderson {
3258a1fc527bSRichard Henderson     FloatParts128 p;
3259a1fc527bSRichard Henderson 
3260a1fc527bSRichard Henderson     if (!floatx80_unpack_canonical(&p, a, s)) {
3261a1fc527bSRichard Henderson         parts_default_nan(&p, s);
3262a1fc527bSRichard Henderson     }
3263a1fc527bSRichard Henderson     return parts_float_to_sint(&p, rmode, scale, INT64_MIN, INT64_MAX, s);
3264a1fc527bSRichard Henderson }
3265a1fc527bSRichard Henderson 
float16_to_int8(float16 a,float_status * s)32660d93d8ecSFrank Chang int8_t float16_to_int8(float16 a, float_status *s)
32670d93d8ecSFrank Chang {
32680d93d8ecSFrank Chang     return float16_to_int8_scalbn(a, s->float_rounding_mode, 0, s);
32690d93d8ecSFrank Chang }
32700d93d8ecSFrank Chang 
float16_to_int16(float16 a,float_status * s)32712f6c74beSRichard Henderson int16_t float16_to_int16(float16 a, float_status *s)
32722f6c74beSRichard Henderson {
32732f6c74beSRichard Henderson     return float16_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
32742f6c74beSRichard Henderson }
32752f6c74beSRichard Henderson 
float16_to_int32(float16 a,float_status * s)32762f6c74beSRichard Henderson int32_t float16_to_int32(float16 a, float_status *s)
32772f6c74beSRichard Henderson {
32782f6c74beSRichard Henderson     return float16_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
32792f6c74beSRichard Henderson }
32802f6c74beSRichard Henderson 
float16_to_int64(float16 a,float_status * s)32812f6c74beSRichard Henderson int64_t float16_to_int64(float16 a, float_status *s)
32822f6c74beSRichard Henderson {
32832f6c74beSRichard Henderson     return float16_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
32842f6c74beSRichard Henderson }
32852f6c74beSRichard Henderson 
float32_to_int16(float32 a,float_status * s)32862f6c74beSRichard Henderson int16_t float32_to_int16(float32 a, float_status *s)
32872f6c74beSRichard Henderson {
32882f6c74beSRichard Henderson     return float32_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
32892f6c74beSRichard Henderson }
32902f6c74beSRichard Henderson 
float32_to_int32(float32 a,float_status * s)32912f6c74beSRichard Henderson int32_t float32_to_int32(float32 a, float_status *s)
32922f6c74beSRichard Henderson {
32932f6c74beSRichard Henderson     return float32_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
32942f6c74beSRichard Henderson }
32952f6c74beSRichard Henderson 
float32_to_int64(float32 a,float_status * s)32962f6c74beSRichard Henderson int64_t float32_to_int64(float32 a, float_status *s)
32972f6c74beSRichard Henderson {
32982f6c74beSRichard Henderson     return float32_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
32992f6c74beSRichard Henderson }
33002f6c74beSRichard Henderson 
float64_to_int16(float64 a,float_status * s)33012f6c74beSRichard Henderson int16_t float64_to_int16(float64 a, float_status *s)
33022f6c74beSRichard Henderson {
33032f6c74beSRichard Henderson     return float64_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
33042f6c74beSRichard Henderson }
33052f6c74beSRichard Henderson 
float64_to_int32(float64 a,float_status * s)33062f6c74beSRichard Henderson int32_t float64_to_int32(float64 a, float_status *s)
33072f6c74beSRichard Henderson {
33082f6c74beSRichard Henderson     return float64_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
33092f6c74beSRichard Henderson }
33102f6c74beSRichard Henderson 
float64_to_int64(float64 a,float_status * s)33112f6c74beSRichard Henderson int64_t float64_to_int64(float64 a, float_status *s)
33122f6c74beSRichard Henderson {
33132f6c74beSRichard Henderson     return float64_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
33142f6c74beSRichard Henderson }
33152f6c74beSRichard Henderson 
float128_to_int32(float128 a,float_status * s)3316463b3f0dSRichard Henderson int32_t float128_to_int32(float128 a, float_status *s)
3317463b3f0dSRichard Henderson {
3318463b3f0dSRichard Henderson     return float128_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
3319463b3f0dSRichard Henderson }
3320463b3f0dSRichard Henderson 
float128_to_int64(float128 a,float_status * s)3321463b3f0dSRichard Henderson int64_t float128_to_int64(float128 a, float_status *s)
3322463b3f0dSRichard Henderson {
3323463b3f0dSRichard Henderson     return float128_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
3324463b3f0dSRichard Henderson }
3325463b3f0dSRichard Henderson 
float128_to_int128(float128 a,float_status * s)3326bea59230SMatheus Ferst Int128 float128_to_int128(float128 a, float_status *s)
3327bea59230SMatheus Ferst {
3328bea59230SMatheus Ferst     return float128_to_int128_scalbn(a, s->float_rounding_mode, 0, s);
3329bea59230SMatheus Ferst }
3330bea59230SMatheus Ferst 
floatx80_to_int32(floatx80 a,float_status * s)3331a1fc527bSRichard Henderson int32_t floatx80_to_int32(floatx80 a, float_status *s)
3332a1fc527bSRichard Henderson {
3333a1fc527bSRichard Henderson     return floatx80_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
3334a1fc527bSRichard Henderson }
3335a1fc527bSRichard Henderson 
floatx80_to_int64(floatx80 a,float_status * s)3336a1fc527bSRichard Henderson int64_t floatx80_to_int64(floatx80 a, float_status *s)
3337a1fc527bSRichard Henderson {
3338a1fc527bSRichard Henderson     return floatx80_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
3339a1fc527bSRichard Henderson }
3340a1fc527bSRichard Henderson 
float16_to_int16_round_to_zero(float16 a,float_status * s)33412f6c74beSRichard Henderson int16_t float16_to_int16_round_to_zero(float16 a, float_status *s)
33422f6c74beSRichard Henderson {
33432f6c74beSRichard Henderson     return float16_to_int16_scalbn(a, float_round_to_zero, 0, s);
33442f6c74beSRichard Henderson }
33452f6c74beSRichard Henderson 
float16_to_int32_round_to_zero(float16 a,float_status * s)33462f6c74beSRichard Henderson int32_t float16_to_int32_round_to_zero(float16 a, float_status *s)
33472f6c74beSRichard Henderson {
33482f6c74beSRichard Henderson     return float16_to_int32_scalbn(a, float_round_to_zero, 0, s);
33492f6c74beSRichard Henderson }
33502f6c74beSRichard Henderson 
float16_to_int64_round_to_zero(float16 a,float_status * s)33512f6c74beSRichard Henderson int64_t float16_to_int64_round_to_zero(float16 a, float_status *s)
33522f6c74beSRichard Henderson {
33532f6c74beSRichard Henderson     return float16_to_int64_scalbn(a, float_round_to_zero, 0, s);
33542f6c74beSRichard Henderson }
33552f6c74beSRichard Henderson 
float32_to_int16_round_to_zero(float32 a,float_status * s)33562f6c74beSRichard Henderson int16_t float32_to_int16_round_to_zero(float32 a, float_status *s)
33572f6c74beSRichard Henderson {
33582f6c74beSRichard Henderson     return float32_to_int16_scalbn(a, float_round_to_zero, 0, s);
33592f6c74beSRichard Henderson }
33602f6c74beSRichard Henderson 
float32_to_int32_round_to_zero(float32 a,float_status * s)33612f6c74beSRichard Henderson int32_t float32_to_int32_round_to_zero(float32 a, float_status *s)
33622f6c74beSRichard Henderson {
33632f6c74beSRichard Henderson     return float32_to_int32_scalbn(a, float_round_to_zero, 0, s);
33642f6c74beSRichard Henderson }
33652f6c74beSRichard Henderson 
float32_to_int64_round_to_zero(float32 a,float_status * s)33662f6c74beSRichard Henderson int64_t float32_to_int64_round_to_zero(float32 a, float_status *s)
33672f6c74beSRichard Henderson {
33682f6c74beSRichard Henderson     return float32_to_int64_scalbn(a, float_round_to_zero, 0, s);
33692f6c74beSRichard Henderson }
33702f6c74beSRichard Henderson 
float64_to_int16_round_to_zero(float64 a,float_status * s)33712f6c74beSRichard Henderson int16_t float64_to_int16_round_to_zero(float64 a, float_status *s)
33722f6c74beSRichard Henderson {
33732f6c74beSRichard Henderson     return float64_to_int16_scalbn(a, float_round_to_zero, 0, s);
33742f6c74beSRichard Henderson }
33752f6c74beSRichard Henderson 
float64_to_int32_round_to_zero(float64 a,float_status * s)33762f6c74beSRichard Henderson int32_t float64_to_int32_round_to_zero(float64 a, float_status *s)
33772f6c74beSRichard Henderson {
33782f6c74beSRichard Henderson     return float64_to_int32_scalbn(a, float_round_to_zero, 0, s);
33792f6c74beSRichard Henderson }
33802f6c74beSRichard Henderson 
float64_to_int64_round_to_zero(float64 a,float_status * s)33812f6c74beSRichard Henderson int64_t float64_to_int64_round_to_zero(float64 a, float_status *s)
33822f6c74beSRichard Henderson {
33832f6c74beSRichard Henderson     return float64_to_int64_scalbn(a, float_round_to_zero, 0, s);
33842f6c74beSRichard Henderson }
3385ab52f973SAlex Bennée 
float128_to_int32_round_to_zero(float128 a,float_status * s)3386463b3f0dSRichard Henderson int32_t float128_to_int32_round_to_zero(float128 a, float_status *s)
338734f0c0a9SLIU Zhiwei {
3388463b3f0dSRichard Henderson     return float128_to_int32_scalbn(a, float_round_to_zero, 0, s);
338934f0c0a9SLIU Zhiwei }
339034f0c0a9SLIU Zhiwei 
float128_to_int64_round_to_zero(float128 a,float_status * s)3391463b3f0dSRichard Henderson int64_t float128_to_int64_round_to_zero(float128 a, float_status *s)
339234f0c0a9SLIU Zhiwei {
3393463b3f0dSRichard Henderson     return float128_to_int64_scalbn(a, float_round_to_zero, 0, s);
339434f0c0a9SLIU Zhiwei }
339534f0c0a9SLIU Zhiwei 
float128_to_int128_round_to_zero(float128 a,float_status * s)3396bea59230SMatheus Ferst Int128 float128_to_int128_round_to_zero(float128 a, float_status *s)
3397bea59230SMatheus Ferst {
3398bea59230SMatheus Ferst     return float128_to_int128_scalbn(a, float_round_to_zero, 0, s);
3399bea59230SMatheus Ferst }
3400bea59230SMatheus Ferst 
floatx80_to_int32_round_to_zero(floatx80 a,float_status * s)3401a1fc527bSRichard Henderson int32_t floatx80_to_int32_round_to_zero(floatx80 a, float_status *s)
3402a1fc527bSRichard Henderson {
3403a1fc527bSRichard Henderson     return floatx80_to_int32_scalbn(a, float_round_to_zero, 0, s);
3404a1fc527bSRichard Henderson }
3405a1fc527bSRichard Henderson 
floatx80_to_int64_round_to_zero(floatx80 a,float_status * s)3406a1fc527bSRichard Henderson int64_t floatx80_to_int64_round_to_zero(floatx80 a, float_status *s)
3407a1fc527bSRichard Henderson {
3408a1fc527bSRichard Henderson     return floatx80_to_int64_scalbn(a, float_round_to_zero, 0, s);
3409a1fc527bSRichard Henderson }
3410a1fc527bSRichard Henderson 
bfloat16_to_int8(bfloat16 a,float_status * s)341100f9ef8fSLIU Zhiwei int8_t bfloat16_to_int8(bfloat16 a, float_status *s)
341200f9ef8fSLIU Zhiwei {
341300f9ef8fSLIU Zhiwei     return bfloat16_to_int8_scalbn(a, s->float_rounding_mode, 0, s);
341400f9ef8fSLIU Zhiwei }
341500f9ef8fSLIU Zhiwei 
bfloat16_to_int16(bfloat16 a,float_status * s)341634f0c0a9SLIU Zhiwei int16_t bfloat16_to_int16(bfloat16 a, float_status *s)
341734f0c0a9SLIU Zhiwei {
341834f0c0a9SLIU Zhiwei     return bfloat16_to_int16_scalbn(a, s->float_rounding_mode, 0, s);
341934f0c0a9SLIU Zhiwei }
342034f0c0a9SLIU Zhiwei 
bfloat16_to_int32(bfloat16 a,float_status * s)342134f0c0a9SLIU Zhiwei int32_t bfloat16_to_int32(bfloat16 a, float_status *s)
342234f0c0a9SLIU Zhiwei {
342334f0c0a9SLIU Zhiwei     return bfloat16_to_int32_scalbn(a, s->float_rounding_mode, 0, s);
342434f0c0a9SLIU Zhiwei }
342534f0c0a9SLIU Zhiwei 
bfloat16_to_int64(bfloat16 a,float_status * s)342634f0c0a9SLIU Zhiwei int64_t bfloat16_to_int64(bfloat16 a, float_status *s)
342734f0c0a9SLIU Zhiwei {
342834f0c0a9SLIU Zhiwei     return bfloat16_to_int64_scalbn(a, s->float_rounding_mode, 0, s);
342934f0c0a9SLIU Zhiwei }
343034f0c0a9SLIU Zhiwei 
bfloat16_to_int8_round_to_zero(bfloat16 a,float_status * s)343100f9ef8fSLIU Zhiwei int8_t bfloat16_to_int8_round_to_zero(bfloat16 a, float_status *s)
343200f9ef8fSLIU Zhiwei {
343300f9ef8fSLIU Zhiwei     return bfloat16_to_int8_scalbn(a, float_round_to_zero, 0, s);
343400f9ef8fSLIU Zhiwei }
343500f9ef8fSLIU Zhiwei 
bfloat16_to_int16_round_to_zero(bfloat16 a,float_status * s)343634f0c0a9SLIU Zhiwei int16_t bfloat16_to_int16_round_to_zero(bfloat16 a, float_status *s)
343734f0c0a9SLIU Zhiwei {
343834f0c0a9SLIU Zhiwei     return bfloat16_to_int16_scalbn(a, float_round_to_zero, 0, s);
343934f0c0a9SLIU Zhiwei }
344034f0c0a9SLIU Zhiwei 
bfloat16_to_int32_round_to_zero(bfloat16 a,float_status * s)344134f0c0a9SLIU Zhiwei int32_t bfloat16_to_int32_round_to_zero(bfloat16 a, float_status *s)
344234f0c0a9SLIU Zhiwei {
344334f0c0a9SLIU Zhiwei     return bfloat16_to_int32_scalbn(a, float_round_to_zero, 0, s);
344434f0c0a9SLIU Zhiwei }
344534f0c0a9SLIU Zhiwei 
bfloat16_to_int64_round_to_zero(bfloat16 a,float_status * s)344634f0c0a9SLIU Zhiwei int64_t bfloat16_to_int64_round_to_zero(bfloat16 a, float_status *s)
344734f0c0a9SLIU Zhiwei {
344834f0c0a9SLIU Zhiwei     return bfloat16_to_int64_scalbn(a, float_round_to_zero, 0, s);
344934f0c0a9SLIU Zhiwei }
345034f0c0a9SLIU Zhiwei 
float64_to_int32_modulo(float64 a,FloatRoundMode rmode,float_status * s)3451e2041f4dSRichard Henderson int32_t float64_to_int32_modulo(float64 a, FloatRoundMode rmode,
3452e2041f4dSRichard Henderson                                 float_status *s)
3453e2041f4dSRichard Henderson {
3454e2041f4dSRichard Henderson     FloatParts64 p;
3455e2041f4dSRichard Henderson 
3456e2041f4dSRichard Henderson     float64_unpack_canonical(&p, a, s);
3457e2041f4dSRichard Henderson     return parts_float_to_sint_modulo(&p, rmode, 31, s);
3458e2041f4dSRichard Henderson }
3459e2041f4dSRichard Henderson 
float64_to_int64_modulo(float64 a,FloatRoundMode rmode,float_status * s)3460e2041f4dSRichard Henderson int64_t float64_to_int64_modulo(float64 a, FloatRoundMode rmode,
3461e2041f4dSRichard Henderson                                 float_status *s)
3462e2041f4dSRichard Henderson {
3463e2041f4dSRichard Henderson     FloatParts64 p;
3464e2041f4dSRichard Henderson 
3465e2041f4dSRichard Henderson     float64_unpack_canonical(&p, a, s);
3466e2041f4dSRichard Henderson     return parts_float_to_sint_modulo(&p, rmode, 63, s);
3467e2041f4dSRichard Henderson }
3468e2041f4dSRichard Henderson 
346934f0c0a9SLIU Zhiwei /*
34704ab4aef0SRichard Henderson  * Floating-point to unsigned integer conversions
3471ab52f973SAlex Bennée  */
3472ab52f973SAlex Bennée 
float16_to_uint8_scalbn(float16 a,FloatRoundMode rmode,int scale,float_status * s)34730d93d8ecSFrank Chang uint8_t float16_to_uint8_scalbn(float16 a, FloatRoundMode rmode, int scale,
34740d93d8ecSFrank Chang                                 float_status *s)
34750d93d8ecSFrank Chang {
347698e256fcSRichard Henderson     FloatParts64 p;
347798e256fcSRichard Henderson 
347898e256fcSRichard Henderson     float16_unpack_canonical(&p, a, s);
34794ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT8_MAX, s);
34800d93d8ecSFrank Chang }
34810d93d8ecSFrank Chang 
float16_to_uint16_scalbn(float16 a,FloatRoundMode rmode,int scale,float_status * s)34823dede407SRichard Henderson uint16_t float16_to_uint16_scalbn(float16 a, FloatRoundMode rmode, int scale,
34832f6c74beSRichard Henderson                                   float_status *s)
34842f6c74beSRichard Henderson {
348598e256fcSRichard Henderson     FloatParts64 p;
348698e256fcSRichard Henderson 
348798e256fcSRichard Henderson     float16_unpack_canonical(&p, a, s);
34884ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT16_MAX, s);
3489ab52f973SAlex Bennée }
3490ab52f973SAlex Bennée 
float16_to_uint32_scalbn(float16 a,FloatRoundMode rmode,int scale,float_status * s)34913dede407SRichard Henderson uint32_t float16_to_uint32_scalbn(float16 a, FloatRoundMode rmode, int scale,
34922f6c74beSRichard Henderson                                   float_status *s)
34932f6c74beSRichard Henderson {
349498e256fcSRichard Henderson     FloatParts64 p;
349598e256fcSRichard Henderson 
349698e256fcSRichard Henderson     float16_unpack_canonical(&p, a, s);
34974ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT32_MAX, s);
34982f6c74beSRichard Henderson }
3499ab52f973SAlex Bennée 
float16_to_uint64_scalbn(float16 a,FloatRoundMode rmode,int scale,float_status * s)35003dede407SRichard Henderson uint64_t float16_to_uint64_scalbn(float16 a, FloatRoundMode rmode, int scale,
35012f6c74beSRichard Henderson                                   float_status *s)
35022f6c74beSRichard Henderson {
350398e256fcSRichard Henderson     FloatParts64 p;
350498e256fcSRichard Henderson 
350598e256fcSRichard Henderson     float16_unpack_canonical(&p, a, s);
35064ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT64_MAX, s);
35072f6c74beSRichard Henderson }
3508ab52f973SAlex Bennée 
float32_to_uint16_scalbn(float32 a,FloatRoundMode rmode,int scale,float_status * s)35093dede407SRichard Henderson uint16_t float32_to_uint16_scalbn(float32 a, FloatRoundMode rmode, int scale,
35102f6c74beSRichard Henderson                                   float_status *s)
35112f6c74beSRichard Henderson {
351298e256fcSRichard Henderson     FloatParts64 p;
351398e256fcSRichard Henderson 
351498e256fcSRichard Henderson     float32_unpack_canonical(&p, a, s);
35154ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT16_MAX, s);
35162f6c74beSRichard Henderson }
3517ab52f973SAlex Bennée 
float32_to_uint32_scalbn(float32 a,FloatRoundMode rmode,int scale,float_status * s)35183dede407SRichard Henderson uint32_t float32_to_uint32_scalbn(float32 a, FloatRoundMode rmode, int scale,
35192f6c74beSRichard Henderson                                   float_status *s)
35202f6c74beSRichard Henderson {
352198e256fcSRichard Henderson     FloatParts64 p;
352298e256fcSRichard Henderson 
352398e256fcSRichard Henderson     float32_unpack_canonical(&p, a, s);
35244ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT32_MAX, s);
35252f6c74beSRichard Henderson }
35262f6c74beSRichard Henderson 
float32_to_uint64_scalbn(float32 a,FloatRoundMode rmode,int scale,float_status * s)35273dede407SRichard Henderson uint64_t float32_to_uint64_scalbn(float32 a, FloatRoundMode rmode, int scale,
35282f6c74beSRichard Henderson                                   float_status *s)
35292f6c74beSRichard Henderson {
353098e256fcSRichard Henderson     FloatParts64 p;
353198e256fcSRichard Henderson 
353298e256fcSRichard Henderson     float32_unpack_canonical(&p, a, s);
35334ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT64_MAX, s);
35342f6c74beSRichard Henderson }
35352f6c74beSRichard Henderson 
float64_to_uint16_scalbn(float64 a,FloatRoundMode rmode,int scale,float_status * s)35363dede407SRichard Henderson uint16_t float64_to_uint16_scalbn(float64 a, FloatRoundMode rmode, int scale,
35372f6c74beSRichard Henderson                                   float_status *s)
35382f6c74beSRichard Henderson {
353998e256fcSRichard Henderson     FloatParts64 p;
354098e256fcSRichard Henderson 
354198e256fcSRichard Henderson     float64_unpack_canonical(&p, a, s);
35424ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT16_MAX, s);
35432f6c74beSRichard Henderson }
35442f6c74beSRichard Henderson 
float64_to_uint32_scalbn(float64 a,FloatRoundMode rmode,int scale,float_status * s)35453dede407SRichard Henderson uint32_t float64_to_uint32_scalbn(float64 a, FloatRoundMode rmode, int scale,
35462f6c74beSRichard Henderson                                   float_status *s)
35472f6c74beSRichard Henderson {
354898e256fcSRichard Henderson     FloatParts64 p;
354998e256fcSRichard Henderson 
355098e256fcSRichard Henderson     float64_unpack_canonical(&p, a, s);
35514ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT32_MAX, s);
35522f6c74beSRichard Henderson }
35532f6c74beSRichard Henderson 
float64_to_uint64_scalbn(float64 a,FloatRoundMode rmode,int scale,float_status * s)35543dede407SRichard Henderson uint64_t float64_to_uint64_scalbn(float64 a, FloatRoundMode rmode, int scale,
35552f6c74beSRichard Henderson                                   float_status *s)
35562f6c74beSRichard Henderson {
355798e256fcSRichard Henderson     FloatParts64 p;
355898e256fcSRichard Henderson 
355998e256fcSRichard Henderson     float64_unpack_canonical(&p, a, s);
35604ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT64_MAX, s);
35614ab4aef0SRichard Henderson }
35624ab4aef0SRichard Henderson 
bfloat16_to_uint8_scalbn(bfloat16 a,FloatRoundMode rmode,int scale,float_status * s)356300f9ef8fSLIU Zhiwei uint8_t bfloat16_to_uint8_scalbn(bfloat16 a, FloatRoundMode rmode,
356400f9ef8fSLIU Zhiwei                                  int scale, float_status *s)
356500f9ef8fSLIU Zhiwei {
356600f9ef8fSLIU Zhiwei     FloatParts64 p;
356700f9ef8fSLIU Zhiwei 
356800f9ef8fSLIU Zhiwei     bfloat16_unpack_canonical(&p, a, s);
356900f9ef8fSLIU Zhiwei     return parts_float_to_uint(&p, rmode, scale, UINT8_MAX, s);
357000f9ef8fSLIU Zhiwei }
357100f9ef8fSLIU Zhiwei 
bfloat16_to_uint16_scalbn(bfloat16 a,FloatRoundMode rmode,int scale,float_status * s)35724ab4aef0SRichard Henderson uint16_t bfloat16_to_uint16_scalbn(bfloat16 a, FloatRoundMode rmode,
35734ab4aef0SRichard Henderson                                    int scale, float_status *s)
35744ab4aef0SRichard Henderson {
35754ab4aef0SRichard Henderson     FloatParts64 p;
35764ab4aef0SRichard Henderson 
35774ab4aef0SRichard Henderson     bfloat16_unpack_canonical(&p, a, s);
35784ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT16_MAX, s);
35794ab4aef0SRichard Henderson }
35804ab4aef0SRichard Henderson 
bfloat16_to_uint32_scalbn(bfloat16 a,FloatRoundMode rmode,int scale,float_status * s)35814ab4aef0SRichard Henderson uint32_t bfloat16_to_uint32_scalbn(bfloat16 a, FloatRoundMode rmode,
35824ab4aef0SRichard Henderson                                    int scale, float_status *s)
35834ab4aef0SRichard Henderson {
35844ab4aef0SRichard Henderson     FloatParts64 p;
35854ab4aef0SRichard Henderson 
35864ab4aef0SRichard Henderson     bfloat16_unpack_canonical(&p, a, s);
35874ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT32_MAX, s);
35884ab4aef0SRichard Henderson }
35894ab4aef0SRichard Henderson 
bfloat16_to_uint64_scalbn(bfloat16 a,FloatRoundMode rmode,int scale,float_status * s)35904ab4aef0SRichard Henderson uint64_t bfloat16_to_uint64_scalbn(bfloat16 a, FloatRoundMode rmode,
35914ab4aef0SRichard Henderson                                    int scale, float_status *s)
35924ab4aef0SRichard Henderson {
35934ab4aef0SRichard Henderson     FloatParts64 p;
35944ab4aef0SRichard Henderson 
35954ab4aef0SRichard Henderson     bfloat16_unpack_canonical(&p, a, s);
35964ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT64_MAX, s);
35974ab4aef0SRichard Henderson }
35984ab4aef0SRichard Henderson 
float128_to_uint32_scalbn(float128 a,FloatRoundMode rmode,int scale,float_status * s)35994ab4aef0SRichard Henderson static uint32_t float128_to_uint32_scalbn(float128 a, FloatRoundMode rmode,
36004ab4aef0SRichard Henderson                                           int scale, float_status *s)
36014ab4aef0SRichard Henderson {
36024ab4aef0SRichard Henderson     FloatParts128 p;
36034ab4aef0SRichard Henderson 
36044ab4aef0SRichard Henderson     float128_unpack_canonical(&p, a, s);
36054ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT32_MAX, s);
36064ab4aef0SRichard Henderson }
36074ab4aef0SRichard Henderson 
float128_to_uint64_scalbn(float128 a,FloatRoundMode rmode,int scale,float_status * s)36084ab4aef0SRichard Henderson static uint64_t float128_to_uint64_scalbn(float128 a, FloatRoundMode rmode,
36094ab4aef0SRichard Henderson                                           int scale, float_status *s)
36104ab4aef0SRichard Henderson {
36114ab4aef0SRichard Henderson     FloatParts128 p;
36124ab4aef0SRichard Henderson 
36134ab4aef0SRichard Henderson     float128_unpack_canonical(&p, a, s);
36144ab4aef0SRichard Henderson     return parts_float_to_uint(&p, rmode, scale, UINT64_MAX, s);
36152f6c74beSRichard Henderson }
36162f6c74beSRichard Henderson 
float128_to_uint128_scalbn(float128 a,FloatRoundMode rmode,int scale,float_status * s)36174de49ddfSMatheus Ferst static Int128 float128_to_uint128_scalbn(float128 a, FloatRoundMode rmode,
36184de49ddfSMatheus Ferst                                          int scale, float_status *s)
36194de49ddfSMatheus Ferst {
36204de49ddfSMatheus Ferst     int flags = 0;
36214de49ddfSMatheus Ferst     Int128 r;
36224de49ddfSMatheus Ferst     FloatParts128 p;
36234de49ddfSMatheus Ferst 
36244de49ddfSMatheus Ferst     float128_unpack_canonical(&p, a, s);
36254de49ddfSMatheus Ferst 
36264de49ddfSMatheus Ferst     switch (p.cls) {
36274de49ddfSMatheus Ferst     case float_class_snan:
36284de49ddfSMatheus Ferst         flags |= float_flag_invalid_snan;
36294de49ddfSMatheus Ferst         /* fall through */
36304de49ddfSMatheus Ferst     case float_class_qnan:
36314de49ddfSMatheus Ferst         flags |= float_flag_invalid;
36324de49ddfSMatheus Ferst         r = UINT128_MAX;
36334de49ddfSMatheus Ferst         break;
36344de49ddfSMatheus Ferst 
36354de49ddfSMatheus Ferst     case float_class_inf:
36364de49ddfSMatheus Ferst         flags = float_flag_invalid | float_flag_invalid_cvti;
36374de49ddfSMatheus Ferst         r = p.sign ? int128_zero() : UINT128_MAX;
36384de49ddfSMatheus Ferst         break;
36394de49ddfSMatheus Ferst 
36404de49ddfSMatheus Ferst     case float_class_zero:
36414de49ddfSMatheus Ferst         return int128_zero();
36424de49ddfSMatheus Ferst 
36434de49ddfSMatheus Ferst     case float_class_normal:
36444de49ddfSMatheus Ferst         if (parts_round_to_int_normal(&p, rmode, scale, 128 - 2)) {
36454de49ddfSMatheus Ferst             flags = float_flag_inexact;
36464de49ddfSMatheus Ferst             if (p.cls == float_class_zero) {
36474de49ddfSMatheus Ferst                 r = int128_zero();
36484de49ddfSMatheus Ferst                 break;
36494de49ddfSMatheus Ferst             }
36504de49ddfSMatheus Ferst         }
36514de49ddfSMatheus Ferst 
36524de49ddfSMatheus Ferst         if (p.sign) {
36534de49ddfSMatheus Ferst             flags = float_flag_invalid | float_flag_invalid_cvti;
36544de49ddfSMatheus Ferst             r = int128_zero();
36554de49ddfSMatheus Ferst         } else if (p.exp <= 127) {
36564de49ddfSMatheus Ferst             int shift = 127 - p.exp;
36574de49ddfSMatheus Ferst             r = int128_urshift(int128_make128(p.frac_lo, p.frac_hi), shift);
36584de49ddfSMatheus Ferst         } else {
36594de49ddfSMatheus Ferst             flags = float_flag_invalid | float_flag_invalid_cvti;
36604de49ddfSMatheus Ferst             r = UINT128_MAX;
36614de49ddfSMatheus Ferst         }
36624de49ddfSMatheus Ferst         break;
36634de49ddfSMatheus Ferst 
36644de49ddfSMatheus Ferst     default:
36654de49ddfSMatheus Ferst         g_assert_not_reached();
36664de49ddfSMatheus Ferst     }
36674de49ddfSMatheus Ferst 
36684de49ddfSMatheus Ferst     float_raise(flags, s);
36694de49ddfSMatheus Ferst     return r;
36704de49ddfSMatheus Ferst }
36714de49ddfSMatheus Ferst 
float16_to_uint8(float16 a,float_status * s)36720d93d8ecSFrank Chang uint8_t float16_to_uint8(float16 a, float_status *s)
36730d93d8ecSFrank Chang {
36740d93d8ecSFrank Chang     return float16_to_uint8_scalbn(a, s->float_rounding_mode, 0, s);
36750d93d8ecSFrank Chang }
36760d93d8ecSFrank Chang 
float16_to_uint16(float16 a,float_status * s)36772f6c74beSRichard Henderson uint16_t float16_to_uint16(float16 a, float_status *s)
36782f6c74beSRichard Henderson {
36792f6c74beSRichard Henderson     return float16_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
36802f6c74beSRichard Henderson }
36812f6c74beSRichard Henderson 
float16_to_uint32(float16 a,float_status * s)36822f6c74beSRichard Henderson uint32_t float16_to_uint32(float16 a, float_status *s)
36832f6c74beSRichard Henderson {
36842f6c74beSRichard Henderson     return float16_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
36852f6c74beSRichard Henderson }
36862f6c74beSRichard Henderson 
float16_to_uint64(float16 a,float_status * s)36872f6c74beSRichard Henderson uint64_t float16_to_uint64(float16 a, float_status *s)
36882f6c74beSRichard Henderson {
36892f6c74beSRichard Henderson     return float16_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
36902f6c74beSRichard Henderson }
36912f6c74beSRichard Henderson 
float32_to_uint16(float32 a,float_status * s)36922f6c74beSRichard Henderson uint16_t float32_to_uint16(float32 a, float_status *s)
36932f6c74beSRichard Henderson {
36942f6c74beSRichard Henderson     return float32_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
36952f6c74beSRichard Henderson }
36962f6c74beSRichard Henderson 
float32_to_uint32(float32 a,float_status * s)36972f6c74beSRichard Henderson uint32_t float32_to_uint32(float32 a, float_status *s)
36982f6c74beSRichard Henderson {
36992f6c74beSRichard Henderson     return float32_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
37002f6c74beSRichard Henderson }
37012f6c74beSRichard Henderson 
float32_to_uint64(float32 a,float_status * s)37022f6c74beSRichard Henderson uint64_t float32_to_uint64(float32 a, float_status *s)
37032f6c74beSRichard Henderson {
37042f6c74beSRichard Henderson     return float32_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
37052f6c74beSRichard Henderson }
37062f6c74beSRichard Henderson 
float64_to_uint16(float64 a,float_status * s)37072f6c74beSRichard Henderson uint16_t float64_to_uint16(float64 a, float_status *s)
37082f6c74beSRichard Henderson {
37092f6c74beSRichard Henderson     return float64_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
37102f6c74beSRichard Henderson }
37112f6c74beSRichard Henderson 
float64_to_uint32(float64 a,float_status * s)37122f6c74beSRichard Henderson uint32_t float64_to_uint32(float64 a, float_status *s)
37132f6c74beSRichard Henderson {
37142f6c74beSRichard Henderson     return float64_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
37152f6c74beSRichard Henderson }
37162f6c74beSRichard Henderson 
float64_to_uint64(float64 a,float_status * s)37172f6c74beSRichard Henderson uint64_t float64_to_uint64(float64 a, float_status *s)
37182f6c74beSRichard Henderson {
37192f6c74beSRichard Henderson     return float64_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
37202f6c74beSRichard Henderson }
37212f6c74beSRichard Henderson 
float128_to_uint32(float128 a,float_status * s)37224ab4aef0SRichard Henderson uint32_t float128_to_uint32(float128 a, float_status *s)
37234ab4aef0SRichard Henderson {
37244ab4aef0SRichard Henderson     return float128_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
37254ab4aef0SRichard Henderson }
37264ab4aef0SRichard Henderson 
float128_to_uint64(float128 a,float_status * s)37274ab4aef0SRichard Henderson uint64_t float128_to_uint64(float128 a, float_status *s)
37284ab4aef0SRichard Henderson {
37294ab4aef0SRichard Henderson     return float128_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
37304ab4aef0SRichard Henderson }
37314ab4aef0SRichard Henderson 
float128_to_uint128(float128 a,float_status * s)37324de49ddfSMatheus Ferst Int128 float128_to_uint128(float128 a, float_status *s)
37334de49ddfSMatheus Ferst {
37344de49ddfSMatheus Ferst     return float128_to_uint128_scalbn(a, s->float_rounding_mode, 0, s);
37354de49ddfSMatheus Ferst }
37364de49ddfSMatheus Ferst 
float16_to_uint16_round_to_zero(float16 a,float_status * s)37372f6c74beSRichard Henderson uint16_t float16_to_uint16_round_to_zero(float16 a, float_status *s)
37382f6c74beSRichard Henderson {
37392f6c74beSRichard Henderson     return float16_to_uint16_scalbn(a, float_round_to_zero, 0, s);
37402f6c74beSRichard Henderson }
37412f6c74beSRichard Henderson 
float16_to_uint32_round_to_zero(float16 a,float_status * s)37422f6c74beSRichard Henderson uint32_t float16_to_uint32_round_to_zero(float16 a, float_status *s)
37432f6c74beSRichard Henderson {
37442f6c74beSRichard Henderson     return float16_to_uint32_scalbn(a, float_round_to_zero, 0, s);
37452f6c74beSRichard Henderson }
37462f6c74beSRichard Henderson 
float16_to_uint64_round_to_zero(float16 a,float_status * s)37472f6c74beSRichard Henderson uint64_t float16_to_uint64_round_to_zero(float16 a, float_status *s)
37482f6c74beSRichard Henderson {
37492f6c74beSRichard Henderson     return float16_to_uint64_scalbn(a, float_round_to_zero, 0, s);
37502f6c74beSRichard Henderson }
37512f6c74beSRichard Henderson 
float32_to_uint16_round_to_zero(float32 a,float_status * s)37522f6c74beSRichard Henderson uint16_t float32_to_uint16_round_to_zero(float32 a, float_status *s)
37532f6c74beSRichard Henderson {
37542f6c74beSRichard Henderson     return float32_to_uint16_scalbn(a, float_round_to_zero, 0, s);
37552f6c74beSRichard Henderson }
37562f6c74beSRichard Henderson 
float32_to_uint32_round_to_zero(float32 a,float_status * s)37572f6c74beSRichard Henderson uint32_t float32_to_uint32_round_to_zero(float32 a, float_status *s)
37582f6c74beSRichard Henderson {
37592f6c74beSRichard Henderson     return float32_to_uint32_scalbn(a, float_round_to_zero, 0, s);
37602f6c74beSRichard Henderson }
37612f6c74beSRichard Henderson 
float32_to_uint64_round_to_zero(float32 a,float_status * s)37622f6c74beSRichard Henderson uint64_t float32_to_uint64_round_to_zero(float32 a, float_status *s)
37632f6c74beSRichard Henderson {
37642f6c74beSRichard Henderson     return float32_to_uint64_scalbn(a, float_round_to_zero, 0, s);
37652f6c74beSRichard Henderson }
37662f6c74beSRichard Henderson 
float64_to_uint16_round_to_zero(float64 a,float_status * s)37672f6c74beSRichard Henderson uint16_t float64_to_uint16_round_to_zero(float64 a, float_status *s)
37682f6c74beSRichard Henderson {
37692f6c74beSRichard Henderson     return float64_to_uint16_scalbn(a, float_round_to_zero, 0, s);
37702f6c74beSRichard Henderson }
37712f6c74beSRichard Henderson 
float64_to_uint32_round_to_zero(float64 a,float_status * s)37722f6c74beSRichard Henderson uint32_t float64_to_uint32_round_to_zero(float64 a, float_status *s)
37732f6c74beSRichard Henderson {
37742f6c74beSRichard Henderson     return float64_to_uint32_scalbn(a, float_round_to_zero, 0, s);
37752f6c74beSRichard Henderson }
37762f6c74beSRichard Henderson 
float64_to_uint64_round_to_zero(float64 a,float_status * s)37772f6c74beSRichard Henderson uint64_t float64_to_uint64_round_to_zero(float64 a, float_status *s)
37782f6c74beSRichard Henderson {
37792f6c74beSRichard Henderson     return float64_to_uint64_scalbn(a, float_round_to_zero, 0, s);
37802f6c74beSRichard Henderson }
3781ab52f973SAlex Bennée 
float128_to_uint32_round_to_zero(float128 a,float_status * s)37824ab4aef0SRichard Henderson uint32_t float128_to_uint32_round_to_zero(float128 a, float_status *s)
378334f0c0a9SLIU Zhiwei {
37844ab4aef0SRichard Henderson     return float128_to_uint32_scalbn(a, float_round_to_zero, 0, s);
378534f0c0a9SLIU Zhiwei }
378634f0c0a9SLIU Zhiwei 
float128_to_uint64_round_to_zero(float128 a,float_status * s)37874ab4aef0SRichard Henderson uint64_t float128_to_uint64_round_to_zero(float128 a, float_status *s)
378834f0c0a9SLIU Zhiwei {
37894ab4aef0SRichard Henderson     return float128_to_uint64_scalbn(a, float_round_to_zero, 0, s);
379034f0c0a9SLIU Zhiwei }
379134f0c0a9SLIU Zhiwei 
float128_to_uint128_round_to_zero(float128 a,float_status * s)37924de49ddfSMatheus Ferst Int128 float128_to_uint128_round_to_zero(float128 a, float_status *s)
37934de49ddfSMatheus Ferst {
37944de49ddfSMatheus Ferst     return float128_to_uint128_scalbn(a, float_round_to_zero, 0, s);
37954de49ddfSMatheus Ferst }
37964de49ddfSMatheus Ferst 
bfloat16_to_uint8(bfloat16 a,float_status * s)379700f9ef8fSLIU Zhiwei uint8_t bfloat16_to_uint8(bfloat16 a, float_status *s)
379800f9ef8fSLIU Zhiwei {
379900f9ef8fSLIU Zhiwei     return bfloat16_to_uint8_scalbn(a, s->float_rounding_mode, 0, s);
380000f9ef8fSLIU Zhiwei }
380100f9ef8fSLIU Zhiwei 
bfloat16_to_uint16(bfloat16 a,float_status * s)380234f0c0a9SLIU Zhiwei uint16_t bfloat16_to_uint16(bfloat16 a, float_status *s)
380334f0c0a9SLIU Zhiwei {
380434f0c0a9SLIU Zhiwei     return bfloat16_to_uint16_scalbn(a, s->float_rounding_mode, 0, s);
380534f0c0a9SLIU Zhiwei }
380634f0c0a9SLIU Zhiwei 
bfloat16_to_uint32(bfloat16 a,float_status * s)380734f0c0a9SLIU Zhiwei uint32_t bfloat16_to_uint32(bfloat16 a, float_status *s)
380834f0c0a9SLIU Zhiwei {
380934f0c0a9SLIU Zhiwei     return bfloat16_to_uint32_scalbn(a, s->float_rounding_mode, 0, s);
381034f0c0a9SLIU Zhiwei }
381134f0c0a9SLIU Zhiwei 
bfloat16_to_uint64(bfloat16 a,float_status * s)381234f0c0a9SLIU Zhiwei uint64_t bfloat16_to_uint64(bfloat16 a, float_status *s)
381334f0c0a9SLIU Zhiwei {
381434f0c0a9SLIU Zhiwei     return bfloat16_to_uint64_scalbn(a, s->float_rounding_mode, 0, s);
381534f0c0a9SLIU Zhiwei }
381634f0c0a9SLIU Zhiwei 
bfloat16_to_uint8_round_to_zero(bfloat16 a,float_status * s)381700f9ef8fSLIU Zhiwei uint8_t bfloat16_to_uint8_round_to_zero(bfloat16 a, float_status *s)
381800f9ef8fSLIU Zhiwei {
381900f9ef8fSLIU Zhiwei     return bfloat16_to_uint8_scalbn(a, float_round_to_zero, 0, s);
382000f9ef8fSLIU Zhiwei }
382100f9ef8fSLIU Zhiwei 
bfloat16_to_uint16_round_to_zero(bfloat16 a,float_status * s)382234f0c0a9SLIU Zhiwei uint16_t bfloat16_to_uint16_round_to_zero(bfloat16 a, float_status *s)
382334f0c0a9SLIU Zhiwei {
382434f0c0a9SLIU Zhiwei     return bfloat16_to_uint16_scalbn(a, float_round_to_zero, 0, s);
382534f0c0a9SLIU Zhiwei }
382634f0c0a9SLIU Zhiwei 
bfloat16_to_uint32_round_to_zero(bfloat16 a,float_status * s)382734f0c0a9SLIU Zhiwei uint32_t bfloat16_to_uint32_round_to_zero(bfloat16 a, float_status *s)
382834f0c0a9SLIU Zhiwei {
382934f0c0a9SLIU Zhiwei     return bfloat16_to_uint32_scalbn(a, float_round_to_zero, 0, s);
383034f0c0a9SLIU Zhiwei }
383134f0c0a9SLIU Zhiwei 
bfloat16_to_uint64_round_to_zero(bfloat16 a,float_status * s)383234f0c0a9SLIU Zhiwei uint64_t bfloat16_to_uint64_round_to_zero(bfloat16 a, float_status *s)
383334f0c0a9SLIU Zhiwei {
383434f0c0a9SLIU Zhiwei     return bfloat16_to_uint64_scalbn(a, float_round_to_zero, 0, s);
383534f0c0a9SLIU Zhiwei }
383634f0c0a9SLIU Zhiwei 
383734f0c0a9SLIU Zhiwei /*
3838e3689519SRichard Henderson  * Signed integer to floating-point conversions
3839c02e1fb8SAlex Bennée  */
3840c02e1fb8SAlex Bennée 
int64_to_float16_scalbn(int64_t a,int scale,float_status * status)38412abdfe24SRichard Henderson float16 int64_to_float16_scalbn(int64_t a, int scale, float_status *status)
38422abdfe24SRichard Henderson {
3843e3689519SRichard Henderson     FloatParts64 p;
3844e3689519SRichard Henderson 
3845e3689519SRichard Henderson     parts_sint_to_float(&p, a, scale, status);
3846e3689519SRichard Henderson     return float16_round_pack_canonical(&p, status);
38472abdfe24SRichard Henderson }
38482abdfe24SRichard Henderson 
int32_to_float16_scalbn(int32_t a,int scale,float_status * status)38492abdfe24SRichard Henderson float16 int32_to_float16_scalbn(int32_t a, int scale, float_status *status)
38502abdfe24SRichard Henderson {
38512abdfe24SRichard Henderson     return int64_to_float16_scalbn(a, scale, status);
38522abdfe24SRichard Henderson }
38532abdfe24SRichard Henderson 
int16_to_float16_scalbn(int16_t a,int scale,float_status * status)38542abdfe24SRichard Henderson float16 int16_to_float16_scalbn(int16_t a, int scale, float_status *status)
38552abdfe24SRichard Henderson {
38562abdfe24SRichard Henderson     return int64_to_float16_scalbn(a, scale, status);
38572abdfe24SRichard Henderson }
38582abdfe24SRichard Henderson 
int64_to_float16(int64_t a,float_status * status)3859c02e1fb8SAlex Bennée float16 int64_to_float16(int64_t a, float_status *status)
3860c02e1fb8SAlex Bennée {
38612abdfe24SRichard Henderson     return int64_to_float16_scalbn(a, 0, status);
3862c02e1fb8SAlex Bennée }
3863c02e1fb8SAlex Bennée 
int32_to_float16(int32_t a,float_status * status)3864c02e1fb8SAlex Bennée float16 int32_to_float16(int32_t a, float_status *status)
3865c02e1fb8SAlex Bennée {
38662abdfe24SRichard Henderson     return int64_to_float16_scalbn(a, 0, status);
3867c02e1fb8SAlex Bennée }
3868c02e1fb8SAlex Bennée 
int16_to_float16(int16_t a,float_status * status)3869c02e1fb8SAlex Bennée float16 int16_to_float16(int16_t a, float_status *status)
3870c02e1fb8SAlex Bennée {
38712abdfe24SRichard Henderson     return int64_to_float16_scalbn(a, 0, status);
38722abdfe24SRichard Henderson }
38732abdfe24SRichard Henderson 
int8_to_float16(int8_t a,float_status * status)38740d93d8ecSFrank Chang float16 int8_to_float16(int8_t a, float_status *status)
38750d93d8ecSFrank Chang {
38760d93d8ecSFrank Chang     return int64_to_float16_scalbn(a, 0, status);
38770d93d8ecSFrank Chang }
38780d93d8ecSFrank Chang 
int64_to_float32_scalbn(int64_t a,int scale,float_status * status)38792abdfe24SRichard Henderson float32 int64_to_float32_scalbn(int64_t a, int scale, float_status *status)
38802abdfe24SRichard Henderson {
3881e3689519SRichard Henderson     FloatParts64 p;
3882e3689519SRichard Henderson 
38835d0204b8SRichard Henderson     /* Without scaling, there are no overflow concerns. */
38845d0204b8SRichard Henderson     if (likely(scale == 0) && can_use_fpu(status)) {
38855d0204b8SRichard Henderson         union_float32 ur;
38865d0204b8SRichard Henderson         ur.h = a;
38875d0204b8SRichard Henderson         return ur.s;
38885d0204b8SRichard Henderson     }
38895d0204b8SRichard Henderson 
3890e3689519SRichard Henderson     parts64_sint_to_float(&p, a, scale, status);
3891e3689519SRichard Henderson     return float32_round_pack_canonical(&p, status);
38922abdfe24SRichard Henderson }
38932abdfe24SRichard Henderson 
int32_to_float32_scalbn(int32_t a,int scale,float_status * status)38942abdfe24SRichard Henderson float32 int32_to_float32_scalbn(int32_t a, int scale, float_status *status)
38952abdfe24SRichard Henderson {
38962abdfe24SRichard Henderson     return int64_to_float32_scalbn(a, scale, status);
38972abdfe24SRichard Henderson }
38982abdfe24SRichard Henderson 
int16_to_float32_scalbn(int16_t a,int scale,float_status * status)38992abdfe24SRichard Henderson float32 int16_to_float32_scalbn(int16_t a, int scale, float_status *status)
39002abdfe24SRichard Henderson {
39012abdfe24SRichard Henderson     return int64_to_float32_scalbn(a, scale, status);
3902c02e1fb8SAlex Bennée }
3903c02e1fb8SAlex Bennée 
int64_to_float32(int64_t a,float_status * status)3904c02e1fb8SAlex Bennée float32 int64_to_float32(int64_t a, float_status *status)
3905c02e1fb8SAlex Bennée {
39062abdfe24SRichard Henderson     return int64_to_float32_scalbn(a, 0, status);
3907c02e1fb8SAlex Bennée }
3908c02e1fb8SAlex Bennée 
int32_to_float32(int32_t a,float_status * status)3909c02e1fb8SAlex Bennée float32 int32_to_float32(int32_t a, float_status *status)
3910c02e1fb8SAlex Bennée {
39112abdfe24SRichard Henderson     return int64_to_float32_scalbn(a, 0, status);
3912c02e1fb8SAlex Bennée }
3913c02e1fb8SAlex Bennée 
int16_to_float32(int16_t a,float_status * status)3914c02e1fb8SAlex Bennée float32 int16_to_float32(int16_t a, float_status *status)
3915c02e1fb8SAlex Bennée {
39162abdfe24SRichard Henderson     return int64_to_float32_scalbn(a, 0, status);
39172abdfe24SRichard Henderson }
39182abdfe24SRichard Henderson 
int64_to_float64_scalbn(int64_t a,int scale,float_status * status)39192abdfe24SRichard Henderson float64 int64_to_float64_scalbn(int64_t a, int scale, float_status *status)
39202abdfe24SRichard Henderson {
3921e3689519SRichard Henderson     FloatParts64 p;
3922e3689519SRichard Henderson 
39235d0204b8SRichard Henderson     /* Without scaling, there are no overflow concerns. */
39245d0204b8SRichard Henderson     if (likely(scale == 0) && can_use_fpu(status)) {
39255d0204b8SRichard Henderson         union_float64 ur;
39265d0204b8SRichard Henderson         ur.h = a;
39275d0204b8SRichard Henderson         return ur.s;
39285d0204b8SRichard Henderson     }
39295d0204b8SRichard Henderson 
3930e3689519SRichard Henderson     parts_sint_to_float(&p, a, scale, status);
3931e3689519SRichard Henderson     return float64_round_pack_canonical(&p, status);
39322abdfe24SRichard Henderson }
39332abdfe24SRichard Henderson 
int32_to_float64_scalbn(int32_t a,int scale,float_status * status)39342abdfe24SRichard Henderson float64 int32_to_float64_scalbn(int32_t a, int scale, float_status *status)
39352abdfe24SRichard Henderson {
39362abdfe24SRichard Henderson     return int64_to_float64_scalbn(a, scale, status);
39372abdfe24SRichard Henderson }
39382abdfe24SRichard Henderson 
int16_to_float64_scalbn(int16_t a,int scale,float_status * status)39392abdfe24SRichard Henderson float64 int16_to_float64_scalbn(int16_t a, int scale, float_status *status)
39402abdfe24SRichard Henderson {
39412abdfe24SRichard Henderson     return int64_to_float64_scalbn(a, scale, status);
3942c02e1fb8SAlex Bennée }
3943c02e1fb8SAlex Bennée 
int64_to_float64(int64_t a,float_status * status)3944c02e1fb8SAlex Bennée float64 int64_to_float64(int64_t a, float_status *status)
3945c02e1fb8SAlex Bennée {
39462abdfe24SRichard Henderson     return int64_to_float64_scalbn(a, 0, status);
3947c02e1fb8SAlex Bennée }
3948c02e1fb8SAlex Bennée 
int32_to_float64(int32_t a,float_status * status)3949c02e1fb8SAlex Bennée float64 int32_to_float64(int32_t a, float_status *status)
3950c02e1fb8SAlex Bennée {
39512abdfe24SRichard Henderson     return int64_to_float64_scalbn(a, 0, status);
3952c02e1fb8SAlex Bennée }
3953c02e1fb8SAlex Bennée 
int16_to_float64(int16_t a,float_status * status)3954c02e1fb8SAlex Bennée float64 int16_to_float64(int16_t a, float_status *status)
3955c02e1fb8SAlex Bennée {
39562abdfe24SRichard Henderson     return int64_to_float64_scalbn(a, 0, status);
3957c02e1fb8SAlex Bennée }
3958c02e1fb8SAlex Bennée 
int64_to_bfloat16_scalbn(int64_t a,int scale,float_status * status)395934f0c0a9SLIU Zhiwei bfloat16 int64_to_bfloat16_scalbn(int64_t a, int scale, float_status *status)
396034f0c0a9SLIU Zhiwei {
3961e3689519SRichard Henderson     FloatParts64 p;
3962e3689519SRichard Henderson 
3963e3689519SRichard Henderson     parts_sint_to_float(&p, a, scale, status);
3964e3689519SRichard Henderson     return bfloat16_round_pack_canonical(&p, status);
396534f0c0a9SLIU Zhiwei }
396634f0c0a9SLIU Zhiwei 
int32_to_bfloat16_scalbn(int32_t a,int scale,float_status * status)396734f0c0a9SLIU Zhiwei bfloat16 int32_to_bfloat16_scalbn(int32_t a, int scale, float_status *status)
396834f0c0a9SLIU Zhiwei {
396934f0c0a9SLIU Zhiwei     return int64_to_bfloat16_scalbn(a, scale, status);
397034f0c0a9SLIU Zhiwei }
397134f0c0a9SLIU Zhiwei 
int16_to_bfloat16_scalbn(int16_t a,int scale,float_status * status)397234f0c0a9SLIU Zhiwei bfloat16 int16_to_bfloat16_scalbn(int16_t a, int scale, float_status *status)
397334f0c0a9SLIU Zhiwei {
397434f0c0a9SLIU Zhiwei     return int64_to_bfloat16_scalbn(a, scale, status);
397534f0c0a9SLIU Zhiwei }
397634f0c0a9SLIU Zhiwei 
int8_to_bfloat16_scalbn(int8_t a,int scale,float_status * status)397700f9ef8fSLIU Zhiwei bfloat16 int8_to_bfloat16_scalbn(int8_t a, int scale, float_status *status)
397800f9ef8fSLIU Zhiwei {
397900f9ef8fSLIU Zhiwei     return int64_to_bfloat16_scalbn(a, scale, status);
398000f9ef8fSLIU Zhiwei }
398100f9ef8fSLIU Zhiwei 
int64_to_bfloat16(int64_t a,float_status * status)398234f0c0a9SLIU Zhiwei bfloat16 int64_to_bfloat16(int64_t a, float_status *status)
398334f0c0a9SLIU Zhiwei {
398434f0c0a9SLIU Zhiwei     return int64_to_bfloat16_scalbn(a, 0, status);
398534f0c0a9SLIU Zhiwei }
398634f0c0a9SLIU Zhiwei 
int32_to_bfloat16(int32_t a,float_status * status)398734f0c0a9SLIU Zhiwei bfloat16 int32_to_bfloat16(int32_t a, float_status *status)
398834f0c0a9SLIU Zhiwei {
398934f0c0a9SLIU Zhiwei     return int64_to_bfloat16_scalbn(a, 0, status);
399034f0c0a9SLIU Zhiwei }
399134f0c0a9SLIU Zhiwei 
int16_to_bfloat16(int16_t a,float_status * status)399234f0c0a9SLIU Zhiwei bfloat16 int16_to_bfloat16(int16_t a, float_status *status)
399334f0c0a9SLIU Zhiwei {
399434f0c0a9SLIU Zhiwei     return int64_to_bfloat16_scalbn(a, 0, status);
399534f0c0a9SLIU Zhiwei }
3996c02e1fb8SAlex Bennée 
int8_to_bfloat16(int8_t a,float_status * status)399700f9ef8fSLIU Zhiwei bfloat16 int8_to_bfloat16(int8_t a, float_status *status)
399800f9ef8fSLIU Zhiwei {
399900f9ef8fSLIU Zhiwei     return int64_to_bfloat16_scalbn(a, 0, status);
400000f9ef8fSLIU Zhiwei }
400100f9ef8fSLIU Zhiwei 
int128_to_float128(Int128 a,float_status * status)400295c1b71eSMatheus Ferst float128 int128_to_float128(Int128 a, float_status *status)
400395c1b71eSMatheus Ferst {
400495c1b71eSMatheus Ferst     FloatParts128 p = { };
400595c1b71eSMatheus Ferst     int shift;
400695c1b71eSMatheus Ferst 
400795c1b71eSMatheus Ferst     if (int128_nz(a)) {
400895c1b71eSMatheus Ferst         p.cls = float_class_normal;
400995c1b71eSMatheus Ferst         if (!int128_nonneg(a)) {
401095c1b71eSMatheus Ferst             p.sign = true;
401195c1b71eSMatheus Ferst             a = int128_neg(a);
401295c1b71eSMatheus Ferst         }
401395c1b71eSMatheus Ferst 
401495c1b71eSMatheus Ferst         shift = clz64(int128_gethi(a));
401595c1b71eSMatheus Ferst         if (shift == 64) {
401695c1b71eSMatheus Ferst             shift += clz64(int128_getlo(a));
401795c1b71eSMatheus Ferst         }
401895c1b71eSMatheus Ferst 
401995c1b71eSMatheus Ferst         p.exp = 127 - shift;
402095c1b71eSMatheus Ferst         a = int128_lshift(a, shift);
402195c1b71eSMatheus Ferst 
402295c1b71eSMatheus Ferst         p.frac_hi = int128_gethi(a);
402395c1b71eSMatheus Ferst         p.frac_lo = int128_getlo(a);
402495c1b71eSMatheus Ferst     } else {
402595c1b71eSMatheus Ferst         p.cls = float_class_zero;
402695c1b71eSMatheus Ferst     }
402795c1b71eSMatheus Ferst 
402895c1b71eSMatheus Ferst     return float128_round_pack_canonical(&p, status);
402995c1b71eSMatheus Ferst }
403095c1b71eSMatheus Ferst 
int64_to_float128(int64_t a,float_status * status)4031e3689519SRichard Henderson float128 int64_to_float128(int64_t a, float_status *status)
4032e3689519SRichard Henderson {
4033e3689519SRichard Henderson     FloatParts128 p;
4034e3689519SRichard Henderson 
4035e3689519SRichard Henderson     parts_sint_to_float(&p, a, 0, status);
4036e3689519SRichard Henderson     return float128_round_pack_canonical(&p, status);
4037e3689519SRichard Henderson }
4038e3689519SRichard Henderson 
int32_to_float128(int32_t a,float_status * status)4039e3689519SRichard Henderson float128 int32_to_float128(int32_t a, float_status *status)
4040e3689519SRichard Henderson {
4041e3689519SRichard Henderson     return int64_to_float128(a, status);
4042e3689519SRichard Henderson }
4043e3689519SRichard Henderson 
int64_to_floatx80(int64_t a,float_status * status)40445f952900SRichard Henderson floatx80 int64_to_floatx80(int64_t a, float_status *status)
40455f952900SRichard Henderson {
40465f952900SRichard Henderson     FloatParts128 p;
40475f952900SRichard Henderson 
40485f952900SRichard Henderson     parts_sint_to_float(&p, a, 0, status);
40495f952900SRichard Henderson     return floatx80_round_pack_canonical(&p, status);
40505f952900SRichard Henderson }
40515f952900SRichard Henderson 
int32_to_floatx80(int32_t a,float_status * status)40525f952900SRichard Henderson floatx80 int32_to_floatx80(int32_t a, float_status *status)
40535f952900SRichard Henderson {
40545f952900SRichard Henderson     return int64_to_floatx80(a, status);
40555f952900SRichard Henderson }
40565f952900SRichard Henderson 
4057c02e1fb8SAlex Bennée /*
405837c954a1SRichard Henderson  * Unsigned Integer to floating-point conversions
4059c02e1fb8SAlex Bennée  */
4060c02e1fb8SAlex Bennée 
uint64_to_float16_scalbn(uint64_t a,int scale,float_status * status)40612abdfe24SRichard Henderson float16 uint64_to_float16_scalbn(uint64_t a, int scale, float_status *status)
40622abdfe24SRichard Henderson {
406337c954a1SRichard Henderson     FloatParts64 p;
406437c954a1SRichard Henderson 
406537c954a1SRichard Henderson     parts_uint_to_float(&p, a, scale, status);
406637c954a1SRichard Henderson     return float16_round_pack_canonical(&p, status);
40672abdfe24SRichard Henderson }
40682abdfe24SRichard Henderson 
uint32_to_float16_scalbn(uint32_t a,int scale,float_status * status)40692abdfe24SRichard Henderson float16 uint32_to_float16_scalbn(uint32_t a, int scale, float_status *status)
40702abdfe24SRichard Henderson {
40712abdfe24SRichard Henderson     return uint64_to_float16_scalbn(a, scale, status);
40722abdfe24SRichard Henderson }
40732abdfe24SRichard Henderson 
uint16_to_float16_scalbn(uint16_t a,int scale,float_status * status)40742abdfe24SRichard Henderson float16 uint16_to_float16_scalbn(uint16_t a, int scale, float_status *status)
40752abdfe24SRichard Henderson {
40762abdfe24SRichard Henderson     return uint64_to_float16_scalbn(a, scale, status);
40772abdfe24SRichard Henderson }
40782abdfe24SRichard Henderson 
uint64_to_float16(uint64_t a,float_status * status)4079c02e1fb8SAlex Bennée float16 uint64_to_float16(uint64_t a, float_status *status)
4080c02e1fb8SAlex Bennée {
40812abdfe24SRichard Henderson     return uint64_to_float16_scalbn(a, 0, status);
4082c02e1fb8SAlex Bennée }
4083c02e1fb8SAlex Bennée 
uint32_to_float16(uint32_t a,float_status * status)4084c02e1fb8SAlex Bennée float16 uint32_to_float16(uint32_t a, float_status *status)
4085c02e1fb8SAlex Bennée {
40862abdfe24SRichard Henderson     return uint64_to_float16_scalbn(a, 0, status);
4087c02e1fb8SAlex Bennée }
4088c02e1fb8SAlex Bennée 
uint16_to_float16(uint16_t a,float_status * status)4089c02e1fb8SAlex Bennée float16 uint16_to_float16(uint16_t a, float_status *status)
4090c02e1fb8SAlex Bennée {
40912abdfe24SRichard Henderson     return uint64_to_float16_scalbn(a, 0, status);
40922abdfe24SRichard Henderson }
40932abdfe24SRichard Henderson 
uint8_to_float16(uint8_t a,float_status * status)40940d93d8ecSFrank Chang float16 uint8_to_float16(uint8_t a, float_status *status)
40950d93d8ecSFrank Chang {
40960d93d8ecSFrank Chang     return uint64_to_float16_scalbn(a, 0, status);
40970d93d8ecSFrank Chang }
40980d93d8ecSFrank Chang 
uint64_to_float32_scalbn(uint64_t a,int scale,float_status * status)40992abdfe24SRichard Henderson float32 uint64_to_float32_scalbn(uint64_t a, int scale, float_status *status)
41002abdfe24SRichard Henderson {
410137c954a1SRichard Henderson     FloatParts64 p;
410237c954a1SRichard Henderson 
41035d0204b8SRichard Henderson     /* Without scaling, there are no overflow concerns. */
41045d0204b8SRichard Henderson     if (likely(scale == 0) && can_use_fpu(status)) {
41055d0204b8SRichard Henderson         union_float32 ur;
41065d0204b8SRichard Henderson         ur.h = a;
41075d0204b8SRichard Henderson         return ur.s;
41085d0204b8SRichard Henderson     }
41095d0204b8SRichard Henderson 
411037c954a1SRichard Henderson     parts_uint_to_float(&p, a, scale, status);
411137c954a1SRichard Henderson     return float32_round_pack_canonical(&p, status);
41122abdfe24SRichard Henderson }
41132abdfe24SRichard Henderson 
uint32_to_float32_scalbn(uint32_t a,int scale,float_status * status)41142abdfe24SRichard Henderson float32 uint32_to_float32_scalbn(uint32_t a, int scale, float_status *status)
41152abdfe24SRichard Henderson {
41162abdfe24SRichard Henderson     return uint64_to_float32_scalbn(a, scale, status);
41172abdfe24SRichard Henderson }
41182abdfe24SRichard Henderson 
uint16_to_float32_scalbn(uint16_t a,int scale,float_status * status)41192abdfe24SRichard Henderson float32 uint16_to_float32_scalbn(uint16_t a, int scale, float_status *status)
41202abdfe24SRichard Henderson {
41212abdfe24SRichard Henderson     return uint64_to_float32_scalbn(a, scale, status);
4122c02e1fb8SAlex Bennée }
4123c02e1fb8SAlex Bennée 
uint64_to_float32(uint64_t a,float_status * status)4124c02e1fb8SAlex Bennée float32 uint64_to_float32(uint64_t a, float_status *status)
4125c02e1fb8SAlex Bennée {
41262abdfe24SRichard Henderson     return uint64_to_float32_scalbn(a, 0, status);
4127c02e1fb8SAlex Bennée }
4128c02e1fb8SAlex Bennée 
uint32_to_float32(uint32_t a,float_status * status)4129c02e1fb8SAlex Bennée float32 uint32_to_float32(uint32_t a, float_status *status)
4130c02e1fb8SAlex Bennée {
41312abdfe24SRichard Henderson     return uint64_to_float32_scalbn(a, 0, status);
4132c02e1fb8SAlex Bennée }
4133c02e1fb8SAlex Bennée 
uint16_to_float32(uint16_t a,float_status * status)4134c02e1fb8SAlex Bennée float32 uint16_to_float32(uint16_t a, float_status *status)
4135c02e1fb8SAlex Bennée {
41362abdfe24SRichard Henderson     return uint64_to_float32_scalbn(a, 0, status);
41372abdfe24SRichard Henderson }
41382abdfe24SRichard Henderson 
uint64_to_float64_scalbn(uint64_t a,int scale,float_status * status)41392abdfe24SRichard Henderson float64 uint64_to_float64_scalbn(uint64_t a, int scale, float_status *status)
41402abdfe24SRichard Henderson {
414137c954a1SRichard Henderson     FloatParts64 p;
414237c954a1SRichard Henderson 
41435d0204b8SRichard Henderson     /* Without scaling, there are no overflow concerns. */
41445d0204b8SRichard Henderson     if (likely(scale == 0) && can_use_fpu(status)) {
41455d0204b8SRichard Henderson         union_float64 ur;
41465d0204b8SRichard Henderson         ur.h = a;
41475d0204b8SRichard Henderson         return ur.s;
41485d0204b8SRichard Henderson     }
41495d0204b8SRichard Henderson 
415037c954a1SRichard Henderson     parts_uint_to_float(&p, a, scale, status);
415137c954a1SRichard Henderson     return float64_round_pack_canonical(&p, status);
41522abdfe24SRichard Henderson }
41532abdfe24SRichard Henderson 
uint32_to_float64_scalbn(uint32_t a,int scale,float_status * status)41542abdfe24SRichard Henderson float64 uint32_to_float64_scalbn(uint32_t a, int scale, float_status *status)
41552abdfe24SRichard Henderson {
41562abdfe24SRichard Henderson     return uint64_to_float64_scalbn(a, scale, status);
41572abdfe24SRichard Henderson }
41582abdfe24SRichard Henderson 
uint16_to_float64_scalbn(uint16_t a,int scale,float_status * status)41592abdfe24SRichard Henderson float64 uint16_to_float64_scalbn(uint16_t a, int scale, float_status *status)
41602abdfe24SRichard Henderson {
41612abdfe24SRichard Henderson     return uint64_to_float64_scalbn(a, scale, status);
4162c02e1fb8SAlex Bennée }
4163c02e1fb8SAlex Bennée 
uint64_to_float64(uint64_t a,float_status * status)4164c02e1fb8SAlex Bennée float64 uint64_to_float64(uint64_t a, float_status *status)
4165c02e1fb8SAlex Bennée {
41662abdfe24SRichard Henderson     return uint64_to_float64_scalbn(a, 0, status);
4167c02e1fb8SAlex Bennée }
4168c02e1fb8SAlex Bennée 
uint32_to_float64(uint32_t a,float_status * status)4169c02e1fb8SAlex Bennée float64 uint32_to_float64(uint32_t a, float_status *status)
4170c02e1fb8SAlex Bennée {
41712abdfe24SRichard Henderson     return uint64_to_float64_scalbn(a, 0, status);
4172c02e1fb8SAlex Bennée }
4173c02e1fb8SAlex Bennée 
uint16_to_float64(uint16_t a,float_status * status)4174c02e1fb8SAlex Bennée float64 uint16_to_float64(uint16_t a, float_status *status)
4175c02e1fb8SAlex Bennée {
41762abdfe24SRichard Henderson     return uint64_to_float64_scalbn(a, 0, status);
4177c02e1fb8SAlex Bennée }
4178c02e1fb8SAlex Bennée 
uint64_to_bfloat16_scalbn(uint64_t a,int scale,float_status * status)417934f0c0a9SLIU Zhiwei bfloat16 uint64_to_bfloat16_scalbn(uint64_t a, int scale, float_status *status)
418034f0c0a9SLIU Zhiwei {
418137c954a1SRichard Henderson     FloatParts64 p;
418237c954a1SRichard Henderson 
418337c954a1SRichard Henderson     parts_uint_to_float(&p, a, scale, status);
418437c954a1SRichard Henderson     return bfloat16_round_pack_canonical(&p, status);
418534f0c0a9SLIU Zhiwei }
418634f0c0a9SLIU Zhiwei 
uint32_to_bfloat16_scalbn(uint32_t a,int scale,float_status * status)418734f0c0a9SLIU Zhiwei bfloat16 uint32_to_bfloat16_scalbn(uint32_t a, int scale, float_status *status)
418834f0c0a9SLIU Zhiwei {
418934f0c0a9SLIU Zhiwei     return uint64_to_bfloat16_scalbn(a, scale, status);
419034f0c0a9SLIU Zhiwei }
419134f0c0a9SLIU Zhiwei 
uint16_to_bfloat16_scalbn(uint16_t a,int scale,float_status * status)419234f0c0a9SLIU Zhiwei bfloat16 uint16_to_bfloat16_scalbn(uint16_t a, int scale, float_status *status)
419334f0c0a9SLIU Zhiwei {
419434f0c0a9SLIU Zhiwei     return uint64_to_bfloat16_scalbn(a, scale, status);
419534f0c0a9SLIU Zhiwei }
419634f0c0a9SLIU Zhiwei 
uint8_to_bfloat16_scalbn(uint8_t a,int scale,float_status * status)419700f9ef8fSLIU Zhiwei bfloat16 uint8_to_bfloat16_scalbn(uint8_t a, int scale, float_status *status)
419800f9ef8fSLIU Zhiwei {
419900f9ef8fSLIU Zhiwei     return uint64_to_bfloat16_scalbn(a, scale, status);
420000f9ef8fSLIU Zhiwei }
420100f9ef8fSLIU Zhiwei 
uint64_to_bfloat16(uint64_t a,float_status * status)420234f0c0a9SLIU Zhiwei bfloat16 uint64_to_bfloat16(uint64_t a, float_status *status)
420334f0c0a9SLIU Zhiwei {
420434f0c0a9SLIU Zhiwei     return uint64_to_bfloat16_scalbn(a, 0, status);
420534f0c0a9SLIU Zhiwei }
420634f0c0a9SLIU Zhiwei 
uint32_to_bfloat16(uint32_t a,float_status * status)420734f0c0a9SLIU Zhiwei bfloat16 uint32_to_bfloat16(uint32_t a, float_status *status)
420834f0c0a9SLIU Zhiwei {
420934f0c0a9SLIU Zhiwei     return uint64_to_bfloat16_scalbn(a, 0, status);
421034f0c0a9SLIU Zhiwei }
421134f0c0a9SLIU Zhiwei 
uint16_to_bfloat16(uint16_t a,float_status * status)421234f0c0a9SLIU Zhiwei bfloat16 uint16_to_bfloat16(uint16_t a, float_status *status)
421334f0c0a9SLIU Zhiwei {
421434f0c0a9SLIU Zhiwei     return uint64_to_bfloat16_scalbn(a, 0, status);
421534f0c0a9SLIU Zhiwei }
421634f0c0a9SLIU Zhiwei 
uint8_to_bfloat16(uint8_t a,float_status * status)421700f9ef8fSLIU Zhiwei bfloat16 uint8_to_bfloat16(uint8_t a, float_status *status)
421800f9ef8fSLIU Zhiwei {
421900f9ef8fSLIU Zhiwei     return uint64_to_bfloat16_scalbn(a, 0, status);
422000f9ef8fSLIU Zhiwei }
422100f9ef8fSLIU Zhiwei 
uint64_to_float128(uint64_t a,float_status * status)422237c954a1SRichard Henderson float128 uint64_to_float128(uint64_t a, float_status *status)
422337c954a1SRichard Henderson {
422437c954a1SRichard Henderson     FloatParts128 p;
422537c954a1SRichard Henderson 
422637c954a1SRichard Henderson     parts_uint_to_float(&p, a, 0, status);
422737c954a1SRichard Henderson     return float128_round_pack_canonical(&p, status);
422837c954a1SRichard Henderson }
422937c954a1SRichard Henderson 
uint128_to_float128(Int128 a,float_status * status)4230f279852bSMatheus Ferst float128 uint128_to_float128(Int128 a, float_status *status)
4231f279852bSMatheus Ferst {
4232f279852bSMatheus Ferst     FloatParts128 p = { };
4233f279852bSMatheus Ferst     int shift;
4234f279852bSMatheus Ferst 
4235f279852bSMatheus Ferst     if (int128_nz(a)) {
4236f279852bSMatheus Ferst         p.cls = float_class_normal;
4237f279852bSMatheus Ferst 
4238f279852bSMatheus Ferst         shift = clz64(int128_gethi(a));
4239f279852bSMatheus Ferst         if (shift == 64) {
4240f279852bSMatheus Ferst             shift += clz64(int128_getlo(a));
4241f279852bSMatheus Ferst         }
4242f279852bSMatheus Ferst 
4243f279852bSMatheus Ferst         p.exp = 127 - shift;
4244f279852bSMatheus Ferst         a = int128_lshift(a, shift);
4245f279852bSMatheus Ferst 
4246f279852bSMatheus Ferst         p.frac_hi = int128_gethi(a);
4247f279852bSMatheus Ferst         p.frac_lo = int128_getlo(a);
4248f279852bSMatheus Ferst     } else {
4249f279852bSMatheus Ferst         p.cls = float_class_zero;
4250f279852bSMatheus Ferst     }
4251f279852bSMatheus Ferst 
4252f279852bSMatheus Ferst     return float128_round_pack_canonical(&p, status);
4253f279852bSMatheus Ferst }
4254f279852bSMatheus Ferst 
4255e1c4667aSRichard Henderson /*
4256e1c4667aSRichard Henderson  * Minimum and maximum
425789360067SAlex Bennée  */
4258e1c4667aSRichard Henderson 
float16_minmax(float16 a,float16 b,float_status * s,int flags)4259e1c4667aSRichard Henderson static float16 float16_minmax(float16 a, float16 b, float_status *s, int flags)
426089360067SAlex Bennée {
4261e1c4667aSRichard Henderson     FloatParts64 pa, pb, *pr;
426289360067SAlex Bennée 
4263e1c4667aSRichard Henderson     float16_unpack_canonical(&pa, a, s);
4264e1c4667aSRichard Henderson     float16_unpack_canonical(&pb, b, s);
4265e1c4667aSRichard Henderson     pr = parts_minmax(&pa, &pb, s, flags);
4266e1c4667aSRichard Henderson 
4267e1c4667aSRichard Henderson     return float16_round_pack_canonical(pr, s);
426889360067SAlex Bennée }
426989360067SAlex Bennée 
bfloat16_minmax(bfloat16 a,bfloat16 b,float_status * s,int flags)4270e1c4667aSRichard Henderson static bfloat16 bfloat16_minmax(bfloat16 a, bfloat16 b,
4271e1c4667aSRichard Henderson                                 float_status *s, int flags)
4272e1c4667aSRichard Henderson {
4273e1c4667aSRichard Henderson     FloatParts64 pa, pb, *pr;
4274e1c4667aSRichard Henderson 
4275e1c4667aSRichard Henderson     bfloat16_unpack_canonical(&pa, a, s);
4276e1c4667aSRichard Henderson     bfloat16_unpack_canonical(&pb, b, s);
4277e1c4667aSRichard Henderson     pr = parts_minmax(&pa, &pb, s, flags);
4278e1c4667aSRichard Henderson 
4279e1c4667aSRichard Henderson     return bfloat16_round_pack_canonical(pr, s);
42806245327aSEmilio G. Cota }
42816245327aSEmilio G. Cota 
float32_minmax(float32 a,float32 b,float_status * s,int flags)4282e1c4667aSRichard Henderson static float32 float32_minmax(float32 a, float32 b, float_status *s, int flags)
4283e1c4667aSRichard Henderson {
4284e1c4667aSRichard Henderson     FloatParts64 pa, pb, *pr;
4285e1c4667aSRichard Henderson 
4286e1c4667aSRichard Henderson     float32_unpack_canonical(&pa, a, s);
4287e1c4667aSRichard Henderson     float32_unpack_canonical(&pb, b, s);
4288e1c4667aSRichard Henderson     pr = parts_minmax(&pa, &pb, s, flags);
4289e1c4667aSRichard Henderson 
4290e1c4667aSRichard Henderson     return float32_round_pack_canonical(pr, s);
429189360067SAlex Bennée }
429289360067SAlex Bennée 
float64_minmax(float64 a,float64 b,float_status * s,int flags)4293e1c4667aSRichard Henderson static float64 float64_minmax(float64 a, float64 b, float_status *s, int flags)
4294e1c4667aSRichard Henderson {
4295e1c4667aSRichard Henderson     FloatParts64 pa, pb, *pr;
4296e1c4667aSRichard Henderson 
4297e1c4667aSRichard Henderson     float64_unpack_canonical(&pa, a, s);
4298e1c4667aSRichard Henderson     float64_unpack_canonical(&pb, b, s);
4299e1c4667aSRichard Henderson     pr = parts_minmax(&pa, &pb, s, flags);
4300e1c4667aSRichard Henderson 
4301e1c4667aSRichard Henderson     return float64_round_pack_canonical(pr, s);
430289360067SAlex Bennée }
430389360067SAlex Bennée 
float128_minmax(float128 a,float128 b,float_status * s,int flags)4304ceebc129SDavid Hildenbrand static float128 float128_minmax(float128 a, float128 b,
4305ceebc129SDavid Hildenbrand                                 float_status *s, int flags)
4306ceebc129SDavid Hildenbrand {
4307ceebc129SDavid Hildenbrand     FloatParts128 pa, pb, *pr;
4308ceebc129SDavid Hildenbrand 
4309ceebc129SDavid Hildenbrand     float128_unpack_canonical(&pa, a, s);
4310ceebc129SDavid Hildenbrand     float128_unpack_canonical(&pb, b, s);
4311ceebc129SDavid Hildenbrand     pr = parts_minmax(&pa, &pb, s, flags);
4312ceebc129SDavid Hildenbrand 
4313ceebc129SDavid Hildenbrand     return float128_round_pack_canonical(pr, s);
4314ceebc129SDavid Hildenbrand }
4315ceebc129SDavid Hildenbrand 
4316e1c4667aSRichard Henderson #define MINMAX_1(type, name, flags) \
4317e1c4667aSRichard Henderson     type type##_##name(type a, type b, float_status *s) \
4318e1c4667aSRichard Henderson     { return type##_minmax(a, b, s, flags); }
431989360067SAlex Bennée 
4320e1c4667aSRichard Henderson #define MINMAX_2(type) \
4321e1c4667aSRichard Henderson     MINMAX_1(type, max, 0)                                                \
4322e1c4667aSRichard Henderson     MINMAX_1(type, maxnum, minmax_isnum)                                  \
4323e1c4667aSRichard Henderson     MINMAX_1(type, maxnummag, minmax_isnum | minmax_ismag)                \
43240e903037SChih-Min Chao     MINMAX_1(type, maximum_number, minmax_isnumber)                       \
4325e1c4667aSRichard Henderson     MINMAX_1(type, min, minmax_ismin)                                     \
4326e1c4667aSRichard Henderson     MINMAX_1(type, minnum, minmax_ismin | minmax_isnum)                   \
43270e903037SChih-Min Chao     MINMAX_1(type, minnummag, minmax_ismin | minmax_isnum | minmax_ismag) \
43280e903037SChih-Min Chao     MINMAX_1(type, minimum_number, minmax_ismin | minmax_isnumber)        \
432989360067SAlex Bennée 
4330e1c4667aSRichard Henderson MINMAX_2(float16)
MINMAX_2(bfloat16)4331e1c4667aSRichard Henderson MINMAX_2(bfloat16)
4332e1c4667aSRichard Henderson MINMAX_2(float32)
4333e1c4667aSRichard Henderson MINMAX_2(float64)
4334ceebc129SDavid Hildenbrand MINMAX_2(float128)
433589360067SAlex Bennée 
4336e1c4667aSRichard Henderson #undef MINMAX_1
4337e1c4667aSRichard Henderson #undef MINMAX_2
43388282310dSLIU Zhiwei 
43396eb169b8SRichard Henderson /*
43406eb169b8SRichard Henderson  * Floating point compare
43410c4c9092SAlex Bennée  */
43420c4c9092SAlex Bennée 
43436eb169b8SRichard Henderson static FloatRelation QEMU_FLATTEN
43446eb169b8SRichard Henderson float16_do_compare(float16 a, float16 b, float_status *s, bool is_quiet)
43456eb169b8SRichard Henderson {
43466eb169b8SRichard Henderson     FloatParts64 pa, pb;
43470c4c9092SAlex Bennée 
43486eb169b8SRichard Henderson     float16_unpack_canonical(&pa, a, s);
43496eb169b8SRichard Henderson     float16_unpack_canonical(&pb, b, s);
43506eb169b8SRichard Henderson     return parts_compare(&pa, &pb, s, is_quiet);
43510c4c9092SAlex Bennée }
43520c4c9092SAlex Bennée 
float16_compare(float16 a,float16 b,float_status * s)435371bfd65cSRichard Henderson FloatRelation float16_compare(float16 a, float16 b, float_status *s)
4354d9fe9db9SEmilio G. Cota {
43556eb169b8SRichard Henderson     return float16_do_compare(a, b, s, false);
4356d9fe9db9SEmilio G. Cota }
4357d9fe9db9SEmilio G. Cota 
float16_compare_quiet(float16 a,float16 b,float_status * s)435871bfd65cSRichard Henderson FloatRelation float16_compare_quiet(float16 a, float16 b, float_status *s)
4359d9fe9db9SEmilio G. Cota {
43606eb169b8SRichard Henderson     return float16_do_compare(a, b, s, true);
43616eb169b8SRichard Henderson }
43626eb169b8SRichard Henderson 
43636eb169b8SRichard Henderson static FloatRelation QEMU_SOFTFLOAT_ATTR
float32_do_compare(float32 a,float32 b,float_status * s,bool is_quiet)43646eb169b8SRichard Henderson float32_do_compare(float32 a, float32 b, float_status *s, bool is_quiet)
43656eb169b8SRichard Henderson {
43666eb169b8SRichard Henderson     FloatParts64 pa, pb;
43676eb169b8SRichard Henderson 
43686eb169b8SRichard Henderson     float32_unpack_canonical(&pa, a, s);
43696eb169b8SRichard Henderson     float32_unpack_canonical(&pb, b, s);
43706eb169b8SRichard Henderson     return parts_compare(&pa, &pb, s, is_quiet);
4371d9fe9db9SEmilio G. Cota }
4372d9fe9db9SEmilio G. Cota 
437371bfd65cSRichard Henderson static FloatRelation QEMU_FLATTEN
float32_hs_compare(float32 xa,float32 xb,float_status * s,bool is_quiet)43746eb169b8SRichard Henderson float32_hs_compare(float32 xa, float32 xb, float_status *s, bool is_quiet)
4375d9fe9db9SEmilio G. Cota {
4376d9fe9db9SEmilio G. Cota     union_float32 ua, ub;
4377d9fe9db9SEmilio G. Cota 
4378d9fe9db9SEmilio G. Cota     ua.s = xa;
4379d9fe9db9SEmilio G. Cota     ub.s = xb;
4380d9fe9db9SEmilio G. Cota 
4381d9fe9db9SEmilio G. Cota     if (QEMU_NO_HARDFLOAT) {
4382d9fe9db9SEmilio G. Cota         goto soft;
4383d9fe9db9SEmilio G. Cota     }
4384d9fe9db9SEmilio G. Cota 
4385d9fe9db9SEmilio G. Cota     float32_input_flush2(&ua.s, &ub.s, s);
4386d9fe9db9SEmilio G. Cota     if (isgreaterequal(ua.h, ub.h)) {
4387d9fe9db9SEmilio G. Cota         if (isgreater(ua.h, ub.h)) {
4388d9fe9db9SEmilio G. Cota             return float_relation_greater;
4389d9fe9db9SEmilio G. Cota         }
4390d9fe9db9SEmilio G. Cota         return float_relation_equal;
4391d9fe9db9SEmilio G. Cota     }
4392d9fe9db9SEmilio G. Cota     if (likely(isless(ua.h, ub.h))) {
4393d9fe9db9SEmilio G. Cota         return float_relation_less;
4394d9fe9db9SEmilio G. Cota     }
43956eb169b8SRichard Henderson     /*
43966eb169b8SRichard Henderson      * The only condition remaining is unordered.
4397d9fe9db9SEmilio G. Cota      * Fall through to set flags.
4398d9fe9db9SEmilio G. Cota      */
4399d9fe9db9SEmilio G. Cota  soft:
44006eb169b8SRichard Henderson     return float32_do_compare(ua.s, ub.s, s, is_quiet);
4401d9fe9db9SEmilio G. Cota }
4402d9fe9db9SEmilio G. Cota 
float32_compare(float32 a,float32 b,float_status * s)440371bfd65cSRichard Henderson FloatRelation float32_compare(float32 a, float32 b, float_status *s)
4404d9fe9db9SEmilio G. Cota {
44056eb169b8SRichard Henderson     return float32_hs_compare(a, b, s, false);
4406d9fe9db9SEmilio G. Cota }
4407d9fe9db9SEmilio G. Cota 
float32_compare_quiet(float32 a,float32 b,float_status * s)440871bfd65cSRichard Henderson FloatRelation float32_compare_quiet(float32 a, float32 b, float_status *s)
4409d9fe9db9SEmilio G. Cota {
44106eb169b8SRichard Henderson     return float32_hs_compare(a, b, s, true);
44116eb169b8SRichard Henderson }
44126eb169b8SRichard Henderson 
44136eb169b8SRichard Henderson static FloatRelation QEMU_SOFTFLOAT_ATTR
float64_do_compare(float64 a,float64 b,float_status * s,bool is_quiet)44146eb169b8SRichard Henderson float64_do_compare(float64 a, float64 b, float_status *s, bool is_quiet)
44156eb169b8SRichard Henderson {
44166eb169b8SRichard Henderson     FloatParts64 pa, pb;
44176eb169b8SRichard Henderson 
44186eb169b8SRichard Henderson     float64_unpack_canonical(&pa, a, s);
44196eb169b8SRichard Henderson     float64_unpack_canonical(&pb, b, s);
44206eb169b8SRichard Henderson     return parts_compare(&pa, &pb, s, is_quiet);
4421d9fe9db9SEmilio G. Cota }
4422d9fe9db9SEmilio G. Cota 
442371bfd65cSRichard Henderson static FloatRelation QEMU_FLATTEN
float64_hs_compare(float64 xa,float64 xb,float_status * s,bool is_quiet)44246eb169b8SRichard Henderson float64_hs_compare(float64 xa, float64 xb, float_status *s, bool is_quiet)
4425d9fe9db9SEmilio G. Cota {
4426d9fe9db9SEmilio G. Cota     union_float64 ua, ub;
4427d9fe9db9SEmilio G. Cota 
4428d9fe9db9SEmilio G. Cota     ua.s = xa;
4429d9fe9db9SEmilio G. Cota     ub.s = xb;
4430d9fe9db9SEmilio G. Cota 
4431d9fe9db9SEmilio G. Cota     if (QEMU_NO_HARDFLOAT) {
4432d9fe9db9SEmilio G. Cota         goto soft;
4433d9fe9db9SEmilio G. Cota     }
4434d9fe9db9SEmilio G. Cota 
4435d9fe9db9SEmilio G. Cota     float64_input_flush2(&ua.s, &ub.s, s);
4436d9fe9db9SEmilio G. Cota     if (isgreaterequal(ua.h, ub.h)) {
4437d9fe9db9SEmilio G. Cota         if (isgreater(ua.h, ub.h)) {
4438d9fe9db9SEmilio G. Cota             return float_relation_greater;
4439d9fe9db9SEmilio G. Cota         }
4440d9fe9db9SEmilio G. Cota         return float_relation_equal;
4441d9fe9db9SEmilio G. Cota     }
4442d9fe9db9SEmilio G. Cota     if (likely(isless(ua.h, ub.h))) {
4443d9fe9db9SEmilio G. Cota         return float_relation_less;
4444d9fe9db9SEmilio G. Cota     }
44456eb169b8SRichard Henderson     /*
44466eb169b8SRichard Henderson      * The only condition remaining is unordered.
4447d9fe9db9SEmilio G. Cota      * Fall through to set flags.
4448d9fe9db9SEmilio G. Cota      */
4449d9fe9db9SEmilio G. Cota  soft:
44506eb169b8SRichard Henderson     return float64_do_compare(ua.s, ub.s, s, is_quiet);
4451d9fe9db9SEmilio G. Cota }
4452d9fe9db9SEmilio G. Cota 
float64_compare(float64 a,float64 b,float_status * s)445371bfd65cSRichard Henderson FloatRelation float64_compare(float64 a, float64 b, float_status *s)
4454d9fe9db9SEmilio G. Cota {
44556eb169b8SRichard Henderson     return float64_hs_compare(a, b, s, false);
4456d9fe9db9SEmilio G. Cota }
4457d9fe9db9SEmilio G. Cota 
float64_compare_quiet(float64 a,float64 b,float_status * s)445871bfd65cSRichard Henderson FloatRelation float64_compare_quiet(float64 a, float64 b, float_status *s)
4459d9fe9db9SEmilio G. Cota {
44606eb169b8SRichard Henderson     return float64_hs_compare(a, b, s, true);
4461d9fe9db9SEmilio G. Cota }
4462d9fe9db9SEmilio G. Cota 
44638282310dSLIU Zhiwei static FloatRelation QEMU_FLATTEN
bfloat16_do_compare(bfloat16 a,bfloat16 b,float_status * s,bool is_quiet)44646eb169b8SRichard Henderson bfloat16_do_compare(bfloat16 a, bfloat16 b, float_status *s, bool is_quiet)
44658282310dSLIU Zhiwei {
446698e256fcSRichard Henderson     FloatParts64 pa, pb;
446798e256fcSRichard Henderson 
446898e256fcSRichard Henderson     bfloat16_unpack_canonical(&pa, a, s);
446998e256fcSRichard Henderson     bfloat16_unpack_canonical(&pb, b, s);
44706eb169b8SRichard Henderson     return parts_compare(&pa, &pb, s, is_quiet);
44718282310dSLIU Zhiwei }
44728282310dSLIU Zhiwei 
bfloat16_compare(bfloat16 a,bfloat16 b,float_status * s)44738282310dSLIU Zhiwei FloatRelation bfloat16_compare(bfloat16 a, bfloat16 b, float_status *s)
44748282310dSLIU Zhiwei {
44756eb169b8SRichard Henderson     return bfloat16_do_compare(a, b, s, false);
44768282310dSLIU Zhiwei }
44778282310dSLIU Zhiwei 
bfloat16_compare_quiet(bfloat16 a,bfloat16 b,float_status * s)44788282310dSLIU Zhiwei FloatRelation bfloat16_compare_quiet(bfloat16 a, bfloat16 b, float_status *s)
44798282310dSLIU Zhiwei {
44806eb169b8SRichard Henderson     return bfloat16_do_compare(a, b, s, true);
44816eb169b8SRichard Henderson }
44826eb169b8SRichard Henderson 
44836eb169b8SRichard Henderson static FloatRelation QEMU_FLATTEN
float128_do_compare(float128 a,float128 b,float_status * s,bool is_quiet)44846eb169b8SRichard Henderson float128_do_compare(float128 a, float128 b, float_status *s, bool is_quiet)
44856eb169b8SRichard Henderson {
44866eb169b8SRichard Henderson     FloatParts128 pa, pb;
44876eb169b8SRichard Henderson 
44886eb169b8SRichard Henderson     float128_unpack_canonical(&pa, a, s);
44896eb169b8SRichard Henderson     float128_unpack_canonical(&pb, b, s);
44906eb169b8SRichard Henderson     return parts_compare(&pa, &pb, s, is_quiet);
44916eb169b8SRichard Henderson }
44926eb169b8SRichard Henderson 
float128_compare(float128 a,float128 b,float_status * s)44936eb169b8SRichard Henderson FloatRelation float128_compare(float128 a, float128 b, float_status *s)
44946eb169b8SRichard Henderson {
44956eb169b8SRichard Henderson     return float128_do_compare(a, b, s, false);
44966eb169b8SRichard Henderson }
44976eb169b8SRichard Henderson 
float128_compare_quiet(float128 a,float128 b,float_status * s)44986eb169b8SRichard Henderson FloatRelation float128_compare_quiet(float128 a, float128 b, float_status *s)
44996eb169b8SRichard Henderson {
45006eb169b8SRichard Henderson     return float128_do_compare(a, b, s, true);
45018282310dSLIU Zhiwei }
45028282310dSLIU Zhiwei 
45031b96b006SRichard Henderson static FloatRelation QEMU_FLATTEN
floatx80_do_compare(floatx80 a,floatx80 b,float_status * s,bool is_quiet)45041b96b006SRichard Henderson floatx80_do_compare(floatx80 a, floatx80 b, float_status *s, bool is_quiet)
45051b96b006SRichard Henderson {
45061b96b006SRichard Henderson     FloatParts128 pa, pb;
45071b96b006SRichard Henderson 
45081b96b006SRichard Henderson     if (!floatx80_unpack_canonical(&pa, a, s) ||
45091b96b006SRichard Henderson         !floatx80_unpack_canonical(&pb, b, s)) {
45101b96b006SRichard Henderson         return float_relation_unordered;
45111b96b006SRichard Henderson     }
45121b96b006SRichard Henderson     return parts_compare(&pa, &pb, s, is_quiet);
45131b96b006SRichard Henderson }
45141b96b006SRichard Henderson 
floatx80_compare(floatx80 a,floatx80 b,float_status * s)45151b96b006SRichard Henderson FloatRelation floatx80_compare(floatx80 a, floatx80 b, float_status *s)
45161b96b006SRichard Henderson {
45171b96b006SRichard Henderson     return floatx80_do_compare(a, b, s, false);
45181b96b006SRichard Henderson }
45191b96b006SRichard Henderson 
floatx80_compare_quiet(floatx80 a,floatx80 b,float_status * s)45201b96b006SRichard Henderson FloatRelation floatx80_compare_quiet(floatx80 a, floatx80 b, float_status *s)
45211b96b006SRichard Henderson {
45221b96b006SRichard Henderson     return floatx80_do_compare(a, b, s, true);
45231b96b006SRichard Henderson }
45241b96b006SRichard Henderson 
452539626b0cSRichard Henderson /*
452639626b0cSRichard Henderson  * Scale by 2**N
4527ce8d4082SRichard Henderson  */
45280bfc9f19SAlex Bennée 
float16_scalbn(float16 a,int n,float_status * status)45290bfc9f19SAlex Bennée float16 float16_scalbn(float16 a, int n, float_status *status)
45300bfc9f19SAlex Bennée {
453139626b0cSRichard Henderson     FloatParts64 p;
453298e256fcSRichard Henderson 
453339626b0cSRichard Henderson     float16_unpack_canonical(&p, a, status);
453439626b0cSRichard Henderson     parts_scalbn(&p, n, status);
453539626b0cSRichard Henderson     return float16_round_pack_canonical(&p, status);
45360bfc9f19SAlex Bennée }
45370bfc9f19SAlex Bennée 
float32_scalbn(float32 a,int n,float_status * status)45380bfc9f19SAlex Bennée float32 float32_scalbn(float32 a, int n, float_status *status)
45390bfc9f19SAlex Bennée {
454039626b0cSRichard Henderson     FloatParts64 p;
454198e256fcSRichard Henderson 
454239626b0cSRichard Henderson     float32_unpack_canonical(&p, a, status);
454339626b0cSRichard Henderson     parts_scalbn(&p, n, status);
454439626b0cSRichard Henderson     return float32_round_pack_canonical(&p, status);
45450bfc9f19SAlex Bennée }
45460bfc9f19SAlex Bennée 
float64_scalbn(float64 a,int n,float_status * status)45470bfc9f19SAlex Bennée float64 float64_scalbn(float64 a, int n, float_status *status)
45480bfc9f19SAlex Bennée {
454939626b0cSRichard Henderson     FloatParts64 p;
455098e256fcSRichard Henderson 
455139626b0cSRichard Henderson     float64_unpack_canonical(&p, a, status);
455239626b0cSRichard Henderson     parts_scalbn(&p, n, status);
455339626b0cSRichard Henderson     return float64_round_pack_canonical(&p, status);
45540bfc9f19SAlex Bennée }
45550bfc9f19SAlex Bennée 
bfloat16_scalbn(bfloat16 a,int n,float_status * status)45568282310dSLIU Zhiwei bfloat16 bfloat16_scalbn(bfloat16 a, int n, float_status *status)
45578282310dSLIU Zhiwei {
455839626b0cSRichard Henderson     FloatParts64 p;
455998e256fcSRichard Henderson 
456039626b0cSRichard Henderson     bfloat16_unpack_canonical(&p, a, status);
456139626b0cSRichard Henderson     parts_scalbn(&p, n, status);
456239626b0cSRichard Henderson     return bfloat16_round_pack_canonical(&p, status);
456339626b0cSRichard Henderson }
456439626b0cSRichard Henderson 
float128_scalbn(float128 a,int n,float_status * status)456539626b0cSRichard Henderson float128 float128_scalbn(float128 a, int n, float_status *status)
456639626b0cSRichard Henderson {
456739626b0cSRichard Henderson     FloatParts128 p;
456839626b0cSRichard Henderson 
456939626b0cSRichard Henderson     float128_unpack_canonical(&p, a, status);
457039626b0cSRichard Henderson     parts_scalbn(&p, n, status);
457139626b0cSRichard Henderson     return float128_round_pack_canonical(&p, status);
45728282310dSLIU Zhiwei }
45738282310dSLIU Zhiwei 
floatx80_scalbn(floatx80 a,int n,float_status * status)4574872e6991SRichard Henderson floatx80 floatx80_scalbn(floatx80 a, int n, float_status *status)
4575872e6991SRichard Henderson {
4576872e6991SRichard Henderson     FloatParts128 p;
4577872e6991SRichard Henderson 
4578872e6991SRichard Henderson     if (!floatx80_unpack_canonical(&p, a, status)) {
4579872e6991SRichard Henderson         return floatx80_default_nan(status);
4580872e6991SRichard Henderson     }
4581872e6991SRichard Henderson     parts_scalbn(&p, n, status);
4582872e6991SRichard Henderson     return floatx80_round_pack_canonical(&p, status);
4583872e6991SRichard Henderson }
4584872e6991SRichard Henderson 
4585c13bb2daSAlex Bennée /*
4586c13bb2daSAlex Bennée  * Square Root
4587c13bb2daSAlex Bennée  */
4588c13bb2daSAlex Bennée 
float16_sqrt(float16 a,float_status * status)458997ff87c0SThomas Huth float16 QEMU_FLATTEN float16_sqrt(float16 a, float_status *status)
4590c13bb2daSAlex Bennée {
45919261b245SRichard Henderson     FloatParts64 p;
459298e256fcSRichard Henderson 
45939261b245SRichard Henderson     float16_unpack_canonical(&p, a, status);
45949261b245SRichard Henderson     parts_sqrt(&p, status, &float16_params);
45959261b245SRichard Henderson     return float16_round_pack_canonical(&p, status);
4596c13bb2daSAlex Bennée }
4597c13bb2daSAlex Bennée 
4598f131bae8SEmilio G. Cota static float32 QEMU_SOFTFLOAT_ATTR
soft_f32_sqrt(float32 a,float_status * status)4599f131bae8SEmilio G. Cota soft_f32_sqrt(float32 a, float_status *status)
4600c13bb2daSAlex Bennée {
46019261b245SRichard Henderson     FloatParts64 p;
460298e256fcSRichard Henderson 
46039261b245SRichard Henderson     float32_unpack_canonical(&p, a, status);
46049261b245SRichard Henderson     parts_sqrt(&p, status, &float32_params);
46059261b245SRichard Henderson     return float32_round_pack_canonical(&p, status);
4606c13bb2daSAlex Bennée }
4607c13bb2daSAlex Bennée 
4608f131bae8SEmilio G. Cota static float64 QEMU_SOFTFLOAT_ATTR
soft_f64_sqrt(float64 a,float_status * status)4609f131bae8SEmilio G. Cota soft_f64_sqrt(float64 a, float_status *status)
4610c13bb2daSAlex Bennée {
46119261b245SRichard Henderson     FloatParts64 p;
461298e256fcSRichard Henderson 
46139261b245SRichard Henderson     float64_unpack_canonical(&p, a, status);
46149261b245SRichard Henderson     parts_sqrt(&p, status, &float64_params);
46159261b245SRichard Henderson     return float64_round_pack_canonical(&p, status);
4616c13bb2daSAlex Bennée }
4617c13bb2daSAlex Bennée 
float32_sqrt(float32 xa,float_status * s)4618f131bae8SEmilio G. Cota float32 QEMU_FLATTEN float32_sqrt(float32 xa, float_status *s)
4619f131bae8SEmilio G. Cota {
4620f131bae8SEmilio G. Cota     union_float32 ua, ur;
4621f131bae8SEmilio G. Cota 
4622f131bae8SEmilio G. Cota     ua.s = xa;
4623f131bae8SEmilio G. Cota     if (unlikely(!can_use_fpu(s))) {
4624f131bae8SEmilio G. Cota         goto soft;
4625f131bae8SEmilio G. Cota     }
4626f131bae8SEmilio G. Cota 
4627f131bae8SEmilio G. Cota     float32_input_flush1(&ua.s, s);
4628f131bae8SEmilio G. Cota     if (QEMU_HARDFLOAT_1F32_USE_FP) {
4629f131bae8SEmilio G. Cota         if (unlikely(!(fpclassify(ua.h) == FP_NORMAL ||
4630f131bae8SEmilio G. Cota                        fpclassify(ua.h) == FP_ZERO) ||
4631f131bae8SEmilio G. Cota                      signbit(ua.h))) {
4632f131bae8SEmilio G. Cota             goto soft;
4633f131bae8SEmilio G. Cota         }
4634f131bae8SEmilio G. Cota     } else if (unlikely(!float32_is_zero_or_normal(ua.s) ||
4635f131bae8SEmilio G. Cota                         float32_is_neg(ua.s))) {
4636f131bae8SEmilio G. Cota         goto soft;
4637f131bae8SEmilio G. Cota     }
4638f131bae8SEmilio G. Cota     ur.h = sqrtf(ua.h);
4639f131bae8SEmilio G. Cota     return ur.s;
4640f131bae8SEmilio G. Cota 
4641f131bae8SEmilio G. Cota  soft:
4642f131bae8SEmilio G. Cota     return soft_f32_sqrt(ua.s, s);
4643f131bae8SEmilio G. Cota }
4644f131bae8SEmilio G. Cota 
float64_sqrt(float64 xa,float_status * s)4645f131bae8SEmilio G. Cota float64 QEMU_FLATTEN float64_sqrt(float64 xa, float_status *s)
4646f131bae8SEmilio G. Cota {
4647f131bae8SEmilio G. Cota     union_float64 ua, ur;
4648f131bae8SEmilio G. Cota 
4649f131bae8SEmilio G. Cota     ua.s = xa;
4650f131bae8SEmilio G. Cota     if (unlikely(!can_use_fpu(s))) {
4651f131bae8SEmilio G. Cota         goto soft;
4652f131bae8SEmilio G. Cota     }
4653f131bae8SEmilio G. Cota 
4654f131bae8SEmilio G. Cota     float64_input_flush1(&ua.s, s);
4655f131bae8SEmilio G. Cota     if (QEMU_HARDFLOAT_1F64_USE_FP) {
4656f131bae8SEmilio G. Cota         if (unlikely(!(fpclassify(ua.h) == FP_NORMAL ||
4657f131bae8SEmilio G. Cota                        fpclassify(ua.h) == FP_ZERO) ||
4658f131bae8SEmilio G. Cota                      signbit(ua.h))) {
4659f131bae8SEmilio G. Cota             goto soft;
4660f131bae8SEmilio G. Cota         }
4661f131bae8SEmilio G. Cota     } else if (unlikely(!float64_is_zero_or_normal(ua.s) ||
4662f131bae8SEmilio G. Cota                         float64_is_neg(ua.s))) {
4663f131bae8SEmilio G. Cota         goto soft;
4664f131bae8SEmilio G. Cota     }
4665f131bae8SEmilio G. Cota     ur.h = sqrt(ua.h);
4666f131bae8SEmilio G. Cota     return ur.s;
4667f131bae8SEmilio G. Cota 
4668f131bae8SEmilio G. Cota  soft:
4669f131bae8SEmilio G. Cota     return soft_f64_sqrt(ua.s, s);
4670f131bae8SEmilio G. Cota }
4671f131bae8SEmilio G. Cota 
float64r32_sqrt(float64 a,float_status * status)467242636fb9SRichard Henderson float64 float64r32_sqrt(float64 a, float_status *status)
467342636fb9SRichard Henderson {
467442636fb9SRichard Henderson     FloatParts64 p;
467542636fb9SRichard Henderson 
467642636fb9SRichard Henderson     float64_unpack_canonical(&p, a, status);
467742636fb9SRichard Henderson     parts_sqrt(&p, status, &float64_params);
467842636fb9SRichard Henderson     return float64r32_round_pack_canonical(&p, status);
467942636fb9SRichard Henderson }
468042636fb9SRichard Henderson 
bfloat16_sqrt(bfloat16 a,float_status * status)46818282310dSLIU Zhiwei bfloat16 QEMU_FLATTEN bfloat16_sqrt(bfloat16 a, float_status *status)
46828282310dSLIU Zhiwei {
46839261b245SRichard Henderson     FloatParts64 p;
468498e256fcSRichard Henderson 
46859261b245SRichard Henderson     bfloat16_unpack_canonical(&p, a, status);
46869261b245SRichard Henderson     parts_sqrt(&p, status, &bfloat16_params);
46879261b245SRichard Henderson     return bfloat16_round_pack_canonical(&p, status);
46889261b245SRichard Henderson }
46899261b245SRichard Henderson 
float128_sqrt(float128 a,float_status * status)46909261b245SRichard Henderson float128 QEMU_FLATTEN float128_sqrt(float128 a, float_status *status)
46919261b245SRichard Henderson {
46929261b245SRichard Henderson     FloatParts128 p;
46939261b245SRichard Henderson 
46949261b245SRichard Henderson     float128_unpack_canonical(&p, a, status);
46959261b245SRichard Henderson     parts_sqrt(&p, status, &float128_params);
46969261b245SRichard Henderson     return float128_round_pack_canonical(&p, status);
46978282310dSLIU Zhiwei }
46988282310dSLIU Zhiwei 
floatx80_sqrt(floatx80 a,float_status * s)4699aa5e19ccSRichard Henderson floatx80 floatx80_sqrt(floatx80 a, float_status *s)
4700aa5e19ccSRichard Henderson {
4701aa5e19ccSRichard Henderson     FloatParts128 p;
4702aa5e19ccSRichard Henderson 
4703aa5e19ccSRichard Henderson     if (!floatx80_unpack_canonical(&p, a, s)) {
4704aa5e19ccSRichard Henderson         return floatx80_default_nan(s);
4705aa5e19ccSRichard Henderson     }
4706aa5e19ccSRichard Henderson     parts_sqrt(&p, s, &floatx80_params[s->floatx80_rounding_precision]);
4707aa5e19ccSRichard Henderson     return floatx80_round_pack_canonical(&p, s);
4708aa5e19ccSRichard Henderson }
4709aa5e19ccSRichard Henderson 
47102fa3546cSRichard Henderson /*
47112fa3546cSRichard Henderson  * log2
47122fa3546cSRichard Henderson  */
float32_log2(float32 a,float_status * status)47132fa3546cSRichard Henderson float32 float32_log2(float32 a, float_status *status)
47142fa3546cSRichard Henderson {
47152fa3546cSRichard Henderson     FloatParts64 p;
47162fa3546cSRichard Henderson 
47172fa3546cSRichard Henderson     float32_unpack_canonical(&p, a, status);
47182fa3546cSRichard Henderson     parts_log2(&p, status, &float32_params);
47192fa3546cSRichard Henderson     return float32_round_pack_canonical(&p, status);
47202fa3546cSRichard Henderson }
47212fa3546cSRichard Henderson 
float64_log2(float64 a,float_status * status)47222fa3546cSRichard Henderson float64 float64_log2(float64 a, float_status *status)
47232fa3546cSRichard Henderson {
47242fa3546cSRichard Henderson     FloatParts64 p;
47252fa3546cSRichard Henderson 
47262fa3546cSRichard Henderson     float64_unpack_canonical(&p, a, status);
47272fa3546cSRichard Henderson     parts_log2(&p, status, &float64_params);
47282fa3546cSRichard Henderson     return float64_round_pack_canonical(&p, status);
47292fa3546cSRichard Henderson }
47302fa3546cSRichard Henderson 
47310218a16eSRichard Henderson /*----------------------------------------------------------------------------
47320218a16eSRichard Henderson | The pattern for a default generated NaN.
47330218a16eSRichard Henderson *----------------------------------------------------------------------------*/
47340218a16eSRichard Henderson 
float16_default_nan(float_status * status)47350218a16eSRichard Henderson float16 float16_default_nan(float_status *status)
47360218a16eSRichard Henderson {
47370fc07cadSRichard Henderson     FloatParts64 p;
47380fc07cadSRichard Henderson 
47390fc07cadSRichard Henderson     parts_default_nan(&p, status);
47400218a16eSRichard Henderson     p.frac >>= float16_params.frac_shift;
474171fd178eSRichard Henderson     return float16_pack_raw(&p);
47420218a16eSRichard Henderson }
47430218a16eSRichard Henderson 
float32_default_nan(float_status * status)47440218a16eSRichard Henderson float32 float32_default_nan(float_status *status)
47450218a16eSRichard Henderson {
47460fc07cadSRichard Henderson     FloatParts64 p;
47470fc07cadSRichard Henderson 
47480fc07cadSRichard Henderson     parts_default_nan(&p, status);
47490218a16eSRichard Henderson     p.frac >>= float32_params.frac_shift;
475071fd178eSRichard Henderson     return float32_pack_raw(&p);
47510218a16eSRichard Henderson }
47520218a16eSRichard Henderson 
float64_default_nan(float_status * status)47530218a16eSRichard Henderson float64 float64_default_nan(float_status *status)
47540218a16eSRichard Henderson {
47550fc07cadSRichard Henderson     FloatParts64 p;
47560fc07cadSRichard Henderson 
47570fc07cadSRichard Henderson     parts_default_nan(&p, status);
47580218a16eSRichard Henderson     p.frac >>= float64_params.frac_shift;
475971fd178eSRichard Henderson     return float64_pack_raw(&p);
47600218a16eSRichard Henderson }
47610218a16eSRichard Henderson 
float128_default_nan(float_status * status)47620218a16eSRichard Henderson float128 float128_default_nan(float_status *status)
47630218a16eSRichard Henderson {
4764e9034ea8SRichard Henderson     FloatParts128 p;
47650218a16eSRichard Henderson 
47660fc07cadSRichard Henderson     parts_default_nan(&p, status);
4767e9034ea8SRichard Henderson     frac_shr(&p, float128_params.frac_shift);
4768e9034ea8SRichard Henderson     return float128_pack_raw(&p);
47690218a16eSRichard Henderson }
4770c13bb2daSAlex Bennée 
bfloat16_default_nan(float_status * status)47718282310dSLIU Zhiwei bfloat16 bfloat16_default_nan(float_status *status)
47728282310dSLIU Zhiwei {
47730fc07cadSRichard Henderson     FloatParts64 p;
47740fc07cadSRichard Henderson 
47750fc07cadSRichard Henderson     parts_default_nan(&p, status);
47768282310dSLIU Zhiwei     p.frac >>= bfloat16_params.frac_shift;
477771fd178eSRichard Henderson     return bfloat16_pack_raw(&p);
47788282310dSLIU Zhiwei }
47798282310dSLIU Zhiwei 
4780d97544c9SAlex Bennée /*----------------------------------------------------------------------------
4781377ed926SRichard Henderson | Returns a quiet NaN from a signalling NaN for the floating point value `a'.
4782377ed926SRichard Henderson *----------------------------------------------------------------------------*/
4783377ed926SRichard Henderson 
float16_silence_nan(float16 a,float_status * status)4784377ed926SRichard Henderson float16 float16_silence_nan(float16 a, float_status *status)
4785377ed926SRichard Henderson {
47863dddb203SRichard Henderson     FloatParts64 p;
47873dddb203SRichard Henderson 
47883dddb203SRichard Henderson     float16_unpack_raw(&p, a);
4789377ed926SRichard Henderson     p.frac <<= float16_params.frac_shift;
479092ff426dSRichard Henderson     parts_silence_nan(&p, status);
4791377ed926SRichard Henderson     p.frac >>= float16_params.frac_shift;
479271fd178eSRichard Henderson     return float16_pack_raw(&p);
4793377ed926SRichard Henderson }
4794377ed926SRichard Henderson 
float32_silence_nan(float32 a,float_status * status)4795377ed926SRichard Henderson float32 float32_silence_nan(float32 a, float_status *status)
4796377ed926SRichard Henderson {
47973dddb203SRichard Henderson     FloatParts64 p;
47983dddb203SRichard Henderson 
47993dddb203SRichard Henderson     float32_unpack_raw(&p, a);
4800377ed926SRichard Henderson     p.frac <<= float32_params.frac_shift;
480192ff426dSRichard Henderson     parts_silence_nan(&p, status);
4802377ed926SRichard Henderson     p.frac >>= float32_params.frac_shift;
480371fd178eSRichard Henderson     return float32_pack_raw(&p);
4804377ed926SRichard Henderson }
4805377ed926SRichard Henderson 
float64_silence_nan(float64 a,float_status * status)4806377ed926SRichard Henderson float64 float64_silence_nan(float64 a, float_status *status)
4807377ed926SRichard Henderson {
48083dddb203SRichard Henderson     FloatParts64 p;
48093dddb203SRichard Henderson 
48103dddb203SRichard Henderson     float64_unpack_raw(&p, a);
4811377ed926SRichard Henderson     p.frac <<= float64_params.frac_shift;
481292ff426dSRichard Henderson     parts_silence_nan(&p, status);
4813377ed926SRichard Henderson     p.frac >>= float64_params.frac_shift;
481471fd178eSRichard Henderson     return float64_pack_raw(&p);
4815377ed926SRichard Henderson }
4816377ed926SRichard Henderson 
bfloat16_silence_nan(bfloat16 a,float_status * status)48178282310dSLIU Zhiwei bfloat16 bfloat16_silence_nan(bfloat16 a, float_status *status)
48188282310dSLIU Zhiwei {
48193dddb203SRichard Henderson     FloatParts64 p;
48203dddb203SRichard Henderson 
48213dddb203SRichard Henderson     bfloat16_unpack_raw(&p, a);
48228282310dSLIU Zhiwei     p.frac <<= bfloat16_params.frac_shift;
482392ff426dSRichard Henderson     parts_silence_nan(&p, status);
48248282310dSLIU Zhiwei     p.frac >>= bfloat16_params.frac_shift;
482571fd178eSRichard Henderson     return bfloat16_pack_raw(&p);
48268282310dSLIU Zhiwei }
4827e6b405feSAlex Bennée 
float128_silence_nan(float128 a,float_status * status)48280018b1f4SRichard Henderson float128 float128_silence_nan(float128 a, float_status *status)
48290018b1f4SRichard Henderson {
48300018b1f4SRichard Henderson     FloatParts128 p;
48310018b1f4SRichard Henderson 
48320018b1f4SRichard Henderson     float128_unpack_raw(&p, a);
48330018b1f4SRichard Henderson     frac_shl(&p, float128_params.frac_shift);
48340018b1f4SRichard Henderson     parts_silence_nan(&p, status);
48350018b1f4SRichard Henderson     frac_shr(&p, float128_params.frac_shift);
48360018b1f4SRichard Henderson     return float128_pack_raw(&p);
48370018b1f4SRichard Henderson }
48380018b1f4SRichard Henderson 
4839e6b405feSAlex Bennée /*----------------------------------------------------------------------------
4840e6b405feSAlex Bennée | If `a' is denormal and we are in flush-to-zero mode then set the
4841e6b405feSAlex Bennée | input-denormal exception and return zero. Otherwise just return the value.
4842e6b405feSAlex Bennée *----------------------------------------------------------------------------*/
4843e6b405feSAlex Bennée 
parts_squash_denormal(FloatParts64 p,float_status * status)4844f8155c1dSRichard Henderson static bool parts_squash_denormal(FloatParts64 p, float_status *status)
4845e6b405feSAlex Bennée {
4846e6b405feSAlex Bennée     if (p.exp == 0 && p.frac != 0) {
4847e6b405feSAlex Bennée         float_raise(float_flag_input_denormal, status);
4848e6b405feSAlex Bennée         return true;
4849e6b405feSAlex Bennée     }
4850e6b405feSAlex Bennée 
4851e6b405feSAlex Bennée     return false;
4852e6b405feSAlex Bennée }
4853e6b405feSAlex Bennée 
float16_squash_input_denormal(float16 a,float_status * status)4854e6b405feSAlex Bennée float16 float16_squash_input_denormal(float16 a, float_status *status)
4855e6b405feSAlex Bennée {
4856e6b405feSAlex Bennée     if (status->flush_inputs_to_zero) {
48573dddb203SRichard Henderson         FloatParts64 p;
48583dddb203SRichard Henderson 
48593dddb203SRichard Henderson         float16_unpack_raw(&p, a);
4860e6b405feSAlex Bennée         if (parts_squash_denormal(p, status)) {
4861e6b405feSAlex Bennée             return float16_set_sign(float16_zero, p.sign);
4862e6b405feSAlex Bennée         }
4863e6b405feSAlex Bennée     }
4864e6b405feSAlex Bennée     return a;
4865e6b405feSAlex Bennée }
4866e6b405feSAlex Bennée 
float32_squash_input_denormal(float32 a,float_status * status)4867e6b405feSAlex Bennée float32 float32_squash_input_denormal(float32 a, float_status *status)
4868e6b405feSAlex Bennée {
4869e6b405feSAlex Bennée     if (status->flush_inputs_to_zero) {
48703dddb203SRichard Henderson         FloatParts64 p;
48713dddb203SRichard Henderson 
48723dddb203SRichard Henderson         float32_unpack_raw(&p, a);
4873e6b405feSAlex Bennée         if (parts_squash_denormal(p, status)) {
4874e6b405feSAlex Bennée             return float32_set_sign(float32_zero, p.sign);
4875e6b405feSAlex Bennée         }
4876e6b405feSAlex Bennée     }
4877e6b405feSAlex Bennée     return a;
4878e6b405feSAlex Bennée }
4879e6b405feSAlex Bennée 
float64_squash_input_denormal(float64 a,float_status * status)4880e6b405feSAlex Bennée float64 float64_squash_input_denormal(float64 a, float_status *status)
4881e6b405feSAlex Bennée {
4882e6b405feSAlex Bennée     if (status->flush_inputs_to_zero) {
48833dddb203SRichard Henderson         FloatParts64 p;
48843dddb203SRichard Henderson 
48853dddb203SRichard Henderson         float64_unpack_raw(&p, a);
4886e6b405feSAlex Bennée         if (parts_squash_denormal(p, status)) {
4887e6b405feSAlex Bennée             return float64_set_sign(float64_zero, p.sign);
4888e6b405feSAlex Bennée         }
4889e6b405feSAlex Bennée     }
4890e6b405feSAlex Bennée     return a;
4891e6b405feSAlex Bennée }
4892e6b405feSAlex Bennée 
bfloat16_squash_input_denormal(bfloat16 a,float_status * status)48938282310dSLIU Zhiwei bfloat16 bfloat16_squash_input_denormal(bfloat16 a, float_status *status)
48948282310dSLIU Zhiwei {
48958282310dSLIU Zhiwei     if (status->flush_inputs_to_zero) {
48963dddb203SRichard Henderson         FloatParts64 p;
48973dddb203SRichard Henderson 
48983dddb203SRichard Henderson         bfloat16_unpack_raw(&p, a);
48998282310dSLIU Zhiwei         if (parts_squash_denormal(p, status)) {
49008282310dSLIU Zhiwei             return bfloat16_set_sign(bfloat16_zero, p.sign);
49018282310dSLIU Zhiwei         }
49028282310dSLIU Zhiwei     }
49038282310dSLIU Zhiwei     return a;
49048282310dSLIU Zhiwei }
49058282310dSLIU Zhiwei 
4906377ed926SRichard Henderson /*----------------------------------------------------------------------------
4907158142c2Sbellard | Normalizes the subnormal extended double-precision floating-point value
4908158142c2Sbellard | represented by the denormalized significand `aSig'.  The normalized exponent
4909158142c2Sbellard | and significand are stored at the locations pointed to by `zExpPtr' and
4910158142c2Sbellard | `zSigPtr', respectively.
4911158142c2Sbellard *----------------------------------------------------------------------------*/
4912158142c2Sbellard 
normalizeFloatx80Subnormal(uint64_t aSig,int32_t * zExpPtr,uint64_t * zSigPtr)491388857acaSLaurent Vivier void normalizeFloatx80Subnormal(uint64_t aSig, int32_t *zExpPtr,
491488857acaSLaurent Vivier                                 uint64_t *zSigPtr)
4915158142c2Sbellard {
49168f506c70SPeter Maydell     int8_t shiftCount;
4917158142c2Sbellard 
49180019d5c3SThomas Huth     shiftCount = clz64(aSig);
4919158142c2Sbellard     *zSigPtr = aSig<<shiftCount;
4920158142c2Sbellard     *zExpPtr = 1 - shiftCount;
4921158142c2Sbellard }
4922158142c2Sbellard 
4923158142c2Sbellard /*----------------------------------------------------------------------------
4924158142c2Sbellard | Takes an abstract floating-point value having sign `zSign', exponent `zExp',
4925158142c2Sbellard | and extended significand formed by the concatenation of `zSig0' and `zSig1',
4926158142c2Sbellard | and returns the proper extended double-precision floating-point value
4927158142c2Sbellard | corresponding to the abstract input.  Ordinarily, the abstract value is
4928158142c2Sbellard | rounded and packed into the extended double-precision format, with the
4929158142c2Sbellard | inexact exception raised if the abstract input cannot be represented
4930158142c2Sbellard | exactly.  However, if the abstract value is too large, the overflow and
4931158142c2Sbellard | inexact exceptions are raised and an infinity or maximal finite value is
4932158142c2Sbellard | returned.  If the abstract value is too small, the input value is rounded to
4933158142c2Sbellard | a subnormal number, and the underflow and inexact exceptions are raised if
4934158142c2Sbellard | the abstract input cannot be represented exactly as a subnormal extended
4935158142c2Sbellard | double-precision floating-point number.
49368da5f1dbSRichard Henderson |     If `roundingPrecision' is floatx80_precision_s or floatx80_precision_d,
49378da5f1dbSRichard Henderson | the result is rounded to the same number of bits as single or double
49388da5f1dbSRichard Henderson | precision, respectively.  Otherwise, the result is rounded to the full
49398da5f1dbSRichard Henderson | precision of the extended double-precision format.
4940158142c2Sbellard |     The input significand must be normalized or smaller.  If the input
4941158142c2Sbellard | significand is not normalized, `zExp' must be 0; in that case, the result
4942158142c2Sbellard | returned is a subnormal number, and it must not require rounding.  The
4943158142c2Sbellard | handling of underflow and overflow follows the IEC/IEEE Standard for Binary
4944158142c2Sbellard | Floating-Point Arithmetic.
4945158142c2Sbellard *----------------------------------------------------------------------------*/
4946158142c2Sbellard 
roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision,bool zSign,int32_t zExp,uint64_t zSig0,uint64_t zSig1,float_status * status)49478da5f1dbSRichard Henderson floatx80 roundAndPackFloatx80(FloatX80RoundPrec roundingPrecision, bool zSign,
4948f4014512SPeter Maydell                               int32_t zExp, uint64_t zSig0, uint64_t zSig1,
4949e5a41ffaSPeter Maydell                               float_status *status)
4950158142c2Sbellard {
49518da5f1dbSRichard Henderson     FloatRoundMode roundingMode;
4952c120391cSRichard Henderson     bool roundNearestEven, increment, isTiny;
4953f42c2224SPeter Maydell     int64_t roundIncrement, roundMask, roundBits;
4954158142c2Sbellard 
4955a2f2d288SPeter Maydell     roundingMode = status->float_rounding_mode;
4956158142c2Sbellard     roundNearestEven = ( roundingMode == float_round_nearest_even );
49578da5f1dbSRichard Henderson     switch (roundingPrecision) {
49588da5f1dbSRichard Henderson     case floatx80_precision_x:
49598da5f1dbSRichard Henderson         goto precision80;
49608da5f1dbSRichard Henderson     case floatx80_precision_d:
4961e9321124SAlex Bennée         roundIncrement = UINT64_C(0x0000000000000400);
4962e9321124SAlex Bennée         roundMask = UINT64_C(0x00000000000007FF);
49638da5f1dbSRichard Henderson         break;
49648da5f1dbSRichard Henderson     case floatx80_precision_s:
4965e9321124SAlex Bennée         roundIncrement = UINT64_C(0x0000008000000000);
4966e9321124SAlex Bennée         roundMask = UINT64_C(0x000000FFFFFFFFFF);
49678da5f1dbSRichard Henderson         break;
49688da5f1dbSRichard Henderson     default:
49698da5f1dbSRichard Henderson         g_assert_not_reached();
4970158142c2Sbellard     }
4971158142c2Sbellard     zSig0 |= ( zSig1 != 0 );
4972dc355b76SPeter Maydell     switch (roundingMode) {
4973dc355b76SPeter Maydell     case float_round_nearest_even:
4974f9288a76SPeter Maydell     case float_round_ties_away:
4975dc355b76SPeter Maydell         break;
4976dc355b76SPeter Maydell     case float_round_to_zero:
4977158142c2Sbellard         roundIncrement = 0;
4978dc355b76SPeter Maydell         break;
4979dc355b76SPeter Maydell     case float_round_up:
4980dc355b76SPeter Maydell         roundIncrement = zSign ? 0 : roundMask;
4981dc355b76SPeter Maydell         break;
4982dc355b76SPeter Maydell     case float_round_down:
4983dc355b76SPeter Maydell         roundIncrement = zSign ? roundMask : 0;
4984dc355b76SPeter Maydell         break;
4985dc355b76SPeter Maydell     default:
4986dc355b76SPeter Maydell         abort();
4987158142c2Sbellard     }
4988158142c2Sbellard     roundBits = zSig0 & roundMask;
4989bb98fe42SAndreas Färber     if ( 0x7FFD <= (uint32_t) ( zExp - 1 ) ) {
4990158142c2Sbellard         if (    ( 0x7FFE < zExp )
4991158142c2Sbellard              || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) )
4992158142c2Sbellard            ) {
4993158142c2Sbellard             goto overflow;
4994158142c2Sbellard         }
4995158142c2Sbellard         if ( zExp <= 0 ) {
4996a2f2d288SPeter Maydell             if (status->flush_to_zero) {
4997ff32e16eSPeter Maydell                 float_raise(float_flag_output_denormal, status);
4998e6afc87fSPeter Maydell                 return packFloatx80(zSign, 0, 0);
4999e6afc87fSPeter Maydell             }
5000a828b373SRichard Henderson             isTiny = status->tininess_before_rounding
5001158142c2Sbellard                   || (zExp < 0 )
5002158142c2Sbellard                   || (zSig0 <= zSig0 + roundIncrement);
5003158142c2Sbellard             shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
5004158142c2Sbellard             zExp = 0;
5005158142c2Sbellard             roundBits = zSig0 & roundMask;
5006ff32e16eSPeter Maydell             if (isTiny && roundBits) {
5007ff32e16eSPeter Maydell                 float_raise(float_flag_underflow, status);
5008ff32e16eSPeter Maydell             }
5009a2f2d288SPeter Maydell             if (roundBits) {
5010d82f3b2dSRichard Henderson                 float_raise(float_flag_inexact, status);
5011a2f2d288SPeter Maydell             }
5012158142c2Sbellard             zSig0 += roundIncrement;
5013bb98fe42SAndreas Färber             if ( (int64_t) zSig0 < 0 ) zExp = 1;
5014158142c2Sbellard             roundIncrement = roundMask + 1;
5015158142c2Sbellard             if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
5016158142c2Sbellard                 roundMask |= roundIncrement;
5017158142c2Sbellard             }
5018158142c2Sbellard             zSig0 &= ~ roundMask;
5019158142c2Sbellard             return packFloatx80( zSign, zExp, zSig0 );
5020158142c2Sbellard         }
5021158142c2Sbellard     }
5022a2f2d288SPeter Maydell     if (roundBits) {
5023d82f3b2dSRichard Henderson         float_raise(float_flag_inexact, status);
5024a2f2d288SPeter Maydell     }
5025158142c2Sbellard     zSig0 += roundIncrement;
5026158142c2Sbellard     if ( zSig0 < roundIncrement ) {
5027158142c2Sbellard         ++zExp;
5028e9321124SAlex Bennée         zSig0 = UINT64_C(0x8000000000000000);
5029158142c2Sbellard     }
5030158142c2Sbellard     roundIncrement = roundMask + 1;
5031158142c2Sbellard     if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
5032158142c2Sbellard         roundMask |= roundIncrement;
5033158142c2Sbellard     }
5034158142c2Sbellard     zSig0 &= ~ roundMask;
5035158142c2Sbellard     if ( zSig0 == 0 ) zExp = 0;
5036158142c2Sbellard     return packFloatx80( zSign, zExp, zSig0 );
5037158142c2Sbellard  precision80:
5038dc355b76SPeter Maydell     switch (roundingMode) {
5039dc355b76SPeter Maydell     case float_round_nearest_even:
5040f9288a76SPeter Maydell     case float_round_ties_away:
5041bb98fe42SAndreas Färber         increment = ((int64_t)zSig1 < 0);
5042dc355b76SPeter Maydell         break;
5043dc355b76SPeter Maydell     case float_round_to_zero:
5044158142c2Sbellard         increment = 0;
5045dc355b76SPeter Maydell         break;
5046dc355b76SPeter Maydell     case float_round_up:
5047dc355b76SPeter Maydell         increment = !zSign && zSig1;
5048dc355b76SPeter Maydell         break;
5049dc355b76SPeter Maydell     case float_round_down:
5050dc355b76SPeter Maydell         increment = zSign && zSig1;
5051dc355b76SPeter Maydell         break;
5052dc355b76SPeter Maydell     default:
5053dc355b76SPeter Maydell         abort();
5054158142c2Sbellard     }
5055bb98fe42SAndreas Färber     if ( 0x7FFD <= (uint32_t) ( zExp - 1 ) ) {
5056158142c2Sbellard         if (    ( 0x7FFE < zExp )
5057158142c2Sbellard              || (    ( zExp == 0x7FFE )
5058e9321124SAlex Bennée                   && ( zSig0 == UINT64_C(0xFFFFFFFFFFFFFFFF) )
5059158142c2Sbellard                   && increment
5060158142c2Sbellard                 )
5061158142c2Sbellard            ) {
5062158142c2Sbellard             roundMask = 0;
5063158142c2Sbellard  overflow:
5064ff32e16eSPeter Maydell             float_raise(float_flag_overflow | float_flag_inexact, status);
5065158142c2Sbellard             if (    ( roundingMode == float_round_to_zero )
5066158142c2Sbellard                  || ( zSign && ( roundingMode == float_round_up ) )
5067158142c2Sbellard                  || ( ! zSign && ( roundingMode == float_round_down ) )
5068158142c2Sbellard                ) {
5069158142c2Sbellard                 return packFloatx80( zSign, 0x7FFE, ~ roundMask );
5070158142c2Sbellard             }
50710f605c88SLaurent Vivier             return packFloatx80(zSign,
50720f605c88SLaurent Vivier                                 floatx80_infinity_high,
50730f605c88SLaurent Vivier                                 floatx80_infinity_low);
5074158142c2Sbellard         }
5075158142c2Sbellard         if ( zExp <= 0 ) {
5076a828b373SRichard Henderson             isTiny = status->tininess_before_rounding
5077158142c2Sbellard                   || (zExp < 0)
5078158142c2Sbellard                   || !increment
5079e9321124SAlex Bennée                   || (zSig0 < UINT64_C(0xFFFFFFFFFFFFFFFF));
5080158142c2Sbellard             shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
5081158142c2Sbellard             zExp = 0;
5082ff32e16eSPeter Maydell             if (isTiny && zSig1) {
5083ff32e16eSPeter Maydell                 float_raise(float_flag_underflow, status);
5084ff32e16eSPeter Maydell             }
5085a2f2d288SPeter Maydell             if (zSig1) {
5086d82f3b2dSRichard Henderson                 float_raise(float_flag_inexact, status);
5087a2f2d288SPeter Maydell             }
5088dc355b76SPeter Maydell             switch (roundingMode) {
5089dc355b76SPeter Maydell             case float_round_nearest_even:
5090f9288a76SPeter Maydell             case float_round_ties_away:
5091bb98fe42SAndreas Färber                 increment = ((int64_t)zSig1 < 0);
5092dc355b76SPeter Maydell                 break;
5093dc355b76SPeter Maydell             case float_round_to_zero:
5094dc355b76SPeter Maydell                 increment = 0;
5095dc355b76SPeter Maydell                 break;
5096dc355b76SPeter Maydell             case float_round_up:
5097dc355b76SPeter Maydell                 increment = !zSign && zSig1;
5098dc355b76SPeter Maydell                 break;
5099dc355b76SPeter Maydell             case float_round_down:
5100dc355b76SPeter Maydell                 increment = zSign && zSig1;
5101dc355b76SPeter Maydell                 break;
5102dc355b76SPeter Maydell             default:
5103dc355b76SPeter Maydell                 abort();
5104158142c2Sbellard             }
5105158142c2Sbellard             if ( increment ) {
5106158142c2Sbellard                 ++zSig0;
510740662886SPhilippe Mathieu-Daudé                 if (!(zSig1 << 1) && roundNearestEven) {
510840662886SPhilippe Mathieu-Daudé                     zSig0 &= ~1;
510940662886SPhilippe Mathieu-Daudé                 }
5110bb98fe42SAndreas Färber                 if ( (int64_t) zSig0 < 0 ) zExp = 1;
5111158142c2Sbellard             }
5112158142c2Sbellard             return packFloatx80( zSign, zExp, zSig0 );
5113158142c2Sbellard         }
5114158142c2Sbellard     }
5115a2f2d288SPeter Maydell     if (zSig1) {
5116d82f3b2dSRichard Henderson         float_raise(float_flag_inexact, status);
5117a2f2d288SPeter Maydell     }
5118158142c2Sbellard     if ( increment ) {
5119158142c2Sbellard         ++zSig0;
5120158142c2Sbellard         if ( zSig0 == 0 ) {
5121158142c2Sbellard             ++zExp;
5122e9321124SAlex Bennée             zSig0 = UINT64_C(0x8000000000000000);
5123158142c2Sbellard         }
5124158142c2Sbellard         else {
512540662886SPhilippe Mathieu-Daudé             if (!(zSig1 << 1) && roundNearestEven) {
512640662886SPhilippe Mathieu-Daudé                 zSig0 &= ~1;
512740662886SPhilippe Mathieu-Daudé             }
5128158142c2Sbellard         }
5129158142c2Sbellard     }
5130158142c2Sbellard     else {
5131158142c2Sbellard         if ( zSig0 == 0 ) zExp = 0;
5132158142c2Sbellard     }
5133158142c2Sbellard     return packFloatx80( zSign, zExp, zSig0 );
5134158142c2Sbellard 
5135158142c2Sbellard }
5136158142c2Sbellard 
5137158142c2Sbellard /*----------------------------------------------------------------------------
5138158142c2Sbellard | Takes an abstract floating-point value having sign `zSign', exponent
5139158142c2Sbellard | `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
5140158142c2Sbellard | and returns the proper extended double-precision floating-point value
5141158142c2Sbellard | corresponding to the abstract input.  This routine is just like
5142158142c2Sbellard | `roundAndPackFloatx80' except that the input significand does not have to be
5143158142c2Sbellard | normalized.
5144158142c2Sbellard *----------------------------------------------------------------------------*/
5145158142c2Sbellard 
normalizeRoundAndPackFloatx80(FloatX80RoundPrec roundingPrecision,bool zSign,int32_t zExp,uint64_t zSig0,uint64_t zSig1,float_status * status)51468da5f1dbSRichard Henderson floatx80 normalizeRoundAndPackFloatx80(FloatX80RoundPrec roundingPrecision,
5147c120391cSRichard Henderson                                        bool zSign, int32_t zExp,
5148e5a41ffaSPeter Maydell                                        uint64_t zSig0, uint64_t zSig1,
5149e5a41ffaSPeter Maydell                                        float_status *status)
5150158142c2Sbellard {
51518f506c70SPeter Maydell     int8_t shiftCount;
5152158142c2Sbellard 
5153158142c2Sbellard     if ( zSig0 == 0 ) {
5154158142c2Sbellard         zSig0 = zSig1;
5155158142c2Sbellard         zSig1 = 0;
5156158142c2Sbellard         zExp -= 64;
5157158142c2Sbellard     }
51580019d5c3SThomas Huth     shiftCount = clz64(zSig0);
5159158142c2Sbellard     shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
5160158142c2Sbellard     zExp -= shiftCount;
5161ff32e16eSPeter Maydell     return roundAndPackFloatx80(roundingPrecision, zSign, zExp,
5162ff32e16eSPeter Maydell                                 zSig0, zSig1, status);
5163158142c2Sbellard 
5164158142c2Sbellard }
5165158142c2Sbellard 
5166158142c2Sbellard /*----------------------------------------------------------------------------
51678229c991SAurelien Jarno | Returns the binary exponential of the single-precision floating-point value
51688229c991SAurelien Jarno | `a'. The operation is performed according to the IEC/IEEE Standard for
51698229c991SAurelien Jarno | Binary Floating-Point Arithmetic.
51708229c991SAurelien Jarno |
51718229c991SAurelien Jarno | Uses the following identities:
51728229c991SAurelien Jarno |
51738229c991SAurelien Jarno | 1. -------------------------------------------------------------------------
51748229c991SAurelien Jarno |      x    x*ln(2)
51758229c991SAurelien Jarno |     2  = e
51768229c991SAurelien Jarno |
51778229c991SAurelien Jarno | 2. -------------------------------------------------------------------------
51788229c991SAurelien Jarno |                      2     3     4     5           n
51798229c991SAurelien Jarno |      x        x     x     x     x     x           x
51808229c991SAurelien Jarno |     e  = 1 + --- + --- + --- + --- + --- + ... + --- + ...
51818229c991SAurelien Jarno |               1!    2!    3!    4!    5!          n!
51828229c991SAurelien Jarno *----------------------------------------------------------------------------*/
51838229c991SAurelien Jarno 
51848229c991SAurelien Jarno static const float64 float32_exp2_coefficients[15] =
51858229c991SAurelien Jarno {
5186d5138cf4SPeter Maydell     const_float64( 0x3ff0000000000000ll ), /*  1 */
5187d5138cf4SPeter Maydell     const_float64( 0x3fe0000000000000ll ), /*  2 */
5188d5138cf4SPeter Maydell     const_float64( 0x3fc5555555555555ll ), /*  3 */
5189d5138cf4SPeter Maydell     const_float64( 0x3fa5555555555555ll ), /*  4 */
5190d5138cf4SPeter Maydell     const_float64( 0x3f81111111111111ll ), /*  5 */
5191d5138cf4SPeter Maydell     const_float64( 0x3f56c16c16c16c17ll ), /*  6 */
5192d5138cf4SPeter Maydell     const_float64( 0x3f2a01a01a01a01all ), /*  7 */
5193d5138cf4SPeter Maydell     const_float64( 0x3efa01a01a01a01all ), /*  8 */
5194d5138cf4SPeter Maydell     const_float64( 0x3ec71de3a556c734ll ), /*  9 */
5195d5138cf4SPeter Maydell     const_float64( 0x3e927e4fb7789f5cll ), /* 10 */
5196d5138cf4SPeter Maydell     const_float64( 0x3e5ae64567f544e4ll ), /* 11 */
5197d5138cf4SPeter Maydell     const_float64( 0x3e21eed8eff8d898ll ), /* 12 */
5198d5138cf4SPeter Maydell     const_float64( 0x3de6124613a86d09ll ), /* 13 */
5199d5138cf4SPeter Maydell     const_float64( 0x3da93974a8c07c9dll ), /* 14 */
5200d5138cf4SPeter Maydell     const_float64( 0x3d6ae7f3e733b81fll ), /* 15 */
52018229c991SAurelien Jarno };
52028229c991SAurelien Jarno 
float32_exp2(float32 a,float_status * status)5203e5a41ffaSPeter Maydell float32 float32_exp2(float32 a, float_status *status)
52048229c991SAurelien Jarno {
5205572c4d86SRichard Henderson     FloatParts64 xp, xnp, tp, rp;
52068229c991SAurelien Jarno     int i;
52078229c991SAurelien Jarno 
5208572c4d86SRichard Henderson     float32_unpack_canonical(&xp, a, status);
5209572c4d86SRichard Henderson     if (unlikely(xp.cls != float_class_normal)) {
5210572c4d86SRichard Henderson         switch (xp.cls) {
5211572c4d86SRichard Henderson         case float_class_snan:
5212572c4d86SRichard Henderson         case float_class_qnan:
5213572c4d86SRichard Henderson             parts_return_nan(&xp, status);
5214572c4d86SRichard Henderson             return float32_round_pack_canonical(&xp, status);
5215572c4d86SRichard Henderson         case float_class_inf:
5216572c4d86SRichard Henderson             return xp.sign ? float32_zero : a;
5217572c4d86SRichard Henderson         case float_class_zero:
5218572c4d86SRichard Henderson             return float32_one;
5219572c4d86SRichard Henderson         default:
5220572c4d86SRichard Henderson             break;
5221ff32e16eSPeter Maydell         }
5222572c4d86SRichard Henderson         g_assert_not_reached();
52238229c991SAurelien Jarno     }
52248229c991SAurelien Jarno 
5225ff32e16eSPeter Maydell     float_raise(float_flag_inexact, status);
52268229c991SAurelien Jarno 
5227f291f45fSRichard Henderson     float64_unpack_canonical(&tp, float64_ln2, status);
5228572c4d86SRichard Henderson     xp = *parts_mul(&xp, &tp, status);
5229572c4d86SRichard Henderson     xnp = xp;
52308229c991SAurelien Jarno 
5231572c4d86SRichard Henderson     float64_unpack_canonical(&rp, float64_one, status);
52328229c991SAurelien Jarno     for (i = 0 ; i < 15 ; i++) {
5233572c4d86SRichard Henderson         float64_unpack_canonical(&tp, float32_exp2_coefficients[i], status);
52341098cc3fSShivaprasad G Bhat         rp = *parts_muladd(&tp, &xnp, &rp, 0, status);
5235572c4d86SRichard Henderson         xnp = *parts_mul(&xnp, &xp, status);
52368229c991SAurelien Jarno     }
52378229c991SAurelien Jarno 
5238572c4d86SRichard Henderson     return float32_round_pack_canonical(&rp, status);
52398229c991SAurelien Jarno }
52408229c991SAurelien Jarno 
52418229c991SAurelien Jarno /*----------------------------------------------------------------------------
52420f721292SLaurent Vivier | Rounds the extended double-precision floating-point value `a'
52430f721292SLaurent Vivier | to the precision provided by floatx80_rounding_precision and returns the
52440f721292SLaurent Vivier | result as an extended double-precision floating-point value.
52450f721292SLaurent Vivier | The operation is performed according to the IEC/IEEE Standard for Binary
52460f721292SLaurent Vivier | Floating-Point Arithmetic.
52470f721292SLaurent Vivier *----------------------------------------------------------------------------*/
52480f721292SLaurent Vivier 
floatx80_round(floatx80 a,float_status * status)52490f721292SLaurent Vivier floatx80 floatx80_round(floatx80 a, float_status *status)
52500f721292SLaurent Vivier {
525145a76b71SRichard Henderson     FloatParts128 p;
525245a76b71SRichard Henderson 
525345a76b71SRichard Henderson     if (!floatx80_unpack_canonical(&p, a, status)) {
525445a76b71SRichard Henderson         return floatx80_default_nan(status);
525545a76b71SRichard Henderson     }
525645a76b71SRichard Henderson     return floatx80_round_pack_canonical(&p, status);
52570f721292SLaurent Vivier }
52580f721292SLaurent Vivier 
softfloat_init(void)5259f6b3b108SEmilio G. Cota static void __attribute__((constructor)) softfloat_init(void)
5260f6b3b108SEmilio G. Cota {
5261f6b3b108SEmilio G. Cota     union_float64 ua, ub, uc, ur;
5262f6b3b108SEmilio G. Cota 
5263f6b3b108SEmilio G. Cota     if (QEMU_NO_HARDFLOAT) {
5264f6b3b108SEmilio G. Cota         return;
5265f6b3b108SEmilio G. Cota     }
5266f6b3b108SEmilio G. Cota     /*
5267f6b3b108SEmilio G. Cota      * Test that the host's FMA is not obviously broken. For example,
5268f6b3b108SEmilio G. Cota      * glibc < 2.23 can perform an incorrect FMA on certain hosts; see
5269f6b3b108SEmilio G. Cota      *   https://sourceware.org/bugzilla/show_bug.cgi?id=13304
5270f6b3b108SEmilio G. Cota      */
5271f6b3b108SEmilio G. Cota     ua.s = 0x0020000000000001ULL;
5272f6b3b108SEmilio G. Cota     ub.s = 0x3ca0000000000000ULL;
5273f6b3b108SEmilio G. Cota     uc.s = 0x0020000000000000ULL;
5274f6b3b108SEmilio G. Cota     ur.h = fma(ua.h, ub.h, uc.h);
5275f6b3b108SEmilio G. Cota     if (ur.s != 0x0020000000000001ULL) {
5276f6b3b108SEmilio G. Cota         force_soft_fma = true;
5277f6b3b108SEmilio G. Cota     }
5278f6b3b108SEmilio G. Cota }
5279