gem5 [DEVELOP-FOR-25.0]
Loading...
Searching...
No Matches
fplib.cc
Go to the documentation of this file.
1/*
2* Copyright (c) 2012-2013, 2017-2018, 2020, 2025 Arm Limited
3* Copyright (c) 2020 Metempsy Technology Consulting
4* All rights reserved
5*
6* The license below extends only to copyright in the software and shall
7* not be construed as granting a license to any other intellectual
8* property including but not limited to intellectual property relating
9* to a hardware implementation of the functionality of the software
10* licensed hereunder. You may use the software subject to the license
11* terms below provided that you ensure that this notice is replicated
12* unmodified and in its entirety in all distributions of the software,
13* modified or unmodified, in source code or in binary form.
14*
15* Redistribution and use in source and binary forms, with or without
16* modification, are permitted provided that the following conditions are
17* met: redistributions of source code must retain the above copyright
18* notice, this list of conditions and the following disclaimer;
19* redistributions in binary form must reproduce the above copyright
20* notice, this list of conditions and the following disclaimer in the
21* documentation and/or other materials provided with the distribution;
22* neither the name of the copyright holders nor the names of its
23* contributors may be used to endorse or promote products derived from
24* this software without specific prior written permission.
25*
26* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37*/
38
39#include <stdint.h>
40
41#include <cassert>
42#include <cmath>
43
44#include "base/logging.hh"
45#include "fplib.hh"
46
47namespace gem5
48{
49
50namespace ArmISA
51{
52
53#define FPLIB_RN 0
54#define FPLIB_RP 1
55#define FPLIB_RM 2
56#define FPLIB_RZ 3
57#define FPLIB_FZ 4
58#define FPLIB_DN 8
59#define FPLIB_AHP 16
60#define FPLIB_FZ16 32
61
62#define FPLIB_IDC 128 // Input Denormal
63#define FPLIB_IXC 16 // Inexact
64#define FPLIB_UFC 8 // Underflow
65#define FPLIB_OFC 4 // Overflow
66#define FPLIB_DZC 2 // Division by Zero
67#define FPLIB_IOC 1 // Invalid Operation
68
69#define FP16_BITS 16
70#define FP32_BITS 32
71#define FP64_BITS 64
72
73#define FP16_EXP_BITS 5
74#define FP32_EXP_BITS 8
75#define FP64_EXP_BITS 11
76
77#define FP16_EXP_BIAS 15
78#define FP32_EXP_BIAS 127
79#define FP64_EXP_BIAS 1023
80
81#define FP16_EXP_INF ((1ULL << FP16_EXP_BITS) - 1)
82#define FP32_EXP_INF ((1ULL << FP32_EXP_BITS) - 1)
83#define FP64_EXP_INF ((1ULL << FP64_EXP_BITS) - 1)
84
85#define FP16_MANT_BITS (FP16_BITS - FP16_EXP_BITS - 1)
86#define FP32_MANT_BITS (FP32_BITS - FP32_EXP_BITS - 1)
87#define FP64_MANT_BITS (FP64_BITS - FP64_EXP_BITS - 1)
88
89#define FP16_EXP(x) ((x) >> FP16_MANT_BITS & ((1ULL << FP16_EXP_BITS) - 1))
90#define FP32_EXP(x) ((x) >> FP32_MANT_BITS & ((1ULL << FP32_EXP_BITS) - 1))
91#define FP64_EXP(x) ((x) >> FP64_MANT_BITS & ((1ULL << FP64_EXP_BITS) - 1))
92
93#define FP16_MANT(x) ((x) & ((1ULL << FP16_MANT_BITS) - 1))
94#define FP32_MANT(x) ((x) & ((1ULL << FP32_MANT_BITS) - 1))
95#define FP64_MANT(x) ((x) & ((1ULL << FP64_MANT_BITS) - 1))
96
97static inline uint16_t
98lsl16(uint16_t x, uint32_t shift)
99{
100 return shift < 16 ? x << shift : 0;
101}
102
103static inline uint16_t
104lsr16(uint16_t x, uint32_t shift)
105{
106 return shift < 16 ? x >> shift : 0;
107}
108
109static inline uint32_t
110lsl32(uint32_t x, uint32_t shift)
111{
112 return shift < 32 ? x << shift : 0;
113}
114
115static inline uint32_t
116lsr32(uint32_t x, uint32_t shift)
117{
118 return shift < 32 ? x >> shift : 0;
119}
120
121static inline uint64_t
122lsl64(uint64_t x, uint32_t shift)
123{
124 return shift < 64 ? x << shift : 0;
125}
126
127static inline uint64_t
128lsr64(uint64_t x, uint32_t shift)
129{
130 return shift < 64 ? x >> shift : 0;
131}
132
133static inline void
134lsl128(uint64_t *r0, uint64_t *r1, uint64_t x0, uint64_t x1, uint32_t shift)
135{
136 if (shift == 0) {
137 *r1 = x1;
138 *r0 = x0;
139 } else if (shift < 64) {
140 *r1 = x1 << shift | x0 >> (64 - shift);
141 *r0 = x0 << shift;
142 } else if (shift < 128) {
143 *r1 = x0 << (shift - 64);
144 *r0 = 0;
145 } else {
146 *r1 = 0;
147 *r0 = 0;
148 }
149}
150
151static inline void
152lsr128(uint64_t *r0, uint64_t *r1, uint64_t x0, uint64_t x1, uint32_t shift)
153{
154 if (shift == 0) {
155 *r1 = x1;
156 *r0 = x0;
157 } else if (shift < 64) {
158 *r0 = x0 >> shift | x1 << (64 - shift);
159 *r1 = x1 >> shift;
160 } else if (shift < 128) {
161 *r0 = x1 >> (shift - 64);
162 *r1 = 0;
163 } else {
164 *r0 = 0;
165 *r1 = 0;
166 }
167}
168
169static inline void
170mul62x62(uint64_t *x0, uint64_t *x1, uint64_t a, uint64_t b)
171{
172 uint32_t mask = ((uint32_t)1 << 31) - 1;
173 uint64_t a0 = a & mask;
174 uint64_t a1 = a >> 31 & mask;
175 uint64_t b0 = b & mask;
176 uint64_t b1 = b >> 31 & mask;
177 uint64_t p0 = a0 * b0;
178 uint64_t p2 = a1 * b1;
179 uint64_t p1 = (a0 + a1) * (b0 + b1) - p0 - p2;
180 uint64_t s0 = p0;
181 uint64_t s1 = (s0 >> 31) + p1;
182 uint64_t s2 = (s1 >> 31) + p2;
183 *x0 = (s0 & mask) | (s1 & mask) << 31 | s2 << 62;
184 *x1 = s2 >> 2;
185}
186
187static inline
188void mul64x32(uint64_t *x0, uint64_t *x1, uint64_t a, uint32_t b)
189{
190 uint64_t t0 = (uint64_t)(uint32_t)a * b;
191 uint64_t t1 = (t0 >> 32) + (a >> 32) * b;
192 *x0 = t1 << 32 | (uint32_t)t0;
193 *x1 = t1 >> 32;
194}
195
196static inline void
197add128(uint64_t *x0, uint64_t *x1, uint64_t a0, uint64_t a1, uint64_t b0,
198 uint64_t b1)
199{
200 *x0 = a0 + b0;
201 *x1 = a1 + b1 + (*x0 < a0);
202}
203
204static inline void
205sub128(uint64_t *x0, uint64_t *x1, uint64_t a0, uint64_t a1, uint64_t b0,
206 uint64_t b1)
207{
208 *x0 = a0 - b0;
209 *x1 = a1 - b1 - (*x0 > a0);
210}
211
212static inline int
213cmp128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
214{
215 return (a1 < b1 ? -1 : a1 > b1 ? 1 : a0 < b0 ? -1 : a0 > b0 ? 1 : 0);
216}
217
218static inline uint16_t
219fp16_normalise(uint16_t mnt, int *exp)
220{
221 int shift;
222
223 if (!mnt) {
224 return 0;
225 }
226
227 for (shift = 8; shift; shift >>= 1) {
228 if (!(mnt >> (16 - shift))) {
229 mnt <<= shift;
230 *exp -= shift;
231 }
232 }
233 return mnt;
234}
235
236static inline uint32_t
237fp32_normalise(uint32_t mnt, int *exp)
238{
239 int shift;
240
241 if (!mnt) {
242 return 0;
243 }
244
245 for (shift = 16; shift; shift >>= 1) {
246 if (!(mnt >> (32 - shift))) {
247 mnt <<= shift;
248 *exp -= shift;
249 }
250 }
251 return mnt;
252}
253
254static inline uint64_t
255fp64_normalise(uint64_t mnt, int *exp)
256{
257 int shift;
258
259 if (!mnt) {
260 return 0;
261 }
262
263 for (shift = 32; shift; shift >>= 1) {
264 if (!(mnt >> (64 - shift))) {
265 mnt <<= shift;
266 *exp -= shift;
267 }
268 }
269 return mnt;
270}
271
272static inline void
273fp128_normalise(uint64_t *mnt0, uint64_t *mnt1, int *exp)
274{
275 uint64_t x0 = *mnt0;
276 uint64_t x1 = *mnt1;
277 int shift;
278
279 if (!x0 && !x1) {
280 return;
281 }
282
283 if (!x1) {
284 x1 = x0;
285 x0 = 0;
286 *exp -= 64;
287 }
288
289 for (shift = 32; shift; shift >>= 1) {
290 if (!(x1 >> (64 - shift))) {
291 x1 = x1 << shift | x0 >> (64 - shift);
292 x0 <<= shift;
293 *exp -= shift;
294 }
295 }
296
297 *mnt0 = x0;
298 *mnt1 = x1;
299}
300
301static inline uint16_t
302fp16_pack(uint16_t sgn, uint16_t exp, uint16_t mnt)
303{
304 return sgn << (FP16_BITS - 1) | exp << FP16_MANT_BITS | FP16_MANT(mnt);
305}
306
307static inline uint32_t
308fp32_pack(uint32_t sgn, uint32_t exp, uint32_t mnt)
309{
310 return sgn << (FP32_BITS - 1) | exp << FP32_MANT_BITS | FP32_MANT(mnt);
311}
312
313static inline uint64_t
314fp64_pack(uint64_t sgn, uint64_t exp, uint64_t mnt)
315{
316 return sgn << (FP64_BITS - 1) | exp << FP64_MANT_BITS | FP64_MANT(mnt);
317}
318
319static inline uint16_t
320fp16_zero(int sgn)
321{
322 return fp16_pack(sgn, 0, 0);
323}
324
325static inline uint32_t
326fp32_zero(int sgn)
327{
328 return fp32_pack(sgn, 0, 0);
329}
330
331static inline uint64_t
332fp64_zero(int sgn)
333{
334 return fp64_pack(sgn, 0, 0);
335}
336
337static inline uint16_t
339{
340 return fp16_pack(sgn, FP16_EXP_INF - 1, -1);
341}
342
343static inline uint32_t
345{
346 return fp32_pack(sgn, FP32_EXP_INF - 1, -1);
347}
348
349static inline uint64_t
351{
352 return fp64_pack(sgn, FP64_EXP_INF - 1, -1);
353}
354
355static inline uint16_t
357{
358 return fp16_pack(sgn, FP16_EXP_INF, 0);
359}
360
361static inline uint32_t
363{
364 return fp32_pack(sgn, FP32_EXP_INF, 0);
365}
366
367static inline uint64_t
369{
370 return fp64_pack(sgn, FP64_EXP_INF, 0);
371}
372
373static inline uint16_t
375{
376 return fp16_pack(0, FP16_EXP_INF, 1ULL << (FP16_MANT_BITS - 1));
377}
378
379static inline uint32_t
381{
382 return fp32_pack(0, FP32_EXP_INF, 1ULL << (FP32_MANT_BITS - 1));
383}
384
385static inline uint64_t
387{
388 return fp64_pack(0, FP64_EXP_INF, 1ULL << (FP64_MANT_BITS - 1));
389}
390
391static inline void
392fp16_unpack(int *sgn, int *exp, uint16_t *mnt, uint16_t x, int mode,
393 int *flags)
394{
395 *sgn = x >> (FP16_BITS - 1);
396 *exp = FP16_EXP(x);
397 *mnt = FP16_MANT(x);
398
399 if (*exp) {
400 *mnt |= 1ULL << FP16_MANT_BITS;
401 } else {
402 // Handle subnormals:
403 // IDC (Input Denormal) is not set in this case.
404 if (*mnt) {
405 if (mode & FPLIB_FZ16) {
406 *mnt = 0;
407 } else {
408 ++*exp;
409 }
410 }
411 }
412}
413
414static inline void
415fp32_unpack(int *sgn, int *exp, uint32_t *mnt, uint32_t x, int mode,
416 int *flags)
417{
418 *sgn = x >> (FP32_BITS - 1);
419 *exp = FP32_EXP(x);
420 *mnt = FP32_MANT(x);
421
422 if (*exp) {
423 *mnt |= 1ULL << FP32_MANT_BITS;
424 } else {
425 // Handle subnormals:
426 if (*mnt) {
427 if (mode & FPLIB_FZ) {
428 *flags |= FPLIB_IDC;
429 *mnt = 0;
430 } else {
431 ++*exp;
432 }
433 }
434 }
435}
436
437static inline void
438fp64_unpack(int *sgn, int *exp, uint64_t *mnt, uint64_t x, int mode,
439 int *flags)
440{
441
442
443 *sgn = x >> (FP64_BITS - 1);
444 *exp = FP64_EXP(x);
445 *mnt = FP64_MANT(x);
446
447 if (*exp) {
448 *mnt |= 1ULL << FP64_MANT_BITS;
449 } else {
450 // Handle subnormals:
451 if (*mnt) {
452 if (mode & FPLIB_FZ) {
453 *flags |= FPLIB_IDC;
454 *mnt = 0;
455 } else {
456 ++*exp;
457 }
458 }
459 }
460}
461
462static inline int
463fp16_is_NaN(int exp, uint16_t mnt)
464{
465 return exp == FP16_EXP_INF && FP16_MANT(mnt);
466}
467
468static inline int
469fp32_is_NaN(int exp, uint32_t mnt)
470{
471 return exp == FP32_EXP_INF && FP32_MANT(mnt);
472}
473
474static inline int
475fp64_is_NaN(int exp, uint64_t mnt)
476{
477 return exp == FP64_EXP_INF && FP64_MANT(mnt);
478}
479
480static inline int
481fp16_is_signalling_NaN(int exp, uint16_t mnt)
482{
483 return fp16_is_NaN(exp, mnt) && !(mnt >> (FP16_MANT_BITS - 1) & 1);
484}
485
486static inline int
487fp32_is_signalling_NaN(int exp, uint32_t mnt)
488{
489 return fp32_is_NaN(exp, mnt) && !(mnt >> (FP32_MANT_BITS - 1) & 1);
490}
491
492static inline int
493fp64_is_signalling_NaN(int exp, uint64_t mnt)
494{
495 return fp64_is_NaN(exp, mnt) && !(mnt >> (FP64_MANT_BITS - 1) & 1);
496}
497
498static inline int
499fp16_is_quiet_NaN(int exp, uint16_t mnt)
500{
501 return exp == FP16_EXP_INF && (mnt >> (FP16_MANT_BITS - 1) & 1);
502}
503
504static inline int
505fp32_is_quiet_NaN(int exp, uint32_t mnt)
506{
507 return exp == FP32_EXP_INF && (mnt >> (FP32_MANT_BITS - 1) & 1);
508}
509
510static inline int
511fp64_is_quiet_NaN(int exp, uint64_t mnt)
512{
513 return exp == FP64_EXP_INF && (mnt >> (FP64_MANT_BITS - 1) & 1);
514}
515
516static inline int
517fp16_is_infinity(int exp, uint16_t mnt)
518{
519 return exp == FP16_EXP_INF && !FP16_MANT(mnt);
520}
521
522static inline int
523fp32_is_infinity(int exp, uint32_t mnt)
524{
525 return exp == FP32_EXP_INF && !FP32_MANT(mnt);
526}
527
528static inline int
529fp64_is_infinity(int exp, uint64_t mnt)
530{
531 return exp == FP64_EXP_INF && !FP64_MANT(mnt);
532}
533
534static inline uint16_t
535fp16_process_NaN(uint16_t a, int mode, int *flags)
536{
537 if (!(a >> (FP16_MANT_BITS - 1) & 1)) {
538 *flags |= FPLIB_IOC;
539 a |= 1ULL << (FP16_MANT_BITS - 1);
540 }
541 return mode & FPLIB_DN ? fp16_defaultNaN() : a;
542}
543
544static inline uint32_t
545fp32_process_NaN(uint32_t a, int mode, int *flags)
546{
547 if (!(a >> (FP32_MANT_BITS - 1) & 1)) {
548 *flags |= FPLIB_IOC;
549 a |= 1ULL << (FP32_MANT_BITS - 1);
550 }
551 return mode & FPLIB_DN ? fp32_defaultNaN() : a;
552}
553
554static inline uint64_t
555fp64_process_NaN(uint64_t a, int mode, int *flags)
556{
557 if (!(a >> (FP64_MANT_BITS - 1) & 1)) {
558 *flags |= FPLIB_IOC;
559 a |= 1ULL << (FP64_MANT_BITS - 1);
560 }
561 return mode & FPLIB_DN ? fp64_defaultNaN() : a;
562}
563
564static uint16_t
565fp16_process_NaNs(uint16_t a, uint16_t b, int mode, int *flags)
566{
567 int a_exp = FP16_EXP(a);
568 uint16_t a_mnt = FP16_MANT(a);
569 int b_exp = FP16_EXP(b);
570 uint16_t b_mnt = FP16_MANT(b);
571
572 // Handle signalling NaNs:
573 if (fp16_is_signalling_NaN(a_exp, a_mnt))
574 return fp16_process_NaN(a, mode, flags);
575 if (fp16_is_signalling_NaN(b_exp, b_mnt))
576 return fp16_process_NaN(b, mode, flags);
577
578 // Handle quiet NaNs:
579 if (fp16_is_NaN(a_exp, a_mnt))
580 return fp16_process_NaN(a, mode, flags);
581 if (fp16_is_NaN(b_exp, b_mnt))
582 return fp16_process_NaN(b, mode, flags);
583
584 return 0;
585}
586
587static uint32_t
588fp32_process_NaNs(uint32_t a, uint32_t b, int mode, int *flags)
589{
590 int a_exp = FP32_EXP(a);
591 uint32_t a_mnt = FP32_MANT(a);
592 int b_exp = FP32_EXP(b);
593 uint32_t b_mnt = FP32_MANT(b);
594
595 // Handle signalling NaNs:
596 if (fp32_is_signalling_NaN(a_exp, a_mnt))
597 return fp32_process_NaN(a, mode, flags);
598 if (fp32_is_signalling_NaN(b_exp, b_mnt))
599 return fp32_process_NaN(b, mode, flags);
600
601 // Handle quiet NaNs:
602 if (fp32_is_NaN(a_exp, a_mnt))
603 return fp32_process_NaN(a, mode, flags);
604 if (fp32_is_NaN(b_exp, b_mnt))
605 return fp32_process_NaN(b, mode, flags);
606
607 return 0;
608}
609
610static uint64_t
611fp64_process_NaNs(uint64_t a, uint64_t b, int mode, int *flags)
612{
613 int a_exp = FP64_EXP(a);
614 uint64_t a_mnt = FP64_MANT(a);
615 int b_exp = FP64_EXP(b);
616 uint64_t b_mnt = FP64_MANT(b);
617
618 // Handle signalling NaNs:
619 if (fp64_is_signalling_NaN(a_exp, a_mnt))
620 return fp64_process_NaN(a, mode, flags);
621 if (fp64_is_signalling_NaN(b_exp, b_mnt))
622 return fp64_process_NaN(b, mode, flags);
623
624 // Handle quiet NaNs:
625 if (fp64_is_NaN(a_exp, a_mnt))
626 return fp64_process_NaN(a, mode, flags);
627 if (fp64_is_NaN(b_exp, b_mnt))
628 return fp64_process_NaN(b, mode, flags);
629
630 return 0;
631}
632
633static uint16_t
634fp16_process_NaNs3(uint16_t a, uint16_t b, uint16_t c, int mode, int *flags)
635{
636 int a_exp = FP16_EXP(a);
637 uint16_t a_mnt = FP16_MANT(a);
638 int b_exp = FP16_EXP(b);
639 uint16_t b_mnt = FP16_MANT(b);
640 int c_exp = FP16_EXP(c);
641 uint16_t c_mnt = FP16_MANT(c);
642
643 // Handle signalling NaNs:
644 if (fp16_is_signalling_NaN(a_exp, a_mnt))
645 return fp16_process_NaN(a, mode, flags);
646 if (fp16_is_signalling_NaN(b_exp, b_mnt))
647 return fp16_process_NaN(b, mode, flags);
648 if (fp16_is_signalling_NaN(c_exp, c_mnt))
649 return fp16_process_NaN(c, mode, flags);
650
651 // Handle quiet NaNs:
652 if (fp16_is_NaN(a_exp, a_mnt))
653 return fp16_process_NaN(a, mode, flags);
654 if (fp16_is_NaN(b_exp, b_mnt))
655 return fp16_process_NaN(b, mode, flags);
656 if (fp16_is_NaN(c_exp, c_mnt))
657 return fp16_process_NaN(c, mode, flags);
658
659 return 0;
660}
661
662static uint32_t
663fp32_process_NaNs3(uint32_t a, uint32_t b, uint32_t c, int mode, int *flags)
664{
665 int a_exp = FP32_EXP(a);
666 uint32_t a_mnt = FP32_MANT(a);
667 int b_exp = FP32_EXP(b);
668 uint32_t b_mnt = FP32_MANT(b);
669 int c_exp = FP32_EXP(c);
670 uint32_t c_mnt = FP32_MANT(c);
671
672 // Handle signalling NaNs:
673 if (fp32_is_signalling_NaN(a_exp, a_mnt))
674 return fp32_process_NaN(a, mode, flags);
675 if (fp32_is_signalling_NaN(b_exp, b_mnt))
676 return fp32_process_NaN(b, mode, flags);
677 if (fp32_is_signalling_NaN(c_exp, c_mnt))
678 return fp32_process_NaN(c, mode, flags);
679
680 // Handle quiet NaNs:
681 if (fp32_is_NaN(a_exp, a_mnt))
682 return fp32_process_NaN(a, mode, flags);
683 if (fp32_is_NaN(b_exp, b_mnt))
684 return fp32_process_NaN(b, mode, flags);
685 if (fp32_is_NaN(c_exp, c_mnt))
686 return fp32_process_NaN(c, mode, flags);
687
688 return 0;
689}
690
691static uint64_t
692fp64_process_NaNs3(uint64_t a, uint64_t b, uint64_t c, int mode, int *flags)
693{
694 int a_exp = FP64_EXP(a);
695 uint64_t a_mnt = FP64_MANT(a);
696 int b_exp = FP64_EXP(b);
697 uint64_t b_mnt = FP64_MANT(b);
698 int c_exp = FP64_EXP(c);
699 uint64_t c_mnt = FP64_MANT(c);
700
701 // Handle signalling NaNs:
702 if (fp64_is_signalling_NaN(a_exp, a_mnt))
703 return fp64_process_NaN(a, mode, flags);
704 if (fp64_is_signalling_NaN(b_exp, b_mnt))
705 return fp64_process_NaN(b, mode, flags);
706 if (fp64_is_signalling_NaN(c_exp, c_mnt))
707 return fp64_process_NaN(c, mode, flags);
708
709 // Handle quiet NaNs:
710 if (fp64_is_NaN(a_exp, a_mnt))
711 return fp64_process_NaN(a, mode, flags);
712 if (fp64_is_NaN(b_exp, b_mnt))
713 return fp64_process_NaN(b, mode, flags);
714 if (fp64_is_NaN(c_exp, c_mnt))
715 return fp64_process_NaN(c, mode, flags);
716
717 return 0;
718}
719
720static uint16_t
721fp16_round_(int sgn, int exp, uint16_t mnt, int rm, int mode, int *flags)
722{
723 int biased_exp; // non-negative exponent value for result
724 uint16_t int_mant; // mantissa for result, less than (2 << FP16_MANT_BITS)
725 int error; // 0, 1, 2 or 3, where 2 means int_mant is wrong by exactly 0.5
726
727 assert(rm != FPRounding_TIEAWAY);
728
729 // Flush to zero:
730 if ((mode & FPLIB_FZ16) && exp < 1) {
731 *flags |= FPLIB_UFC;
732 return fp16_zero(sgn);
733 }
734
735 // The bottom FP16_EXP_BITS bits of mnt are orred together:
736 mnt = (4ULL << FP16_MANT_BITS | mnt >> (FP16_EXP_BITS - 1) |
737 ((mnt & ((1ULL << FP16_EXP_BITS) - 1)) != 0));
738
739 if (exp > 0) {
740 biased_exp = exp;
741 int_mant = mnt >> 2;
742 error = mnt & 3;
743 } else {
744 biased_exp = 0;
745 int_mant = lsr16(mnt, 3 - exp);
746 error = (lsr16(mnt, 1 - exp) & 3) | !!(mnt & (lsl16(1, 1 - exp) - 1));
747 }
748
749 if (!biased_exp && error) { // xx should also check fpscr_val<11>
750 *flags |= FPLIB_UFC;
751 }
752
753 // Round up:
754 if ((rm == FPLIB_RN && (error == 3 ||
755 (error == 2 && (int_mant & 1)))) ||
756 (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) && error)) {
757 ++int_mant;
758 if (int_mant == 1ULL << FP16_MANT_BITS) {
759 // Rounded up from denormalized to normalized
760 biased_exp = 1;
761 }
762 if (int_mant == 2ULL << FP16_MANT_BITS) {
763 // Rounded up to next exponent
764 ++biased_exp;
765 int_mant >>= 1;
766 }
767 }
768
769 // Handle rounding to odd aka Von Neumann rounding:
770 if (error && rm == FPRounding_ODD)
771 int_mant |= 1;
772
773 // Handle overflow:
774 if (!(mode & FPLIB_AHP)) {
775 if (biased_exp >= (int)FP16_EXP_INF) {
776 *flags |= FPLIB_OFC | FPLIB_IXC;
777 if (rm == FPLIB_RN || (rm == FPLIB_RP && !sgn) ||
778 (rm == FPLIB_RM && sgn)) {
779 return fp16_infinity(sgn);
780 } else {
781 return fp16_max_normal(sgn);
782 }
783 }
784 } else {
785 if (biased_exp >= (int)FP16_EXP_INF + 1) {
786 *flags |= FPLIB_IOC;
787 return fp16_pack(sgn, FP16_EXP_INF, -1);
788 }
789 }
790
791 if (error) {
792 *flags |= FPLIB_IXC;
793 }
794
795 return fp16_pack(sgn, biased_exp, int_mant);
796}
797
798static uint16_t
799fp16_round(int sgn, int exp, uint16_t mnt, int mode, int *flags)
800{
801 return fp16_round_(sgn, exp, mnt, mode & 3, mode, flags);
802}
803
804static uint32_t
805fp32_round_(int sgn, int exp, uint32_t mnt, int rm, int mode, int *flags)
806{
807 int biased_exp; // non-negative exponent value for result
808 uint32_t int_mant; // mantissa for result, less than (2 << FP32_MANT_BITS)
809 int error; // 0, 1, 2 or 3, where 2 means int_mant is wrong by exactly 0.5
810
811 assert(rm != FPRounding_TIEAWAY);
812
813 // Flush to zero:
814 if ((mode & FPLIB_FZ) && exp < 1) {
815 *flags |= FPLIB_UFC;
816 return fp32_zero(sgn);
817 }
818
819 // The bottom FP32_EXP_BITS bits of mnt are orred together:
820 mnt = (4ULL << FP32_MANT_BITS | mnt >> (FP32_EXP_BITS - 1) |
821 ((mnt & ((1ULL << FP32_EXP_BITS) - 1)) != 0));
822
823 if (exp > 0) {
824 biased_exp = exp;
825 int_mant = mnt >> 2;
826 error = mnt & 3;
827 } else {
828 biased_exp = 0;
829 int_mant = lsr32(mnt, 3 - exp);
830 error = (lsr32(mnt, 1 - exp) & 3) | !!(mnt & (lsl32(1, 1 - exp) - 1));
831 }
832
833 if (!biased_exp && error) { // xx should also check fpscr_val<11>
834 *flags |= FPLIB_UFC;
835 }
836
837 // Round up:
838 if ((rm == FPLIB_RN && (error == 3 ||
839 (error == 2 && (int_mant & 1)))) ||
840 (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) && error)) {
841 ++int_mant;
842 if (int_mant == 1ULL << FP32_MANT_BITS) {
843 // Rounded up from denormalized to normalized
844 biased_exp = 1;
845 }
846 if (int_mant == 2ULL << FP32_MANT_BITS) {
847 // Rounded up to next exponent
848 ++biased_exp;
849 int_mant >>= 1;
850 }
851 }
852
853 // Handle rounding to odd aka Von Neumann rounding:
854 if (error && rm == FPRounding_ODD)
855 int_mant |= 1;
856
857 // Handle overflow:
858 if (biased_exp >= (int)FP32_EXP_INF) {
859 *flags |= FPLIB_OFC | FPLIB_IXC;
860 if (rm == FPLIB_RN || (rm == FPLIB_RP && !sgn) ||
861 (rm == FPLIB_RM && sgn)) {
862 return fp32_infinity(sgn);
863 } else {
864 return fp32_max_normal(sgn);
865 }
866 }
867
868 if (error) {
869 *flags |= FPLIB_IXC;
870 }
871
872 return fp32_pack(sgn, biased_exp, int_mant);
873}
874
875static uint32_t
876fp32_round(int sgn, int exp, uint32_t mnt, int mode, int *flags)
877{
878 return fp32_round_(sgn, exp, mnt, mode & 3, mode, flags);
879}
880
881static uint64_t
882fp64_round_(int sgn, int exp, uint64_t mnt, int rm, int mode, int *flags)
883{
884 int biased_exp; // non-negative exponent value for result
885 uint64_t int_mant; // mantissa for result, less than (2 << FP64_MANT_BITS)
886 int error; // 0, 1, 2 or 3, where 2 means int_mant is wrong by exactly 0.5
887
888 assert(rm != FPRounding_TIEAWAY);
889
890 // Flush to zero:
891 if ((mode & FPLIB_FZ) && exp < 1) {
892 *flags |= FPLIB_UFC;
893 return fp64_zero(sgn);
894 }
895
896 // The bottom FP64_EXP_BITS bits of mnt are orred together:
897 mnt = (4ULL << FP64_MANT_BITS | mnt >> (FP64_EXP_BITS - 1) |
898 ((mnt & ((1ULL << FP64_EXP_BITS) - 1)) != 0));
899
900 if (exp > 0) {
901 biased_exp = exp;
902 int_mant = mnt >> 2;
903 error = mnt & 3;
904 } else {
905 biased_exp = 0;
906 int_mant = lsr64(mnt, 3 - exp);
907 error = (lsr64(mnt, 1 - exp) & 3) | !!(mnt & (lsl64(1, 1 - exp) - 1));
908 }
909
910 if (!biased_exp && error) { // xx should also check fpscr_val<11>
911 *flags |= FPLIB_UFC;
912 }
913
914 // Round up:
915 if ((rm == FPLIB_RN && (error == 3 ||
916 (error == 2 && (int_mant & 1)))) ||
917 (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) && error)) {
918 ++int_mant;
919 if (int_mant == 1ULL << FP64_MANT_BITS) {
920 // Rounded up from denormalized to normalized
921 biased_exp = 1;
922 }
923 if (int_mant == 2ULL << FP64_MANT_BITS) {
924 // Rounded up to next exponent
925 ++biased_exp;
926 int_mant >>= 1;
927 }
928 }
929
930 // Handle rounding to odd aka Von Neumann rounding:
931 if (error && rm == FPRounding_ODD)
932 int_mant |= 1;
933
934 // Handle overflow:
935 if (biased_exp >= (int)FP64_EXP_INF) {
936 *flags |= FPLIB_OFC | FPLIB_IXC;
937 if (rm == FPLIB_RN || (rm == FPLIB_RP && !sgn) ||
938 (rm == FPLIB_RM && sgn)) {
939 return fp64_infinity(sgn);
940 } else {
941 return fp64_max_normal(sgn);
942 }
943 }
944
945 if (error) {
946 *flags |= FPLIB_IXC;
947 }
948
949 return fp64_pack(sgn, biased_exp, int_mant);
950}
951
952static uint64_t
953fp64_round(int sgn, int exp, uint64_t mnt, int mode, int *flags)
954{
955 return fp64_round_(sgn, exp, mnt, mode & 3, mode, flags);
956}
957
958static int
959fp16_compare_eq(uint16_t a, uint16_t b, int mode, int *flags)
960{
961 int a_sgn, a_exp, b_sgn, b_exp;
962 uint16_t a_mnt, b_mnt;
963
964 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
965 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
966
967 if (fp16_is_NaN(a_exp, a_mnt) ||
968 fp16_is_NaN(b_exp, b_mnt)) {
969 if (fp16_is_signalling_NaN(a_exp, a_mnt) ||
970 fp16_is_signalling_NaN(b_exp, b_mnt))
971 *flags |= FPLIB_IOC;
972 return 0;
973 }
974 return a == b || (!a_mnt && !b_mnt);
975}
976
977static int
978fp16_compare_ge(uint16_t a, uint16_t b, int mode, int *flags)
979{
980 int a_sgn, a_exp, b_sgn, b_exp;
981 uint16_t a_mnt, b_mnt;
982
983 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
984 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
985
986 if (fp16_is_NaN(a_exp, a_mnt) ||
987 fp16_is_NaN(b_exp, b_mnt)) {
988 *flags |= FPLIB_IOC;
989 return 0;
990 }
991 if (!a_mnt && !b_mnt)
992 return 1;
993 if (a_sgn != b_sgn)
994 return b_sgn;
995 if (a_exp != b_exp)
996 return a_sgn ^ (a_exp > b_exp);
997 if (a_mnt != b_mnt)
998 return a_sgn ^ (a_mnt > b_mnt);
999 return 1;
1000}
1001
1002static int
1003fp16_compare_gt(uint16_t a, uint16_t b, int mode, int *flags)
1004{
1005 int a_sgn, a_exp, b_sgn, b_exp;
1006 uint16_t a_mnt, b_mnt;
1007
1008 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1009 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1010
1011 if (fp16_is_NaN(a_exp, a_mnt) ||
1012 fp16_is_NaN(b_exp, b_mnt)) {
1013 *flags |= FPLIB_IOC;
1014 return 0;
1015 }
1016 if (!a_mnt && !b_mnt)
1017 return 0;
1018 if (a_sgn != b_sgn)
1019 return b_sgn;
1020 if (a_exp != b_exp)
1021 return a_sgn ^ (a_exp > b_exp);
1022 if (a_mnt != b_mnt)
1023 return a_sgn ^ (a_mnt > b_mnt);
1024 return 0;
1025}
1026
1027static int
1028fp16_compare_un(uint16_t a, uint16_t b, int mode, int *flags)
1029{
1030 int a_sgn, a_exp, b_sgn, b_exp;
1031 uint16_t a_mnt, b_mnt;
1032
1033 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1034 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1035
1036 if (fp16_is_NaN(a_exp, a_mnt) ||
1037 fp16_is_NaN(b_exp, b_mnt)) {
1038 if (fp16_is_signalling_NaN(a_exp, a_mnt) ||
1039 fp16_is_signalling_NaN(b_exp, b_mnt))
1040 *flags |= FPLIB_IOC;
1041 return 1;
1042 }
1043 return 0;
1044}
1045
1046static int
1047fp32_compare_eq(uint32_t a, uint32_t b, int mode, int *flags)
1048{
1049 int a_sgn, a_exp, b_sgn, b_exp;
1050 uint32_t a_mnt, b_mnt;
1051
1052 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1053 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1054
1055 if (fp32_is_NaN(a_exp, a_mnt) ||
1056 fp32_is_NaN(b_exp, b_mnt)) {
1057 if (fp32_is_signalling_NaN(a_exp, a_mnt) ||
1058 fp32_is_signalling_NaN(b_exp, b_mnt))
1059 *flags |= FPLIB_IOC;
1060 return 0;
1061 }
1062 return a == b || (!a_mnt && !b_mnt);
1063}
1064
1065static int
1066fp32_compare_ge(uint32_t a, uint32_t b, int mode, int *flags)
1067{
1068 int a_sgn, a_exp, b_sgn, b_exp;
1069 uint32_t a_mnt, b_mnt;
1070
1071 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1072 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1073
1074 if (fp32_is_NaN(a_exp, a_mnt) ||
1075 fp32_is_NaN(b_exp, b_mnt)) {
1076 *flags |= FPLIB_IOC;
1077 return 0;
1078 }
1079 if (!a_mnt && !b_mnt)
1080 return 1;
1081 if (a_sgn != b_sgn)
1082 return b_sgn;
1083 if (a_exp != b_exp)
1084 return a_sgn ^ (a_exp > b_exp);
1085 if (a_mnt != b_mnt)
1086 return a_sgn ^ (a_mnt > b_mnt);
1087 return 1;
1088}
1089
1090static int
1091fp32_compare_gt(uint32_t a, uint32_t b, int mode, int *flags)
1092{
1093 int a_sgn, a_exp, b_sgn, b_exp;
1094 uint32_t a_mnt, b_mnt;
1095
1096 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1097 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1098
1099 if (fp32_is_NaN(a_exp, a_mnt) ||
1100 fp32_is_NaN(b_exp, b_mnt)) {
1101 *flags |= FPLIB_IOC;
1102 return 0;
1103 }
1104 if (!a_mnt && !b_mnt)
1105 return 0;
1106 if (a_sgn != b_sgn)
1107 return b_sgn;
1108 if (a_exp != b_exp)
1109 return a_sgn ^ (a_exp > b_exp);
1110 if (a_mnt != b_mnt)
1111 return a_sgn ^ (a_mnt > b_mnt);
1112 return 0;
1113}
1114
1115static int
1116fp32_compare_un(uint32_t a, uint32_t b, int mode, int *flags)
1117{
1118 int a_sgn, a_exp, b_sgn, b_exp;
1119 uint32_t a_mnt, b_mnt;
1120
1121 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1122 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1123
1124 if (fp32_is_NaN(a_exp, a_mnt) ||
1125 fp32_is_NaN(b_exp, b_mnt)) {
1126 if (fp32_is_signalling_NaN(a_exp, a_mnt) ||
1127 fp32_is_signalling_NaN(b_exp, b_mnt))
1128 *flags |= FPLIB_IOC;
1129 return 1;
1130 }
1131 return 0;
1132}
1133
1134static int
1135fp64_compare_eq(uint64_t a, uint64_t b, int mode, int *flags)
1136{
1137 int a_sgn, a_exp, b_sgn, b_exp;
1138 uint64_t a_mnt, b_mnt;
1139
1140 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1141 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1142
1143 if (fp64_is_NaN(a_exp, a_mnt) ||
1144 fp64_is_NaN(b_exp, b_mnt)) {
1145 if (fp64_is_signalling_NaN(a_exp, a_mnt) ||
1146 fp64_is_signalling_NaN(b_exp, b_mnt))
1147 *flags |= FPLIB_IOC;
1148 return 0;
1149 }
1150 return a == b || (!a_mnt && !b_mnt);
1151}
1152
1153static int
1154fp64_compare_ge(uint64_t a, uint64_t b, int mode, int *flags)
1155{
1156 int a_sgn, a_exp, b_sgn, b_exp;
1157 uint64_t a_mnt, b_mnt;
1158
1159 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1160 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1161
1162 if (fp64_is_NaN(a_exp, a_mnt) ||
1163 fp64_is_NaN(b_exp, b_mnt)) {
1164 *flags |= FPLIB_IOC;
1165 return 0;
1166 }
1167 if (!a_mnt && !b_mnt)
1168 return 1;
1169 if (a_sgn != b_sgn)
1170 return b_sgn;
1171 if (a_exp != b_exp)
1172 return a_sgn ^ (a_exp > b_exp);
1173 if (a_mnt != b_mnt)
1174 return a_sgn ^ (a_mnt > b_mnt);
1175 return 1;
1176}
1177
1178static int
1179fp64_compare_gt(uint64_t a, uint64_t b, int mode, int *flags)
1180{
1181 int a_sgn, a_exp, b_sgn, b_exp;
1182 uint64_t a_mnt, b_mnt;
1183
1184 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1185 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1186
1187 if (fp64_is_NaN(a_exp, a_mnt) ||
1188 fp64_is_NaN(b_exp, b_mnt)) {
1189 *flags |= FPLIB_IOC;
1190 return 0;
1191 }
1192 if (!a_mnt && !b_mnt)
1193 return 0;
1194 if (a_sgn != b_sgn)
1195 return b_sgn;
1196 if (a_exp != b_exp)
1197 return a_sgn ^ (a_exp > b_exp);
1198 if (a_mnt != b_mnt)
1199 return a_sgn ^ (a_mnt > b_mnt);
1200 return 0;
1201}
1202
1203static int
1204fp64_compare_un(uint64_t a, uint64_t b, int mode, int *flags)
1205{
1206 int a_sgn, a_exp, b_sgn, b_exp;
1207 uint64_t a_mnt, b_mnt;
1208
1209 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1210 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1211
1212 if (fp64_is_NaN(a_exp, a_mnt) ||
1213 fp64_is_NaN(b_exp, b_mnt)) {
1214 if (fp64_is_signalling_NaN(a_exp, a_mnt) ||
1215 fp64_is_signalling_NaN(b_exp, b_mnt))
1216 *flags |= FPLIB_IOC;
1217 return 1;
1218 }
1219 return 0;
1220}
1221
1222static uint16_t
1223fp16_add(uint16_t a, uint16_t b, int neg, int mode, int *flags)
1224{
1225 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1226 uint16_t a_mnt, b_mnt, x, x_mnt;
1227
1228 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1229 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1230
1231 if ((x = fp16_process_NaNs(a, b, mode, flags))) {
1232 return x;
1233 }
1234
1235 b_sgn ^= neg;
1236
1237 // Handle infinities and zeroes:
1238 if (a_exp == FP16_EXP_INF && b_exp == FP16_EXP_INF && a_sgn != b_sgn) {
1239 *flags |= FPLIB_IOC;
1240 return fp16_defaultNaN();
1241 } else if (a_exp == FP16_EXP_INF) {
1242 return fp16_infinity(a_sgn);
1243 } else if (b_exp == FP16_EXP_INF) {
1244 return fp16_infinity(b_sgn);
1245 } else if (!a_mnt && !b_mnt && a_sgn == b_sgn) {
1246 return fp16_zero(a_sgn);
1247 }
1248
1249 a_mnt <<= 3;
1250 b_mnt <<= 3;
1251 if (a_exp >= b_exp) {
1252 b_mnt = (lsr16(b_mnt, a_exp - b_exp) |
1253 !!(b_mnt & (lsl16(1, a_exp - b_exp) - 1)));
1254 b_exp = a_exp;
1255 } else {
1256 a_mnt = (lsr16(a_mnt, b_exp - a_exp) |
1257 !!(a_mnt & (lsl16(1, b_exp - a_exp) - 1)));
1258 a_exp = b_exp;
1259 }
1260 x_sgn = a_sgn;
1261 x_exp = a_exp;
1262 if (a_sgn == b_sgn) {
1263 x_mnt = a_mnt + b_mnt;
1264 } else if (a_mnt >= b_mnt) {
1265 x_mnt = a_mnt - b_mnt;
1266 } else {
1267 x_sgn ^= 1;
1268 x_mnt = b_mnt - a_mnt;
1269 }
1270
1271 if (!x_mnt) {
1272 // Sign of exact zero result depends on rounding mode
1273 return fp16_zero((mode & 3) == 2);
1274 }
1275
1276 x_mnt = fp16_normalise(x_mnt, &x_exp);
1277
1278 return fp16_round(x_sgn, x_exp + FP16_EXP_BITS - 3, x_mnt << 1,
1279 mode, flags);
1280}
1281
1282static uint32_t
1283fp32_add(uint32_t a, uint32_t b, int neg, int mode, int *flags)
1284{
1285 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1286 uint32_t a_mnt, b_mnt, x, x_mnt;
1287
1288 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1289 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1290
1291 if ((x = fp32_process_NaNs(a, b, mode, flags))) {
1292 return x;
1293 }
1294
1295 b_sgn ^= neg;
1296
1297 // Handle infinities and zeroes:
1298 if (a_exp == FP32_EXP_INF && b_exp == FP32_EXP_INF && a_sgn != b_sgn) {
1299 *flags |= FPLIB_IOC;
1300 return fp32_defaultNaN();
1301 } else if (a_exp == FP32_EXP_INF) {
1302 return fp32_infinity(a_sgn);
1303 } else if (b_exp == FP32_EXP_INF) {
1304 return fp32_infinity(b_sgn);
1305 } else if (!a_mnt && !b_mnt && a_sgn == b_sgn) {
1306 return fp32_zero(a_sgn);
1307 }
1308
1309 a_mnt <<= 3;
1310 b_mnt <<= 3;
1311 if (a_exp >= b_exp) {
1312 b_mnt = (lsr32(b_mnt, a_exp - b_exp) |
1313 !!(b_mnt & (lsl32(1, a_exp - b_exp) - 1)));
1314 b_exp = a_exp;
1315 } else {
1316 a_mnt = (lsr32(a_mnt, b_exp - a_exp) |
1317 !!(a_mnt & (lsl32(1, b_exp - a_exp) - 1)));
1318 a_exp = b_exp;
1319 }
1320 x_sgn = a_sgn;
1321 x_exp = a_exp;
1322 if (a_sgn == b_sgn) {
1323 x_mnt = a_mnt + b_mnt;
1324 } else if (a_mnt >= b_mnt) {
1325 x_mnt = a_mnt - b_mnt;
1326 } else {
1327 x_sgn ^= 1;
1328 x_mnt = b_mnt - a_mnt;
1329 }
1330
1331 if (!x_mnt) {
1332 // Sign of exact zero result depends on rounding mode
1333 return fp32_zero((mode & 3) == 2);
1334 }
1335
1336 x_mnt = fp32_normalise(x_mnt, &x_exp);
1337
1338 return fp32_round(x_sgn, x_exp + FP32_EXP_BITS - 3, x_mnt << 1,
1339 mode, flags);
1340}
1341
1342static uint64_t
1343fp64_add(uint64_t a, uint64_t b, int neg, int mode, int *flags)
1344{
1345 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1346 uint64_t a_mnt, b_mnt, x, x_mnt;
1347
1348 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1349 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1350
1351 if ((x = fp64_process_NaNs(a, b, mode, flags))) {
1352 return x;
1353 }
1354
1355 b_sgn ^= neg;
1356
1357 // Handle infinities and zeroes:
1358 if (a_exp == FP64_EXP_INF && b_exp == FP64_EXP_INF && a_sgn != b_sgn) {
1359 *flags |= FPLIB_IOC;
1360 return fp64_defaultNaN();
1361 } else if (a_exp == FP64_EXP_INF) {
1362 return fp64_infinity(a_sgn);
1363 } else if (b_exp == FP64_EXP_INF) {
1364 return fp64_infinity(b_sgn);
1365 } else if (!a_mnt && !b_mnt && a_sgn == b_sgn) {
1366 return fp64_zero(a_sgn);
1367 }
1368
1369 a_mnt <<= 3;
1370 b_mnt <<= 3;
1371 if (a_exp >= b_exp) {
1372 b_mnt = (lsr64(b_mnt, a_exp - b_exp) |
1373 !!(b_mnt & (lsl64(1, a_exp - b_exp) - 1)));
1374 b_exp = a_exp;
1375 } else {
1376 a_mnt = (lsr64(a_mnt, b_exp - a_exp) |
1377 !!(a_mnt & (lsl64(1, b_exp - a_exp) - 1)));
1378 a_exp = b_exp;
1379 }
1380 x_sgn = a_sgn;
1381 x_exp = a_exp;
1382 if (a_sgn == b_sgn) {
1383 x_mnt = a_mnt + b_mnt;
1384 } else if (a_mnt >= b_mnt) {
1385 x_mnt = a_mnt - b_mnt;
1386 } else {
1387 x_sgn ^= 1;
1388 x_mnt = b_mnt - a_mnt;
1389 }
1390
1391 if (!x_mnt) {
1392 // Sign of exact zero result depends on rounding mode
1393 return fp64_zero((mode & 3) == 2);
1394 }
1395
1396 x_mnt = fp64_normalise(x_mnt, &x_exp);
1397
1398 return fp64_round(x_sgn, x_exp + FP64_EXP_BITS - 3, x_mnt << 1,
1399 mode, flags);
1400}
1401
1402static uint16_t
1403fp16_halved_add(uint16_t a, uint16_t b, int neg, int mode, int *flags)
1404{
1405 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1406 uint16_t a_mnt, b_mnt, x, x_mnt;
1407
1408 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1409 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1410
1411 if ((x = fp16_process_NaNs(a, b, mode, flags))) {
1412 return x;
1413 }
1414
1415 b_sgn ^= neg;
1416
1417 // Handle infinities and zeroes:
1418 if (a_exp == FP16_EXP_INF && b_exp == FP16_EXP_INF && a_sgn != b_sgn) {
1419 *flags |= FPLIB_IOC;
1420 return fp16_defaultNaN();
1421 } else if (a_exp == FP16_EXP_INF) {
1422 return fp16_infinity(a_sgn);
1423 } else if (b_exp == FP16_EXP_INF) {
1424 return fp16_infinity(b_sgn);
1425 } else if (!a_mnt && !b_mnt && a_sgn == b_sgn) {
1426 return fp16_zero(a_sgn);
1427 }
1428
1429 a_mnt <<= 3;
1430 b_mnt <<= 3;
1431 if (a_exp >= b_exp) {
1432 b_mnt = (lsr16(b_mnt, a_exp - b_exp) |
1433 !!(b_mnt & (lsl16(1, a_exp - b_exp) - 1)));
1434 b_exp = a_exp;
1435 } else {
1436 a_mnt = (lsr16(a_mnt, b_exp - a_exp) |
1437 !!(a_mnt & (lsl16(1, b_exp - a_exp) - 1)));
1438 a_exp = b_exp;
1439 }
1440 x_sgn = a_sgn;
1441 x_exp = a_exp;
1442 if (a_sgn == b_sgn) {
1443 x_mnt = a_mnt + b_mnt;
1444 } else if (a_mnt >= b_mnt) {
1445 x_mnt = a_mnt - b_mnt;
1446 } else {
1447 x_sgn ^= 1;
1448 x_mnt = b_mnt - a_mnt;
1449 }
1450
1451 if (!x_mnt) {
1452 // Sign of exact zero result depends on rounding mode
1453 return fp16_zero((mode & 3) == 2);
1454 }
1455
1456 x_exp -= 1; // halved
1457 x_mnt = fp16_normalise(x_mnt, &x_exp);
1458
1459 return fp16_round(x_sgn, x_exp + FP16_EXP_BITS - 3, x_mnt << 1,
1460 mode, flags);
1461}
1462
1463static uint16_t
1464fp16_mul(uint16_t a, uint16_t b, int mode, int *flags)
1465{
1466 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1467 uint16_t a_mnt, b_mnt, x;
1468 uint32_t x_mnt;
1469
1470 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1471 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1472
1473 if ((x = fp16_process_NaNs(a, b, mode, flags))) {
1474 return x;
1475 }
1476
1477 // Handle infinities and zeroes:
1478 if ((a_exp == FP16_EXP_INF && !b_mnt) ||
1479 (b_exp == FP16_EXP_INF && !a_mnt)) {
1480 *flags |= FPLIB_IOC;
1481 return fp16_defaultNaN();
1482 } else if (a_exp == FP16_EXP_INF || b_exp == FP16_EXP_INF) {
1483 return fp16_infinity(a_sgn ^ b_sgn);
1484 } else if (!a_mnt || !b_mnt) {
1485 return fp16_zero(a_sgn ^ b_sgn);
1486 }
1487
1488 // Multiply and normalise:
1489 x_sgn = a_sgn ^ b_sgn;
1490 x_exp = a_exp + b_exp - FP16_EXP_BIAS + 2 * FP16_EXP_BITS + 1;
1491 x_mnt = (uint32_t)a_mnt * b_mnt;
1492 x_mnt = fp32_normalise(x_mnt, &x_exp);
1493
1494 // Convert to FP16_BITS bits, collapsing error into bottom bit:
1495 x_mnt = lsr32(x_mnt, FP16_BITS - 1) | !!lsl32(x_mnt, FP16_BITS + 1);
1496
1497 return fp16_round(x_sgn, x_exp, x_mnt, mode, flags);
1498}
1499
1500static uint32_t
1501fp32_mul(uint32_t a, uint32_t b, int mode, int *flags)
1502{
1503 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1504 uint32_t a_mnt, b_mnt, x;
1505 uint64_t x_mnt;
1506
1507 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1508 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1509
1510 if ((x = fp32_process_NaNs(a, b, mode, flags))) {
1511 return x;
1512 }
1513
1514 // Handle infinities and zeroes:
1515 if ((a_exp == FP32_EXP_INF && !b_mnt) ||
1516 (b_exp == FP32_EXP_INF && !a_mnt)) {
1517 *flags |= FPLIB_IOC;
1518 return fp32_defaultNaN();
1519 } else if (a_exp == FP32_EXP_INF || b_exp == FP32_EXP_INF) {
1520 return fp32_infinity(a_sgn ^ b_sgn);
1521 } else if (!a_mnt || !b_mnt) {
1522 return fp32_zero(a_sgn ^ b_sgn);
1523 }
1524
1525 // Multiply and normalise:
1526 x_sgn = a_sgn ^ b_sgn;
1527 x_exp = a_exp + b_exp - FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1;
1528 x_mnt = (uint64_t)a_mnt * b_mnt;
1529 x_mnt = fp64_normalise(x_mnt, &x_exp);
1530
1531 // Convert to FP32_BITS bits, collapsing error into bottom bit:
1532 x_mnt = lsr64(x_mnt, FP32_BITS - 1) | !!lsl64(x_mnt, FP32_BITS + 1);
1533
1534 return fp32_round(x_sgn, x_exp, x_mnt, mode, flags);
1535}
1536
1537static uint64_t
1538fp64_mul(uint64_t a, uint64_t b, int mode, int *flags)
1539{
1540 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1541 uint64_t a_mnt, b_mnt, x;
1542 uint64_t x0_mnt, x1_mnt;
1543
1544 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1545 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1546
1547 if ((x = fp64_process_NaNs(a, b, mode, flags))) {
1548 return x;
1549 }
1550
1551 // Handle infinities and zeroes:
1552 if ((a_exp == FP64_EXP_INF && !b_mnt) ||
1553 (b_exp == FP64_EXP_INF && !a_mnt)) {
1554 *flags |= FPLIB_IOC;
1555 return fp64_defaultNaN();
1556 } else if (a_exp == FP64_EXP_INF || b_exp == FP64_EXP_INF) {
1557 return fp64_infinity(a_sgn ^ b_sgn);
1558 } else if (!a_mnt || !b_mnt) {
1559 return fp64_zero(a_sgn ^ b_sgn);
1560 }
1561
1562 // Multiply and normalise:
1563 x_sgn = a_sgn ^ b_sgn;
1564 x_exp = a_exp + b_exp - FP64_EXP_BIAS + 2 * FP64_EXP_BITS + 1;
1565 mul62x62(&x0_mnt, &x1_mnt, a_mnt, b_mnt);
1566 fp128_normalise(&x0_mnt, &x1_mnt, &x_exp);
1567
1568 // Convert to FP64_BITS bits, collapsing error into bottom bit:
1569 x0_mnt = x1_mnt << 1 | !!x0_mnt;
1570
1571 return fp64_round(x_sgn, x_exp, x0_mnt, mode, flags);
1572}
1573
1574static uint16_t
1575fp16_muladd(uint16_t a, uint16_t b, uint16_t c, int scale,
1576 int mode, int *flags)
1577{
1578 int a_sgn, a_exp, b_sgn, b_exp, c_sgn, c_exp, x_sgn, x_exp, y_sgn, y_exp;
1579 uint16_t a_mnt, b_mnt, c_mnt, x;
1580 uint32_t x_mnt, y_mnt;
1581
1582 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1583 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1584 fp16_unpack(&c_sgn, &c_exp, &c_mnt, c, mode, flags);
1585
1586 x = fp16_process_NaNs3(a, b, c, mode, flags);
1587
1588 // Quiet NaN added to product of zero and infinity:
1589 if (fp16_is_quiet_NaN(a_exp, a_mnt) &&
1590 ((!b_mnt && fp16_is_infinity(c_exp, c_mnt)) ||
1591 (!c_mnt && fp16_is_infinity(b_exp, b_mnt)))) {
1592 x = fp16_defaultNaN();
1593 *flags |= FPLIB_IOC;
1594 }
1595
1596 if (x) {
1597 return x;
1598 }
1599
1600 // Handle infinities and zeroes:
1601 if ((b_exp == FP16_EXP_INF && !c_mnt) ||
1602 (c_exp == FP16_EXP_INF && !b_mnt) ||
1603 (a_exp == FP16_EXP_INF &&
1604 (b_exp == FP16_EXP_INF || c_exp == FP16_EXP_INF) &&
1605 (a_sgn != (b_sgn ^ c_sgn)))) {
1606 *flags |= FPLIB_IOC;
1607 return fp16_defaultNaN();
1608 }
1609 if (a_exp == FP16_EXP_INF)
1610 return fp16_infinity(a_sgn);
1611 if (b_exp == FP16_EXP_INF || c_exp == FP16_EXP_INF)
1612 return fp16_infinity(b_sgn ^ c_sgn);
1613 if (!a_mnt && (!b_mnt || !c_mnt) && a_sgn == (b_sgn ^ c_sgn))
1614 return fp16_zero(a_sgn);
1615
1616 x_sgn = a_sgn;
1617 x_exp = a_exp + 2 * FP16_EXP_BITS - 3;
1618 x_mnt = (uint32_t)a_mnt << (FP16_MANT_BITS + 4);
1619
1620 // Multiply:
1621 y_sgn = b_sgn ^ c_sgn;
1622 y_exp = b_exp + c_exp - FP16_EXP_BIAS + 2 * FP16_EXP_BITS + 1 - 3;
1623 y_mnt = (uint32_t)b_mnt * c_mnt << 3;
1624 if (!y_mnt) {
1625 y_exp = x_exp;
1626 }
1627
1628 // Add:
1629 if (x_exp >= y_exp) {
1630 y_mnt = (lsr32(y_mnt, x_exp - y_exp) |
1631 !!(y_mnt & (lsl32(1, x_exp - y_exp) - 1)));
1632 y_exp = x_exp;
1633 } else {
1634 x_mnt = (lsr32(x_mnt, y_exp - x_exp) |
1635 !!(x_mnt & (lsl32(1, y_exp - x_exp) - 1)));
1636 x_exp = y_exp;
1637 }
1638 if (x_sgn == y_sgn) {
1639 x_mnt = x_mnt + y_mnt;
1640 } else if (x_mnt >= y_mnt) {
1641 x_mnt = x_mnt - y_mnt;
1642 } else {
1643 x_sgn ^= 1;
1644 x_mnt = y_mnt - x_mnt;
1645 }
1646
1647 if (!x_mnt) {
1648 // Sign of exact zero result depends on rounding mode
1649 return fp16_zero((mode & 3) == 2);
1650 }
1651
1652 // Normalise into FP16_BITS bits, collapsing error into bottom bit:
1653 x_mnt = fp32_normalise(x_mnt, &x_exp);
1654 x_mnt = x_mnt >> (FP16_BITS - 1) | !!(uint16_t)(x_mnt << 1);
1655
1656 return fp16_round(x_sgn, x_exp + scale, x_mnt, mode, flags);
1657}
1658
1659static uint32_t
1660fp32_muladd(uint32_t a, uint32_t b, uint32_t c, int scale,
1661 int mode, int *flags)
1662{
1663 int a_sgn, a_exp, b_sgn, b_exp, c_sgn, c_exp, x_sgn, x_exp, y_sgn, y_exp;
1664 uint32_t a_mnt, b_mnt, c_mnt, x;
1665 uint64_t x_mnt, y_mnt;
1666
1667 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1668 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1669 fp32_unpack(&c_sgn, &c_exp, &c_mnt, c, mode, flags);
1670
1671 x = fp32_process_NaNs3(a, b, c, mode, flags);
1672
1673 // Quiet NaN added to product of zero and infinity:
1674 if (fp32_is_quiet_NaN(a_exp, a_mnt) &&
1675 ((!b_mnt && fp32_is_infinity(c_exp, c_mnt)) ||
1676 (!c_mnt && fp32_is_infinity(b_exp, b_mnt)))) {
1677 x = fp32_defaultNaN();
1678 *flags |= FPLIB_IOC;
1679 }
1680
1681 if (x) {
1682 return x;
1683 }
1684
1685 // Handle infinities and zeroes:
1686 if ((b_exp == FP32_EXP_INF && !c_mnt) ||
1687 (c_exp == FP32_EXP_INF && !b_mnt) ||
1688 (a_exp == FP32_EXP_INF &&
1689 (b_exp == FP32_EXP_INF || c_exp == FP32_EXP_INF) &&
1690 (a_sgn != (b_sgn ^ c_sgn)))) {
1691 *flags |= FPLIB_IOC;
1692 return fp32_defaultNaN();
1693 }
1694 if (a_exp == FP32_EXP_INF)
1695 return fp32_infinity(a_sgn);
1696 if (b_exp == FP32_EXP_INF || c_exp == FP32_EXP_INF)
1697 return fp32_infinity(b_sgn ^ c_sgn);
1698 if (!a_mnt && (!b_mnt || !c_mnt) && a_sgn == (b_sgn ^ c_sgn))
1699 return fp32_zero(a_sgn);
1700
1701 x_sgn = a_sgn;
1702 x_exp = a_exp + 2 * FP32_EXP_BITS - 3;
1703 x_mnt = (uint64_t)a_mnt << (FP32_MANT_BITS + 4);
1704
1705 // Multiply:
1706 y_sgn = b_sgn ^ c_sgn;
1707 y_exp = b_exp + c_exp - FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1 - 3;
1708 y_mnt = (uint64_t)b_mnt * c_mnt << 3;
1709 if (!y_mnt) {
1710 y_exp = x_exp;
1711 }
1712
1713 // Add:
1714 if (x_exp >= y_exp) {
1715 y_mnt = (lsr64(y_mnt, x_exp - y_exp) |
1716 !!(y_mnt & (lsl64(1, x_exp - y_exp) - 1)));
1717 y_exp = x_exp;
1718 } else {
1719 x_mnt = (lsr64(x_mnt, y_exp - x_exp) |
1720 !!(x_mnt & (lsl64(1, y_exp - x_exp) - 1)));
1721 x_exp = y_exp;
1722 }
1723 if (x_sgn == y_sgn) {
1724 x_mnt = x_mnt + y_mnt;
1725 } else if (x_mnt >= y_mnt) {
1726 x_mnt = x_mnt - y_mnt;
1727 } else {
1728 x_sgn ^= 1;
1729 x_mnt = y_mnt - x_mnt;
1730 }
1731
1732 if (!x_mnt) {
1733 // Sign of exact zero result depends on rounding mode
1734 return fp32_zero((mode & 3) == 2);
1735 }
1736
1737 // Normalise into FP32_BITS bits, collapsing error into bottom bit:
1738 x_mnt = fp64_normalise(x_mnt, &x_exp);
1739 x_mnt = x_mnt >> (FP32_BITS - 1) | !!(uint32_t)(x_mnt << 1);
1740
1741 return fp32_round(x_sgn, x_exp + scale, x_mnt, mode, flags);
1742}
1743
1744static uint64_t
1745fp64_muladd(uint64_t a, uint64_t b, uint64_t c, int scale,
1746 int mode, int *flags)
1747{
1748 int a_sgn, a_exp, b_sgn, b_exp, c_sgn, c_exp, x_sgn, x_exp, y_sgn, y_exp;
1749 uint64_t a_mnt, b_mnt, c_mnt, x;
1750 uint64_t x0_mnt, x1_mnt, y0_mnt, y1_mnt;
1751
1752 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1753 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1754 fp64_unpack(&c_sgn, &c_exp, &c_mnt, c, mode, flags);
1755
1756 x = fp64_process_NaNs3(a, b, c, mode, flags);
1757
1758 // Quiet NaN added to product of zero and infinity:
1759 if (fp64_is_quiet_NaN(a_exp, a_mnt) &&
1760 ((!b_mnt && fp64_is_infinity(c_exp, c_mnt)) ||
1761 (!c_mnt && fp64_is_infinity(b_exp, b_mnt)))) {
1762 x = fp64_defaultNaN();
1763 *flags |= FPLIB_IOC;
1764 }
1765
1766 if (x) {
1767 return x;
1768 }
1769
1770 // Handle infinities and zeroes:
1771 if ((b_exp == FP64_EXP_INF && !c_mnt) ||
1772 (c_exp == FP64_EXP_INF && !b_mnt) ||
1773 (a_exp == FP64_EXP_INF &&
1774 (b_exp == FP64_EXP_INF || c_exp == FP64_EXP_INF) &&
1775 (a_sgn != (b_sgn ^ c_sgn)))) {
1776 *flags |= FPLIB_IOC;
1777 return fp64_defaultNaN();
1778 }
1779 if (a_exp == FP64_EXP_INF)
1780 return fp64_infinity(a_sgn);
1781 if (b_exp == FP64_EXP_INF || c_exp == FP64_EXP_INF)
1782 return fp64_infinity(b_sgn ^ c_sgn);
1783 if (!a_mnt && (!b_mnt || !c_mnt) && a_sgn == (b_sgn ^ c_sgn))
1784 return fp64_zero(a_sgn);
1785
1786 x_sgn = a_sgn;
1787 x_exp = a_exp + FP64_EXP_BITS;
1788 x0_mnt = 0;
1789 x1_mnt = a_mnt;
1790
1791 // Multiply:
1792 y_sgn = b_sgn ^ c_sgn;
1793 y_exp = b_exp + c_exp - FP64_EXP_BIAS + 2 * FP64_EXP_BITS + 1 - 3;
1794 mul62x62(&y0_mnt, &y1_mnt, b_mnt, c_mnt << 3);
1795 if (!y0_mnt && !y1_mnt) {
1796 y_exp = x_exp;
1797 }
1798
1799 // Add:
1800 if (x_exp >= y_exp) {
1801 uint64_t t0, t1;
1802 lsl128(&t0, &t1, y0_mnt, y1_mnt,
1803 x_exp - y_exp < 128 ? 128 - (x_exp - y_exp) : 0);
1804 lsr128(&y0_mnt, &y1_mnt, y0_mnt, y1_mnt, x_exp - y_exp);
1805 y0_mnt |= !!(t0 | t1);
1806 y_exp = x_exp;
1807 } else {
1808 uint64_t t0, t1;
1809 lsl128(&t0, &t1, x0_mnt, x1_mnt,
1810 y_exp - x_exp < 128 ? 128 - (y_exp - x_exp) : 0);
1811 lsr128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, y_exp - x_exp);
1812 x0_mnt |= !!(t0 | t1);
1813 x_exp = y_exp;
1814 }
1815 if (x_sgn == y_sgn) {
1816 add128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, y0_mnt, y1_mnt);
1817 } else if (cmp128(x0_mnt, x1_mnt, y0_mnt, y1_mnt) >= 0) {
1818 sub128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, y0_mnt, y1_mnt);
1819 } else {
1820 x_sgn ^= 1;
1821 sub128(&x0_mnt, &x1_mnt, y0_mnt, y1_mnt, x0_mnt, x1_mnt);
1822 }
1823
1824 if (!x0_mnt && !x1_mnt) {
1825 // Sign of exact zero result depends on rounding mode
1826 return fp64_zero((mode & 3) == 2);
1827 }
1828
1829 // Normalise into FP64_BITS bits, collapsing error into bottom bit:
1830 fp128_normalise(&x0_mnt, &x1_mnt, &x_exp);
1831 x0_mnt = x1_mnt << 1 | !!x0_mnt;
1832
1833 return fp64_round(x_sgn, x_exp + scale, x0_mnt, mode, flags);
1834}
1835
1836static uint16_t
1837fp16_div(uint16_t a, uint16_t b, int mode, int *flags)
1838{
1839 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1840 uint16_t a_mnt, b_mnt, x;
1841 uint32_t x_mnt;
1842
1843 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1844 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1845
1846 if ((x = fp16_process_NaNs(a, b, mode, flags)))
1847 return x;
1848
1849 // Handle infinities and zeroes:
1850 if ((a_exp == FP16_EXP_INF && b_exp == FP16_EXP_INF) ||
1851 (!a_mnt && !b_mnt)) {
1852 *flags |= FPLIB_IOC;
1853 return fp16_defaultNaN();
1854 }
1855 if (a_exp == FP16_EXP_INF || !b_mnt) {
1856 if (a_exp != FP16_EXP_INF)
1857 *flags |= FPLIB_DZC;
1858 return fp16_infinity(a_sgn ^ b_sgn);
1859 }
1860 if (!a_mnt || b_exp == FP16_EXP_INF)
1861 return fp16_zero(a_sgn ^ b_sgn);
1862
1863 // Divide, setting bottom bit if inexact:
1864 a_mnt = fp16_normalise(a_mnt, &a_exp);
1865 x_sgn = a_sgn ^ b_sgn;
1866 x_exp = a_exp - b_exp + (FP16_EXP_BIAS + FP16_BITS + 2 * FP16_EXP_BITS - 3);
1867 x_mnt = ((uint32_t)a_mnt << (FP16_MANT_BITS - FP16_EXP_BITS + 3)) / b_mnt;
1868 x_mnt |= (x_mnt * b_mnt !=
1869 (uint32_t)a_mnt << (FP16_MANT_BITS - FP16_EXP_BITS + 3));
1870
1871 // Normalise into FP16_BITS bits, collapsing error into bottom bit:
1872 x_mnt = fp32_normalise(x_mnt, &x_exp);
1873 x_mnt = x_mnt >> (FP16_BITS - 1) | !!(uint16_t)(x_mnt << 1);
1874
1875 return fp16_round(x_sgn, x_exp, x_mnt, mode, flags);
1876}
1877
1878static uint32_t
1879fp32_div(uint32_t a, uint32_t b, int mode, int *flags)
1880{
1881 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1882 uint32_t a_mnt, b_mnt, x;
1883 uint64_t x_mnt;
1884
1885 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1886 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1887
1888 if ((x = fp32_process_NaNs(a, b, mode, flags)))
1889 return x;
1890
1891 // Handle infinities and zeroes:
1892 if ((a_exp == FP32_EXP_INF && b_exp == FP32_EXP_INF) ||
1893 (!a_mnt && !b_mnt)) {
1894 *flags |= FPLIB_IOC;
1895 return fp32_defaultNaN();
1896 }
1897 if (a_exp == FP32_EXP_INF || !b_mnt) {
1898 if (a_exp != FP32_EXP_INF)
1899 *flags |= FPLIB_DZC;
1900 return fp32_infinity(a_sgn ^ b_sgn);
1901 }
1902 if (!a_mnt || b_exp == FP32_EXP_INF)
1903 return fp32_zero(a_sgn ^ b_sgn);
1904
1905 // Divide, setting bottom bit if inexact:
1906 a_mnt = fp32_normalise(a_mnt, &a_exp);
1907 x_sgn = a_sgn ^ b_sgn;
1908 x_exp = a_exp - b_exp + (FP32_EXP_BIAS + FP32_BITS + 2 * FP32_EXP_BITS - 3);
1909 x_mnt = ((uint64_t)a_mnt << (FP32_MANT_BITS - FP32_EXP_BITS + 3)) / b_mnt;
1910 x_mnt |= (x_mnt * b_mnt !=
1911 (uint64_t)a_mnt << (FP32_MANT_BITS - FP32_EXP_BITS + 3));
1912
1913 // Normalise into FP32_BITS bits, collapsing error into bottom bit:
1914 x_mnt = fp64_normalise(x_mnt, &x_exp);
1915 x_mnt = x_mnt >> (FP32_BITS - 1) | !!(uint32_t)(x_mnt << 1);
1916
1917 return fp32_round(x_sgn, x_exp, x_mnt, mode, flags);
1918}
1919
1920static uint64_t
1921fp64_div(uint64_t a, uint64_t b, int mode, int *flags)
1922{
1923 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp, c;
1924 uint64_t a_mnt, b_mnt, x, x_mnt, x0_mnt, x1_mnt;
1925
1926 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1927 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1928
1929 if ((x = fp64_process_NaNs(a, b, mode, flags)))
1930 return x;
1931
1932 // Handle infinities and zeroes:
1933 if ((a_exp == FP64_EXP_INF && b_exp == FP64_EXP_INF) ||
1934 (!a_mnt && !b_mnt)) {
1935 *flags |= FPLIB_IOC;
1936 return fp64_defaultNaN();
1937 }
1938 if (a_exp == FP64_EXP_INF || !b_mnt) {
1939 if (a_exp != FP64_EXP_INF)
1940 *flags |= FPLIB_DZC;
1941 return fp64_infinity(a_sgn ^ b_sgn);
1942 }
1943 if (!a_mnt || b_exp == FP64_EXP_INF)
1944 return fp64_zero(a_sgn ^ b_sgn);
1945
1946 // Find reciprocal of divisor with Newton-Raphson:
1947 a_mnt = fp64_normalise(a_mnt, &a_exp);
1948 b_mnt = fp64_normalise(b_mnt, &b_exp);
1949 x_mnt = ~(uint64_t)0 / (b_mnt >> 31);
1950 mul64x32(&x0_mnt, &x1_mnt, b_mnt, x_mnt);
1951 sub128(&x0_mnt, &x1_mnt, 0, (uint64_t)1 << 32, x0_mnt, x1_mnt);
1952 lsr128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, 32);
1953 mul64x32(&x0_mnt, &x1_mnt, x0_mnt, x_mnt);
1954 lsr128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, 33);
1955
1956 // Multiply by dividend:
1957 x_sgn = a_sgn ^ b_sgn;
1958 x_exp = a_exp - b_exp + FP64_EXP_BIAS + 8;
1959 mul62x62(&x0_mnt, &x1_mnt, x0_mnt, a_mnt >> 2);
1960 lsr128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, 4);
1961 x_mnt = x1_mnt;
1962
1963 // This is an underestimate, so try adding one:
1964 mul62x62(&x0_mnt, &x1_mnt, b_mnt >> 2, x_mnt + 1);
1965 c = cmp128(x0_mnt, x1_mnt, 0, a_mnt >> 11);
1966 if (c <= 0) {
1967 ++x_mnt;
1968 }
1969
1970 x_mnt = fp64_normalise(x_mnt, &x_exp);
1971
1972 return fp64_round(x_sgn, x_exp, x_mnt << 1 | !!c, mode, flags);
1973}
1974
1975static void
1976set_fpscr0(FPSCR &fpscr, int flags)
1977{
1978 if (flags & FPLIB_IDC) {
1979 fpscr.idc = 1;
1980 }
1981 if (flags & FPLIB_IOC) {
1982 fpscr.ioc = 1;
1983 }
1984 if (flags & FPLIB_DZC) {
1985 fpscr.dzc = 1;
1986 }
1987 if (flags & FPLIB_OFC) {
1988 fpscr.ofc = 1;
1989 }
1990 if (flags & FPLIB_UFC) {
1991 fpscr.ufc = 1;
1992 }
1993 if (flags & FPLIB_IXC) {
1994 fpscr.ixc = 1;
1995 }
1996}
1997
1998static uint16_t
1999fp16_scale(uint16_t a, int16_t b, int mode, int *flags)
2000{
2001 int a_sgn, a_exp;
2002 uint16_t a_mnt;
2003
2004 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2005
2006 // Handle NaNs:
2007 if (fp16_is_NaN(a_exp, a_mnt)) {
2008 return fp16_process_NaN(a, mode, flags);
2009 }
2010
2011 // Handle zeroes:
2012 if (!a_mnt) {
2013 return fp16_zero(a_sgn);
2014 }
2015
2016 // Handle infinities:
2017 if (a_exp == FP16_EXP_INF) {
2018 return fp16_infinity(a_sgn);
2019 }
2020
2021 b = b < -300 ? -300 : b;
2022 b = b > 300 ? 300 : b;
2023 a_exp += b;
2024 a_mnt <<= 3;
2025
2026 a_mnt = fp16_normalise(a_mnt, &a_exp);
2027
2028 return fp16_round(a_sgn, a_exp + FP16_EXP_BITS - 3, a_mnt << 1,
2029 mode, flags);
2030}
2031
2032static uint32_t
2033fp32_scale(uint32_t a, int32_t b, int mode, int *flags)
2034{
2035 int a_sgn, a_exp;
2036 uint32_t a_mnt;
2037
2038 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2039
2040 // Handle NaNs:
2041 if (fp32_is_NaN(a_exp, a_mnt)) {
2042 return fp32_process_NaN(a, mode, flags);
2043 }
2044
2045 // Handle zeroes:
2046 if (!a_mnt) {
2047 return fp32_zero(a_sgn);
2048 }
2049
2050 // Handle infinities:
2051 if (a_exp == FP32_EXP_INF) {
2052 return fp32_infinity(a_sgn);
2053 }
2054
2055 b = b < -300 ? -300 : b;
2056 b = b > 300 ? 300 : b;
2057 a_exp += b;
2058 a_mnt <<= 3;
2059
2060 a_mnt = fp32_normalise(a_mnt, &a_exp);
2061
2062 return fp32_round(a_sgn, a_exp + FP32_EXP_BITS - 3, a_mnt << 1,
2063 mode, flags);
2064}
2065
2066static uint64_t
2067fp64_scale(uint64_t a, int64_t b, int mode, int *flags)
2068{
2069 int a_sgn, a_exp;
2070 uint64_t a_mnt;
2071
2072 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2073
2074 // Handle NaNs:
2075 if (fp64_is_NaN(a_exp, a_mnt)) {
2076 return fp64_process_NaN(a, mode, flags);
2077 }
2078
2079 // Handle zeroes:
2080 if (!a_mnt) {
2081 return fp64_zero(a_sgn);
2082 }
2083
2084 // Handle infinities:
2085 if (a_exp == FP64_EXP_INF) {
2086 return fp64_infinity(a_sgn);
2087 }
2088
2089 b = b < -3000 ? -3000 : b;
2090 b = b > 3000 ? 3000 : b;
2091 a_exp += b;
2092 a_mnt <<= 3;
2093
2094 a_mnt = fp64_normalise(a_mnt, &a_exp);
2095
2096 return fp64_round(a_sgn, a_exp + FP64_EXP_BITS - 3, a_mnt << 1,
2097 mode, flags);
2098}
2099
2100static uint16_t
2101fp16_sqrt(uint16_t a, int mode, int *flags)
2102{
2103 int a_sgn, a_exp, x_sgn, x_exp;
2104 uint16_t a_mnt, x_mnt;
2105 uint32_t x, t0, t1;
2106
2107 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2108
2109 // Handle NaNs:
2110 if (fp16_is_NaN(a_exp, a_mnt))
2111 return fp16_process_NaN(a, mode, flags);
2112
2113 // Handle infinities and zeroes:
2114 if (!a_mnt)
2115 return fp16_zero(a_sgn);
2116 if (a_exp == FP16_EXP_INF && !a_sgn)
2117 return fp16_infinity(a_sgn);
2118 if (a_sgn) {
2119 *flags |= FPLIB_IOC;
2120 return fp16_defaultNaN();
2121 }
2122
2123 a_mnt = fp16_normalise(a_mnt, &a_exp);
2124 if (a_exp & 1) {
2125 ++a_exp;
2126 a_mnt >>= 1;
2127 }
2128
2129 // x = (a * 3 + 5) / 8
2130 x = ((uint32_t)a_mnt << 14) + ((uint32_t)a_mnt << 13) + ((uint32_t)5 << 28);
2131
2132 // x = (a / x + x) / 2; // 8-bit accuracy
2133 x = (((uint32_t)a_mnt << 16) / (x >> 15) + (x >> 16)) << 15;
2134
2135 // x = (a / x + x) / 2; // 16-bit accuracy
2136 x = (((uint32_t)a_mnt << 16) / (x >> 15) + (x >> 16)) << 15;
2137
2138 x_sgn = 0;
2139 x_exp = (a_exp + 27) >> 1;
2140 x_mnt = ((x - (1 << 18)) >> 19) + 1;
2141 t1 = (uint32_t)x_mnt * x_mnt;
2142 t0 = (uint32_t)a_mnt << 9;
2143 if (t1 > t0) {
2144 --x_mnt;
2145 }
2146
2147 x_mnt = fp16_normalise(x_mnt, &x_exp);
2148
2149 return fp16_round(x_sgn, x_exp, x_mnt << 1 | (t1 != t0), mode, flags);
2150}
2151
2152static uint32_t
2153fp32_sqrt(uint32_t a, int mode, int *flags)
2154{
2155 int a_sgn, a_exp, x_sgn, x_exp;
2156 uint32_t a_mnt, x, x_mnt;
2157 uint64_t t0, t1;
2158
2159 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2160
2161 // Handle NaNs:
2162 if (fp32_is_NaN(a_exp, a_mnt))
2163 return fp32_process_NaN(a, mode, flags);
2164
2165 // Handle infinities and zeroes:
2166 if (!a_mnt)
2167 return fp32_zero(a_sgn);
2168 if (a_exp == FP32_EXP_INF && !a_sgn)
2169 return fp32_infinity(a_sgn);
2170 if (a_sgn) {
2171 *flags |= FPLIB_IOC;
2172 return fp32_defaultNaN();
2173 }
2174
2175 a_mnt = fp32_normalise(a_mnt, &a_exp);
2176 if (!(a_exp & 1)) {
2177 ++a_exp;
2178 a_mnt >>= 1;
2179 }
2180
2181 // x = (a * 3 + 5) / 8
2182 x = (a_mnt >> 2) + (a_mnt >> 3) + ((uint32_t)5 << 28);
2183
2184 // x = (a / x + x) / 2; // 8-bit accuracy
2185 x = (a_mnt / (x >> 15) + (x >> 16)) << 15;
2186
2187 // x = (a / x + x) / 2; // 16-bit accuracy
2188 x = (a_mnt / (x >> 15) + (x >> 16)) << 15;
2189
2190 // x = (a / x + x) / 2; // 32-bit accuracy
2191 x = ((((uint64_t)a_mnt << 32) / x) >> 2) + (x >> 1);
2192
2193 x_sgn = 0;
2194 x_exp = (a_exp + 147) >> 1;
2195 x_mnt = ((x - (1 << 5)) >> 6) + 1;
2196 t1 = (uint64_t)x_mnt * x_mnt;
2197 t0 = (uint64_t)a_mnt << 19;
2198 if (t1 > t0) {
2199 --x_mnt;
2200 }
2201
2202 x_mnt = fp32_normalise(x_mnt, &x_exp);
2203
2204 return fp32_round(x_sgn, x_exp, x_mnt << 1 | (t1 != t0), mode, flags);
2205}
2206
2207static uint64_t
2208fp64_sqrt(uint64_t a, int mode, int *flags)
2209{
2210 int a_sgn, a_exp, x_sgn, x_exp, c;
2211 uint64_t a_mnt, x_mnt, r, x0, x1;
2212 uint32_t x;
2213
2214 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2215
2216 // Handle NaNs:
2217 if (fp64_is_NaN(a_exp, a_mnt))
2218 return fp64_process_NaN(a, mode, flags);
2219
2220 // Handle infinities and zeroes:
2221 if (!a_mnt)
2222 return fp64_zero(a_sgn);
2223 if (a_exp == FP64_EXP_INF && !a_sgn)
2224 return fp64_infinity(a_sgn);
2225 if (a_sgn) {
2226 *flags |= FPLIB_IOC;
2227 return fp64_defaultNaN();
2228 }
2229
2230 a_mnt = fp64_normalise(a_mnt, &a_exp);
2231 if (a_exp & 1) {
2232 ++a_exp;
2233 a_mnt >>= 1;
2234 }
2235
2236 // x = (a * 3 + 5) / 8
2237 x = (a_mnt >> 34) + (a_mnt >> 35) + ((uint32_t)5 << 28);
2238
2239 // x = (a / x + x) / 2; // 8-bit accuracy
2240 x = ((a_mnt >> 32) / (x >> 15) + (x >> 16)) << 15;
2241
2242 // x = (a / x + x) / 2; // 16-bit accuracy
2243 x = ((a_mnt >> 32) / (x >> 15) + (x >> 16)) << 15;
2244
2245 // x = (a / x + x) / 2; // 32-bit accuracy
2246 x = ((a_mnt / x) >> 2) + (x >> 1);
2247
2248 // r = 1 / x; // 32-bit accuracy
2249 r = ((uint64_t)1 << 62) / x;
2250
2251 // r = r * (2 - x * r); // 64-bit accuracy
2252 mul64x32(&x0, &x1, -(uint64_t)x * r << 1, r);
2253 lsr128(&x0, &x1, x0, x1, 31);
2254
2255 // x = (x + a * r) / 2; // 64-bit accuracy
2256 mul62x62(&x0, &x1, a_mnt >> 10, x0 >> 2);
2257 lsl128(&x0, &x1, x0, x1, 5);
2258 lsr128(&x0, &x1, x0, x1, 56);
2259
2260 x0 = ((uint64_t)x << 31) + (x0 >> 1);
2261
2262 x_sgn = 0;
2263 x_exp = (a_exp + 1053) >> 1;
2264 x_mnt = x0;
2265 x_mnt = ((x_mnt - (1 << 8)) >> 9) + 1;
2266 mul62x62(&x0, &x1, x_mnt, x_mnt);
2267 lsl128(&x0, &x1, x0, x1, 19);
2268 c = cmp128(x0, x1, 0, a_mnt);
2269 if (c > 0)
2270 --x_mnt;
2271
2272 x_mnt = fp64_normalise(x_mnt, &x_exp);
2273
2274 return fp64_round(x_sgn, x_exp, x_mnt << 1 | !!c, mode, flags);
2275}
2276
2277static int
2278modeConv(FPSCR fpscr)
2279{
2280 uint32_t x = (uint32_t)fpscr;
2281 return (x >> 22 & 0xf) | (x >> 19 & 1 ? FPLIB_FZ16 : 0);
2282 // AHP bit is ignored. Only fplibConvert uses AHP.
2283}
2284
2285static void
2286set_fpscr(FPSCR &fpscr, int flags)
2287{
2288 // translate back to FPSCR
2289 bool underflow = false;
2290 if (flags & FPLIB_IDC) {
2291 fpscr.idc = 1;
2292 }
2293 if (flags & FPLIB_IOC) {
2294 fpscr.ioc = 1;
2295 }
2296 if (flags & FPLIB_DZC) {
2297 fpscr.dzc = 1;
2298 }
2299 if (flags & FPLIB_OFC) {
2300 fpscr.ofc = 1;
2301 }
2302 if (flags & FPLIB_UFC) {
2303 underflow = true; //xx Why is this required?
2304 fpscr.ufc = 1;
2305 }
2306 if ((flags & FPLIB_IXC) && !(underflow && fpscr.fz)) {
2307 fpscr.ixc = 1;
2308 }
2309}
2310
2311template <>
2312bool
2313fplibCompareEQ(uint16_t a, uint16_t b, FPSCR &fpscr)
2314{
2315 int flags = 0;
2316 int x = fp16_compare_eq(a, b, modeConv(fpscr), &flags);
2317 set_fpscr(fpscr, flags);
2318 return x;
2319}
2320
2321template <>
2322bool
2323fplibCompareGE(uint16_t a, uint16_t b, FPSCR &fpscr)
2324{
2325 int flags = 0;
2326 int x = fp16_compare_ge(a, b, modeConv(fpscr), &flags);
2327 set_fpscr(fpscr, flags);
2328 return x;
2329}
2330
2331template <>
2332bool
2333fplibCompareGT(uint16_t a, uint16_t b, FPSCR &fpscr)
2334{
2335 int flags = 0;
2336 int x = fp16_compare_gt(a, b, modeConv(fpscr), &flags);
2337 set_fpscr(fpscr, flags);
2338 return x;
2339}
2340
2341template <>
2342bool
2343fplibCompareUN(uint16_t a, uint16_t b, FPSCR &fpscr)
2344{
2345 int flags = 0;
2346 int x = fp16_compare_un(a, b, modeConv(fpscr), &flags);
2347 set_fpscr(fpscr, flags);
2348 return x;
2349}
2350
2351template <>
2352bool
2353fplibCompareEQ(uint32_t a, uint32_t b, FPSCR &fpscr)
2354{
2355 int flags = 0;
2356 int x = fp32_compare_eq(a, b, modeConv(fpscr), &flags);
2357 set_fpscr(fpscr, flags);
2358 return x;
2359}
2360
2361template <>
2362bool
2363fplibCompareGE(uint32_t a, uint32_t b, FPSCR &fpscr)
2364{
2365 int flags = 0;
2366 int x = fp32_compare_ge(a, b, modeConv(fpscr), &flags);
2367 set_fpscr(fpscr, flags);
2368 return x;
2369}
2370
2371template <>
2372bool
2373fplibCompareGT(uint32_t a, uint32_t b, FPSCR &fpscr)
2374{
2375 int flags = 0;
2376 int x = fp32_compare_gt(a, b, modeConv(fpscr), &flags);
2377 set_fpscr(fpscr, flags);
2378 return x;
2379}
2380
2381template <>
2382bool
2383fplibCompareUN(uint32_t a, uint32_t b, FPSCR &fpscr)
2384{
2385 int flags = 0;
2386 int x = fp32_compare_un(a, b, modeConv(fpscr), &flags);
2387 set_fpscr(fpscr, flags);
2388 return x;
2389}
2390
2391template <>
2392bool
2393fplibCompareEQ(uint64_t a, uint64_t b, FPSCR &fpscr)
2394{
2395 int flags = 0;
2396 int x = fp64_compare_eq(a, b, modeConv(fpscr), &flags);
2397 set_fpscr(fpscr, flags);
2398 return x;
2399}
2400
2401template <>
2402bool
2403fplibCompareGE(uint64_t a, uint64_t b, FPSCR &fpscr)
2404{
2405 int flags = 0;
2406 int x = fp64_compare_ge(a, b, modeConv(fpscr), &flags);
2407 set_fpscr(fpscr, flags);
2408 return x;
2409}
2410
2411template <>
2412bool
2413fplibCompareGT(uint64_t a, uint64_t b, FPSCR &fpscr)
2414{
2415 int flags = 0;
2416 int x = fp64_compare_gt(a, b, modeConv(fpscr), &flags);
2417 set_fpscr(fpscr, flags);
2418 return x;
2419}
2420
2421template <>
2422bool
2423fplibCompareUN(uint64_t a, uint64_t b, FPSCR &fpscr)
2424{
2425 int flags = 0;
2426 int x = fp64_compare_un(a, b, modeConv(fpscr), &flags);
2427 set_fpscr(fpscr, flags);
2428 return x;
2429}
2430
2431template <>
2432uint16_t
2433fplibAbs(uint16_t op)
2434{
2435 return op & ~(1ULL << (FP16_BITS - 1));
2436}
2437
2438template <>
2439uint32_t
2440fplibAbs(uint32_t op)
2441{
2442 return op & ~(1ULL << (FP32_BITS - 1));
2443}
2444
2445template <>
2446uint64_t
2447fplibAbs(uint64_t op)
2448{
2449 return op & ~(1ULL << (FP64_BITS - 1));
2450}
2451
2452template <>
2453uint16_t
2454fplibAdd(uint16_t op1, uint16_t op2, FPSCR &fpscr)
2455{
2456 int flags = 0;
2457 uint16_t result = fp16_add(op1, op2, 0, modeConv(fpscr), &flags);
2458 set_fpscr0(fpscr, flags);
2459 return result;
2460}
2461
2462template <>
2463uint32_t
2464fplibAdd(uint32_t op1, uint32_t op2, FPSCR &fpscr)
2465{
2466 int flags = 0;
2467 uint32_t result = fp32_add(op1, op2, 0, modeConv(fpscr), &flags);
2468 set_fpscr0(fpscr, flags);
2469 return result;
2470}
2471
2472template <>
2473uint64_t
2474fplibAdd(uint64_t op1, uint64_t op2, FPSCR &fpscr)
2475{
2476 int flags = 0;
2477 uint64_t result = fp64_add(op1, op2, 0, modeConv(fpscr), &flags);
2478 set_fpscr0(fpscr, flags);
2479 return result;
2480}
2481
2482template <>
2483int
2484fplibCompare(uint16_t op1, uint16_t op2, bool signal_nans, FPSCR &fpscr)
2485{
2486 int mode = modeConv(fpscr);
2487 int flags = 0;
2488 int sgn1, exp1, sgn2, exp2, result;
2489 uint16_t mnt1, mnt2;
2490
2491 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
2492 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
2493
2494 if (fp16_is_NaN(exp1, mnt1) || fp16_is_NaN(exp2, mnt2)) {
2495 result = 3;
2496 if (fp16_is_signalling_NaN(exp1, mnt1) ||
2497 fp16_is_signalling_NaN(exp2, mnt2) || signal_nans)
2498 flags |= FPLIB_IOC;
2499 } else {
2500 if (op1 == op2 || (!mnt1 && !mnt2)) {
2501 result = 6;
2502 } else if (sgn1 != sgn2) {
2503 result = sgn1 ? 8 : 2;
2504 } else if (exp1 != exp2) {
2505 result = sgn1 ^ (exp1 < exp2) ? 8 : 2;
2506 } else {
2507 result = sgn1 ^ (mnt1 < mnt2) ? 8 : 2;
2508 }
2509 }
2510
2511 set_fpscr0(fpscr, flags);
2512
2513 return result;
2514}
2515
2516template <>
2517int
2518fplibCompare(uint32_t op1, uint32_t op2, bool signal_nans, FPSCR &fpscr)
2519{
2520 int mode = modeConv(fpscr);
2521 int flags = 0;
2522 int sgn1, exp1, sgn2, exp2, result;
2523 uint32_t mnt1, mnt2;
2524
2525 fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
2526 fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
2527
2528 if (fp32_is_NaN(exp1, mnt1) || fp32_is_NaN(exp2, mnt2)) {
2529 result = 3;
2530 if (fp32_is_signalling_NaN(exp1, mnt1) ||
2531 fp32_is_signalling_NaN(exp2, mnt2) || signal_nans)
2532 flags |= FPLIB_IOC;
2533 } else {
2534 if (op1 == op2 || (!mnt1 && !mnt2)) {
2535 result = 6;
2536 } else if (sgn1 != sgn2) {
2537 result = sgn1 ? 8 : 2;
2538 } else if (exp1 != exp2) {
2539 result = sgn1 ^ (exp1 < exp2) ? 8 : 2;
2540 } else {
2541 result = sgn1 ^ (mnt1 < mnt2) ? 8 : 2;
2542 }
2543 }
2544
2545 set_fpscr0(fpscr, flags);
2546
2547 return result;
2548}
2549
2550template <>
2551int
2552fplibCompare(uint64_t op1, uint64_t op2, bool signal_nans, FPSCR &fpscr)
2553{
2554 int mode = modeConv(fpscr);
2555 int flags = 0;
2556 int sgn1, exp1, sgn2, exp2, result;
2557 uint64_t mnt1, mnt2;
2558
2559 fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
2560 fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
2561
2562 if (fp64_is_NaN(exp1, mnt1) || fp64_is_NaN(exp2, mnt2)) {
2563 result = 3;
2564 if (fp64_is_signalling_NaN(exp1, mnt1) ||
2565 fp64_is_signalling_NaN(exp2, mnt2) || signal_nans)
2566 flags |= FPLIB_IOC;
2567 } else {
2568 if (op1 == op2 || (!mnt1 && !mnt2)) {
2569 result = 6;
2570 } else if (sgn1 != sgn2) {
2571 result = sgn1 ? 8 : 2;
2572 } else if (exp1 != exp2) {
2573 result = sgn1 ^ (exp1 < exp2) ? 8 : 2;
2574 } else {
2575 result = sgn1 ^ (mnt1 < mnt2) ? 8 : 2;
2576 }
2577 }
2578
2579 set_fpscr0(fpscr, flags);
2580
2581 return result;
2582}
2583
2584static uint16_t
2586{
2587 return fp16_pack(op >> (FP32_BITS - 1), FP16_EXP_INF,
2588 1ULL << (FP16_MANT_BITS - 1) |
2590}
2591
2592static uint16_t
2594{
2595 return fp16_pack(op >> (FP64_BITS - 1), FP16_EXP_INF,
2596 1ULL << (FP16_MANT_BITS - 1) |
2598}
2599
2600static uint32_t
2602{
2603 return fp32_pack(op >> (FP16_BITS - 1), FP32_EXP_INF,
2604 1ULL << (FP32_MANT_BITS - 1) |
2605 (uint32_t)op << (FP32_MANT_BITS - FP16_MANT_BITS));
2606}
2607
2608static uint32_t
2610{
2611 return fp32_pack(op >> (FP64_BITS - 1), FP32_EXP_INF,
2612 1ULL << (FP32_MANT_BITS - 1) |
2614}
2615
2616static uint64_t
2618{
2619 return fp64_pack(op >> (FP16_BITS - 1), FP64_EXP_INF,
2620 1ULL << (FP64_MANT_BITS - 1) |
2621 (uint64_t)op << (FP64_MANT_BITS - FP16_MANT_BITS));
2622}
2623
2624static uint64_t
2626{
2627 return fp64_pack(op >> (FP32_BITS - 1), FP64_EXP_INF,
2628 1ULL << (FP64_MANT_BITS - 1) |
2629 (uint64_t)op << (FP64_MANT_BITS - FP32_MANT_BITS));
2630}
2631
2632static uint16_t
2634{
2635 return fp16_pack(sgn, FP16_EXP_BIAS, 1ULL << (FP16_MANT_BITS - 1));
2636}
2637
2638static uint32_t
2640{
2641 return fp32_pack(sgn, FP32_EXP_BIAS, 1ULL << (FP32_MANT_BITS - 1));
2642}
2643
2644static uint64_t
2646{
2647 return fp64_pack(sgn, FP64_EXP_BIAS, 1ULL << (FP64_MANT_BITS - 1));
2648}
2649
2650static uint16_t
2652{
2653 return fp16_pack(sgn, FP16_EXP_BIAS + 1, 1ULL << (FP16_MANT_BITS - 1));
2654}
2655
2656static uint32_t
2658{
2659 return fp32_pack(sgn, FP32_EXP_BIAS + 1, 1ULL << (FP32_MANT_BITS - 1));
2660}
2661
2662static uint64_t
2664{
2665 return fp64_pack(sgn, FP64_EXP_BIAS + 1, 1ULL << (FP64_MANT_BITS - 1));
2666}
2667
2668static uint16_t
2670{
2671 return fp16_pack(sgn, FP16_EXP_BIAS + 1, 0);
2672}
2673
2674static uint32_t
2676{
2677 return fp32_pack(sgn, FP32_EXP_BIAS + 1, 0);
2678}
2679
2680static uint64_t
2682{
2683 return fp64_pack(sgn, FP64_EXP_BIAS + 1, 0);
2684}
2685
2686template <>
2687uint16_t
2688fplibConvert(uint32_t op, FPRounding rounding, FPSCR &fpscr)
2689{
2690 int mode = modeConv(fpscr);
2691 int flags = 0;
2692 int sgn, exp;
2693 uint32_t mnt;
2694 uint16_t result;
2695
2696 // Unpack floating-point operand optionally with flush-to-zero:
2697 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
2698
2699 bool alt_hp = fpscr.ahp;
2700
2701 if (fp32_is_NaN(exp, mnt)) {
2702 if (alt_hp) {
2703 result = fp16_zero(sgn);
2704 } else if (fpscr.dn) {
2705 result = fp16_defaultNaN();
2706 } else {
2707 result = fp16_FPConvertNaN_32(op);
2708 }
2709 if (!(mnt >> (FP32_MANT_BITS - 1) & 1) || alt_hp) {
2710 flags |= FPLIB_IOC;
2711 }
2712 } else if (exp == FP32_EXP_INF) {
2713 if (alt_hp) {
2714 result = ((uint16_t)sgn << (FP16_BITS - 1) |
2715 ((1ULL << (FP16_BITS - 1)) - 1));
2716 flags |= FPLIB_IOC;
2717 } else {
2718 result = fp16_infinity(sgn);
2719 }
2720 } else if (!mnt) {
2721 result = fp16_zero(sgn);
2722 } else {
2723 result =
2725 mnt >> (FP32_MANT_BITS - FP16_BITS) |
2726 !!(mnt & ((1ULL << (FP32_MANT_BITS - FP16_BITS)) - 1)),
2727 rounding, (mode & 0xf) | alt_hp << 4, &flags);
2728 }
2729
2730 set_fpscr0(fpscr, flags);
2731
2732 return result;
2733}
2734
2735template <>
2736uint16_t
2737fplibConvert(uint64_t op, FPRounding rounding, FPSCR &fpscr)
2738{
2739 int mode = modeConv(fpscr);
2740 int flags = 0;
2741 int sgn, exp;
2742 uint64_t mnt;
2743 uint16_t result;
2744
2745 // Unpack floating-point operand optionally with flush-to-zero:
2746 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
2747
2748 bool alt_hp = fpscr.ahp;
2749
2750 if (fp64_is_NaN(exp, mnt)) {
2751 if (alt_hp) {
2752 result = fp16_zero(sgn);
2753 } else if (fpscr.dn) {
2754 result = fp16_defaultNaN();
2755 } else {
2756 result = fp16_FPConvertNaN_64(op);
2757 }
2758 if (!(mnt >> (FP64_MANT_BITS - 1) & 1) || alt_hp) {
2759 flags |= FPLIB_IOC;
2760 }
2761 } else if (exp == FP64_EXP_INF) {
2762 if (alt_hp) {
2763 result = ((uint16_t)sgn << (FP16_BITS - 1) |
2764 ((1ULL << (FP16_BITS - 1)) - 1));
2765 flags |= FPLIB_IOC;
2766 } else {
2767 result = fp16_infinity(sgn);
2768 }
2769 } else if (!mnt) {
2770 result = fp16_zero(sgn);
2771 } else {
2772 result =
2774 mnt >> (FP64_MANT_BITS - FP16_BITS) |
2775 !!(mnt & ((1ULL << (FP64_MANT_BITS - FP16_BITS)) - 1)),
2776 rounding, (mode & 0xf) | alt_hp << 4, &flags);
2777 }
2778
2779 set_fpscr0(fpscr, flags);
2780
2781 return result;
2782}
2783
2784template <>
2785uint32_t
2786fplibConvert(uint16_t op, FPRounding rounding, FPSCR &fpscr)
2787{
2788 int mode = modeConv(fpscr);
2789 int flags = 0;
2790 int sgn, exp;
2791 uint16_t mnt;
2792 uint32_t result;
2793
2794 // Unpack floating-point operand optionally with flush-to-zero:
2795 fp16_unpack(&sgn, &exp, &mnt, op, mode & 0xf, &flags);
2796
2797 if (fp16_is_NaN(exp, mnt) && !fpscr.ahp) {
2798 if (fpscr.dn) {
2799 result = fp32_defaultNaN();
2800 } else {
2801 result = fp32_FPConvertNaN_16(op);
2802 }
2803 if (!(mnt >> (FP16_MANT_BITS - 1) & 1)) {
2804 flags |= FPLIB_IOC;
2805 }
2806 } else if (exp == FP16_EXP_INF && !fpscr.ahp) {
2807 result = fp32_infinity(sgn);
2808 } else if (!mnt) {
2809 result = fp32_zero(sgn);
2810 } else {
2811 mnt = fp16_normalise(mnt, &exp);
2812 result = fp32_pack(sgn, (exp - FP16_EXP_BIAS +
2814 (uint32_t)mnt << (FP32_MANT_BITS - FP16_BITS + 1));
2815 }
2816
2817 set_fpscr0(fpscr, flags);
2818
2819 return result;
2820}
2821
2822template <>
2823uint32_t
2824fplibConvert(uint64_t op, FPRounding rounding, FPSCR &fpscr)
2825{
2826 int mode = modeConv(fpscr);
2827 int flags = 0;
2828 int sgn, exp;
2829 uint64_t mnt;
2830 uint32_t result;
2831
2832 // Unpack floating-point operand optionally with flush-to-zero:
2833 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
2834
2835 if (fp64_is_NaN(exp, mnt)) {
2836 if (fpscr.dn) {
2837 result = fp32_defaultNaN();
2838 } else {
2839 result = fp32_FPConvertNaN_64(op);
2840 }
2841 if (!(mnt >> (FP64_MANT_BITS - 1) & 1)) {
2842 flags |= FPLIB_IOC;
2843 }
2844 } else if (exp == FP64_EXP_INF) {
2845 result = fp32_infinity(sgn);
2846 } else if (!mnt) {
2847 result = fp32_zero(sgn);
2848 } else {
2849 result =
2851 mnt >> (FP64_MANT_BITS - FP32_BITS) |
2852 !!(mnt & ((1ULL << (FP64_MANT_BITS - FP32_BITS)) - 1)),
2853 rounding, mode, &flags);
2854 }
2855
2856 set_fpscr0(fpscr, flags);
2857
2858 return result;
2859}
2860
2861template <>
2862uint64_t
2863fplibConvert(uint16_t op, FPRounding rounding, FPSCR &fpscr)
2864{
2865 int mode = modeConv(fpscr);
2866 int flags = 0;
2867 int sgn, exp;
2868 uint16_t mnt;
2869 uint64_t result;
2870
2871 // Unpack floating-point operand optionally with flush-to-zero:
2872 fp16_unpack(&sgn, &exp, &mnt, op, mode & 0xf, &flags);
2873
2874 if (fp16_is_NaN(exp, mnt) && !fpscr.ahp) {
2875 if (fpscr.dn) {
2876 result = fp64_defaultNaN();
2877 } else {
2878 result = fp64_FPConvertNaN_16(op);
2879 }
2880 if (!(mnt >> (FP16_MANT_BITS - 1) & 1)) {
2881 flags |= FPLIB_IOC;
2882 }
2883 } else if (exp == FP16_EXP_INF && !fpscr.ahp) {
2884 result = fp64_infinity(sgn);
2885 } else if (!mnt) {
2886 result = fp64_zero(sgn);
2887 } else {
2888 mnt = fp16_normalise(mnt, &exp);
2889 result = fp64_pack(sgn, (exp - FP16_EXP_BIAS +
2891 (uint64_t)mnt << (FP64_MANT_BITS - FP16_BITS + 1));
2892 }
2893
2894 set_fpscr0(fpscr, flags);
2895
2896 return result;
2897}
2898
2899template <>
2900uint64_t
2901fplibConvert(uint32_t op, FPRounding rounding, FPSCR &fpscr)
2902{
2903 int mode = modeConv(fpscr);
2904 int flags = 0;
2905 int sgn, exp;
2906 uint32_t mnt;
2907 uint64_t result;
2908
2909 // Unpack floating-point operand optionally with flush-to-zero:
2910 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
2911
2912 if (fp32_is_NaN(exp, mnt)) {
2913 if (fpscr.dn) {
2914 result = fp64_defaultNaN();
2915 } else {
2916 result = fp64_FPConvertNaN_32(op);
2917 }
2918 if (!(mnt >> (FP32_MANT_BITS - 1) & 1)) {
2919 flags |= FPLIB_IOC;
2920 }
2921 } else if (exp == FP32_EXP_INF) {
2922 result = fp64_infinity(sgn);
2923 } else if (!mnt) {
2924 result = fp64_zero(sgn);
2925 } else {
2926 mnt = fp32_normalise(mnt, &exp);
2927 result = fp64_pack(sgn, (exp - FP32_EXP_BIAS +
2929 (uint64_t)mnt << (FP64_MANT_BITS - FP32_BITS + 1));
2930 }
2931
2932 set_fpscr0(fpscr, flags);
2933
2934 return result;
2935}
2936
2937template <>
2938uint16_t
2939fplibMulAdd(uint16_t addend, uint16_t op1, uint16_t op2, FPSCR &fpscr)
2940{
2941 int flags = 0;
2942 uint16_t result = fp16_muladd(addend, op1, op2, 0, modeConv(fpscr), &flags);
2943 set_fpscr0(fpscr, flags);
2944 return result;
2945}
2946
2947template <>
2948uint32_t
2949fplibMulAdd(uint32_t addend, uint32_t op1, uint32_t op2, FPSCR &fpscr)
2950{
2951 int flags = 0;
2952 uint32_t result = fp32_muladd(addend, op1, op2, 0, modeConv(fpscr), &flags);
2953 set_fpscr0(fpscr, flags);
2954 return result;
2955}
2956
2957template <>
2958uint64_t
2959fplibMulAdd(uint64_t addend, uint64_t op1, uint64_t op2, FPSCR &fpscr)
2960{
2961 int flags = 0;
2962 uint64_t result = fp64_muladd(addend, op1, op2, 0, modeConv(fpscr), &flags);
2963 set_fpscr0(fpscr, flags);
2964 return result;
2965}
2966
2967template <>
2968uint16_t
2969fplibDiv(uint16_t op1, uint16_t op2, FPSCR &fpscr)
2970{
2971 int flags = 0;
2972 uint16_t result = fp16_div(op1, op2, modeConv(fpscr), &flags);
2973 set_fpscr0(fpscr, flags);
2974 return result;
2975}
2976
2977template <>
2978uint32_t
2979fplibDiv(uint32_t op1, uint32_t op2, FPSCR &fpscr)
2980{
2981 int flags = 0;
2982 uint32_t result = fp32_div(op1, op2, modeConv(fpscr), &flags);
2983 set_fpscr0(fpscr, flags);
2984 return result;
2985}
2986
2987template <>
2988uint64_t
2989fplibDiv(uint64_t op1, uint64_t op2, FPSCR &fpscr)
2990{
2991 int flags = 0;
2992 uint64_t result = fp64_div(op1, op2, modeConv(fpscr), &flags);
2993 set_fpscr0(fpscr, flags);
2994 return result;
2995}
2996
2997template <>
2998uint16_t
2999fplibExpA(uint16_t op)
3000{
3001 static uint16_t coeff[32] = {
3002 0x0000,
3003 0x0016,
3004 0x002d,
3005 0x0045,
3006 0x005d,
3007 0x0075,
3008 0x008e,
3009 0x00a8,
3010 0x00c2,
3011 0x00dc,
3012 0x00f8,
3013 0x0114,
3014 0x0130,
3015 0x014d,
3016 0x016b,
3017 0x0189,
3018 0x01a8,
3019 0x01c8,
3020 0x01e8,
3021 0x0209,
3022 0x022b,
3023 0x024e,
3024 0x0271,
3025 0x0295,
3026 0x02ba,
3027 0x02e0,
3028 0x0306,
3029 0x032e,
3030 0x0356,
3031 0x037f,
3032 0x03a9,
3033 0x03d4
3034 };
3035 return ((((op >> 5) & ((1 << FP16_EXP_BITS) - 1)) << FP16_MANT_BITS) |
3036 coeff[op & ((1 << 5) - 1)]);
3037}
3038
3039template <>
3040uint32_t
3041fplibExpA(uint32_t op)
3042{
3043 static uint32_t coeff[64] = {
3044 0x000000,
3045 0x0164d2,
3046 0x02cd87,
3047 0x043a29,
3048 0x05aac3,
3049 0x071f62,
3050 0x08980f,
3051 0x0a14d5,
3052 0x0b95c2,
3053 0x0d1adf,
3054 0x0ea43a,
3055 0x1031dc,
3056 0x11c3d3,
3057 0x135a2b,
3058 0x14f4f0,
3059 0x16942d,
3060 0x1837f0,
3061 0x19e046,
3062 0x1b8d3a,
3063 0x1d3eda,
3064 0x1ef532,
3065 0x20b051,
3066 0x227043,
3067 0x243516,
3068 0x25fed7,
3069 0x27cd94,
3070 0x29a15b,
3071 0x2b7a3a,
3072 0x2d583f,
3073 0x2f3b79,
3074 0x3123f6,
3075 0x3311c4,
3076 0x3504f3,
3077 0x36fd92,
3078 0x38fbaf,
3079 0x3aff5b,
3080 0x3d08a4,
3081 0x3f179a,
3082 0x412c4d,
3083 0x4346cd,
3084 0x45672a,
3085 0x478d75,
3086 0x49b9be,
3087 0x4bec15,
3088 0x4e248c,
3089 0x506334,
3090 0x52a81e,
3091 0x54f35b,
3092 0x5744fd,
3093 0x599d16,
3094 0x5bfbb8,
3095 0x5e60f5,
3096 0x60ccdf,
3097 0x633f89,
3098 0x65b907,
3099 0x68396a,
3100 0x6ac0c7,
3101 0x6d4f30,
3102 0x6fe4ba,
3103 0x728177,
3104 0x75257d,
3105 0x77d0df,
3106 0x7a83b3,
3107 0x7d3e0c
3108 };
3109 return ((((op >> 6) & ((1 << FP32_EXP_BITS) - 1)) << FP32_MANT_BITS) |
3110 coeff[op & ((1 << 6) - 1)]);
3111}
3112
3113template <>
3114uint64_t
3115fplibExpA(uint64_t op)
3116{
3117 static uint64_t coeff[64] = {
3118 0x0000000000000ULL,
3119 0x02c9a3e778061ULL,
3120 0x059b0d3158574ULL,
3121 0x0874518759bc8ULL,
3122 0x0b5586cf9890fULL,
3123 0x0e3ec32d3d1a2ULL,
3124 0x11301d0125b51ULL,
3125 0x1429aaea92de0ULL,
3126 0x172b83c7d517bULL,
3127 0x1a35beb6fcb75ULL,
3128 0x1d4873168b9aaULL,
3129 0x2063b88628cd6ULL,
3130 0x2387a6e756238ULL,
3131 0x26b4565e27cddULL,
3132 0x29e9df51fdee1ULL,
3133 0x2d285a6e4030bULL,
3134 0x306fe0a31b715ULL,
3135 0x33c08b26416ffULL,
3136 0x371a7373aa9cbULL,
3137 0x3a7db34e59ff7ULL,
3138 0x3dea64c123422ULL,
3139 0x4160a21f72e2aULL,
3140 0x44e086061892dULL,
3141 0x486a2b5c13cd0ULL,
3142 0x4bfdad5362a27ULL,
3143 0x4f9b2769d2ca7ULL,
3144 0x5342b569d4f82ULL,
3145 0x56f4736b527daULL,
3146 0x5ab07dd485429ULL,
3147 0x5e76f15ad2148ULL,
3148 0x6247eb03a5585ULL,
3149 0x6623882552225ULL,
3150 0x6a09e667f3bcdULL,
3151 0x6dfb23c651a2fULL,
3152 0x71f75e8ec5f74ULL,
3153 0x75feb564267c9ULL,
3154 0x7a11473eb0187ULL,
3155 0x7e2f336cf4e62ULL,
3156 0x82589994cce13ULL,
3157 0x868d99b4492edULL,
3158 0x8ace5422aa0dbULL,
3159 0x8f1ae99157736ULL,
3160 0x93737b0cdc5e5ULL,
3161 0x97d829fde4e50ULL,
3162 0x9c49182a3f090ULL,
3163 0xa0c667b5de565ULL,
3164 0xa5503b23e255dULL,
3165 0xa9e6b5579fdbfULL,
3166 0xae89f995ad3adULL,
3167 0xb33a2b84f15fbULL,
3168 0xb7f76f2fb5e47ULL,
3169 0xbcc1e904bc1d2ULL,
3170 0xc199bdd85529cULL,
3171 0xc67f12e57d14bULL,
3172 0xcb720dcef9069ULL,
3173 0xd072d4a07897cULL,
3174 0xd5818dcfba487ULL,
3175 0xda9e603db3285ULL,
3176 0xdfc97337b9b5fULL,
3177 0xe502ee78b3ff6ULL,
3178 0xea4afa2a490daULL,
3179 0xefa1bee615a27ULL,
3180 0xf50765b6e4540ULL,
3181 0xfa7c1819e90d8ULL
3182 };
3183 return ((((op >> 6) & ((1 << FP64_EXP_BITS) - 1)) << FP64_MANT_BITS) |
3184 coeff[op & ((1 << 6) - 1)]);
3185}
3186
3187static uint16_t
3188fp16_repack(int sgn, int exp, uint16_t mnt)
3189{
3190 return fp16_pack(sgn, mnt >> FP16_MANT_BITS ? exp : 0, mnt);
3191}
3192
3193static uint32_t
3194fp32_repack(int sgn, int exp, uint32_t mnt)
3195{
3196 return fp32_pack(sgn, mnt >> FP32_MANT_BITS ? exp : 0, mnt);
3197}
3198
3199static uint64_t
3200fp64_repack(int sgn, int exp, uint64_t mnt)
3201{
3202 return fp64_pack(sgn, mnt >> FP64_MANT_BITS ? exp : 0, mnt);
3203}
3204
3205static void
3206fp16_minmaxnum(uint16_t *op1, uint16_t *op2, int sgn)
3207{
3208 // Treat a single quiet-NaN as +Infinity/-Infinity
3209 if (!((uint16_t)~(*op1 << 1) >> FP16_MANT_BITS) &&
3210 (uint16_t)~(*op2 << 1) >> FP16_MANT_BITS)
3211 *op1 = fp16_infinity(sgn);
3212 if (!((uint16_t)~(*op2 << 1) >> FP16_MANT_BITS) &&
3213 (uint16_t)~(*op1 << 1) >> FP16_MANT_BITS)
3214 *op2 = fp16_infinity(sgn);
3215}
3216
3217static void
3218fp32_minmaxnum(uint32_t *op1, uint32_t *op2, int sgn)
3219{
3220 // Treat a single quiet-NaN as +Infinity/-Infinity
3221 if (!((uint32_t)~(*op1 << 1) >> FP32_MANT_BITS) &&
3222 (uint32_t)~(*op2 << 1) >> FP32_MANT_BITS)
3223 *op1 = fp32_infinity(sgn);
3224 if (!((uint32_t)~(*op2 << 1) >> FP32_MANT_BITS) &&
3225 (uint32_t)~(*op1 << 1) >> FP32_MANT_BITS)
3226 *op2 = fp32_infinity(sgn);
3227}
3228
3229static void
3230fp64_minmaxnum(uint64_t *op1, uint64_t *op2, int sgn)
3231{
3232 // Treat a single quiet-NaN as +Infinity/-Infinity
3233 if (!((uint64_t)~(*op1 << 1) >> FP64_MANT_BITS) &&
3234 (uint64_t)~(*op2 << 1) >> FP64_MANT_BITS)
3235 *op1 = fp64_infinity(sgn);
3236 if (!((uint64_t)~(*op2 << 1) >> FP64_MANT_BITS) &&
3237 (uint64_t)~(*op1 << 1) >> FP64_MANT_BITS)
3238 *op2 = fp64_infinity(sgn);
3239}
3240
3241template <>
3242uint16_t
3243fplibMax(uint16_t op1, uint16_t op2, FPSCR &fpscr)
3244{
3245 int mode = modeConv(fpscr);
3246 int flags = 0;
3247 int sgn1, exp1, sgn2, exp2;
3248 uint16_t mnt1, mnt2, x, result;
3249
3250 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3251 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3252
3253 if ((x = fp16_process_NaNs(op1, op2, mode, &flags))) {
3254 result = x;
3255 } else {
3256 result = ((sgn1 != sgn2 ? sgn2 : sgn1 ^ (op1 > op2)) ?
3257 fp16_repack(sgn1, exp1, mnt1) :
3258 fp16_repack(sgn2, exp2, mnt2));
3259 }
3260 set_fpscr0(fpscr, flags);
3261 return result;
3262}
3263
3264template <>
3265uint32_t
3266fplibMax(uint32_t op1, uint32_t op2, FPSCR &fpscr)
3267{
3268 int mode = modeConv(fpscr);
3269 int flags = 0;
3270 int sgn1, exp1, sgn2, exp2;
3271 uint32_t mnt1, mnt2, x, result;
3272
3273 fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3274 fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3275
3276 if ((x = fp32_process_NaNs(op1, op2, mode, &flags))) {
3277 result = x;
3278 } else {
3279 result = ((sgn1 != sgn2 ? sgn2 : sgn1 ^ (op1 > op2)) ?
3280 fp32_repack(sgn1, exp1, mnt1) :
3281 fp32_repack(sgn2, exp2, mnt2));
3282 }
3283 set_fpscr0(fpscr, flags);
3284 return result;
3285}
3286
3287template <>
3288uint64_t
3289fplibMax(uint64_t op1, uint64_t op2, FPSCR &fpscr)
3290{
3291 int mode = modeConv(fpscr);
3292 int flags = 0;
3293 int sgn1, exp1, sgn2, exp2;
3294 uint64_t mnt1, mnt2, x, result;
3295
3296 fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3297 fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3298
3299 if ((x = fp64_process_NaNs(op1, op2, mode, &flags))) {
3300 result = x;
3301 } else {
3302 result = ((sgn1 != sgn2 ? sgn2 : sgn1 ^ (op1 > op2)) ?
3303 fp64_repack(sgn1, exp1, mnt1) :
3304 fp64_repack(sgn2, exp2, mnt2));
3305 }
3306 set_fpscr0(fpscr, flags);
3307 return result;
3308}
3309
3310template <>
3311uint16_t
3312fplibMaxNum(uint16_t op1, uint16_t op2, FPSCR &fpscr)
3313{
3314 fp16_minmaxnum(&op1, &op2, 1);
3315 return fplibMax<uint16_t>(op1, op2, fpscr);
3316}
3317
3318template <>
3319uint32_t
3320fplibMaxNum(uint32_t op1, uint32_t op2, FPSCR &fpscr)
3321{
3322 fp32_minmaxnum(&op1, &op2, 1);
3323 return fplibMax<uint32_t>(op1, op2, fpscr);
3324}
3325
3326template <>
3327uint64_t
3328fplibMaxNum(uint64_t op1, uint64_t op2, FPSCR &fpscr)
3329{
3330 fp64_minmaxnum(&op1, &op2, 1);
3331 return fplibMax<uint64_t>(op1, op2, fpscr);
3332}
3333
3334template <>
3335uint16_t
3336fplibMin(uint16_t op1, uint16_t op2, FPSCR &fpscr)
3337{
3338 int mode = modeConv(fpscr);
3339 int flags = 0;
3340 int sgn1, exp1, sgn2, exp2;
3341 uint16_t mnt1, mnt2, x, result;
3342
3343 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3344 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3345
3346 if ((x = fp16_process_NaNs(op1, op2, mode, &flags))) {
3347 result = x;
3348 } else {
3349 result = ((sgn1 != sgn2 ? sgn1 : sgn1 ^ (op1 < op2)) ?
3350 fp16_repack(sgn1, exp1, mnt1) :
3351 fp16_repack(sgn2, exp2, mnt2));
3352 }
3353 set_fpscr0(fpscr, flags);
3354 return result;
3355}
3356
3357template <>
3358uint32_t
3359fplibMin(uint32_t op1, uint32_t op2, FPSCR &fpscr)
3360{
3361 int mode = modeConv(fpscr);
3362 int flags = 0;
3363 int sgn1, exp1, sgn2, exp2;
3364 uint32_t mnt1, mnt2, x, result;
3365
3366 fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3367 fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3368
3369 if ((x = fp32_process_NaNs(op1, op2, mode, &flags))) {
3370 result = x;
3371 } else {
3372 result = ((sgn1 != sgn2 ? sgn1 : sgn1 ^ (op1 < op2)) ?
3373 fp32_repack(sgn1, exp1, mnt1) :
3374 fp32_repack(sgn2, exp2, mnt2));
3375 }
3376 set_fpscr0(fpscr, flags);
3377 return result;
3378}
3379
3380template <>
3381uint64_t
3382fplibMin(uint64_t op1, uint64_t op2, FPSCR &fpscr)
3383{
3384 int mode = modeConv(fpscr);
3385 int flags = 0;
3386 int sgn1, exp1, sgn2, exp2;
3387 uint64_t mnt1, mnt2, x, result;
3388
3389 fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3390 fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3391
3392 if ((x = fp64_process_NaNs(op1, op2, mode, &flags))) {
3393 result = x;
3394 } else {
3395 result = ((sgn1 != sgn2 ? sgn1 : sgn1 ^ (op1 < op2)) ?
3396 fp64_repack(sgn1, exp1, mnt1) :
3397 fp64_repack(sgn2, exp2, mnt2));
3398 }
3399 set_fpscr0(fpscr, flags);
3400 return result;
3401}
3402
3403template <>
3404uint16_t
3405fplibMinNum(uint16_t op1, uint16_t op2, FPSCR &fpscr)
3406{
3407 fp16_minmaxnum(&op1, &op2, 0);
3408 return fplibMin<uint16_t>(op1, op2, fpscr);
3409}
3410
3411template <>
3412uint32_t
3413fplibMinNum(uint32_t op1, uint32_t op2, FPSCR &fpscr)
3414{
3415 fp32_minmaxnum(&op1, &op2, 0);
3416 return fplibMin<uint32_t>(op1, op2, fpscr);
3417}
3418
3419template <>
3420uint64_t
3421fplibMinNum(uint64_t op1, uint64_t op2, FPSCR &fpscr)
3422{
3423 fp64_minmaxnum(&op1, &op2, 0);
3424 return fplibMin<uint64_t>(op1, op2, fpscr);
3425}
3426
3427template <>
3428uint16_t
3429fplibMul(uint16_t op1, uint16_t op2, FPSCR &fpscr)
3430{
3431 int flags = 0;
3432 uint16_t result = fp16_mul(op1, op2, modeConv(fpscr), &flags);
3433 set_fpscr0(fpscr, flags);
3434 return result;
3435}
3436
3437template <>
3438uint32_t
3439fplibMul(uint32_t op1, uint32_t op2, FPSCR &fpscr)
3440{
3441 int flags = 0;
3442 uint32_t result = fp32_mul(op1, op2, modeConv(fpscr), &flags);
3443 set_fpscr0(fpscr, flags);
3444 return result;
3445}
3446
3447template <>
3448uint64_t
3449fplibMul(uint64_t op1, uint64_t op2, FPSCR &fpscr)
3450{
3451 int flags = 0;
3452 uint64_t result = fp64_mul(op1, op2, modeConv(fpscr), &flags);
3453 set_fpscr0(fpscr, flags);
3454 return result;
3455}
3456
3457template <>
3458uint16_t
3459fplibMulX(uint16_t op1, uint16_t op2, FPSCR &fpscr)
3460{
3461 int mode = modeConv(fpscr);
3462 int flags = 0;
3463 int sgn1, exp1, sgn2, exp2;
3464 uint16_t mnt1, mnt2, result;
3465
3466 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3467 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3468
3469 result = fp16_process_NaNs(op1, op2, mode, &flags);
3470 if (!result) {
3471 if ((exp1 == FP16_EXP_INF && !mnt2) ||
3472 (exp2 == FP16_EXP_INF && !mnt1)) {
3473 result = fp16_FPTwo(sgn1 ^ sgn2);
3474 } else if (exp1 == FP16_EXP_INF || exp2 == FP16_EXP_INF) {
3475 result = fp16_infinity(sgn1 ^ sgn2);
3476 } else if (!mnt1 || !mnt2) {
3477 result = fp16_zero(sgn1 ^ sgn2);
3478 } else {
3479 result = fp16_mul(op1, op2, mode, &flags);
3480 }
3481 }
3482
3483 set_fpscr0(fpscr, flags);
3484
3485 return result;
3486}
3487
3488template <>
3489uint32_t
3490fplibMulX(uint32_t op1, uint32_t op2, FPSCR &fpscr)
3491{
3492 int mode = modeConv(fpscr);
3493 int flags = 0;
3494 int sgn1, exp1, sgn2, exp2;
3495 uint32_t mnt1, mnt2, result;
3496
3497 fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3498 fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3499
3500 result = fp32_process_NaNs(op1, op2, mode, &flags);
3501 if (!result) {
3502 if ((exp1 == FP32_EXP_INF && !mnt2) ||
3503 (exp2 == FP32_EXP_INF && !mnt1)) {
3504 result = fp32_FPTwo(sgn1 ^ sgn2);
3505 } else if (exp1 == FP32_EXP_INF || exp2 == FP32_EXP_INF) {
3506 result = fp32_infinity(sgn1 ^ sgn2);
3507 } else if (!mnt1 || !mnt2) {
3508 result = fp32_zero(sgn1 ^ sgn2);
3509 } else {
3510 result = fp32_mul(op1, op2, mode, &flags);
3511 }
3512 }
3513
3514 set_fpscr0(fpscr, flags);
3515
3516 return result;
3517}
3518
3519template <>
3520uint64_t
3521fplibMulX(uint64_t op1, uint64_t op2, FPSCR &fpscr)
3522{
3523 int mode = modeConv(fpscr);
3524 int flags = 0;
3525 int sgn1, exp1, sgn2, exp2;
3526 uint64_t mnt1, mnt2, result;
3527
3528 fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3529 fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3530
3531 result = fp64_process_NaNs(op1, op2, mode, &flags);
3532 if (!result) {
3533 if ((exp1 == FP64_EXP_INF && !mnt2) ||
3534 (exp2 == FP64_EXP_INF && !mnt1)) {
3535 result = fp64_FPTwo(sgn1 ^ sgn2);
3536 } else if (exp1 == FP64_EXP_INF || exp2 == FP64_EXP_INF) {
3537 result = fp64_infinity(sgn1 ^ sgn2);
3538 } else if (!mnt1 || !mnt2) {
3539 result = fp64_zero(sgn1 ^ sgn2);
3540 } else {
3541 result = fp64_mul(op1, op2, mode, &flags);
3542 }
3543 }
3544
3545 set_fpscr0(fpscr, flags);
3546
3547 return result;
3548}
3549
3550template <>
3551uint16_t
3552fplibNeg(uint16_t op)
3553{
3554 return op ^ 1ULL << (FP16_BITS - 1);
3555}
3556
3557template <>
3558uint32_t
3559fplibNeg(uint32_t op)
3560{
3561 return op ^ 1ULL << (FP32_BITS - 1);
3562}
3563
3564template <>
3565uint64_t
3566fplibNeg(uint64_t op)
3567{
3568 return op ^ 1ULL << (FP64_BITS - 1);
3569}
3570
3571static const uint8_t recip_sqrt_estimate[256] = {
3572 255, 253, 251, 249, 247, 245, 243, 242, 240, 238, 236, 234, 233, 231, 229, 228,
3573 226, 224, 223, 221, 219, 218, 216, 215, 213, 212, 210, 209, 207, 206, 204, 203,
3574 201, 200, 198, 197, 196, 194, 193, 192, 190, 189, 188, 186, 185, 184, 183, 181,
3575 180, 179, 178, 176, 175, 174, 173, 172, 170, 169, 168, 167, 166, 165, 164, 163,
3576 162, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146,
3577 145, 144, 143, 142, 141, 140, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131,
3578 131, 130, 129, 128, 127, 126, 126, 125, 124, 123, 122, 121, 121, 120, 119, 118,
3579 118, 117, 116, 115, 114, 114, 113, 112, 111, 111, 110, 109, 109, 108, 107, 106,
3580 105, 104, 103, 101, 100, 99, 97, 96, 95, 93, 92, 91, 90, 88, 87, 86,
3581 85, 84, 82, 81, 80, 79, 78, 77, 76, 75, 74, 72, 71, 70, 69, 68,
3582 67, 66, 65, 64, 63, 62, 61, 60, 60, 59, 58, 57, 56, 55, 54, 53,
3583 52, 51, 51, 50, 49, 48, 47, 46, 46, 45, 44, 43, 42, 42, 41, 40,
3584 39, 38, 38, 37, 36, 35, 35, 34, 33, 33, 32, 31, 30, 30, 29, 28,
3585 28, 27, 26, 26, 25, 24, 24, 23, 22, 22, 21, 20, 20, 19, 19, 18,
3586 17, 17, 16, 16, 15, 14, 14, 13, 13, 12, 11, 11, 10, 10, 9, 9,
3587 8, 8, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0
3588};
3589
3590template <>
3591uint16_t
3592fplibRSqrtEstimate(uint16_t op, FPSCR &fpscr)
3593{
3594 int mode = modeConv(fpscr);
3595 int flags = 0;
3596 int sgn, exp;
3597 uint16_t mnt, result;
3598
3599 fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
3600
3601 if (fp16_is_NaN(exp, mnt)) {
3602 result = fp16_process_NaN(op, mode, &flags);
3603 } else if (!mnt) {
3604 result = fp16_infinity(sgn);
3605 flags |= FPLIB_DZC;
3606 } else if (sgn) {
3607 result = fp16_defaultNaN();
3608 flags |= FPLIB_IOC;
3609 } else if (exp == FP16_EXP_INF) {
3610 result = fp16_zero(0);
3611 } else {
3612 exp += FP16_EXP_BITS;
3613 mnt = fp16_normalise(mnt, &exp);
3614 mnt = recip_sqrt_estimate[(~exp & 1) << 7 |
3615 (mnt >> (FP16_BITS - 8) & 127)];
3616 result = fp16_pack(0, (3 * FP16_EXP_BIAS - exp - 1) >> 1,
3617 mnt << (FP16_MANT_BITS - 8));
3618 }
3619
3620 set_fpscr0(fpscr, flags);
3621
3622 return result;
3623}
3624
3625template <>
3626uint32_t
3627fplibRSqrtEstimate(uint32_t op, FPSCR &fpscr)
3628{
3629 int mode = modeConv(fpscr);
3630 int flags = 0;
3631 int sgn, exp;
3632 uint32_t mnt, result;
3633
3634 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
3635
3636 if (fp32_is_NaN(exp, mnt)) {
3637 result = fp32_process_NaN(op, mode, &flags);
3638 } else if (!mnt) {
3639 result = fp32_infinity(sgn);
3640 flags |= FPLIB_DZC;
3641 } else if (sgn) {
3642 result = fp32_defaultNaN();
3643 flags |= FPLIB_IOC;
3644 } else if (exp == FP32_EXP_INF) {
3645 result = fp32_zero(0);
3646 } else {
3647 exp += FP32_EXP_BITS;
3648 mnt = fp32_normalise(mnt, &exp);
3649 mnt = recip_sqrt_estimate[(~exp & 1) << 7 |
3650 (mnt >> (FP32_BITS - 8) & 127)];
3651 result = fp32_pack(0, (3 * FP32_EXP_BIAS - exp - 1) >> 1,
3652 mnt << (FP32_MANT_BITS - 8));
3653 }
3654
3655 set_fpscr0(fpscr, flags);
3656
3657 return result;
3658}
3659
3660template <>
3661uint64_t
3662fplibRSqrtEstimate(uint64_t op, FPSCR &fpscr)
3663{
3664 int mode = modeConv(fpscr);
3665 int flags = 0;
3666 int sgn, exp;
3667 uint64_t mnt, result;
3668
3669 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
3670
3671 if (fp64_is_NaN(exp, mnt)) {
3672 result = fp64_process_NaN(op, mode, &flags);
3673 } else if (!mnt) {
3674 result = fp64_infinity(sgn);
3675 flags |= FPLIB_DZC;
3676 } else if (sgn) {
3677 result = fp64_defaultNaN();
3678 flags |= FPLIB_IOC;
3679 } else if (exp == FP64_EXP_INF) {
3680 result = fp32_zero(0);
3681 } else {
3682 exp += FP64_EXP_BITS;
3683 mnt = fp64_normalise(mnt, &exp);
3684 mnt = recip_sqrt_estimate[(~exp & 1) << 7 |
3685 (mnt >> (FP64_BITS - 8) & 127)];
3686 result = fp64_pack(0, (3 * FP64_EXP_BIAS - exp - 1) >> 1,
3687 mnt << (FP64_MANT_BITS - 8));
3688 }
3689
3690 set_fpscr0(fpscr, flags);
3691
3692 return result;
3693}
3694
3695template <>
3696uint16_t
3697fplibRSqrtStepFused(uint16_t op1, uint16_t op2, FPSCR &fpscr)
3698{
3699 int mode = modeConv(fpscr);
3700 int flags = 0;
3701 int sgn1, exp1, sgn2, exp2;
3702 uint16_t mnt1, mnt2, result;
3703
3704 op1 = fplibNeg<uint16_t>(op1);
3705 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3706 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3707
3708 result = fp16_process_NaNs(op1, op2, mode, &flags);
3709 if (!result) {
3710 if ((exp1 == FP16_EXP_INF && !mnt2) ||
3711 (exp2 == FP16_EXP_INF && !mnt1)) {
3712 result = fp16_FPOnePointFive(0);
3713 } else if (exp1 == FP16_EXP_INF || exp2 == FP16_EXP_INF) {
3714 result = fp16_infinity(sgn1 ^ sgn2);
3715 } else {
3716 result = fp16_muladd(fp16_FPThree(0), op1, op2, -1, mode, &flags);
3717 }
3718 }
3719
3720 set_fpscr0(fpscr, flags);
3721
3722 return result;
3723}
3724
3725template <>
3726uint32_t
3727fplibRSqrtStepFused(uint32_t op1, uint32_t op2, FPSCR &fpscr)
3728{
3729 int mode = modeConv(fpscr);
3730 int flags = 0;
3731 int sgn1, exp1, sgn2, exp2;
3732 uint32_t mnt1, mnt2, result;
3733
3734 op1 = fplibNeg<uint32_t>(op1);
3735 fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3736 fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3737
3738 result = fp32_process_NaNs(op1, op2, mode, &flags);
3739 if (!result) {
3740 if ((exp1 == FP32_EXP_INF && !mnt2) ||
3741 (exp2 == FP32_EXP_INF && !mnt1)) {
3742 result = fp32_FPOnePointFive(0);
3743 } else if (exp1 == FP32_EXP_INF || exp2 == FP32_EXP_INF) {
3744 result = fp32_infinity(sgn1 ^ sgn2);
3745 } else {
3746 result = fp32_muladd(fp32_FPThree(0), op1, op2, -1, mode, &flags);
3747 }
3748 }
3749
3750 set_fpscr0(fpscr, flags);
3751
3752 return result;
3753}
3754
3755template <>
3756uint64_t
3757fplibRSqrtStepFused(uint64_t op1, uint64_t op2, FPSCR &fpscr)
3758{
3759 int mode = modeConv(fpscr);
3760 int flags = 0;
3761 int sgn1, exp1, sgn2, exp2;
3762 uint64_t mnt1, mnt2, result;
3763
3764 op1 = fplibNeg<uint64_t>(op1);
3765 fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3766 fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3767
3768 result = fp64_process_NaNs(op1, op2, mode, &flags);
3769 if (!result) {
3770 if ((exp1 == FP64_EXP_INF && !mnt2) ||
3771 (exp2 == FP64_EXP_INF && !mnt1)) {
3772 result = fp64_FPOnePointFive(0);
3773 } else if (exp1 == FP64_EXP_INF || exp2 == FP64_EXP_INF) {
3774 result = fp64_infinity(sgn1 ^ sgn2);
3775 } else {
3776 result = fp64_muladd(fp64_FPThree(0), op1, op2, -1, mode, &flags);
3777 }
3778 }
3779
3780 set_fpscr0(fpscr, flags);
3781
3782 return result;
3783}
3784
3785template <>
3786uint16_t
3787fplibRecipEstimate(uint16_t op, FPSCR &fpscr)
3788{
3789 int mode = modeConv(fpscr);
3790 int flags = 0;
3791 int sgn, exp;
3792 uint16_t mnt, result;
3793
3794 fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
3795
3796 if (fp16_is_NaN(exp, mnt)) {
3797 result = fp16_process_NaN(op, mode, &flags);
3798 } else if (exp == FP16_EXP_INF) {
3799 result = fp16_zero(sgn);
3800 } else if (!mnt) {
3801 result = fp16_infinity(sgn);
3802 flags |= FPLIB_DZC;
3803 } else if (!((uint16_t)(op << 1) >> (FP16_MANT_BITS - 1))) {
3804 bool overflow_to_inf = false;
3805 switch (FPCRRounding(fpscr)) {
3806 case FPRounding_TIEEVEN:
3807 overflow_to_inf = true;
3808 break;
3809 case FPRounding_POSINF:
3810 overflow_to_inf = !sgn;
3811 break;
3812 case FPRounding_NEGINF:
3813 overflow_to_inf = sgn;
3814 break;
3815 case FPRounding_ZERO:
3816 overflow_to_inf = false;
3817 break;
3818 default:
3819 panic("Unrecognized FP rounding mode");
3820 }
3821 result = overflow_to_inf ? fp16_infinity(sgn) : fp16_max_normal(sgn);
3822 flags |= FPLIB_OFC | FPLIB_IXC;
3823 } else if (fpscr.fz16 && exp >= 2 * FP16_EXP_BIAS - 1) {
3824 result = fp16_zero(sgn);
3825 flags |= FPLIB_UFC;
3826 } else {
3827 exp += FP16_EXP_BITS;
3828 mnt = fp16_normalise(mnt, &exp);
3829 int result_exp = 2 * FP16_EXP_BIAS - 1 - exp;
3830 uint16_t fraction = (((uint32_t)1 << 19) /
3831 (mnt >> (FP16_BITS - 10) | 1) + 1) >> 1;
3832 fraction <<= FP16_MANT_BITS - 8;
3833 if (result_exp == 0) {
3834 fraction >>= 1;
3835 } else if (result_exp == -1) {
3836 fraction >>= 2;
3837 result_exp = 0;
3838 }
3839 result = fp16_pack(sgn, result_exp, fraction);
3840 }
3841
3842 set_fpscr0(fpscr, flags);
3843
3844 return result;
3845}
3846
3847template <>
3848uint32_t
3849fplibRecipEstimate(uint32_t op, FPSCR &fpscr)
3850{
3851 int mode = modeConv(fpscr);
3852 int flags = 0;
3853 int sgn, exp;
3854 uint32_t mnt, result;
3855
3856 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
3857
3858 if (fp32_is_NaN(exp, mnt)) {
3859 result = fp32_process_NaN(op, mode, &flags);
3860 } else if (exp == FP32_EXP_INF) {
3861 result = fp32_zero(sgn);
3862 } else if (!mnt) {
3863 result = fp32_infinity(sgn);
3864 flags |= FPLIB_DZC;
3865 } else if (!((uint32_t)(op << 1) >> (FP32_MANT_BITS - 1))) {
3866 bool overflow_to_inf = false;
3867 switch (FPCRRounding(fpscr)) {
3868 case FPRounding_TIEEVEN:
3869 overflow_to_inf = true;
3870 break;
3871 case FPRounding_POSINF:
3872 overflow_to_inf = !sgn;
3873 break;
3874 case FPRounding_NEGINF:
3875 overflow_to_inf = sgn;
3876 break;
3877 case FPRounding_ZERO:
3878 overflow_to_inf = false;
3879 break;
3880 default:
3881 panic("Unrecognized FP rounding mode");
3882 }
3883 result = overflow_to_inf ? fp32_infinity(sgn) : fp32_max_normal(sgn);
3884 flags |= FPLIB_OFC | FPLIB_IXC;
3885 } else if (fpscr.fz && exp >= 2 * FP32_EXP_BIAS - 1) {
3886 result = fp32_zero(sgn);
3887 flags |= FPLIB_UFC;
3888 } else {
3889 exp += FP32_EXP_BITS;
3890 mnt = fp32_normalise(mnt, &exp);
3891 int result_exp = 2 * FP32_EXP_BIAS - 1 - exp;
3892 uint32_t fraction = (((uint32_t)1 << 19) /
3893 (mnt >> (FP32_BITS - 10) | 1) + 1) >> 1;
3894 fraction <<= FP32_MANT_BITS - 8;
3895 if (result_exp == 0) {
3896 fraction >>= 1;
3897 } else if (result_exp == -1) {
3898 fraction >>= 2;
3899 result_exp = 0;
3900 }
3901 result = fp32_pack(sgn, result_exp, fraction);
3902 }
3903
3904 set_fpscr0(fpscr, flags);
3905
3906 return result;
3907}
3908
3909template <>
3910uint64_t
3911fplibRecipEstimate(uint64_t op, FPSCR &fpscr)
3912{
3913 int mode = modeConv(fpscr);
3914 int flags = 0;
3915 int sgn, exp;
3916 uint64_t mnt, result;
3917
3918 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
3919
3920 if (fp64_is_NaN(exp, mnt)) {
3921 result = fp64_process_NaN(op, mode, &flags);
3922 } else if (exp == FP64_EXP_INF) {
3923 result = fp64_zero(sgn);
3924 } else if (!mnt) {
3925 result = fp64_infinity(sgn);
3926 flags |= FPLIB_DZC;
3927 } else if (!((uint64_t)(op << 1) >> (FP64_MANT_BITS - 1))) {
3928 bool overflow_to_inf = false;
3929 switch (FPCRRounding(fpscr)) {
3930 case FPRounding_TIEEVEN:
3931 overflow_to_inf = true;
3932 break;
3933 case FPRounding_POSINF:
3934 overflow_to_inf = !sgn;
3935 break;
3936 case FPRounding_NEGINF:
3937 overflow_to_inf = sgn;
3938 break;
3939 case FPRounding_ZERO:
3940 overflow_to_inf = false;
3941 break;
3942 default:
3943 panic("Unrecognized FP rounding mode");
3944 }
3945 result = overflow_to_inf ? fp64_infinity(sgn) : fp64_max_normal(sgn);
3946 flags |= FPLIB_OFC | FPLIB_IXC;
3947 } else if (fpscr.fz && exp >= 2 * FP64_EXP_BIAS - 1) {
3948 result = fp64_zero(sgn);
3949 flags |= FPLIB_UFC;
3950 } else {
3951 exp += FP64_EXP_BITS;
3952 mnt = fp64_normalise(mnt, &exp);
3953 int result_exp = 2 * FP64_EXP_BIAS - 1 - exp;
3954 uint64_t fraction = (((uint32_t)1 << 19) /
3955 (mnt >> (FP64_BITS - 10) | 1) + 1) >> 1;
3956 fraction <<= FP64_MANT_BITS - 8;
3957 if (result_exp == 0) {
3958 fraction >>= 1;
3959 } else if (result_exp == -1) {
3960 fraction >>= 2;
3961 result_exp = 0;
3962 }
3963 result = fp64_pack(sgn, result_exp, fraction);
3964 }
3965
3966 set_fpscr0(fpscr, flags);
3967
3968 return result;
3969}
3970
3971template <>
3972uint16_t
3973fplibRecipStepFused(uint16_t op1, uint16_t op2, FPSCR &fpscr)
3974{
3975 int mode = modeConv(fpscr);
3976 int flags = 0;
3977 int sgn1, exp1, sgn2, exp2;
3978 uint16_t mnt1, mnt2, result;
3979
3980 op1 = fplibNeg<uint16_t>(op1);
3981 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3982 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3983
3984 result = fp16_process_NaNs(op1, op2, mode, &flags);
3985 if (!result) {
3986 if ((exp1 == FP16_EXP_INF && !mnt2) ||
3987 (exp2 == FP16_EXP_INF && !mnt1)) {
3988 result = fp16_FPTwo(0);
3989 } else if (exp1 == FP16_EXP_INF || exp2 == FP16_EXP_INF) {
3990 result = fp16_infinity(sgn1 ^ sgn2);
3991 } else {
3992 result = fp16_muladd(fp16_FPTwo(0), op1, op2, 0, mode, &flags);
3993 }
3994 }
3995
3996 set_fpscr0(fpscr, flags);
3997
3998 return result;
3999}
4000
4001template <>
4002uint32_t
4003fplibRecipStepFused(uint32_t op1, uint32_t op2, FPSCR &fpscr)
4004{
4005 int mode = modeConv(fpscr);
4006 int flags = 0;
4007 int sgn1, exp1, sgn2, exp2;
4008 uint32_t mnt1, mnt2, result;
4009
4010 op1 = fplibNeg<uint32_t>(op1);
4011 fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
4012 fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
4013
4014 result = fp32_process_NaNs(op1, op2, mode, &flags);
4015 if (!result) {
4016 if ((exp1 == FP32_EXP_INF && !mnt2) ||
4017 (exp2 == FP32_EXP_INF && !mnt1)) {
4018 result = fp32_FPTwo(0);
4019 } else if (exp1 == FP32_EXP_INF || exp2 == FP32_EXP_INF) {
4020 result = fp32_infinity(sgn1 ^ sgn2);
4021 } else {
4022 result = fp32_muladd(fp32_FPTwo(0), op1, op2, 0, mode, &flags);
4023 }
4024 }
4025
4026 set_fpscr0(fpscr, flags);
4027
4028 return result;
4029}
4030
4031template <>
4032uint64_t
4033fplibRecipStepFused(uint64_t op1, uint64_t op2, FPSCR &fpscr)
4034{
4035 int mode = modeConv(fpscr);
4036 int flags = 0;
4037 int sgn1, exp1, sgn2, exp2;
4038 uint64_t mnt1, mnt2, result;
4039
4040 op1 = fplibNeg<uint64_t>(op1);
4041 fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
4042 fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
4043
4044 result = fp64_process_NaNs(op1, op2, mode, &flags);
4045 if (!result) {
4046 if ((exp1 == FP64_EXP_INF && !mnt2) ||
4047 (exp2 == FP64_EXP_INF && !mnt1)) {
4048 result = fp64_FPTwo(0);
4049 } else if (exp1 == FP64_EXP_INF || exp2 == FP64_EXP_INF) {
4050 result = fp64_infinity(sgn1 ^ sgn2);
4051 } else {
4052 result = fp64_muladd(fp64_FPTwo(0), op1, op2, 0, mode, &flags);
4053 }
4054 }
4055
4056 set_fpscr0(fpscr, flags);
4057
4058 return result;
4059}
4060
4061template <>
4062uint16_t
4063fplibRecpX(uint16_t op, FPSCR &fpscr)
4064{
4065 int mode = modeConv(fpscr);
4066 int flags = 0;
4067 int sgn, exp;
4068 uint16_t mnt, result;
4069
4070 fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
4071
4072 if (fp16_is_NaN(exp, mnt)) {
4073 result = fp16_process_NaN(op, mode, &flags);
4074 }
4075 else {
4076 if (!mnt) { // Zero and denormals
4077 result = fp16_pack(sgn, FP16_EXP_INF - 1, 0);
4078 } else { // Infinities and normals
4079 result = fp16_pack(sgn, exp ^ FP16_EXP_INF, 0);
4080 }
4081 }
4082
4083 set_fpscr0(fpscr, flags);
4084
4085 return result;
4086}
4087
4088template <>
4089uint32_t
4090fplibRecpX(uint32_t op, FPSCR &fpscr)
4091{
4092 int mode = modeConv(fpscr);
4093 int flags = 0;
4094 int sgn, exp;
4095 uint32_t mnt, result;
4096
4097 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
4098
4099 if (fp32_is_NaN(exp, mnt)) {
4100 result = fp32_process_NaN(op, mode, &flags);
4101 }
4102 else {
4103 if (!mnt) { // Zero and denormals
4104 result = fp32_pack(sgn, FP32_EXP_INF - 1, 0);
4105 } else { // Infinities and normals
4106 result = fp32_pack(sgn, exp ^ FP32_EXP_INF, 0);
4107 }
4108 }
4109
4110 set_fpscr0(fpscr, flags);
4111
4112 return result;
4113}
4114
4115template <>
4116uint64_t
4117fplibRecpX(uint64_t op, FPSCR &fpscr)
4118{
4119 int mode = modeConv(fpscr);
4120 int flags = 0;
4121 int sgn, exp;
4122 uint64_t mnt, result;
4123
4124 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
4125
4126 if (fp64_is_NaN(exp, mnt)) {
4127 result = fp64_process_NaN(op, mode, &flags);
4128 }
4129 else {
4130 if (!mnt) { // Zero and denormals
4131 result = fp64_pack(sgn, FP64_EXP_INF - 1, 0);
4132 } else { // Infinities and normals
4133 result = fp64_pack(sgn, exp ^ FP64_EXP_INF, 0);
4134 }
4135 }
4136
4137 set_fpscr0(fpscr, flags);
4138
4139 return result;
4140}
4141
4142template <>
4143uint16_t
4144fplibRoundInt(uint16_t op, FPRounding rounding, bool exact, FPSCR &fpscr)
4145{
4146 int expint = FP16_EXP_BIAS + FP16_MANT_BITS;
4147 int mode = modeConv(fpscr);
4148 int flags = 0;
4149 int sgn, exp;
4150 uint16_t mnt, result;
4151
4152 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
4153 fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
4154
4155 // Handle NaNs, infinities and zeroes:
4156 if (fp16_is_NaN(exp, mnt)) {
4157 result = fp16_process_NaN(op, mode, &flags);
4158 } else if (exp == FP16_EXP_INF) {
4159 result = fp16_infinity(sgn);
4160 } else if (!mnt) {
4161 result = fp16_zero(sgn);
4162 } else if (exp >= expint) {
4163 // There are no fractional bits
4164 result = op;
4165 } else {
4166 // Truncate towards zero:
4167 uint16_t x = expint - exp >= FP16_BITS ? 0 : mnt >> (expint - exp);
4168 int err = exp < expint - FP16_BITS ? 1 :
4169 ((mnt << 1 >> (expint - exp - 1) & 3) |
4170 ((uint16_t)(mnt << 2 << (FP16_BITS + exp - expint)) != 0));
4171 switch (rounding) {
4172 case FPRounding_TIEEVEN:
4173 x += (err == 3 || (err == 2 && (x & 1)));
4174 break;
4175 case FPRounding_POSINF:
4176 x += err && !sgn;
4177 break;
4178 case FPRounding_NEGINF:
4179 x += err && sgn;
4180 break;
4181 case FPRounding_ZERO:
4182 break;
4183 case FPRounding_TIEAWAY:
4184 x += err >> 1;
4185 break;
4186 default:
4187 panic("Unrecognized FP rounding mode");
4188 }
4189
4190 if (x == 0) {
4191 result = fp16_zero(sgn);
4192 } else {
4193 exp = expint;
4194 mnt = fp16_normalise(x, &exp);
4195 result = fp16_pack(sgn, exp + FP16_EXP_BITS, mnt >> FP16_EXP_BITS);
4196 }
4197
4198 if (err && exact)
4199 flags |= FPLIB_IXC;
4200 }
4201
4202 set_fpscr0(fpscr, flags);
4203
4204 return result;
4205}
4206
4207template <>
4208uint32_t
4209fplibRoundInt(uint32_t op, FPRounding rounding, bool exact, FPSCR &fpscr)
4210{
4211 int expint = FP32_EXP_BIAS + FP32_MANT_BITS;
4212 int mode = modeConv(fpscr);
4213 int flags = 0;
4214 int sgn, exp;
4215 uint32_t mnt, result;
4216
4217 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
4218 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
4219
4220 // Handle NaNs, infinities and zeroes:
4221 if (fp32_is_NaN(exp, mnt)) {
4222 result = fp32_process_NaN(op, mode, &flags);
4223 } else if (exp == FP32_EXP_INF) {
4224 result = fp32_infinity(sgn);
4225 } else if (!mnt) {
4226 result = fp32_zero(sgn);
4227 } else if (exp >= expint) {
4228 // There are no fractional bits
4229 result = op;
4230 } else {
4231 // Truncate towards zero:
4232 uint32_t x = expint - exp >= FP32_BITS ? 0 : mnt >> (expint - exp);
4233 int err = exp < expint - FP32_BITS ? 1 :
4234 ((mnt << 1 >> (expint - exp - 1) & 3) |
4235 ((uint32_t)(mnt << 2 << (FP32_BITS + exp - expint)) != 0));
4236 switch (rounding) {
4237 case FPRounding_TIEEVEN:
4238 x += (err == 3 || (err == 2 && (x & 1)));
4239 break;
4240 case FPRounding_POSINF:
4241 x += err && !sgn;
4242 break;
4243 case FPRounding_NEGINF:
4244 x += err && sgn;
4245 break;
4246 case FPRounding_ZERO:
4247 break;
4248 case FPRounding_TIEAWAY:
4249 x += err >> 1;
4250 break;
4251 default:
4252 panic("Unrecognized FP rounding mode");
4253 }
4254
4255 if (x == 0) {
4256 result = fp32_zero(sgn);
4257 } else {
4258 exp = expint;
4259 mnt = fp32_normalise(x, &exp);
4260 result = fp32_pack(sgn, exp + FP32_EXP_BITS, mnt >> FP32_EXP_BITS);
4261 }
4262
4263 if (err && exact)
4264 flags |= FPLIB_IXC;
4265 }
4266
4267 set_fpscr0(fpscr, flags);
4268
4269 return result;
4270}
4271
4272template <>
4273uint64_t
4274fplibRoundInt(uint64_t op, FPRounding rounding, bool exact, FPSCR &fpscr)
4275{
4276 int expint = FP64_EXP_BIAS + FP64_MANT_BITS;
4277 int mode = modeConv(fpscr);
4278 int flags = 0;
4279 int sgn, exp;
4280 uint64_t mnt, result;
4281
4282 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
4283 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
4284
4285 // Handle NaNs, infinities and zeroes:
4286 if (fp64_is_NaN(exp, mnt)) {
4287 result = fp64_process_NaN(op, mode, &flags);
4288 } else if (exp == FP64_EXP_INF) {
4289 result = fp64_infinity(sgn);
4290 } else if (!mnt) {
4291 result = fp64_zero(sgn);
4292 } else if (exp >= expint) {
4293 // There are no fractional bits
4294 result = op;
4295 } else {
4296 // Truncate towards zero:
4297 uint64_t x = expint - exp >= FP64_BITS ? 0 : mnt >> (expint - exp);
4298 int err = exp < expint - FP64_BITS ? 1 :
4299 ((mnt << 1 >> (expint - exp - 1) & 3) |
4300 ((uint64_t)(mnt << 2 << (FP64_BITS + exp - expint)) != 0));
4301 switch (rounding) {
4302 case FPRounding_TIEEVEN:
4303 x += (err == 3 || (err == 2 && (x & 1)));
4304 break;
4305 case FPRounding_POSINF:
4306 x += err && !sgn;
4307 break;
4308 case FPRounding_NEGINF:
4309 x += err && sgn;
4310 break;
4311 case FPRounding_ZERO:
4312 break;
4313 case FPRounding_TIEAWAY:
4314 x += err >> 1;
4315 break;
4316 default:
4317 panic("Unrecognized FP rounding mode");
4318 }
4319
4320 if (x == 0) {
4321 result = fp64_zero(sgn);
4322 } else {
4323 exp = expint;
4324 mnt = fp64_normalise(x, &exp);
4325 result = fp64_pack(sgn, exp + FP64_EXP_BITS, mnt >> FP64_EXP_BITS);
4326 }
4327
4328 if (err && exact)
4329 flags |= FPLIB_IXC;
4330 }
4331
4332 set_fpscr0(fpscr, flags);
4333
4334 return result;
4335}
4336
4337template <>
4338uint16_t
4339fplibScale(uint16_t op1, uint16_t op2, FPSCR &fpscr)
4340{
4341 int flags = 0;
4342 uint16_t result = fp16_scale(op1, (int16_t)op2, modeConv(fpscr), &flags);
4343 set_fpscr0(fpscr, flags);
4344 return result;
4345}
4346
4347template <>
4348uint32_t
4349fplibScale(uint32_t op1, uint32_t op2, FPSCR &fpscr)
4350{
4351 int flags = 0;
4352 uint32_t result = fp32_scale(op1, (int32_t)op2, modeConv(fpscr), &flags);
4353 set_fpscr0(fpscr, flags);
4354 return result;
4355}
4356
4357template <>
4358uint64_t
4359fplibScale(uint64_t op1, uint64_t op2, FPSCR &fpscr)
4360{
4361 int flags = 0;
4362 uint64_t result = fp64_scale(op1, (int64_t)op2, modeConv(fpscr), &flags);
4363 set_fpscr0(fpscr, flags);
4364 return result;
4365}
4366
4367template <>
4368uint16_t
4369fplibSqrt(uint16_t op, FPSCR &fpscr)
4370{
4371 int flags = 0;
4372 uint16_t result = fp16_sqrt(op, modeConv(fpscr), &flags);
4373 set_fpscr0(fpscr, flags);
4374 return result;
4375}
4376
4377template <>
4378uint32_t
4379fplibSqrt(uint32_t op, FPSCR &fpscr)
4380{
4381 int flags = 0;
4382 uint32_t result = fp32_sqrt(op, modeConv(fpscr), &flags);
4383 set_fpscr0(fpscr, flags);
4384 return result;
4385}
4386
4387template <>
4388uint64_t
4389fplibSqrt(uint64_t op, FPSCR &fpscr)
4390{
4391 int flags = 0;
4392 uint64_t result = fp64_sqrt(op, modeConv(fpscr), &flags);
4393 set_fpscr0(fpscr, flags);
4394 return result;
4395}
4396
4397template <>
4398uint16_t
4399fplibSub(uint16_t op1, uint16_t op2, FPSCR &fpscr)
4400{
4401 int flags = 0;
4402 uint16_t result = fp16_add(op1, op2, 1, modeConv(fpscr), &flags);
4403 set_fpscr0(fpscr, flags);
4404 return result;
4405}
4406
4407template <>
4408uint32_t
4409fplibSub(uint32_t op1, uint32_t op2, FPSCR &fpscr)
4410{
4411 int flags = 0;
4412 uint32_t result = fp32_add(op1, op2, 1, modeConv(fpscr), &flags);
4413 set_fpscr0(fpscr, flags);
4414 return result;
4415}
4416
4417template <>
4418uint64_t
4419fplibSub(uint64_t op1, uint64_t op2, FPSCR &fpscr)
4420{
4421 int flags = 0;
4422 uint64_t result = fp64_add(op1, op2, 1, modeConv(fpscr), &flags);
4423 set_fpscr0(fpscr, flags);
4424 return result;
4425}
4426
4427template <>
4428uint16_t
4429fplibTrigMulAdd(uint8_t coeff_index, uint16_t op1, uint16_t op2, FPSCR &fpscr)
4430{
4431 static uint16_t coeff[2][8] = {
4432 {
4433 0x3c00,
4434 0xb155,
4435 0x2030,
4436 0x0000,
4437 0x0000,
4438 0x0000,
4439 0x0000,
4440 0x0000,
4441 },
4442 {
4443 0x3c00,
4444 0xb800,
4445 0x293a,
4446 0x0000,
4447 0x0000,
4448 0x0000,
4449 0x0000,
4450 0x0000
4451 }
4452 };
4453 int flags = 0;
4454 uint16_t result =
4455 fp16_muladd(coeff[op2 >> (FP16_BITS - 1)][coeff_index], op1,
4456 fplibAbs(op2), 0, modeConv(fpscr), &flags);
4457 set_fpscr0(fpscr, flags);
4458 return result;
4459}
4460
4461template <>
4462uint32_t
4463fplibTrigMulAdd(uint8_t coeff_index, uint32_t op1, uint32_t op2, FPSCR &fpscr)
4464{
4465 static uint32_t coeff[2][8] = {
4466 {
4467 0x3f800000,
4468 0xbe2aaaab,
4469 0x3c088886,
4470 0xb95008b9,
4471 0x36369d6d,
4472 0x00000000,
4473 0x00000000,
4474 0x00000000
4475 },
4476 {
4477 0x3f800000,
4478 0xbf000000,
4479 0x3d2aaaa6,
4480 0xbab60705,
4481 0x37cd37cc,
4482 0x00000000,
4483 0x00000000,
4484 0x00000000
4485 }
4486 };
4487 int flags = 0;
4488 uint32_t result =
4489 fp32_muladd(coeff[op2 >> (FP32_BITS - 1)][coeff_index], op1,
4490 fplibAbs(op2), 0, modeConv(fpscr), &flags);
4491 set_fpscr0(fpscr, flags);
4492 return result;
4493}
4494
4495template <>
4496uint64_t
4497fplibTrigMulAdd(uint8_t coeff_index, uint64_t op1, uint64_t op2, FPSCR &fpscr)
4498{
4499 static uint64_t coeff[2][8] = {
4500 {
4501 0x3ff0000000000000ULL,
4502 0xbfc5555555555543ULL,
4503 0x3f8111111110f30cULL,
4504 0xbf2a01a019b92fc6ULL,
4505 0x3ec71de351f3d22bULL,
4506 0xbe5ae5e2b60f7b91ULL,
4507 0x3de5d8408868552fULL,
4508 0x0000000000000000ULL
4509 },
4510 {
4511 0x3ff0000000000000ULL,
4512 0xbfe0000000000000ULL,
4513 0x3fa5555555555536ULL,
4514 0xbf56c16c16c13a0bULL,
4515 0x3efa01a019b1e8d8ULL,
4516 0xbe927e4f7282f468ULL,
4517 0x3e21ee96d2641b13ULL,
4518 0xbda8f76380fbb401ULL
4519 }
4520 };
4521 int flags = 0;
4522 uint64_t result =
4523 fp64_muladd(coeff[op2 >> (FP64_BITS - 1)][coeff_index], op1,
4524 fplibAbs(op2), 0, modeConv(fpscr), &flags);
4525 set_fpscr0(fpscr, flags);
4526 return result;
4527}
4528
4529template <>
4530uint16_t
4531fplibTrigSMul(uint16_t op1, uint16_t op2, FPSCR &fpscr)
4532{
4533 int flags = 0;
4534 int sgn, exp;
4535 uint16_t mnt;
4536
4537 int mode = modeConv(fpscr);
4538 uint16_t result = fp16_mul(op1, op1, mode, &flags);
4539 set_fpscr0(fpscr, flags);
4540
4541 fp16_unpack(&sgn, &exp, &mnt, result, mode, &flags);
4542 if (!fp16_is_NaN(exp, mnt)) {
4543 result = (result & ~(1ULL << (FP16_BITS - 1))) |
4544 op2 << (FP16_BITS - 1);
4545 }
4546 return result;
4547}
4548
4549template <>
4550uint32_t
4551fplibTrigSMul(uint32_t op1, uint32_t op2, FPSCR &fpscr)
4552{
4553 int flags = 0;
4554 int sgn, exp;
4555 uint32_t mnt;
4556
4557 int mode = modeConv(fpscr);
4558 uint32_t result = fp32_mul(op1, op1, mode, &flags);
4559 set_fpscr0(fpscr, flags);
4560
4561 fp32_unpack(&sgn, &exp, &mnt, result, mode, &flags);
4562 if (!fp32_is_NaN(exp, mnt)) {
4563 result = (result & ~(1ULL << (FP32_BITS - 1))) | op2 << (FP32_BITS - 1);
4564 }
4565 return result;
4566}
4567
4568template <>
4569uint64_t
4570fplibTrigSMul(uint64_t op1, uint64_t op2, FPSCR &fpscr)
4571{
4572 int flags = 0;
4573 int sgn, exp;
4574 uint64_t mnt;
4575
4576 int mode = modeConv(fpscr);
4577 uint64_t result = fp64_mul(op1, op1, mode, &flags);
4578 set_fpscr0(fpscr, flags);
4579
4580 fp64_unpack(&sgn, &exp, &mnt, result, mode, &flags);
4581 if (!fp64_is_NaN(exp, mnt)) {
4582 result = (result & ~(1ULL << (FP64_BITS - 1))) | op2 << (FP64_BITS - 1);
4583 }
4584 return result;
4585}
4586
4587template <>
4588uint16_t
4589fplibTrigSSel(uint16_t op1, uint16_t op2, FPSCR &fpscr)
4590{
4591 static constexpr uint16_t fpOne =
4592 (uint16_t)FP16_EXP_BIAS << FP16_MANT_BITS; // 1.0
4593 if (op2 & 1)
4594 op1 = fpOne;
4595 return op1 ^ ((op2 >> 1) << (FP16_BITS - 1));
4596}
4597
4598template <>
4599uint32_t
4600fplibTrigSSel(uint32_t op1, uint32_t op2, FPSCR &fpscr)
4601{
4602 static constexpr uint32_t fpOne =
4603 (uint32_t)FP32_EXP_BIAS << FP32_MANT_BITS; // 1.0
4604 if (op2 & 1)
4605 op1 = fpOne;
4606 return op1 ^ ((op2 >> 1) << (FP32_BITS - 1));
4607}
4608
4609template <>
4610uint64_t
4611fplibTrigSSel(uint64_t op1, uint64_t op2, FPSCR &fpscr)
4612{
4613 static constexpr uint64_t fpOne =
4614 (uint64_t)FP64_EXP_BIAS << FP64_MANT_BITS; // 1.0
4615 if (op2 & 1)
4616 op1 = fpOne;
4617 return op1 ^ ((op2 >> 1) << (FP64_BITS - 1));
4618}
4619
4620static uint64_t
4621FPToFixed_64(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding,
4622 int *flags)
4623{
4624 int expmax = FP64_EXP_BIAS + FP64_BITS - 1;
4625 uint64_t x;
4626 int err;
4627
4628 if (exp > expmax) {
4629 *flags = FPLIB_IOC;
4630 return ((uint64_t)!u << (FP64_BITS - 1)) - !sgn;
4631 }
4632
4633 x = lsr64(mnt << FP64_EXP_BITS, expmax - exp);
4634 err = (exp > expmax - 2 ? 0 :
4635 (lsr64(mnt << FP64_EXP_BITS, expmax - 2 - exp) & 3) |
4636 !!(mnt << FP64_EXP_BITS & (lsl64(1, expmax - 2 - exp) - 1)));
4637
4638 switch (rounding) {
4639 case FPRounding_TIEEVEN:
4640 x += (err == 3 || (err == 2 && (x & 1)));
4641 break;
4642 case FPRounding_POSINF:
4643 x += err && !sgn;
4644 break;
4645 case FPRounding_NEGINF:
4646 x += err && sgn;
4647 break;
4648 case FPRounding_ZERO:
4649 break;
4650 case FPRounding_TIEAWAY:
4651 x += err >> 1;
4652 break;
4653 default:
4654 panic("Unrecognized FP rounding mode");
4655 }
4656
4657 if (u ? sgn && x : x > (1ULL << (FP64_BITS - 1)) - !sgn) {
4658 *flags = FPLIB_IOC;
4659 return ((uint64_t)!u << (FP64_BITS - 1)) - !sgn;
4660 }
4661
4662 if (err) {
4663 *flags = FPLIB_IXC;
4664 }
4665
4666 return sgn ? -x : x;
4667}
4668
4669static uint32_t
4670FPToFixed_32(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding,
4671 int *flags)
4672{
4673 uint64_t x = FPToFixed_64(sgn, exp, mnt, u, rounding, flags);
4674 if (u ? x >= 1ULL << FP32_BITS :
4675 !(x < 1ULL << (FP32_BITS - 1) ||
4676 (uint64_t)-x <= (uint64_t)1 << (FP32_BITS - 1))) {
4677 *flags = FPLIB_IOC;
4678 x = ((uint32_t)!u << (FP32_BITS - 1)) - !sgn;
4679 }
4680 return x;
4681}
4682
4683static uint16_t
4684FPToFixed_16(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding,
4685 int *flags)
4686{
4687 uint64_t x = FPToFixed_64(sgn, exp, mnt, u, rounding, flags);
4688 if (u ? x >= 1ULL << FP16_BITS :
4689 !(x < 1ULL << (FP16_BITS - 1) ||
4690 (uint64_t)-x <= (uint64_t)1 << (FP16_BITS - 1))) {
4691 *flags = FPLIB_IOC;
4692 x = ((uint16_t)!u << (FP16_BITS - 1)) - !sgn;
4693 }
4694 return x;
4695}
4696
4697template <>
4698uint16_t
4699fplibFPToFixed(uint16_t op, int fbits, bool u, FPRounding rounding,
4700 FPSCR &fpscr)
4701{
4702 int flags = 0;
4703 int sgn, exp;
4704 uint16_t mnt, result;
4705
4706 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
4707 fp16_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
4708
4709 // If NaN, set cumulative flag or take exception:
4710 if (fp16_is_NaN(exp, mnt)) {
4711 flags = FPLIB_IOC;
4712 result = 0;
4713 } else {
4714 assert(fbits >= 0);
4715 // Infinity is treated as an ordinary normalised number that saturates.
4716 result =
4717 FPToFixed_16(sgn, exp + FP64_EXP_BIAS - FP16_EXP_BIAS + fbits,
4718 (uint64_t)mnt << (FP64_MANT_BITS - FP16_MANT_BITS),
4719 u, rounding, &flags);
4720 }
4721
4722 set_fpscr0(fpscr, flags);
4723
4724 return result;
4725}
4726
4727template <>
4728uint32_t
4729fplibFPToFixed(uint16_t op, int fbits, bool u, FPRounding rounding,
4730 FPSCR &fpscr)
4731{
4732 int flags = 0;
4733 int sgn, exp;
4734 uint16_t mnt;
4735 uint32_t result;
4736
4737 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
4738 fp16_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
4739
4740 // If NaN, set cumulative flag or take exception:
4741 if (fp16_is_NaN(exp, mnt)) {
4742 flags = FPLIB_IOC;
4743 result = 0;
4744 } else {
4745 assert(fbits >= 0);
4746 if (exp == FP16_EXP_INF)
4747 exp = 255; // infinity: make it big enough to saturate
4748 result =
4749 FPToFixed_32(sgn, exp + FP64_EXP_BIAS - FP16_EXP_BIAS + fbits,
4750 (uint64_t)mnt << (FP64_MANT_BITS - FP16_MANT_BITS),
4751 u, rounding, &flags);
4752 }
4753
4754 set_fpscr0(fpscr, flags);
4755
4756 return result;
4757}
4758
4759template <>
4760uint32_t
4761fplibFPToFixed(uint32_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
4762{
4763 int flags = 0;
4764 int sgn, exp;
4765 uint32_t mnt, result;
4766
4767 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
4768 fp32_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
4769
4770 // If NaN, set cumulative flag or take exception:
4771 if (fp32_is_NaN(exp, mnt)) {
4772 flags = FPLIB_IOC;
4773 result = 0;
4774 } else {
4775 assert(fbits >= 0);
4776 // Infinity is treated as an ordinary normalised number that saturates.
4777 result =
4778 FPToFixed_32(sgn, exp + FP64_EXP_BIAS - FP32_EXP_BIAS + fbits,
4779 (uint64_t)mnt << (FP64_MANT_BITS - FP32_MANT_BITS),
4780 u, rounding, &flags);
4781 }
4782
4783 set_fpscr0(fpscr, flags);
4784
4785 return result;
4786}
4787
4788template <>
4789uint32_t
4790fplibFPToFixed(uint64_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
4791{
4792 int flags = 0;
4793 int sgn, exp;
4794 uint64_t mnt;
4795 uint32_t result;
4796
4797 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
4798 fp64_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
4799
4800 // If NaN, set cumulative flag or take exception:
4801 if (fp64_is_NaN(exp, mnt)) {
4802 flags = FPLIB_IOC;
4803 result = 0;
4804 } else {
4805 assert(fbits >= 0);
4806 // Infinity is treated as an ordinary normalised number that saturates.
4807 result = FPToFixed_32(sgn, exp + fbits, mnt, u, rounding, &flags);
4808 }
4809
4810 set_fpscr0(fpscr, flags);
4811
4812 return result;
4813}
4814
4815uint32_t
4816fplibFPToFixedJS(uint64_t op, FPSCR &fpscr, bool is64, uint8_t& nz)
4817{
4818 int flags = 0;
4819 uint32_t result;
4820 bool Z = true;
4821
4822 uint32_t sgn = bits(op, 63);
4823 int32_t exp = bits(op, 62, 52);
4824 uint64_t mnt = bits(op, 51, 0);
4825
4826 if (exp == 0) {
4827 if (mnt != 0) {
4828 if (fpscr.fz) {
4829 flags |= FPLIB_IDC;
4830 } else {
4831 flags |= FPLIB_IXC;
4832 Z = 0;
4833 }
4834 }
4835 result = 0;
4836 } else if (exp == 0x7ff) {
4837 flags |= FPLIB_IOC;
4838 result = 0;
4839 Z = 0;
4840 } else {
4841 mnt |= 1ULL << FP64_MANT_BITS;
4842 int mnt_shft = exp - FP64_EXP_BIAS - 52;
4843 bool err = true;
4844
4845 if (abs(mnt_shft) >= FP64_BITS) {
4846 result = 0;
4847 Z = 0;
4848 } else if (mnt_shft >= 0) {
4849 result = lsl64(mnt, mnt_shft);
4850 } else if (mnt_shft < 0) {
4851 err = lsl64(mnt, mnt_shft+FP64_BITS) != 0;
4852 result = lsr64(mnt, abs(mnt_shft));
4853 }
4854 uint64_t max_result = (1UL << (FP32_BITS - 1)) -!sgn;
4855 if ((exp - FP64_EXP_BIAS) > 31 || result > max_result) {
4856 flags |= FPLIB_IOC;
4857 Z = false;
4858 } else if (err) {
4859 flags |= FPLIB_IXC;
4860 Z = false;
4861 }
4862 result = sgn ? -result : result;
4863 }
4864 if (sgn == 1 && result == 0)
4865 Z = false;
4866
4867 if (is64) {
4868 nz = Z? 0x1: 0x0;
4869 } else {
4870 fpscr.n = 0;
4871 fpscr.z = (int)Z;
4872 fpscr.c = 0;
4873 fpscr.v = 0;
4874 }
4875
4876 set_fpscr0(fpscr, flags);
4877 return result;
4878}
4879
4880template <>
4881uint64_t
4882fplibFPToFixed(uint16_t op, int fbits, bool u, FPRounding rounding,
4883 FPSCR &fpscr)
4884{
4885 int flags = 0;
4886 int sgn, exp;
4887 uint16_t mnt;
4888 uint64_t result;
4889
4890 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
4891 fp16_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
4892
4893 // If NaN, set cumulative flag or take exception:
4894 if (fp16_is_NaN(exp, mnt)) {
4895 flags = FPLIB_IOC;
4896 result = 0;
4897 } else {
4898 assert(fbits >= 0);
4899 if (exp == FP16_EXP_INF)
4900 exp = 255; // infinity: make it big enough to saturate
4901 result =
4902 FPToFixed_64(sgn, exp + FP64_EXP_BIAS - FP16_EXP_BIAS + fbits,
4903 (uint64_t)mnt << (FP64_MANT_BITS - FP16_MANT_BITS),
4904 u, rounding, &flags);
4905 }
4906
4907 set_fpscr0(fpscr, flags);
4908
4909 return result;
4910}
4911
4912template <>
4913uint64_t
4914fplibFPToFixed(uint32_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
4915{
4916 int flags = 0;
4917 int sgn, exp;
4918 uint32_t mnt;
4919 uint64_t result;
4920
4921 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
4922 fp32_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
4923
4924 // If NaN, set cumulative flag or take exception:
4925 if (fp32_is_NaN(exp, mnt)) {
4926 flags = FPLIB_IOC;
4927 result = 0;
4928 } else {
4929 assert(fbits >= 0);
4930 // Infinity is treated as an ordinary normalised number that saturates.
4931 result =
4932 FPToFixed_64(sgn, exp + FP64_EXP_BIAS - FP32_EXP_BIAS + fbits,
4933 (uint64_t)mnt << (FP64_MANT_BITS - FP32_MANT_BITS),
4934 u, rounding, &flags);
4935 }
4936
4937 set_fpscr0(fpscr, flags);
4938
4939 return result;
4940}
4941
4942template <>
4943uint64_t
4944fplibFPToFixed(uint64_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
4945{
4946 int flags = 0;
4947 int sgn, exp;
4948 uint64_t mnt, result;
4949
4950 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
4951 fp64_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
4952
4953 // If NaN, set cumulative flag or take exception:
4954 if (fp64_is_NaN(exp, mnt)) {
4955 flags = FPLIB_IOC;
4956 result = 0;
4957 } else {
4958 assert(fbits >= 0);
4959 // Infinity is treated as an ordinary normalised number that saturates.
4960 result = FPToFixed_64(sgn, exp + fbits, mnt, u, rounding, &flags);
4961 }
4962
4963 set_fpscr0(fpscr, flags);
4964
4965 return result;
4966}
4967
4968static uint16_t
4969fp16_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
4970{
4971 int x_sgn = !u && a >> (FP64_BITS - 1);
4972 int x_exp = FP16_EXP_BIAS + FP64_BITS - 1 - fbits;
4973 uint64_t x_mnt = x_sgn ? -a : a;
4974
4975 // Handle zero:
4976 if (!x_mnt) {
4977 return fp16_zero(0);
4978 }
4979
4980 // Normalise into FP16_BITS bits, collapsing error into bottom bit:
4981 x_mnt = fp64_normalise(x_mnt, &x_exp);
4982 x_mnt = (x_mnt >> (FP64_BITS - FP16_BITS - 1) |
4983 !!(x_mnt & ((1ULL << (FP64_BITS - FP16_BITS - 1)) - 1)));
4984
4985 return fp16_round(x_sgn, x_exp, x_mnt, mode, flags);
4986}
4987
4988static uint32_t
4989fp32_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
4990{
4991 int x_sgn = !u && a >> (FP64_BITS - 1);
4992 int x_exp = FP32_EXP_BIAS + FP64_BITS - 1 - fbits;
4993 uint64_t x_mnt = x_sgn ? -a : a;
4994
4995 // Handle zero:
4996 if (!x_mnt) {
4997 return fp32_zero(0);
4998 }
4999
5000 // Normalise into FP32_BITS bits, collapsing error into bottom bit:
5001 x_mnt = fp64_normalise(x_mnt, &x_exp);
5002 x_mnt = (x_mnt >> (FP64_BITS - FP32_BITS - 1) |
5003 !!(x_mnt & ((1ULL << (FP64_BITS - FP32_BITS - 1)) - 1)));
5004
5005 return fp32_round(x_sgn, x_exp, x_mnt, mode, flags);
5006}
5007
5008static uint64_t
5009fp64_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
5010{
5011 int x_sgn = !u && a >> (FP64_BITS - 1);
5012 int x_exp = FP64_EXP_BIAS + FP64_BITS - 1 - fbits;
5013 uint64_t x_mnt = x_sgn ? -a : a;
5014
5015 // Handle zero:
5016 if (!x_mnt) {
5017 return fp64_zero(0);
5018 }
5019
5020 x_mnt = fp64_normalise(x_mnt, &x_exp);
5021
5022 return fp64_round(x_sgn, x_exp, x_mnt << 1, mode, flags);
5023}
5024
5025template <>
5026uint16_t
5027fplibFixedToFP(uint64_t op, int fbits, bool u, FPRounding rounding,
5028 FPSCR &fpscr)
5029{
5030 int flags = 0;
5031 uint16_t res = fp16_cvtf(op, fbits, u,
5032 (int)rounding | (modeConv(fpscr) & 0xFC),
5033 &flags);
5034 set_fpscr0(fpscr, flags);
5035 return res;
5036}
5037
5038template <>
5039uint32_t
5040fplibFixedToFP(uint64_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
5041{
5042 int flags = 0;
5043 uint32_t res = fp32_cvtf(op, fbits, u,
5044 (int)rounding | (modeConv(fpscr) & 0xFC),
5045 &flags);
5046 set_fpscr0(fpscr, flags);
5047 return res;
5048}
5049
5050template <>
5051uint64_t
5052fplibFixedToFP(uint64_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
5053{
5054 int flags = 0;
5055 uint64_t res = fp64_cvtf(op, fbits, u,
5056 (int)rounding | (modeConv(fpscr) & 0xFC),
5057 &flags);
5058 set_fpscr0(fpscr, flags);
5059 return res;
5060}
5061
5062template <>
5063uint16_t
5065{
5066 return fp16_infinity(sgn);
5067}
5068
5069template <>
5070uint32_t
5072{
5073 return fp32_infinity(sgn);
5074}
5075
5076template <>
5077uint64_t
5079{
5080 return fp64_infinity(sgn);
5081}
5082
5083template <>
5084uint16_t
5086{
5087 return fp16_defaultNaN();
5088}
5089
5090template <>
5091uint32_t
5093{
5094 return fp32_defaultNaN();
5095}
5096
5097template <>
5098uint64_t
5100{
5101 return fp64_defaultNaN();
5102}
5103
5104
5105template <>
5106uint16_t
5107fplib32RSqrtStep(uint16_t op1, uint16_t op2, FPSCR &fpscr)
5108{
5109 int mode = modeConv(fpscr);
5110 int flags = 0;
5111 int sgn1, exp1, sgn2, exp2;
5112 uint16_t mnt1, mnt2, result;
5113
5114 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
5115 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
5116
5117 result = fp16_process_NaNs(op1, op2, mode, &flags);
5118 if (!result) {
5119 if ((exp1 == FP16_EXP_INF && !mnt2) ||
5120 (exp2 == FP16_EXP_INF && !mnt1)) {
5121 result = fp16_FPOnePointFive(0);
5122 } else {
5123 uint16_t product = fp16_mul(op1, op2, mode, &flags);
5124 result = fp16_halved_add(fp16_FPThree(0), product, 1, mode,
5125 &flags);
5126 }
5127 }
5128
5129 set_fpscr0(fpscr, flags);
5130
5131 return result;
5132}
5133
5134template <>
5135uint16_t
5136fplib32RecipStep(uint16_t op1, uint16_t op2, FPSCR &fpscr)
5137{
5138 int mode = modeConv(fpscr);
5139 int flags = 0;
5140 int sgn1, exp1, sgn2, exp2;
5141 uint16_t mnt1, mnt2, result;
5142
5143 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
5144 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
5145
5146 result = fp16_process_NaNs(op1, op2, mode, &flags);
5147 if (!result) {
5148 if ((exp1 == FP16_EXP_INF && !mnt2) ||
5149 (exp2 == FP16_EXP_INF && !mnt1)) {
5150 result = fp16_FPTwo(0);
5151 } else {
5152 uint16_t product = fp16_mul(op1, op2, mode, &flags);
5153 result = fp16_add(fp16_FPTwo(0), product, 1, mode, &flags);
5154 }
5155 }
5156
5157 set_fpscr0(fpscr, flags);
5158
5159 return result;
5160}
5161
5162} // namespace ArmISA
5163} // namespace gem5
#define FPLIB_RN
Definition fplib.cc:53
#define FPLIB_DN
Definition fplib.cc:58
#define FPLIB_FZ16
Definition fplib.cc:60
#define FPLIB_DZC
Definition fplib.cc:66
#define FP32_EXP_BITS
Definition fplib.cc:74
#define FP16_MANT(x)
Definition fplib.cc:93
#define FP32_BITS
Definition fplib.cc:70
#define FP64_EXP_INF
Definition fplib.cc:83
#define FP32_MANT_BITS
Definition fplib.cc:86
#define FPLIB_RP
Definition fplib.cc:54
#define FPLIB_IOC
Definition fplib.cc:67
#define FP16_MANT_BITS
Definition fplib.cc:85
#define FP16_EXP_BITS
Definition fplib.cc:73
#define FP64_EXP_BITS
Definition fplib.cc:75
#define FP64_MANT_BITS
Definition fplib.cc:87
#define FPLIB_AHP
Definition fplib.cc:59
#define FPLIB_OFC
Definition fplib.cc:65
#define FP64_MANT(x)
Definition fplib.cc:95
#define FP16_EXP_INF
Definition fplib.cc:81
#define FP32_EXP(x)
Definition fplib.cc:90
#define FP64_EXP_BIAS
Definition fplib.cc:79
#define FP16_EXP(x)
Definition fplib.cc:89
#define FPLIB_IDC
Definition fplib.cc:62
#define FPLIB_FZ
Definition fplib.cc:57
#define FP16_BITS
Definition fplib.cc:69
#define FP32_MANT(x)
Definition fplib.cc:94
#define FP32_EXP_BIAS
Definition fplib.cc:78
#define FPLIB_IXC
Definition fplib.cc:63
#define FP32_EXP_INF
Definition fplib.cc:82
#define FP64_EXP(x)
Definition fplib.cc:91
#define FPLIB_UFC
Definition fplib.cc:64
#define FP64_BITS
Definition fplib.cc:71
#define FP16_EXP_BIAS
Definition fplib.cc:77
#define FPLIB_RM
Definition fplib.cc:55
Floating-point library code, which will gradually replace vfp.hh.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
uint16_t fplibMax(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:3243
static uint64_t fp64_FPOnePointFive(int sgn)
Definition fplib.cc:2645
uint16_t fplib32RSqrtStep(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:5107
uint32_t fplibFPToFixedJS(uint64_t op, FPSCR &fpscr, bool is64, uint8_t &nz)
Floating-point JS convert to a signed integer, with rounding to zero.
Definition fplib.cc:4816
uint16_t fplib32RecipStep(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:5136
static int fp64_is_infinity(int exp, uint64_t mnt)
Definition fplib.cc:529
static uint32_t fp32_FPConvertNaN_16(uint16_t op)
Definition fplib.cc:2601
static FPRounding FPCRRounding(FPSCR &fpscr)
Definition fplib.hh:71
static uint64_t fp64_process_NaNs(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:611
uint16_t fplibMinNum(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:3405
static uint16_t fp16_normalise(uint16_t mnt, int *exp)
Definition fplib.cc:219
static int fp32_compare_un(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:1116
static uint32_t fp32_scale(uint32_t a, int32_t b, int mode, int *flags)
Definition fplib.cc:2033
static void fp32_unpack(int *sgn, int *exp, uint32_t *mnt, uint32_t x, int mode, int *flags)
Definition fplib.cc:415
uint16_t fplibMaxNum(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:3312
static uint64_t fp64_FPConvertNaN_32(uint32_t op)
Definition fplib.cc:2625
static int modeConv(FPSCR fpscr)
Definition fplib.cc:2278
static uint64_t fp64_round(int sgn, int exp, uint64_t mnt, int mode, int *flags)
Definition fplib.cc:953
uint16_t fplibDiv(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:2969
static int fp16_compare_ge(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:978
Bitfield< 22 > a1
static uint32_t fp32_FPThree(int sgn)
Definition fplib.cc:2657
static uint64_t fp64_process_NaN(uint64_t a, int mode, int *flags)
Definition fplib.cc:555
static uint64_t fp64_pack(uint64_t sgn, uint64_t exp, uint64_t mnt)
Definition fplib.cc:314
static void fp64_unpack(int *sgn, int *exp, uint64_t *mnt, uint64_t x, int mode, int *flags)
Definition fplib.cc:438
static uint16_t fp16_scale(uint16_t a, int16_t b, int mode, int *flags)
Definition fplib.cc:1999
static uint64_t fp64_process_NaNs3(uint64_t a, uint64_t b, uint64_t c, int mode, int *flags)
Definition fplib.cc:692
uint16_t fplibRSqrtEstimate(uint16_t op, FPSCR &fpscr)
Definition fplib.cc:3592
static uint16_t fp16_zero(int sgn)
Definition fplib.cc:320
uint16_t fplibNeg(uint16_t op)
Definition fplib.cc:3552
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
static uint16_t fp16_max_normal(int sgn)
Definition fplib.cc:338
bool fplibCompareGT(uint16_t a, uint16_t b, FPSCR &fpscr)
Definition fplib.cc:2333
static uint16_t lsl16(uint16_t x, uint32_t shift)
Definition fplib.cc:98
Bitfield< 4, 0 > mode
Definition misc_types.hh:74
static int fp64_compare_un(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:1204
uint16_t fplibRecipEstimate(uint16_t op, FPSCR &fpscr)
Definition fplib.cc:3787
Bitfield< 3, 0 > rm
Definition types.hh:118
static uint16_t fp16_process_NaN(uint16_t a, int mode, int *flags)
Definition fplib.cc:535
static uint16_t fp16_FPConvertNaN_32(uint32_t op)
Definition fplib.cc:2585
static int fp16_is_quiet_NaN(int exp, uint16_t mnt)
Definition fplib.cc:499
static uint32_t fp32_round_(int sgn, int exp, uint32_t mnt, int rm, int mode, int *flags)
Definition fplib.cc:805
static void fp16_unpack(int *sgn, int *exp, uint16_t *mnt, uint16_t x, int mode, int *flags)
Definition fplib.cc:392
static uint32_t fp32_defaultNaN()
Definition fplib.cc:380
static uint32_t FPToFixed_32(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding, int *flags)
Definition fplib.cc:4670
static int fp64_compare_ge(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:1154
static uint32_t lsr32(uint32_t x, uint32_t shift)
Definition fplib.cc:116
static uint64_t FPToFixed_64(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding, int *flags)
Definition fplib.cc:4621
static uint16_t fp16_div(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:1837
uint16_t fplibConvert(uint32_t op, FPRounding rounding, FPSCR &fpscr)
Definition fplib.cc:2688
Bitfield< 7 > b
uint16_t fplibExpA(uint16_t op)
Definition fplib.cc:2999
static uint32_t fp32_FPTwo(int sgn)
Definition fplib.cc:2675
uint16_t fplibTrigSSel(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:4589
static int fp32_compare_gt(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:1091
static uint64_t fp64_FPConvertNaN_16(uint16_t op)
Definition fplib.cc:2617
uint16_t fplibFixedToFP(uint64_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
Definition fplib.cc:5027
Bitfield< 6 > err
static uint16_t fp16_FPOnePointFive(int sgn)
Definition fplib.cc:2633
static uint16_t fp16_add(uint16_t a, uint16_t b, int neg, int mode, int *flags)
Definition fplib.cc:1223
static int fp32_compare_eq(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:1047
uint16_t fplibSqrt(uint16_t op, FPSCR &fpscr)
Definition fplib.cc:4369
static uint16_t fp16_pack(uint16_t sgn, uint16_t exp, uint16_t mnt)
Definition fplib.cc:302
static uint64_t fp64_div(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:1921
static uint32_t fp32_normalise(uint32_t mnt, int *exp)
Definition fplib.cc:237
static uint32_t fp32_infinity(int sgn)
Definition fplib.cc:362
static uint64_t lsr64(uint64_t x, uint32_t shift)
Definition fplib.cc:128
bool fplibCompareEQ(uint16_t a, uint16_t b, FPSCR &fpscr)
Definition fplib.cc:2313
static uint32_t fp32_process_NaNs3(uint32_t a, uint32_t b, uint32_t c, int mode, int *flags)
Definition fplib.cc:663
static int fp64_is_NaN(int exp, uint64_t mnt)
Definition fplib.cc:475
uint16_t fplibAdd(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:2454
static uint16_t fp16_FPTwo(int sgn)
Definition fplib.cc:2669
static uint16_t fp16_sqrt(uint16_t a, int mode, int *flags)
Definition fplib.cc:2101
static int fp32_is_NaN(int exp, uint32_t mnt)
Definition fplib.cc:469
static uint64_t fp64_FPTwo(int sgn)
Definition fplib.cc:2681
static uint16_t lsr16(uint16_t x, uint32_t shift)
Definition fplib.cc:104
static int fp64_compare_eq(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:1135
static uint16_t fp16_infinity(int sgn)
Definition fplib.cc:356
uint16_t fplibMulX(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:3459
static uint32_t fp32_FPConvertNaN_64(uint64_t op)
Definition fplib.cc:2609
static uint16_t fp16_muladd(uint16_t a, uint16_t b, uint16_t c, int scale, int mode, int *flags)
Definition fplib.cc:1575
static void set_fpscr0(FPSCR &fpscr, int flags)
Definition fplib.cc:1976
static uint64_t fp64_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
Definition fplib.cc:5009
uint16_t fplibAbs(uint16_t op)
Definition fplib.cc:2433
static uint16_t FPToFixed_16(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding, int *flags)
Definition fplib.cc:4684
static uint16_t fp16_defaultNaN()
Definition fplib.cc:374
static uint32_t lsl32(uint32_t x, uint32_t shift)
Definition fplib.cc:110
static void add128(uint64_t *x0, uint64_t *x1, uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
Definition fplib.cc:197
static uint32_t fp32_FPOnePointFive(int sgn)
Definition fplib.cc:2639
bool fplibCompareGE(uint16_t a, uint16_t b, FPSCR &fpscr)
Definition fplib.cc:2323
static uint64_t fp64_infinity(int sgn)
Definition fplib.cc:368
static int fp64_compare_gt(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:1179
static int fp16_is_infinity(int exp, uint16_t mnt)
Definition fplib.cc:517
uint16_t fplibMul(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:3429
static uint64_t fp64_FPThree(int sgn)
Definition fplib.cc:2663
static uint64_t fp64_sqrt(uint64_t a, int mode, int *flags)
Definition fplib.cc:2208
static void fp64_minmaxnum(uint64_t *op1, uint64_t *op2, int sgn)
Definition fplib.cc:3230
static int fp16_compare_eq(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:959
static uint16_t fp16_process_NaNs(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:565
uint16_t fplibScale(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:4339
static int fp32_is_signalling_NaN(int exp, uint32_t mnt)
Definition fplib.cc:487
static int fp32_compare_ge(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:1066
static uint16_t fp16_round_(int sgn, int exp, uint16_t mnt, int rm, int mode, int *flags)
Definition fplib.cc:721
static int fp16_is_NaN(int exp, uint16_t mnt)
Definition fplib.cc:463
Bitfield< 29 > c
Definition misc_types.hh:53
static void fp16_minmaxnum(uint16_t *op1, uint16_t *op2, int sgn)
Definition fplib.cc:3206
static uint16_t fp16_mul(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:1464
static void lsl128(uint64_t *r0, uint64_t *r1, uint64_t x0, uint64_t x1, uint32_t shift)
Definition fplib.cc:134
static uint32_t fp32_round(int sgn, int exp, uint32_t mnt, int mode, int *flags)
Definition fplib.cc:876
Bitfield< 8 > a
Definition misc_types.hh:66
static uint32_t fp32_zero(int sgn)
Definition fplib.cc:326
static void lsr128(uint64_t *r0, uint64_t *r1, uint64_t x0, uint64_t x1, uint32_t shift)
Definition fplib.cc:152
static uint32_t fp32_pack(uint32_t sgn, uint32_t exp, uint32_t mnt)
Definition fplib.cc:308
static void mul64x32(uint64_t *x0, uint64_t *x1, uint64_t a, uint32_t b)
Definition fplib.cc:188
Bitfield< 22 > u
uint16_t fplibRecpX(uint16_t op, FPSCR &fpscr)
Definition fplib.cc:4063
static uint16_t fp16_repack(int sgn, int exp, uint16_t mnt)
Definition fplib.cc:3188
static uint64_t fp64_scale(uint64_t a, int64_t b, int mode, int *flags)
Definition fplib.cc:2067
static int fp16_is_signalling_NaN(int exp, uint16_t mnt)
Definition fplib.cc:481
static uint64_t fp64_repack(int sgn, int exp, uint64_t mnt)
Definition fplib.cc:3200
uint16_t fplibRecipStepFused(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:3973
uint16_t fplibTrigSMul(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:4531
uint16_t fplibTrigMulAdd(uint8_t coeff_index, uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:4429
uint16_t fplibRSqrtStepFused(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:3697
static void fp32_minmaxnum(uint32_t *op1, uint32_t *op2, int sgn)
Definition fplib.cc:3218
int fplibCompare(uint16_t op1, uint16_t op2, bool signal_nans, FPSCR &fpscr)
Definition fplib.cc:2484
static uint64_t fp64_add(uint64_t a, uint64_t b, int neg, int mode, int *flags)
Definition fplib.cc:1343
uint16_t fplibDefaultNaN()
Definition fplib.cc:5085
static uint32_t fp32_process_NaNs(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:588
static uint64_t fp64_defaultNaN()
Definition fplib.cc:386
static const uint8_t recip_sqrt_estimate[256]
Definition fplib.cc:3571
static uint32_t fp32_process_NaN(uint32_t a, int mode, int *flags)
Definition fplib.cc:545
uint16_t fplibFPToFixed(uint16_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
Definition fplib.cc:4699
uint16_t fplibSub(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:4399
static int fp16_compare_gt(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:1003
static uint16_t fp16_process_NaNs3(uint16_t a, uint16_t b, uint16_t c, int mode, int *flags)
Definition fplib.cc:634
uint16_t fplibMulAdd(uint16_t addend, uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:2939
static uint64_t lsl64(uint64_t x, uint32_t shift)
Definition fplib.cc:122
static int fp32_is_infinity(int exp, uint32_t mnt)
Definition fplib.cc:523
Bitfield< 1 > t1
static uint64_t fp64_zero(int sgn)
Definition fplib.cc:332
static uint32_t fp32_sqrt(uint32_t a, int mode, int *flags)
Definition fplib.cc:2153
static int fp64_is_quiet_NaN(int exp, uint64_t mnt)
Definition fplib.cc:511
static uint16_t fp16_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
Definition fplib.cc:4969
static int fp16_compare_un(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:1028
static uint16_t fp16_FPThree(int sgn)
Definition fplib.cc:2651
static uint32_t fp32_muladd(uint32_t a, uint32_t b, uint32_t c, int scale, int mode, int *flags)
Definition fplib.cc:1660
static uint32_t fp32_add(uint32_t a, uint32_t b, int neg, int mode, int *flags)
Definition fplib.cc:1283
static void sub128(uint64_t *x0, uint64_t *x1, uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
Definition fplib.cc:205
static uint16_t fp16_halved_add(uint16_t a, uint16_t b, int neg, int mode, int *flags)
Definition fplib.cc:1403
static int fp32_is_quiet_NaN(int exp, uint32_t mnt)
Definition fplib.cc:505
static uint64_t fp64_max_normal(int sgn)
Definition fplib.cc:350
static uint32_t fp32_div(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:1879
uint16_t fplibInfinity(int sgn)
Definition fplib.cc:5064
uint16_t fplibRoundInt(uint16_t op, FPRounding rounding, bool exact, FPSCR &fpscr)
Definition fplib.cc:4144
static uint16_t fp16_round(int sgn, int exp, uint16_t mnt, int mode, int *flags)
Definition fplib.cc:799
static void set_fpscr(FPSCR &fpscr, int flags)
Definition fplib.cc:2286
static uint64_t fp64_mul(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:1538
Bitfield< 6, 5 > shift
Definition types.hh:117
static uint16_t fp16_FPConvertNaN_64(uint64_t op)
Definition fplib.cc:2593
static uint32_t fp32_repack(int sgn, int exp, uint32_t mnt)
Definition fplib.cc:3194
static uint64_t fp64_round_(int sgn, int exp, uint64_t mnt, int rm, int mode, int *flags)
Definition fplib.cc:882
@ FPRounding_POSINF
Definition fplib.hh:63
@ FPRounding_ZERO
Definition fplib.hh:65
@ FPRounding_TIEEVEN
Definition fplib.hh:62
@ FPRounding_TIEAWAY
Definition fplib.hh:66
@ FPRounding_ODD
Definition fplib.hh:67
@ FPRounding_NEGINF
Definition fplib.hh:64
uint16_t fplibMin(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:3336
static uint64_t fp64_muladd(uint64_t a, uint64_t b, uint64_t c, int scale, int mode, int *flags)
Definition fplib.cc:1745
static uint32_t fp32_mul(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:1501
static int fp64_is_signalling_NaN(int exp, uint64_t mnt)
Definition fplib.cc:493
bool fplibCompareUN(uint16_t a, uint16_t b, FPSCR &fpscr)
Definition fplib.cc:2343
static uint32_t fp32_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
Definition fplib.cc:4989
static void fp128_normalise(uint64_t *mnt0, uint64_t *mnt1, int *exp)
Definition fplib.cc:273
static uint64_t fp64_normalise(uint64_t mnt, int *exp)
Definition fplib.cc:255
Bitfield< 0 > t0
static uint32_t fp32_max_normal(int sgn)
Definition fplib.cc:344
static void mul62x62(uint64_t *x0, uint64_t *x1, uint64_t a, uint64_t b)
Definition fplib.cc:170
static int cmp128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
Definition fplib.cc:213
Bitfield< 20, 18 > a0
Bitfield< 3 > r0
Bitfield< 7, 4 > b1
Definition qarma.hh:65
Bitfield< 3, 0 > b0
Definition qarma.hh:66
Bitfield< 3 > x
Definition pagetable.hh:76
Bitfield< 4 > op
Definition types.hh:83
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36

Generated on Mon May 26 2025 09:18:57 for gem5 by doxygen 1.13.2