gem5 [DEVELOP-FOR-25.1]
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 // 0x0
54#define FPLIB_RP 1 // 0x1
55#define FPLIB_RM 2 // 0x2
56#define FPLIB_RZ 3 // 0x3
57#define FPLIB_FZ 4 // 0x4
58#define FPLIB_DN 8 // 0x8
59#define FPLIB_AHP 16 // 0x10
60#define FPLIB_FZ16 32 // 0x20
61#define FPLIB_FIZ 64 // 0x40
62#define FPLIB_AH 128 // 0x80
63#define FPLIB_NEP 256 // 0x100
64#define FPLIB_FPEXEC 512 // 0x200, Raise exception.
65
66#define FPLIB_IDC 128 // Input Denormal
67#define FPLIB_IXC 16 // Inexact
68#define FPLIB_UFC 8 // Underflow
69#define FPLIB_OFC 4 // Overflow
70#define FPLIB_DZC 2 // Division by Zero
71#define FPLIB_IOC 1 // Invalid Operation
72
73#define FP16_BITS 16
74#define FP32_BITS 32
75#define FP64_BITS 64
76
77#define FP16_EXP_BITS 5
78#define FP32_EXP_BITS 8
79#define FP64_EXP_BITS 11
80
81#define FP16_EXP_BIAS 15
82#define FP32_EXP_BIAS 127
83#define FP64_EXP_BIAS 1023
84
85#define FP16_EXP_INF ((1ULL << FP16_EXP_BITS) - 1)
86#define FP32_EXP_INF ((1ULL << FP32_EXP_BITS) - 1)
87#define FP64_EXP_INF ((1ULL << FP64_EXP_BITS) - 1)
88
89#define FP16_MANT_BITS (FP16_BITS - FP16_EXP_BITS - 1)
90#define FP32_MANT_BITS (FP32_BITS - FP32_EXP_BITS - 1)
91#define FP64_MANT_BITS (FP64_BITS - FP64_EXP_BITS - 1)
92
93#define FP16_EXP(x) ((x) >> FP16_MANT_BITS & ((1ULL << FP16_EXP_BITS) - 1))
94#define FP32_EXP(x) ((x) >> FP32_MANT_BITS & ((1ULL << FP32_EXP_BITS) - 1))
95#define FP64_EXP(x) ((x) >> FP64_MANT_BITS & ((1ULL << FP64_EXP_BITS) - 1))
96
97#define FP16_MANT(x) ((x) & ((1ULL << FP16_MANT_BITS) - 1))
98#define FP32_MANT(x) ((x) & ((1ULL << FP32_MANT_BITS) - 1))
99#define FP64_MANT(x) ((x) & ((1ULL << FP64_MANT_BITS) - 1))
100
101static inline uint16_t
102lsl16(uint16_t x, uint32_t shift)
103{
104 return shift < 16 ? x << shift : 0;
105}
106
107static inline uint16_t
108lsr16(uint16_t x, uint32_t shift)
109{
110 return shift < 16 ? x >> shift : 0;
111}
112
113static inline uint32_t
114lsl32(uint32_t x, uint32_t shift)
115{
116 return shift < 32 ? x << shift : 0;
117}
118
119static inline uint32_t
120lsr32(uint32_t x, uint32_t shift)
121{
122 return shift < 32 ? x >> shift : 0;
123}
124
125static inline uint64_t
126lsl64(uint64_t x, uint32_t shift)
127{
128 return shift < 64 ? x << shift : 0;
129}
130
131static inline uint64_t
132lsr64(uint64_t x, uint32_t shift)
133{
134 return shift < 64 ? x >> shift : 0;
135}
136
137static inline void
138lsl128(uint64_t *r0, uint64_t *r1, uint64_t x0, uint64_t x1, uint32_t shift)
139{
140 if (shift == 0) {
141 *r1 = x1;
142 *r0 = x0;
143 } else if (shift < 64) {
144 *r1 = x1 << shift | x0 >> (64 - shift);
145 *r0 = x0 << shift;
146 } else if (shift < 128) {
147 *r1 = x0 << (shift - 64);
148 *r0 = 0;
149 } else {
150 *r1 = 0;
151 *r0 = 0;
152 }
153}
154
155static inline void
156lsr128(uint64_t *r0, uint64_t *r1, uint64_t x0, uint64_t x1, uint32_t shift)
157{
158 if (shift == 0) {
159 *r1 = x1;
160 *r0 = x0;
161 } else if (shift < 64) {
162 *r0 = x0 >> shift | x1 << (64 - shift);
163 *r1 = x1 >> shift;
164 } else if (shift < 128) {
165 *r0 = x1 >> (shift - 64);
166 *r1 = 0;
167 } else {
168 *r0 = 0;
169 *r1 = 0;
170 }
171}
172
173static inline void
174mul62x62(uint64_t *x0, uint64_t *x1, uint64_t a, uint64_t b)
175{
176 uint32_t mask = ((uint32_t)1 << 31) - 1;
177 uint64_t a0 = a & mask;
178 uint64_t a1 = a >> 31 & mask;
179 uint64_t b0 = b & mask;
180 uint64_t b1 = b >> 31 & mask;
181 uint64_t p0 = a0 * b0;
182 uint64_t p2 = a1 * b1;
183 uint64_t p1 = (a0 + a1) * (b0 + b1) - p0 - p2;
184 uint64_t s0 = p0;
185 uint64_t s1 = (s0 >> 31) + p1;
186 uint64_t s2 = (s1 >> 31) + p2;
187 *x0 = (s0 & mask) | (s1 & mask) << 31 | s2 << 62;
188 *x1 = s2 >> 2;
189}
190
191static inline
192void mul64x32(uint64_t *x0, uint64_t *x1, uint64_t a, uint32_t b)
193{
194 uint64_t t0 = (uint64_t)(uint32_t)a * b;
195 uint64_t t1 = (t0 >> 32) + (a >> 32) * b;
196 *x0 = t1 << 32 | (uint32_t)t0;
197 *x1 = t1 >> 32;
198}
199
200static inline void
201add128(uint64_t *x0, uint64_t *x1, uint64_t a0, uint64_t a1, uint64_t b0,
202 uint64_t b1)
203{
204 *x0 = a0 + b0;
205 *x1 = a1 + b1 + (*x0 < a0);
206}
207
208static inline void
209sub128(uint64_t *x0, uint64_t *x1, uint64_t a0, uint64_t a1, uint64_t b0,
210 uint64_t b1)
211{
212 *x0 = a0 - b0;
213 *x1 = a1 - b1 - (*x0 > a0);
214}
215
216static inline int
217cmp128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
218{
219 return (a1 < b1 ? -1 : a1 > b1 ? 1 : a0 < b0 ? -1 : a0 > b0 ? 1 : 0);
220}
221
222static inline uint16_t
223fp16_normalise(uint16_t mnt, int *exp)
224{
225 int shift;
226
227 if (!mnt) {
228 return 0;
229 }
230
231 for (shift = 8; shift; shift >>= 1) {
232 if (!(mnt >> (16 - shift))) {
233 mnt <<= shift;
234 *exp -= shift;
235 }
236 }
237 return mnt;
238}
239
240static inline uint32_t
241fp32_normalise(uint32_t mnt, int *exp)
242{
243 int shift;
244
245 if (!mnt) {
246 return 0;
247 }
248
249 for (shift = 16; shift; shift >>= 1) {
250 if (!(mnt >> (32 - shift))) {
251 mnt <<= shift;
252 *exp -= shift;
253 }
254 }
255 return mnt;
256}
257
258static inline uint64_t
259fp64_normalise(uint64_t mnt, int *exp)
260{
261 int shift;
262
263 if (!mnt) {
264 return 0;
265 }
266
267 for (shift = 32; shift; shift >>= 1) {
268 if (!(mnt >> (64 - shift))) {
269 mnt <<= shift;
270 *exp -= shift;
271 }
272 }
273 return mnt;
274}
275
276static inline void
277fp128_normalise(uint64_t *mnt0, uint64_t *mnt1, int *exp)
278{
279 uint64_t x0 = *mnt0;
280 uint64_t x1 = *mnt1;
281 int shift;
282
283 if (!x0 && !x1) {
284 return;
285 }
286
287 if (!x1) {
288 x1 = x0;
289 x0 = 0;
290 *exp -= 64;
291 }
292
293 for (shift = 32; shift; shift >>= 1) {
294 if (!(x1 >> (64 - shift))) {
295 x1 = x1 << shift | x0 >> (64 - shift);
296 x0 <<= shift;
297 *exp -= shift;
298 }
299 }
300
301 *mnt0 = x0;
302 *mnt1 = x1;
303}
304
305static inline uint16_t
306fp16_pack(uint16_t sgn, uint16_t exp, uint16_t mnt)
307{
308 return sgn << (FP16_BITS - 1) | exp << FP16_MANT_BITS | FP16_MANT(mnt);
309}
310
311static inline uint32_t
312fp32_pack(uint32_t sgn, uint32_t exp, uint32_t mnt)
313{
314 return sgn << (FP32_BITS - 1) | exp << FP32_MANT_BITS | FP32_MANT(mnt);
315}
316
317static inline uint64_t
318fp64_pack(uint64_t sgn, uint64_t exp, uint64_t mnt)
319{
320 return sgn << (FP64_BITS - 1) | exp << FP64_MANT_BITS | FP64_MANT(mnt);
321}
322
323static inline uint16_t
324fp16_zero(int sgn)
325{
326 return fp16_pack(sgn, 0, 0);
327}
328
329static inline uint32_t
330fp32_zero(int sgn)
331{
332 return fp32_pack(sgn, 0, 0);
333}
334
335static inline uint64_t
336fp64_zero(int sgn)
337{
338 return fp64_pack(sgn, 0, 0);
339}
340
341static inline uint16_t
343{
344 return fp16_pack(sgn, FP16_EXP_INF - 1, -1);
345}
346
347static inline uint32_t
349{
350 return fp32_pack(sgn, FP32_EXP_INF - 1, -1);
351}
352
353static inline uint64_t
355{
356 return fp64_pack(sgn, FP64_EXP_INF - 1, -1);
357}
358
359static inline uint16_t
361{
362 return fp16_pack(sgn, FP16_EXP_INF, 0);
363}
364
365static inline uint32_t
367{
368 return fp32_pack(sgn, FP32_EXP_INF, 0);
369}
370
371static inline uint64_t
373{
374 return fp64_pack(sgn, FP64_EXP_INF, 0);
375}
376
377static inline uint16_t
379{
380 uint16_t sgn = (mode & FPLIB_AH) > 0 ? 1 : 0;
381 return fp16_pack(sgn, FP16_EXP_INF, 1ULL << (FP16_MANT_BITS - 1));
382}
383
384static inline uint32_t
386{
387 uint32_t sgn = (mode & FPLIB_AH) > 0 ? 1 : 0;
388 return fp32_pack(sgn, FP32_EXP_INF, 1ULL << (FP32_MANT_BITS - 1));
389}
390
391static inline uint64_t
393{
394 uint64_t sgn = (mode & FPLIB_AH) > 0 ? 1 : 0;
395 return fp64_pack(sgn, FP64_EXP_INF, 1ULL << (FP64_MANT_BITS - 1));
396}
397
398static inline void
399fp16_unpack(int *sgn, int *exp, uint16_t *mnt, uint16_t x, int mode,
400 int *flags)
401{
402 *sgn = x >> (FP16_BITS - 1);
403 *exp = FP16_EXP(x);
404 *mnt = FP16_MANT(x);
405
406 if (*exp) {
407 *mnt |= 1ULL << FP16_MANT_BITS;
408 } else {
409 // Handle subnormals:
410 // IDC (Input Denormal) is not set in this case.
411 if (*mnt) {
412 if (mode & FPLIB_FZ16) {
413 *mnt = 0;
414 } else {
415 ++*exp;
416 }
417 }
418 }
419}
420
421static inline void
422fp32_unpack(int *sgn, int *exp, uint32_t *mnt, uint32_t x, int mode,
423 int *flags)
424{
425 *sgn = x >> (FP32_BITS - 1);
426 *exp = FP32_EXP(x);
427 *mnt = FP32_MANT(x);
428
429 if (*exp) {
430 *mnt |= 1ULL << FP32_MANT_BITS;
431 } else {
432 // Handle subnormals:
433 if (*mnt) {
434 bool fiz = mode & FPLIB_FIZ;
435 bool fz = (mode & FPLIB_FZ) && !(mode & FPLIB_AH);
436 if (fiz || fz) {
437 if (fz && (mode & FPLIB_FPEXEC))
438 *flags |= FPLIB_IDC;
439 *mnt = 0;
440 } else {
441 ++*exp;
442 }
443 }
444 }
445}
446
447static inline void
448fp64_unpack(int *sgn, int *exp, uint64_t *mnt, uint64_t x, int mode,
449 int *flags)
450{
451 *sgn = x >> (FP64_BITS - 1);
452 *exp = FP64_EXP(x);
453 *mnt = FP64_MANT(x);
454
455 if (*exp) {
456 *mnt |= 1ULL << FP64_MANT_BITS;
457 } else {
458 // Handle subnormals:
459 if (*mnt) {
460 bool fiz = mode & FPLIB_FIZ;
461 bool fz = (mode & FPLIB_FZ) && !(mode & FPLIB_AH);
462 if (fiz || fz) {
463 if (fz && (mode & FPLIB_FPEXEC))
464 *flags |= FPLIB_IDC;
465 *mnt = 0;
466 } else {
467 ++*exp;
468 }
469 }
470 }
471}
472
473static inline int
474fp16_is_NaN(int exp, uint16_t mnt)
475{
476 return exp == FP16_EXP_INF && FP16_MANT(mnt);
477}
478
479static inline int
480fp32_is_NaN(int exp, uint32_t mnt)
481{
482 return exp == FP32_EXP_INF && FP32_MANT(mnt);
483}
484
485static inline int
486fp64_is_NaN(int exp, uint64_t mnt)
487{
488 return exp == FP64_EXP_INF && FP64_MANT(mnt);
489}
490
491static inline int
492fp16_is_signalling_NaN(int exp, uint16_t mnt)
493{
494 return fp16_is_NaN(exp, mnt) && !(mnt >> (FP16_MANT_BITS - 1) & 1);
495}
496
497static inline int
498fp32_is_signalling_NaN(int exp, uint32_t mnt)
499{
500 return fp32_is_NaN(exp, mnt) && !(mnt >> (FP32_MANT_BITS - 1) & 1);
501}
502
503static inline int
504fp64_is_signalling_NaN(int exp, uint64_t mnt)
505{
506 return fp64_is_NaN(exp, mnt) && !(mnt >> (FP64_MANT_BITS - 1) & 1);
507}
508
509static inline int
510fp16_is_quiet_NaN(int exp, uint16_t mnt)
511{
512 return exp == FP16_EXP_INF && (mnt >> (FP16_MANT_BITS - 1) & 1);
513}
514
515static inline int
516fp32_is_quiet_NaN(int exp, uint32_t mnt)
517{
518 return exp == FP32_EXP_INF && (mnt >> (FP32_MANT_BITS - 1) & 1);
519}
520
521static inline int
522fp64_is_quiet_NaN(int exp, uint64_t mnt)
523{
524 return exp == FP64_EXP_INF && (mnt >> (FP64_MANT_BITS - 1) & 1);
525}
526
527static inline int
528fp16_is_infinity(int exp, uint16_t mnt)
529{
530 return exp == FP16_EXP_INF && !FP16_MANT(mnt);
531}
532
533static inline int
534fp32_is_infinity(int exp, uint32_t mnt)
535{
536 return exp == FP32_EXP_INF && !FP32_MANT(mnt);
537}
538
539static inline int
540fp64_is_infinity(int exp, uint64_t mnt)
541{
542 return exp == FP64_EXP_INF && !FP64_MANT(mnt);
543}
544
545[[maybe_unused]]
546static inline int
547fp16_is_denormal(int exp, uint16_t mnt)
548{
549 return exp == 1 && !(mnt >> FP16_MANT_BITS);
550}
551
552static inline int
553fp32_is_denormal(int exp, uint32_t mnt)
554{
555 return exp == 1 && !(mnt >> FP32_MANT_BITS);
556}
557
558static inline int
559fp64_is_denormal(int exp, uint64_t mnt)
560{
561 return exp == 1 && !(mnt >> FP64_MANT_BITS);
562}
563
564static inline uint16_t
565fp16_process_NaN(uint16_t a, int mode, int *flags)
566{
567 if (!(a >> (FP16_MANT_BITS - 1) & 1)) {
568 if (mode & FPLIB_FPEXEC)
569 *flags |= FPLIB_IOC;
570 a |= 1ULL << (FP16_MANT_BITS - 1);
571 }
572 return mode & FPLIB_DN ? fp16_defaultNaN(mode) : a;
573}
574
575static inline uint32_t
576fp32_process_NaN(uint32_t a, int mode, int *flags)
577{
578 if (!(a >> (FP32_MANT_BITS - 1) & 1)) {
579 if (mode & FPLIB_FPEXEC)
580 *flags |= FPLIB_IOC;
581 a |= 1ULL << (FP32_MANT_BITS - 1);
582 }
583 return mode & FPLIB_DN ? fp32_defaultNaN(mode) : a;
584}
585
586static inline uint64_t
587fp64_process_NaN(uint64_t a, int mode, int *flags)
588{
589 if (!(a >> (FP64_MANT_BITS - 1) & 1)) {
590 if (mode & FPLIB_FPEXEC)
591 *flags |= FPLIB_IOC;
592 a |= 1ULL << (FP64_MANT_BITS - 1);
593 }
594 return mode & FPLIB_DN ? fp64_defaultNaN(mode) : a;
595}
596
597static uint16_t
598fp16_process_NaNs(uint16_t a, uint16_t b, int mode, int *flags)
599{
600 int a_exp = FP16_EXP(a);
601 uint16_t a_mnt = FP16_MANT(a);
602 int b_exp = FP16_EXP(b);
603 uint16_t b_mnt = FP16_MANT(b);
604
605 // Handle NaN propogate when enabling FEAT_AFP.
606 if (mode & FPLIB_AH) {
607 if (fp16_is_NaN(a_exp, a_mnt) && fp16_is_NaN(b_exp, b_mnt)) {
608 if (fp16_is_signalling_NaN(a_exp, a_mnt) ||
609 fp16_is_signalling_NaN(b_exp, b_mnt)) {
610 if (mode & FPLIB_FPEXEC)
611 *flags |= FPLIB_IOC;
612 a |= 1ULL << (FP16_MANT_BITS - 1);
613 }
614
615 return fp16_process_NaN(a, mode, flags);
616 }
617 }
618
619 // Handle signalling NaNs:
620 if (fp16_is_signalling_NaN(a_exp, a_mnt))
621 return fp16_process_NaN(a, mode, flags);
622 if (fp16_is_signalling_NaN(b_exp, b_mnt))
623 return fp16_process_NaN(b, mode, flags);
624
625 // Handle quiet NaNs:
626 if (fp16_is_NaN(a_exp, a_mnt))
627 return fp16_process_NaN(a, mode, flags);
628 if (fp16_is_NaN(b_exp, b_mnt))
629 return fp16_process_NaN(b, mode, flags);
630
631 return 0;
632}
633
634static uint32_t
635fp32_process_NaNs(uint32_t a, uint32_t b, int mode, int *flags)
636{
637 int a_exp = FP32_EXP(a);
638 uint32_t a_mnt = FP32_MANT(a);
639 int b_exp = FP32_EXP(b);
640 uint32_t b_mnt = FP32_MANT(b);
641
642 // Handle NaN propogate when enabling FEAT_AFP.
643 if (mode & FPLIB_AH) {
644 if (fp32_is_NaN(a_exp, a_mnt) && fp32_is_NaN(b_exp, b_mnt)) {
645 if (fp32_is_signalling_NaN(a_exp, a_mnt) ||
646 fp32_is_signalling_NaN(b_exp, b_mnt)) {
647 if (mode & FPLIB_FPEXEC)
648 *flags |= FPLIB_IOC;
649 a |= 1ULL << (FP32_MANT_BITS - 1);
650 }
651
652 return fp32_process_NaN(a, mode, flags);
653 }
654 }
655
656 // Handle signalling NaNs:
657 if (fp32_is_signalling_NaN(a_exp, a_mnt))
658 return fp32_process_NaN(a, mode, flags);
659 if (fp32_is_signalling_NaN(b_exp, b_mnt))
660 return fp32_process_NaN(b, mode, flags);
661
662 // Handle quiet NaNs:
663 if (fp32_is_NaN(a_exp, a_mnt))
664 return fp32_process_NaN(a, mode, flags);
665 if (fp32_is_NaN(b_exp, b_mnt))
666 return fp32_process_NaN(b, mode, flags);
667
668 return 0;
669}
670
671static uint64_t
672fp64_process_NaNs(uint64_t a, uint64_t b, int mode, int *flags)
673{
674 int a_exp = FP64_EXP(a);
675 uint64_t a_mnt = FP64_MANT(a);
676 int b_exp = FP64_EXP(b);
677 uint64_t b_mnt = FP64_MANT(b);
678
679 // Handle NaN propogate when enabling FEAT_AFP.
680 if (mode & FPLIB_AH) {
681 if (fp64_is_NaN(a_exp, a_mnt) && fp64_is_NaN(b_exp, b_mnt)) {
682 if (fp64_is_signalling_NaN(a_exp, a_mnt) ||
683 fp64_is_signalling_NaN(b_exp, b_mnt)) {
684 if (mode & FPLIB_FPEXEC)
685 *flags |= FPLIB_IOC;
686 a |= 1ULL << (FP64_MANT_BITS - 1);
687 }
688
689 return fp64_process_NaN(a, mode, flags);
690 }
691 }
692
693 // Handle signalling NaNs:
694 if (fp64_is_signalling_NaN(a_exp, a_mnt))
695 return fp64_process_NaN(a, mode, flags);
696 if (fp64_is_signalling_NaN(b_exp, b_mnt))
697 return fp64_process_NaN(b, mode, flags);
698
699 // Handle quiet NaNs:
700 if (fp64_is_NaN(a_exp, a_mnt))
701 return fp64_process_NaN(a, mode, flags);
702 if (fp64_is_NaN(b_exp, b_mnt))
703 return fp64_process_NaN(b, mode, flags);
704
705 return 0;
706}
707
708static uint16_t
709fp16_process_NaNs3(uint16_t a, uint16_t b, uint16_t c, int mode, int *flags)
710{
711 int a_exp = FP16_EXP(a);
712 uint16_t a_mnt = FP16_MANT(a);
713 int b_exp = FP16_EXP(b);
714 uint16_t b_mnt = FP16_MANT(b);
715 int c_exp = FP16_EXP(c);
716 uint16_t c_mnt = FP16_MANT(c);
717
718 if (mode & FPLIB_AH) {
719 bool op1_nan = fp16_is_NaN(a_exp, a_mnt);
720 bool op2_nan = fp16_is_NaN(b_exp, b_mnt);
721 bool op3_nan = fp16_is_NaN(c_exp, c_mnt);
722 bool op1_snan = fp16_is_signalling_NaN(a_exp, a_mnt);
723 bool op2_snan = fp16_is_signalling_NaN(b_exp, b_mnt);
724 bool op3_snan = fp16_is_signalling_NaN(c_exp, c_mnt);
725 if (op1_nan && op2_nan && op3_nan) {
726 if (op1_snan || op2_snan || op3_snan) {
727 if (mode & FPLIB_FPEXEC)
728 *flags |= FPLIB_IOC;
729 b |= 1ULL << (FP16_MANT_BITS - 1);
730 }
731 return fp16_process_NaN(b, mode, flags);
732 } else if (op2_nan && (op1_nan || op3_nan)) {
733 if (op1_snan || op2_snan || op3_snan) {
734 if (mode & FPLIB_FPEXEC)
735 *flags |= FPLIB_IOC;
736 b |= 1ULL << (FP16_MANT_BITS - 1);
737 }
738 return fp16_process_NaN(b, mode, flags);
739 } else if (op3_nan && op1_nan) {
740 if (op1_snan || op2_snan || op3_snan) {
741 if (mode & FPLIB_FPEXEC)
742 *flags |= FPLIB_IOC;
743 c |= 1ULL << (FP16_MANT_BITS - 1);
744 }
745 return fp16_process_NaN(c, mode, flags);
746 }
747 }
748
749 // Handle signalling NaNs:
750 if (fp16_is_signalling_NaN(a_exp, a_mnt))
751 return fp16_process_NaN(a, mode, flags);
752 if (fp16_is_signalling_NaN(b_exp, b_mnt))
753 return fp16_process_NaN(b, mode, flags);
754 if (fp16_is_signalling_NaN(c_exp, c_mnt))
755 return fp16_process_NaN(c, mode, flags);
756
757 // Handle quiet NaNs:
758 if (fp16_is_NaN(a_exp, a_mnt))
759 return fp16_process_NaN(a, mode, flags);
760 if (fp16_is_NaN(b_exp, b_mnt))
761 return fp16_process_NaN(b, mode, flags);
762 if (fp16_is_NaN(c_exp, c_mnt))
763 return fp16_process_NaN(c, mode, flags);
764
765 return 0;
766}
767
768static uint32_t
769fp32_process_NaNs3(uint32_t a, uint32_t b, uint32_t c, int mode, int *flags)
770{
771 int a_exp = FP32_EXP(a);
772 uint32_t a_mnt = FP32_MANT(a);
773 int b_exp = FP32_EXP(b);
774 uint32_t b_mnt = FP32_MANT(b);
775 int c_exp = FP32_EXP(c);
776 uint32_t c_mnt = FP32_MANT(c);
777
778 if (mode & FPLIB_AH) {
779 bool op1_nan = fp32_is_NaN(a_exp, a_mnt);
780 bool op2_nan = fp32_is_NaN(b_exp, b_mnt);
781 bool op3_nan = fp32_is_NaN(c_exp, c_mnt);
782 bool op1_snan = fp32_is_signalling_NaN(a_exp, a_mnt);
783 bool op2_snan = fp32_is_signalling_NaN(b_exp, b_mnt);
784 bool op3_snan = fp32_is_signalling_NaN(c_exp, c_mnt);
785 if (op1_nan && op2_nan && op3_nan) {
786 if (op1_snan || op2_snan || op3_snan) {
787 if (mode & FPLIB_FPEXEC)
788 *flags |= FPLIB_IOC;
789 b |= 1ULL << (FP32_MANT_BITS - 1);
790 }
791 return fp32_process_NaN(b, mode, flags);
792 } else if (op2_nan && (op1_nan || op3_nan)) {
793 if (op1_snan || op2_snan || op3_snan) {
794 if (mode & FPLIB_FPEXEC)
795 *flags |= FPLIB_IOC;
796 b |= 1ULL << (FP32_MANT_BITS - 1);
797 }
798 return fp32_process_NaN(b, mode, flags);
799 } else if (op3_nan && op1_nan) {
800 if (op1_snan || op2_snan || op3_snan) {
801 if (mode & FPLIB_FPEXEC)
802 *flags |= FPLIB_IOC;
803 c |= 1ULL << (FP32_MANT_BITS - 1);
804 }
805 return fp32_process_NaN(c, mode, flags);
806 }
807 }
808
809 // Handle signalling NaNs:
810 if (fp32_is_signalling_NaN(a_exp, a_mnt))
811 return fp32_process_NaN(a, mode, flags);
812 if (fp32_is_signalling_NaN(b_exp, b_mnt))
813 return fp32_process_NaN(b, mode, flags);
814 if (fp32_is_signalling_NaN(c_exp, c_mnt))
815 return fp32_process_NaN(c, mode, flags);
816
817 // Handle quiet NaNs:
818 if (fp32_is_NaN(a_exp, a_mnt))
819 return fp32_process_NaN(a, mode, flags);
820 if (fp32_is_NaN(b_exp, b_mnt))
821 return fp32_process_NaN(b, mode, flags);
822 if (fp32_is_NaN(c_exp, c_mnt))
823 return fp32_process_NaN(c, mode, flags);
824
825 return 0;
826}
827
828static uint64_t
829fp64_process_NaNs3(uint64_t a, uint64_t b, uint64_t c, int mode, int *flags)
830{
831 int a_exp = FP64_EXP(a);
832 uint64_t a_mnt = FP64_MANT(a);
833 int b_exp = FP64_EXP(b);
834 uint64_t b_mnt = FP64_MANT(b);
835 int c_exp = FP64_EXP(c);
836 uint64_t c_mnt = FP64_MANT(c);
837
838 if (mode & FPLIB_AH) {
839 bool op1_nan = fp64_is_NaN(a_exp, a_mnt);
840 bool op2_nan = fp64_is_NaN(b_exp, b_mnt);
841 bool op3_nan = fp64_is_NaN(c_exp, c_mnt);
842 bool op1_snan = fp64_is_signalling_NaN(a_exp, a_mnt);
843 bool op2_snan = fp64_is_signalling_NaN(b_exp, b_mnt);
844 bool op3_snan = fp64_is_signalling_NaN(c_exp, c_mnt);
845 if (op1_nan && op2_nan && op3_nan) {
846 if (op1_snan || op2_snan || op3_snan) {
847 if (mode & FPLIB_FPEXEC)
848 *flags |= FPLIB_IOC;
849 b |= 1ULL << (FP64_MANT_BITS - 1);
850 }
851 return fp64_process_NaN(b, mode, flags);
852 } else if (op2_nan && (op1_nan || op3_nan)) {
853 if (op1_snan || op2_snan || op3_snan) {
854 if (mode & FPLIB_FPEXEC)
855 *flags |= FPLIB_IOC;
856 b |= 1ULL << (FP64_MANT_BITS - 1);
857 }
858 return fp64_process_NaN(b, mode, flags);
859 } else if (op3_nan && op1_nan) {
860 if (op1_snan || op2_snan || op3_snan) {
861 if (mode & FPLIB_FPEXEC)
862 *flags |= FPLIB_IOC;
863 c |= 1ULL << (FP64_MANT_BITS - 1);
864 }
865 return fp64_process_NaN(c, mode, flags);
866 }
867 }
868
869 // Handle signalling NaNs:
870 if (fp64_is_signalling_NaN(a_exp, a_mnt))
871 return fp64_process_NaN(a, mode, flags);
872 if (fp64_is_signalling_NaN(b_exp, b_mnt))
873 return fp64_process_NaN(b, mode, flags);
874 if (fp64_is_signalling_NaN(c_exp, c_mnt))
875 return fp64_process_NaN(c, mode, flags);
876
877 // Handle quiet NaNs:
878 if (fp64_is_NaN(a_exp, a_mnt))
879 return fp64_process_NaN(a, mode, flags);
880 if (fp64_is_NaN(b_exp, b_mnt))
881 return fp64_process_NaN(b, mode, flags);
882 if (fp64_is_NaN(c_exp, c_mnt))
883 return fp64_process_NaN(c, mode, flags);
884
885 return 0;
886}
887
888static uint32_t
890{
891 uint32_t sgn = op >> (FP16_BITS - 1);
892 uint32_t mnt = FP16_MANT(op);
893
894 mnt = mnt << (FP32_MANT_BITS - FP16_MANT_BITS);
895
896 return fp32_pack(sgn, FP32_EXP_INF, mnt);
897}
898
899static uint32_t
900fp16_process_NaNs4(uint16_t a, uint16_t b, uint16_t c, uint16_t d, int mode,
901 int *flags)
902{
903 int a_exp = FP16_EXP(a);
904 uint16_t a_mnt = FP16_MANT(a);
905 int b_exp = FP16_EXP(b);
906 uint16_t b_mnt = FP16_MANT(b);
907 int c_exp = FP16_EXP(c);
908 uint16_t c_mnt = FP16_MANT(c);
909 int d_exp = FP16_EXP(d);
910 uint16_t d_mnt = FP16_MANT(d);
911
912 // Handle signalling NaNs:
913 if (fp16_is_signalling_NaN(a_exp, a_mnt)) {
915 }
916 if (fp16_is_signalling_NaN(b_exp, b_mnt)) {
918 }
919 if (fp16_is_signalling_NaN(c_exp, c_mnt)) {
921 }
922 if (fp16_is_signalling_NaN(d_exp, d_mnt)) {
924 }
925
926 // Handle quiet NaNs:
927 if (fp16_is_NaN(a_exp, a_mnt)) {
929 }
930 if (fp16_is_NaN(b_exp, b_mnt)) {
932 }
933 if (fp16_is_NaN(c_exp, c_mnt)) {
935 }
936 if (fp16_is_NaN(d_exp, d_mnt)) {
938 }
939
940 return 0;
941}
942
943static uint32_t
944fp32_process_NaNs4(uint32_t a, uint32_t b, uint32_t c, uint32_t d,
945 int mode, int *flags)
946{
947 int a_exp = FP32_EXP(a);
948 uint32_t a_mnt = FP32_MANT(a);
949 int b_exp = FP32_EXP(b);
950 uint32_t b_mnt = FP32_MANT(b);
951 int c_exp = FP32_EXP(c);
952 uint32_t c_mnt = FP32_MANT(c);
953 int d_exp = FP32_EXP(d);
954 uint32_t d_mnt = FP32_MANT(d);
955
956 // Handle signalling NaNs:
957 if (fp32_is_signalling_NaN(a_exp, a_mnt))
958 return fp32_process_NaN(a, mode, flags);
959 if (fp32_is_signalling_NaN(b_exp, b_mnt))
960 return fp32_process_NaN(b, mode, flags);
961 if (fp32_is_signalling_NaN(c_exp, c_mnt))
962 return fp32_process_NaN(c, mode, flags);
963 if (fp32_is_signalling_NaN(d_exp, d_mnt))
964 return fp32_process_NaN(d, mode, flags);
965
966 // Handle quiet NaNs:
967 if (fp32_is_NaN(a_exp, a_mnt))
968 return fp32_process_NaN(a, mode, flags);
969 if (fp32_is_NaN(b_exp, b_mnt))
970 return fp32_process_NaN(b, mode, flags);
971 if (fp32_is_NaN(c_exp, c_mnt))
972 return fp32_process_NaN(c, mode, flags);
973 if (fp32_is_NaN(d_exp, d_mnt))
974 return fp32_process_NaN(d, mode, flags);
975
976 return 0;
977}
978
979static uint32_t
980fp32_process_NaNs3H(uint32_t a, uint16_t b, uint16_t c, int mode, int *flags)
981{
982 int a_exp = FP32_EXP(a);
983 uint32_t a_mnt = FP32_MANT(a);
984 int b_exp = FP16_EXP(b);
985 uint16_t b_mnt = FP16_MANT(b);
986 int c_exp = FP16_EXP(c);
987 uint16_t c_mnt = FP16_MANT(c);
988
989 if (mode & FPLIB_AH) {
990 bool op1_nan = fp32_is_NaN(a_exp, a_mnt);
991 bool op2_nan = fp16_is_NaN(b_exp, b_mnt);
992 bool op3_nan = fp16_is_NaN(c_exp, c_mnt);
993 bool op1_snan = fp32_is_signalling_NaN(a_exp, a_mnt);
994 bool op2_snan = fp16_is_signalling_NaN(b_exp, b_mnt);
995 bool op3_snan = fp16_is_signalling_NaN(c_exp, c_mnt);
996 if (op1_nan && op2_nan && op3_nan) {
997 if (op1_snan || op2_snan || op3_snan) {
998 if (mode & FPLIB_FPEXEC)
999 *flags |= FPLIB_IOC;
1000 b |= 1ULL << (FP16_MANT_BITS - 1);
1001 }
1003 } else if (op2_nan && (op1_nan || op3_nan)) {
1004 if (op1_snan || op2_snan || op3_snan) {
1005 if (mode & FPLIB_FPEXEC)
1006 *flags |= FPLIB_IOC;
1007 b |= 1ULL << (FP16_MANT_BITS - 1);
1008 }
1010 } else if (op3_nan && op1_nan) {
1011 if (op1_snan || op2_snan || op3_snan) {
1012 if (mode & FPLIB_FPEXEC)
1013 *flags |= FPLIB_IOC;
1014 c |= 1ULL << (FP16_MANT_BITS - 1);
1015 }
1017 }
1018 }
1019
1020 // Handle signalling NaNs:
1021 if (fp32_is_signalling_NaN(a_exp, a_mnt))
1022 return fp32_process_NaN(a, mode, flags);
1023 if (fp16_is_signalling_NaN(b_exp, b_mnt))
1025 if (fp16_is_signalling_NaN(c_exp, c_mnt))
1027
1028 // Handle quiet NaNs:
1029 if (fp32_is_NaN(a_exp, a_mnt))
1030 return fp32_process_NaN(a, mode, flags);
1031 if (fp16_is_NaN(b_exp, b_mnt))
1033 if (fp16_is_NaN(c_exp, c_mnt))
1035
1036 return 0;
1037}
1038
1039static uint16_t
1040fp16_round_(int sgn, int exp, uint16_t mnt, int rm, int mode, int *flags)
1041{
1042 // non-negative exponent value for result
1043 int biased_exp, biased_exp_afp;
1044 // mantissa for result, less than (2 << FP16_MANT_BITS)
1045 uint16_t int_mant, int_mant_afp;
1046 // 0, 1, 2 or 3, where 2 means int_mant is wrong by exactly 0.5
1047 int error, error_afp;
1048
1049 assert(rm != FPRounding_TIEAWAY);
1050
1051 // Flush to zero:
1052 // Deal with flush-to-zero before rounding if FPCR.AH != '1'.
1053 if (((mode & FPLIB_FZ16) && !(mode & FPLIB_AH)) && exp < 1) {
1054 if (mode & FPLIB_FPEXEC)
1055 *flags |= FPLIB_UFC;
1056 return fp16_zero(sgn);
1057 }
1058
1059 // The bottom FP16_EXP_BITS bits of mnt are orred together:
1060 mnt = (4ULL << FP16_MANT_BITS | mnt >> (FP16_EXP_BITS - 1) |
1061 ((mnt & ((1ULL << FP16_EXP_BITS) - 1)) != 0));
1062
1063 biased_exp_afp = exp;
1064 int_mant_afp = mnt >> 2;
1065 error_afp = mnt & 3;
1066 if (exp > 0) {
1067 biased_exp = exp;
1068 int_mant = mnt >> 2;
1069 error = mnt & 3;
1070 } else {
1071 biased_exp = 0;
1072 int_mant = lsr16(mnt, 3 - exp);
1073 error = (lsr16(mnt, 1 - exp) & 3) | !!(mnt & (lsl16(1, 1 - exp) - 1));
1074 }
1075
1076 // xx should also check fpscr_val<11>
1077 if (!(mode & FPLIB_AH) && !biased_exp && error) {
1078 if (mode & FPLIB_FPEXEC)
1079 *flags |= FPLIB_UFC;
1080 }
1081
1082 // Round up when enabling FEAT_AFP:
1083 if (mode & FPLIB_AH) {
1084 if ((rm == FPLIB_RN && (error_afp == 3 ||
1085 (error_afp == 2 && (int_mant_afp & 1)))) ||
1086 (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) &&
1087 error_afp)) {
1088 ++int_mant_afp;
1089 if (int_mant_afp == 2ULL << FP16_MANT_BITS) {
1090 // Rounded up to next exponent
1091 ++biased_exp_afp;
1092 int_mant_afp >>= 1;
1093 }
1094 }
1095 }
1096
1097 // Round up:
1098 if ((rm == FPLIB_RN && (error == 3 ||
1099 (error == 2 && (int_mant & 1)))) ||
1100 (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) && error)) {
1101 ++int_mant;
1102 if (int_mant == 1ULL << FP16_MANT_BITS) {
1103 // Rounded up from denormalized to normalized
1104 biased_exp = 1;
1105 }
1106 if (int_mant == 2ULL << FP16_MANT_BITS) {
1107 // Rounded up to next exponent
1108 ++biased_exp;
1109 int_mant >>= 1;
1110 }
1111 }
1112
1113 // Handle rounding to odd aka Von Neumann rounding:
1114 if (error && rm == FPRounding_ODD)
1115 int_mant |= 1;
1116
1117 // Flush to zero:
1118 // Deal with overflow and generate result.
1119 // Deal with flush-to-zero and underflow after rounding if FPCR.AH == '1'.
1120 if (biased_exp_afp < 1) {
1121 if ((mode & FPLIB_FZ16) && (mode & FPLIB_AH)) {
1122 if (mode & FPLIB_FPEXEC)
1123 *flags |= FPLIB_UFC | FPLIB_IXC;
1124 return fp16_zero(sgn);
1125 } else if (error) {
1126 if (mode & FPLIB_FPEXEC)
1127 *flags |= FPLIB_UFC;
1128 }
1129 }
1130
1131 // Handle overflow:
1132 if (!(mode & FPLIB_AHP)) {
1133 if (biased_exp >= (int)FP16_EXP_INF) {
1134 if (mode & FPLIB_FPEXEC)
1135 *flags |= FPLIB_OFC | FPLIB_IXC;
1136 if (rm == FPLIB_RN || (rm == FPLIB_RP && !sgn) ||
1137 (rm == FPLIB_RM && sgn)) {
1138 return fp16_infinity(sgn);
1139 } else {
1140 return fp16_max_normal(sgn);
1141 }
1142 }
1143 } else {
1144 if (biased_exp >= (int)FP16_EXP_INF + 1) {
1145 if (mode & FPLIB_FPEXEC)
1146 *flags |= FPLIB_IOC;
1147 return fp16_pack(sgn, FP16_EXP_INF, -1);
1148 }
1149 }
1150
1151 if (error) {
1152 if (mode & FPLIB_FPEXEC)
1153 *flags |= FPLIB_IXC;
1154 }
1155
1156 return fp16_pack(sgn, biased_exp, int_mant);
1157}
1158
1159static uint16_t
1160fp16_round(int sgn, int exp, uint16_t mnt, int mode, int *flags)
1161{
1162 return fp16_round_(sgn, exp, mnt, mode & 3, mode, flags);
1163}
1164
1165static uint32_t
1166fp32_round_(int sgn, int exp, uint32_t mnt, int rm, int mode, int *flags,
1167 bool rm_odd=false)
1168{
1169 // non-negative exponent value for result
1170 int biased_exp, biased_exp_afp;
1171 // mantissa for result, less than (2 << FP32_MANT_BITS)
1172 uint32_t int_mant, int_mant_afp;
1173 // 0, 1, 2 or 3, where 2 means int_mant is wrong by exactly 0.5
1174 int error, error_afp;
1175
1176 assert(rm != FPRounding_TIEAWAY);
1177
1178 // Flush to zero:
1179 // Deal with flush-to-zero before rounding if FPCR.AH != '1'.
1180 if (((mode & FPLIB_FZ) && !(mode & FPLIB_AH)) && exp < 1) {
1181 if (mode & FPLIB_FPEXEC)
1182 *flags |= FPLIB_UFC;
1183 return fp32_zero(sgn);
1184 }
1185
1186 // The bottom FP32_EXP_BITS bits of mnt are orred together
1187 mnt = (4ULL << FP32_MANT_BITS | mnt >> (FP32_EXP_BITS - 1) |
1188 ((mnt & ((1ULL << FP32_EXP_BITS) - 1)) != 0));
1189
1190 biased_exp_afp = exp;
1191 int_mant_afp = mnt >> 2;
1192 error_afp = mnt & 3;
1193 if (exp > 0) {
1194 biased_exp = exp;
1195 int_mant = mnt >> 2;
1196 error = mnt & 3;
1197 } else {
1198 biased_exp = 0;
1199 int_mant = lsr32(mnt, 3 - exp);
1200 error = (lsr32(mnt, 1 - exp) & 3) | !!(mnt & (lsl32(1, 1 - exp) - 1));
1201 }
1202
1203 // Underflow occurs if exponent is too small before rounding, and result is
1204 // inexact or the Underflow exception is trapped. This applies before
1205 // rounding if FPCR.AH != '1'.
1206 // xx should also check fpscr_val<11>
1207 if (!(mode & FPLIB_AH) && !biased_exp && error) {
1208 if (mode & FPLIB_FPEXEC)
1209 *flags |= FPLIB_UFC;
1210 }
1211
1212 // Round up when enabling FEAT_AFP:
1213 if (mode & FPLIB_AH) {
1214 if ((rm == FPLIB_RN && (error_afp == 3 ||
1215 (error_afp == 2 && (int_mant_afp & 1)))) ||
1216 (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) &&
1217 error_afp)) {
1218 ++int_mant_afp;
1219 if (int_mant_afp == 2ULL << FP32_MANT_BITS) {
1220 // Rounded up to next exponent
1221 ++biased_exp_afp;
1222 int_mant_afp >>= 1;
1223 }
1224 }
1225 }
1226
1227 // Round up:
1228 if ((rm == FPLIB_RN && (error == 3 ||
1229 (error == 2 && (int_mant & 1)))) ||
1230 (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) && error)) {
1231 ++int_mant;
1232 if (int_mant == 1ULL << FP32_MANT_BITS) {
1233 // Rounded up from denormalized to normalized
1234 biased_exp = 1;
1235 }
1236 if (int_mant == 2ULL << FP32_MANT_BITS) {
1237 // Rounded up to next exponent
1238 ++biased_exp;
1239 int_mant >>= 1;
1240 }
1241 }
1242
1243 // Handle rounding to odd aka Von Neumann rounding:
1244 if (error && rm == FPRounding_ODD)
1245 int_mant |= 1;
1246
1247 // Flush to zero:
1248 // Deal with overflow and generate result.
1249 // Deal with flush-to-zero and underflow after rounding if FPCR.AH == '1'.
1250 if (biased_exp_afp < 1) {
1251 if ((mode & FPLIB_FZ) && (mode & FPLIB_AH)) {
1252 if (mode & FPLIB_FPEXEC)
1253 *flags |= FPLIB_UFC | FPLIB_IXC;
1254 return fp32_zero(sgn);
1255 } else if (error) {
1256 if (mode & FPLIB_FPEXEC)
1257 *flags |= FPLIB_UFC;
1258 }
1259 }
1260
1261 // Handle overflow:
1262 if (biased_exp >= (int)FP32_EXP_INF) {
1263 if (mode & FPLIB_FPEXEC)
1264 *flags |= FPLIB_OFC | FPLIB_IXC;
1265 if (rm == FPLIB_RN || (rm == FPLIB_RP && !sgn) ||
1266 (rm == FPLIB_RM && sgn) || rm_odd) {
1267 return fp32_infinity(sgn);
1268 } else {
1269 return fp32_max_normal(sgn);
1270 }
1271 }
1272
1273 if (error) {
1274 if (mode & FPLIB_FPEXEC)
1275 *flags |= FPLIB_IXC;
1276 }
1277
1278 return fp32_pack(sgn, biased_exp, int_mant);
1279}
1280
1281static uint32_t
1282fp32_round(int sgn, int exp, uint32_t mnt, int mode, int *flags)
1283{
1284 return fp32_round_(sgn, exp, mnt, mode & 3, mode, flags);
1285}
1286
1287static uint64_t
1288fp64_round_(int sgn, int exp, uint64_t mnt, int rm, int mode, int *flags)
1289{
1290 // non-negative exponent value for result
1291 int biased_exp, biased_exp_afp;
1292 // mantissa for result, less than (2 << FP64_MANT_BITS)
1293 uint64_t int_mant, int_mant_afp;
1294 // 0, 1, 2 or 3, where 2 means int_mant is wrong by exactly 0.5
1295 int error, error_afp;
1296 assert(rm != FPRounding_TIEAWAY);
1297
1298 // Deal with flush-to-zero before rounding if FPCR.AH != '1'.
1299 if (((mode & FPLIB_FZ) && !(mode & FPLIB_AH)) && exp < 1) {
1300 if (mode & FPLIB_FPEXEC)
1301 *flags |= FPLIB_UFC;
1302 return fp64_zero(sgn);
1303 }
1304
1305 // The bottom FP64_EXP_BITS bits of mnt are orred together:
1306 mnt = (4ULL << FP64_MANT_BITS | mnt >> (FP64_EXP_BITS - 1) |
1307 ((mnt & ((1ULL << FP64_EXP_BITS) - 1)) != 0));
1308
1309 biased_exp_afp = exp;
1310 int_mant_afp = mnt >> 2;
1311 error_afp = mnt & 3;
1312 if (exp > 0) {
1313 biased_exp = exp;
1314 int_mant = mnt >> 2;
1315 error = mnt & 3;
1316 } else {
1317 biased_exp = 0;
1318 int_mant = lsr64(mnt, 3 - exp);
1319 error = (lsr64(mnt, 1 - exp) & 3) | !!(mnt & (lsl64(1, 1 - exp) - 1));
1320 }
1321
1322 // xx should also check fpscr_val<11>
1323 if (!(mode & FPLIB_AH) && !biased_exp && error) {
1324 if (mode & FPLIB_FPEXEC)
1325 *flags |= FPLIB_UFC;
1326 }
1327
1328 // Round up when enabling FEAT_AFP:
1329 if (mode & FPLIB_AH) {
1330 if ((rm == FPLIB_RN && (error_afp == 3 ||
1331 (error_afp == 2 && (int_mant_afp & 1)))) ||
1332 (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) &&
1333 error_afp)) {
1334 ++int_mant_afp;
1335 if (int_mant_afp == 2ULL << FP64_MANT_BITS) {
1336 // Rounded up to next exponent
1337 ++biased_exp_afp;
1338 int_mant_afp >>= 1;
1339 }
1340 }
1341 }
1342
1343 // Round up:
1344 if ((rm == FPLIB_RN && (error == 3 ||
1345 (error == 2 && (int_mant & 1)))) ||
1346 (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) && error)) {
1347 ++int_mant;
1348 if (int_mant == 1ULL << FP64_MANT_BITS) {
1349 // Rounded up from denormalized to normalized
1350 biased_exp = 1;
1351 }
1352 if (int_mant == 2ULL << FP64_MANT_BITS) {
1353 // Rounded up to next exponent
1354 ++biased_exp;
1355 int_mant >>= 1;
1356 }
1357 }
1358
1359 // Handle rounding to odd aka Von Neumann rounding:
1360 if (error && rm == FPRounding_ODD)
1361 int_mant |= 1;
1362
1363 // Flush to zero:
1364 // Deal with overflow and generate result.
1365 // Deal with flush-to-zero and underflow after rounding if FPCR.AH == '1'.
1366 if (biased_exp_afp < 1) {
1367 if ((mode & FPLIB_FZ) && (mode & FPLIB_AH)) {
1368 if (mode & FPLIB_FPEXEC)
1369 *flags |= FPLIB_UFC | FPLIB_IXC;
1370 return fp64_zero(sgn);
1371 } else if (error) {
1372 if (mode & FPLIB_FPEXEC)
1373 *flags |= FPLIB_UFC;
1374 }
1375 }
1376
1377 // Handle overflow:
1378 if (biased_exp >= (int)FP64_EXP_INF) {
1379 if (mode & FPLIB_FPEXEC)
1380 *flags |= FPLIB_OFC | FPLIB_IXC;
1381 if (rm == FPLIB_RN || (rm == FPLIB_RP && !sgn) ||
1382 (rm == FPLIB_RM && sgn)) {
1383 return fp64_infinity(sgn);
1384 } else {
1385 return fp64_max_normal(sgn);
1386 }
1387 }
1388
1389 if (error) {
1390 if (mode & FPLIB_FPEXEC)
1391 *flags |= FPLIB_IXC;
1392 }
1393
1394 return fp64_pack(sgn, biased_exp, int_mant);
1395}
1396
1397static uint64_t
1398fp64_round(int sgn, int exp, uint64_t mnt, int mode, int *flags)
1399{
1400 return fp64_round_(sgn, exp, mnt, mode & 3, mode, flags);
1401}
1402
1403static int
1404fp16_compare_eq(uint16_t a, uint16_t b, int mode, int *flags)
1405{
1406 int a_sgn, a_exp, b_sgn, b_exp;
1407 uint16_t a_mnt, b_mnt;
1408
1409 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1410 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1411
1412 if (fp16_is_NaN(a_exp, a_mnt) ||
1413 fp16_is_NaN(b_exp, b_mnt)) {
1414 if (fp16_is_signalling_NaN(a_exp, a_mnt) ||
1415 fp16_is_signalling_NaN(b_exp, b_mnt))
1416 *flags |= FPLIB_IOC;
1417 return 0;
1418 }
1419 return a == b || (!a_mnt && !b_mnt);
1420}
1421
1422static int
1423fp16_compare_ge(uint16_t a, uint16_t b, int mode, int *flags)
1424{
1425 int a_sgn, a_exp, b_sgn, b_exp;
1426 uint16_t a_mnt, b_mnt;
1427
1428 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1429 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1430
1431 if (fp16_is_NaN(a_exp, a_mnt) ||
1432 fp16_is_NaN(b_exp, b_mnt)) {
1433 *flags |= FPLIB_IOC;
1434 return 0;
1435 }
1436 if (!a_mnt && !b_mnt)
1437 return 1;
1438 if (a_sgn != b_sgn)
1439 return b_sgn;
1440 if (a_exp != b_exp)
1441 return a_sgn ^ (a_exp > b_exp);
1442 if (a_mnt != b_mnt)
1443 return a_sgn ^ (a_mnt > b_mnt);
1444 return 1;
1445}
1446
1447static int
1448fp16_compare_gt(uint16_t a, uint16_t b, int mode, int *flags)
1449{
1450 int a_sgn, a_exp, b_sgn, b_exp;
1451 uint16_t a_mnt, b_mnt;
1452
1453 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1454 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1455
1456 if (fp16_is_NaN(a_exp, a_mnt) ||
1457 fp16_is_NaN(b_exp, b_mnt)) {
1458 *flags |= FPLIB_IOC;
1459 return 0;
1460 }
1461 if (!a_mnt && !b_mnt)
1462 return 0;
1463 if (a_sgn != b_sgn)
1464 return b_sgn;
1465 if (a_exp != b_exp)
1466 return a_sgn ^ (a_exp > b_exp);
1467 if (a_mnt != b_mnt)
1468 return a_sgn ^ (a_mnt > b_mnt);
1469 return 0;
1470}
1471
1472static int
1473fp16_compare_un(uint16_t a, uint16_t b, int mode, int *flags)
1474{
1475 int a_sgn, a_exp, b_sgn, b_exp;
1476 uint16_t a_mnt, b_mnt;
1477
1478 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1479 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1480
1481 if (fp16_is_NaN(a_exp, a_mnt) ||
1482 fp16_is_NaN(b_exp, b_mnt)) {
1483 if (fp16_is_signalling_NaN(a_exp, a_mnt) ||
1484 fp16_is_signalling_NaN(b_exp, b_mnt))
1485 *flags |= FPLIB_IOC;
1486 return 1;
1487 }
1488 return 0;
1489}
1490
1491static int
1492fp32_compare_eq(uint32_t a, uint32_t b, int mode, int *flags)
1493{
1494 int a_sgn, a_exp, b_sgn, b_exp;
1495 uint32_t a_mnt, b_mnt;
1496
1497 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1498 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1499
1500 if (fp32_is_NaN(a_exp, a_mnt) ||
1501 fp32_is_NaN(b_exp, b_mnt)) {
1502 if (fp32_is_signalling_NaN(a_exp, a_mnt) ||
1503 fp32_is_signalling_NaN(b_exp, b_mnt))
1504 *flags |= FPLIB_IOC;
1505 return 0;
1506 }
1507
1508 // FPProcessDenorms2
1509 if (mode & FPLIB_AH) {
1510 if (fp32_is_denormal(a_exp, a_mnt) || fp32_is_denormal(b_exp, b_mnt)) {
1511 *flags |= FPLIB_IDC;
1512 }
1513 }
1514
1515 return a == b || (!a_mnt && !b_mnt);
1516}
1517
1518static int
1519fp32_compare_ge(uint32_t a, uint32_t b, int mode, int *flags)
1520{
1521 int a_sgn, a_exp, b_sgn, b_exp;
1522 uint32_t a_mnt, b_mnt;
1523
1524 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1525 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1526
1527 if (fp32_is_NaN(a_exp, a_mnt) ||
1528 fp32_is_NaN(b_exp, b_mnt)) {
1529 *flags |= FPLIB_IOC;
1530 return 0;
1531 }
1532
1533 // FPProcessDenorms2
1534 if (mode & FPLIB_AH) {
1535 if (fp32_is_denormal(a_exp, a_mnt) || fp32_is_denormal(b_exp, b_mnt)) {
1536 *flags |= FPLIB_IDC;
1537 }
1538 }
1539
1540 if (!a_mnt && !b_mnt)
1541 return 1;
1542 if (a_sgn != b_sgn)
1543 return b_sgn;
1544 if (a_exp != b_exp)
1545 return a_sgn ^ (a_exp > b_exp);
1546 if (a_mnt != b_mnt)
1547 return a_sgn ^ (a_mnt > b_mnt);
1548 return 1;
1549}
1550
1551static int
1552fp32_compare_gt(uint32_t a, uint32_t b, int mode, int *flags)
1553{
1554 int a_sgn, a_exp, b_sgn, b_exp;
1555 uint32_t a_mnt, b_mnt;
1556
1557 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1558 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1559
1560 if (fp32_is_NaN(a_exp, a_mnt) ||
1561 fp32_is_NaN(b_exp, b_mnt)) {
1562 *flags |= FPLIB_IOC;
1563 return 0;
1564 }
1565
1566 // FPProcessDenorms2
1567 if (mode & FPLIB_AH) {
1568 if (fp32_is_denormal(a_exp, a_mnt) || fp32_is_denormal(b_exp, b_mnt)) {
1569 *flags |= FPLIB_IDC;
1570 }
1571 }
1572
1573 if (!a_mnt && !b_mnt)
1574 return 0;
1575 if (a_sgn != b_sgn)
1576 return b_sgn;
1577 if (a_exp != b_exp)
1578 return a_sgn ^ (a_exp > b_exp);
1579 if (a_mnt != b_mnt)
1580 return a_sgn ^ (a_mnt > b_mnt);
1581 return 0;
1582}
1583
1584static int
1585fp32_compare_un(uint32_t a, uint32_t b, int mode, int *flags)
1586{
1587 int a_sgn, a_exp, b_sgn, b_exp;
1588 uint32_t a_mnt, b_mnt;
1589
1590 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1591 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1592
1593 if (fp32_is_NaN(a_exp, a_mnt) ||
1594 fp32_is_NaN(b_exp, b_mnt)) {
1595 if (fp32_is_signalling_NaN(a_exp, a_mnt) ||
1596 fp32_is_signalling_NaN(b_exp, b_mnt))
1597 *flags |= FPLIB_IOC;
1598 return 1;
1599 }
1600
1601 // FPProcessDenorms2
1602 if (mode & FPLIB_AH) {
1603 if (fp32_is_denormal(a_exp, a_mnt) || fp32_is_denormal(b_exp, b_mnt)) {
1604 *flags |= FPLIB_IDC;
1605 }
1606 }
1607
1608 return 0;
1609}
1610
1611static int
1612fp64_compare_eq(uint64_t a, uint64_t b, int mode, int *flags)
1613{
1614 int a_sgn, a_exp, b_sgn, b_exp;
1615 uint64_t a_mnt, b_mnt;
1616
1617 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1618 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1619
1620 if (fp64_is_NaN(a_exp, a_mnt) ||
1621 fp64_is_NaN(b_exp, b_mnt)) {
1622 if (fp64_is_signalling_NaN(a_exp, a_mnt) ||
1623 fp64_is_signalling_NaN(b_exp, b_mnt))
1624 *flags |= FPLIB_IOC;
1625 return 0;
1626 }
1627
1628 // FPProcessDenorms2
1629 if (mode & FPLIB_AH) {
1630 if (fp64_is_denormal(a_exp, a_mnt) || fp64_is_denormal(b_exp, b_mnt)) {
1631 *flags |= FPLIB_IDC;
1632 }
1633 }
1634
1635 return a == b || (!a_mnt && !b_mnt);
1636}
1637
1638static int
1639fp64_compare_ge(uint64_t a, uint64_t b, int mode, int *flags)
1640{
1641 int a_sgn, a_exp, b_sgn, b_exp;
1642 uint64_t a_mnt, b_mnt;
1643
1644 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1645 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1646
1647 if (fp64_is_NaN(a_exp, a_mnt) ||
1648 fp64_is_NaN(b_exp, b_mnt)) {
1649 *flags |= FPLIB_IOC;
1650 return 0;
1651 }
1652
1653 // FPProcessDenorms2
1654 if (mode & FPLIB_AH) {
1655 if (fp64_is_denormal(a_exp, a_mnt) || fp64_is_denormal(b_exp, b_mnt)) {
1656 *flags |= FPLIB_IDC;
1657 }
1658 }
1659
1660 if (!a_mnt && !b_mnt)
1661 return 1;
1662 if (a_sgn != b_sgn)
1663 return b_sgn;
1664 if (a_exp != b_exp)
1665 return a_sgn ^ (a_exp > b_exp);
1666 if (a_mnt != b_mnt)
1667 return a_sgn ^ (a_mnt > b_mnt);
1668 return 1;
1669}
1670
1671static int
1672fp64_compare_gt(uint64_t a, uint64_t b, int mode, int *flags)
1673{
1674 int a_sgn, a_exp, b_sgn, b_exp;
1675 uint64_t a_mnt, b_mnt;
1676
1677 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1678 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1679
1680 if (fp64_is_NaN(a_exp, a_mnt) ||
1681 fp64_is_NaN(b_exp, b_mnt)) {
1682 *flags |= FPLIB_IOC;
1683 return 0;
1684 }
1685
1686 // FPProcessDenorms2
1687 if (mode & FPLIB_AH) {
1688 if (fp64_is_denormal(a_exp, a_mnt) || fp64_is_denormal(b_exp, b_mnt)) {
1689 *flags |= FPLIB_IDC;
1690 }
1691 }
1692
1693 if (!a_mnt && !b_mnt)
1694 return 0;
1695 if (a_sgn != b_sgn)
1696 return b_sgn;
1697 if (a_exp != b_exp)
1698 return a_sgn ^ (a_exp > b_exp);
1699 if (a_mnt != b_mnt)
1700 return a_sgn ^ (a_mnt > b_mnt);
1701 return 0;
1702}
1703
1704static int
1705fp64_compare_un(uint64_t a, uint64_t b, int mode, int *flags)
1706{
1707 int a_sgn, a_exp, b_sgn, b_exp;
1708 uint64_t a_mnt, b_mnt;
1709
1710 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1711 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1712
1713 if (fp64_is_NaN(a_exp, a_mnt) ||
1714 fp64_is_NaN(b_exp, b_mnt)) {
1715 if (fp64_is_signalling_NaN(a_exp, a_mnt) ||
1716 fp64_is_signalling_NaN(b_exp, b_mnt))
1717 *flags |= FPLIB_IOC;
1718 return 1;
1719 }
1720
1721 // FPProcessDenorms2
1722 if (mode & FPLIB_AH) {
1723 if (fp64_is_denormal(a_exp, a_mnt) || fp64_is_denormal(b_exp, b_mnt)) {
1724 *flags |= FPLIB_IDC;
1725 }
1726 }
1727
1728 return 0;
1729}
1730
1731static uint16_t
1732fp16_add(uint16_t a, uint16_t b, int neg, int mode, int *flags)
1733{
1734 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1735 uint16_t a_mnt, b_mnt, x, x_mnt;
1736
1737 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1738 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1739
1740 if ((x = fp16_process_NaNs(a, b, mode, flags))) {
1741 return x;
1742 }
1743
1744 b_sgn ^= neg;
1745
1746 // Handle infinities and zeroes:
1747 if (a_exp == FP16_EXP_INF && b_exp == FP16_EXP_INF && a_sgn != b_sgn) {
1748 *flags |= FPLIB_IOC;
1749 return fp16_defaultNaN(mode);
1750 } else if (a_exp == FP16_EXP_INF) {
1751 return fp16_infinity(a_sgn);
1752 } else if (b_exp == FP16_EXP_INF) {
1753 return fp16_infinity(b_sgn);
1754 } else if (!a_mnt && !b_mnt && a_sgn == b_sgn) {
1755 return fp16_zero(a_sgn);
1756 }
1757
1758 a_mnt <<= 3;
1759 b_mnt <<= 3;
1760 if (a_exp >= b_exp) {
1761 b_mnt = (lsr16(b_mnt, a_exp - b_exp) |
1762 !!(b_mnt & (lsl16(1, a_exp - b_exp) - 1)));
1763 b_exp = a_exp;
1764 } else {
1765 a_mnt = (lsr16(a_mnt, b_exp - a_exp) |
1766 !!(a_mnt & (lsl16(1, b_exp - a_exp) - 1)));
1767 a_exp = b_exp;
1768 }
1769 x_sgn = a_sgn;
1770 x_exp = a_exp;
1771 if (a_sgn == b_sgn) {
1772 x_mnt = a_mnt + b_mnt;
1773 } else if (a_mnt >= b_mnt) {
1774 x_mnt = a_mnt - b_mnt;
1775 } else {
1776 x_sgn ^= 1;
1777 x_mnt = b_mnt - a_mnt;
1778 }
1779
1780 if (!x_mnt) {
1781 // Sign of exact zero result depends on rounding mode
1782 return fp16_zero((mode & 3) == 2);
1783 }
1784
1785 x_mnt = fp16_normalise(x_mnt, &x_exp);
1786
1787 return fp16_round(x_sgn, x_exp + FP16_EXP_BITS - 3, x_mnt << 1,
1788 mode, flags);
1789}
1790
1791static uint32_t
1792fp32_add(uint32_t a, uint32_t b, int neg, int mode, int *flags,
1793 bool rm_odd=false)
1794{
1795 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1796 uint32_t a_mnt, b_mnt, x, x_mnt;
1797
1798 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1799 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1800
1801 if ((x = fp32_process_NaNs(a, b, mode, flags))) {
1802 return x;
1803 }
1804
1805 // FPProcessDenorms2
1806 if (mode & FPLIB_AH) {
1807 if (fp32_is_denormal(a_exp, a_mnt) || fp32_is_denormal(b_exp, b_mnt)) {
1808 *flags |= FPLIB_IDC;
1809 }
1810 }
1811
1812 b_sgn ^= neg;
1813
1814 // Handle infinities and zeroes:
1815 if (a_exp == FP32_EXP_INF && b_exp == FP32_EXP_INF && a_sgn != b_sgn) {
1816 *flags |= FPLIB_IOC;
1817 return fp32_defaultNaN(mode);
1818 } else if (a_exp == FP32_EXP_INF) {
1819 return fp32_infinity(a_sgn);
1820 } else if (b_exp == FP32_EXP_INF) {
1821 return fp32_infinity(b_sgn);
1822 } else if (!a_mnt && !b_mnt && a_sgn == b_sgn) {
1823 return fp32_zero(a_sgn);
1824 }
1825
1826 a_mnt <<= 3;
1827 b_mnt <<= 3;
1828 if (a_exp >= b_exp) {
1829 b_mnt = (lsr32(b_mnt, a_exp - b_exp) |
1830 !!(b_mnt & (lsl32(1, a_exp - b_exp) - 1)));
1831 b_exp = a_exp;
1832 } else {
1833 a_mnt = (lsr32(a_mnt, b_exp - a_exp) |
1834 !!(a_mnt & (lsl32(1, b_exp - a_exp) - 1)));
1835 a_exp = b_exp;
1836 }
1837 x_sgn = a_sgn;
1838 x_exp = a_exp;
1839 if (a_sgn == b_sgn) {
1840 x_mnt = a_mnt + b_mnt;
1841 } else if (a_mnt >= b_mnt) {
1842 x_mnt = a_mnt - b_mnt;
1843 } else {
1844 x_sgn ^= 1;
1845 x_mnt = b_mnt - a_mnt;
1846 }
1847
1848 if (!x_mnt) {
1849 // Sign of exact zero result depends on rounding mode
1850 return fp32_zero(!rm_odd && (mode & 3) == 2);
1851 }
1852
1853 x_mnt = fp32_normalise(x_mnt, &x_exp);
1854
1855 if (rm_odd) {
1856 return fp32_round_(x_sgn, x_exp + FP32_EXP_BITS - 3, x_mnt << 1,
1857 FPRounding_ODD, mode, flags, true);
1858 } else {
1859 return fp32_round(x_sgn, x_exp + FP32_EXP_BITS - 3, x_mnt << 1,
1860 mode, flags);
1861 }
1862}
1863
1864static uint64_t
1865fp64_add(uint64_t a, uint64_t b, int neg, int mode, int *flags)
1866{
1867 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1868 uint64_t a_mnt, b_mnt, x, x_mnt;
1869
1870 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1871 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1872
1873 if ((x = fp64_process_NaNs(a, b, mode, flags))) {
1874 return x;
1875 }
1876
1877 // FPProcessDenorms2
1878 if (mode & FPLIB_AH) {
1879 if (fp64_is_denormal(a_exp, a_mnt) || fp64_is_denormal(b_exp, b_mnt)) {
1880 *flags |= FPLIB_IDC;
1881 }
1882 }
1883
1884 b_sgn ^= neg;
1885
1886 // Handle infinities and zeroes:
1887 if (a_exp == FP64_EXP_INF && b_exp == FP64_EXP_INF && a_sgn != b_sgn) {
1888 *flags |= FPLIB_IOC;
1889 return fp64_defaultNaN(mode);
1890 } else if (a_exp == FP64_EXP_INF) {
1891 return fp64_infinity(a_sgn);
1892 } else if (b_exp == FP64_EXP_INF) {
1893 return fp64_infinity(b_sgn);
1894 } else if (!a_mnt && !b_mnt && a_sgn == b_sgn) {
1895 return fp64_zero(a_sgn);
1896 }
1897
1898 a_mnt <<= 3;
1899 b_mnt <<= 3;
1900 if (a_exp >= b_exp) {
1901 b_mnt = (lsr64(b_mnt, a_exp - b_exp) |
1902 !!(b_mnt & (lsl64(1, a_exp - b_exp) - 1)));
1903 b_exp = a_exp;
1904 } else {
1905 a_mnt = (lsr64(a_mnt, b_exp - a_exp) |
1906 !!(a_mnt & (lsl64(1, b_exp - a_exp) - 1)));
1907 a_exp = b_exp;
1908 }
1909 x_sgn = a_sgn;
1910 x_exp = a_exp;
1911 if (a_sgn == b_sgn) {
1912 x_mnt = a_mnt + b_mnt;
1913 } else if (a_mnt >= b_mnt) {
1914 x_mnt = a_mnt - b_mnt;
1915 } else {
1916 x_sgn ^= 1;
1917 x_mnt = b_mnt - a_mnt;
1918 }
1919
1920 if (!x_mnt) {
1921 // Sign of exact zero result depends on rounding mode
1922 return fp64_zero((mode & 3) == 2);
1923 }
1924
1925 x_mnt = fp64_normalise(x_mnt, &x_exp);
1926
1927 return fp64_round(x_sgn, x_exp + FP64_EXP_BITS - 3, x_mnt << 1,
1928 mode, flags);
1929}
1930
1931static uint16_t
1932fp16_halved_add(uint16_t a, uint16_t b, int neg, int mode, int *flags)
1933{
1934 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1935 uint16_t a_mnt, b_mnt, x, x_mnt;
1936
1937 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
1938 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
1939
1940 if ((x = fp16_process_NaNs(a, b, mode, flags))) {
1941 return x;
1942 }
1943
1944 b_sgn ^= neg;
1945
1946 // Handle infinities and zeroes:
1947 if (a_exp == FP16_EXP_INF && b_exp == FP16_EXP_INF && a_sgn != b_sgn) {
1948 *flags |= FPLIB_IOC;
1949 return fp16_defaultNaN(mode);
1950 } else if (a_exp == FP16_EXP_INF) {
1951 return fp16_infinity(a_sgn);
1952 } else if (b_exp == FP16_EXP_INF) {
1953 return fp16_infinity(b_sgn);
1954 } else if (!a_mnt && !b_mnt && a_sgn == b_sgn) {
1955 return fp16_zero(a_sgn);
1956 }
1957
1958 a_mnt <<= 3;
1959 b_mnt <<= 3;
1960 if (a_exp >= b_exp) {
1961 b_mnt = (lsr16(b_mnt, a_exp - b_exp) |
1962 !!(b_mnt & (lsl16(1, a_exp - b_exp) - 1)));
1963 b_exp = a_exp;
1964 } else {
1965 a_mnt = (lsr16(a_mnt, b_exp - a_exp) |
1966 !!(a_mnt & (lsl16(1, b_exp - a_exp) - 1)));
1967 a_exp = b_exp;
1968 }
1969 x_sgn = a_sgn;
1970 x_exp = a_exp;
1971 if (a_sgn == b_sgn) {
1972 x_mnt = a_mnt + b_mnt;
1973 } else if (a_mnt >= b_mnt) {
1974 x_mnt = a_mnt - b_mnt;
1975 } else {
1976 x_sgn ^= 1;
1977 x_mnt = b_mnt - a_mnt;
1978 }
1979
1980 if (!x_mnt) {
1981 // Sign of exact zero result depends on rounding mode
1982 return fp16_zero((mode & 3) == 2);
1983 }
1984
1985 x_exp -= 1; // halved
1986 x_mnt = fp16_normalise(x_mnt, &x_exp);
1987
1988 return fp16_round(x_sgn, x_exp + FP16_EXP_BITS - 3, x_mnt << 1,
1989 mode, flags);
1990}
1991
1992static uint16_t
1993fp16_mul(uint16_t a, uint16_t b, int mode, int *flags)
1994{
1995 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
1996 uint16_t a_mnt, b_mnt, x;
1997 uint32_t x_mnt;
1998
1999 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2000 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
2001
2002 if ((x = fp16_process_NaNs(a, b, mode, flags))) {
2003 return x;
2004 }
2005
2006 // Handle infinities and zeroes:
2007 if ((a_exp == FP16_EXP_INF && !b_mnt) ||
2008 (b_exp == FP16_EXP_INF && !a_mnt)) {
2009 *flags |= FPLIB_IOC;
2010 return fp16_defaultNaN(mode);
2011 } else if (a_exp == FP16_EXP_INF || b_exp == FP16_EXP_INF) {
2012 return fp16_infinity(a_sgn ^ b_sgn);
2013 } else if (!a_mnt || !b_mnt) {
2014 return fp16_zero(a_sgn ^ b_sgn);
2015 }
2016
2017 // Multiply and normalise:
2018 x_sgn = a_sgn ^ b_sgn;
2019 x_exp = a_exp + b_exp - FP16_EXP_BIAS + 2 * FP16_EXP_BITS + 1;
2020 x_mnt = (uint32_t)a_mnt * b_mnt;
2021 x_mnt = fp32_normalise(x_mnt, &x_exp);
2022
2023 // Convert to FP16_BITS bits, collapsing error into bottom bit:
2024 x_mnt = lsr32(x_mnt, FP16_BITS - 1) | !!lsl32(x_mnt, FP16_BITS + 1);
2025
2026 return fp16_round(x_sgn, x_exp, x_mnt, mode, flags);
2027}
2028
2029static uint32_t
2030fp32_mul(uint32_t a, uint32_t b, int mode, int *flags, bool rm_odd=false)
2031{
2032 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
2033 uint32_t a_mnt, b_mnt, x;
2034 uint64_t x_mnt;
2035
2036 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2037 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
2038
2039 if ((x = fp32_process_NaNs(a, b, mode, flags))) {
2040 return x;
2041 }
2042
2043 // FPProcessDenorms2
2044 if (mode & FPLIB_AH) {
2045 if (fp32_is_denormal(a_exp, a_mnt) || fp32_is_denormal(b_exp, b_mnt)) {
2046 *flags |= FPLIB_IDC;
2047 }
2048 }
2049
2050 // Handle infinities and zeroes:
2051 if ((a_exp == FP32_EXP_INF && !b_mnt) ||
2052 (b_exp == FP32_EXP_INF && !a_mnt)) {
2053 *flags |= FPLIB_IOC;
2054 return fp32_defaultNaN(mode);
2055 } else if (a_exp == FP32_EXP_INF || b_exp == FP32_EXP_INF) {
2056 return fp32_infinity(a_sgn ^ b_sgn);
2057 } else if (!a_mnt || !b_mnt) {
2058 return fp32_zero(a_sgn ^ b_sgn);
2059 }
2060
2061 // Multiply and normalise:
2062 x_sgn = a_sgn ^ b_sgn;
2063 x_exp = a_exp + b_exp - FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1;
2064 x_mnt = (uint64_t)a_mnt * b_mnt;
2065 x_mnt = fp64_normalise(x_mnt, &x_exp);
2066
2067 // Convert to FP32_BITS bits, collapsing error into bottom bit:
2068 x_mnt = lsr64(x_mnt, FP32_BITS - 1) | !!lsl64(x_mnt, FP32_BITS + 1);
2069
2070 if (rm_odd) {
2071 return fp32_round_(x_sgn, x_exp, x_mnt, FPRounding_ODD, mode, flags,
2072 true);
2073 } else {
2074 return fp32_round(x_sgn, x_exp, x_mnt, mode, flags);
2075 }
2076}
2077
2078static uint64_t
2079fp64_mul(uint64_t a, uint64_t b, int mode, int *flags)
2080{
2081 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
2082 uint64_t a_mnt, b_mnt, x;
2083 uint64_t x0_mnt, x1_mnt;
2084
2085 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2086 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
2087
2088 if ((x = fp64_process_NaNs(a, b, mode, flags))) {
2089 return x;
2090 }
2091
2092 // FPProcessDenorms2
2093 if (mode & FPLIB_AH) {
2094 if (fp64_is_denormal(a_exp, a_mnt) || fp64_is_denormal(b_exp, b_mnt)) {
2095 *flags |= FPLIB_IDC;
2096 }
2097 }
2098
2099 // Handle infinities and zeroes:
2100 if ((a_exp == FP64_EXP_INF && !b_mnt) ||
2101 (b_exp == FP64_EXP_INF && !a_mnt)) {
2102 *flags |= FPLIB_IOC;
2103 return fp64_defaultNaN(mode);
2104 } else if (a_exp == FP64_EXP_INF || b_exp == FP64_EXP_INF) {
2105 return fp64_infinity(a_sgn ^ b_sgn);
2106 } else if (!a_mnt || !b_mnt) {
2107 return fp64_zero(a_sgn ^ b_sgn);
2108 }
2109
2110 // Multiply and normalise:
2111 x_sgn = a_sgn ^ b_sgn;
2112 x_exp = a_exp + b_exp - FP64_EXP_BIAS + 2 * FP64_EXP_BITS + 1;
2113 mul62x62(&x0_mnt, &x1_mnt, a_mnt, b_mnt);
2114 fp128_normalise(&x0_mnt, &x1_mnt, &x_exp);
2115
2116 // Convert to FP64_BITS bits, collapsing error into bottom bit:
2117 x0_mnt = x1_mnt << 1 | !!x0_mnt;
2118
2119 return fp64_round(x_sgn, x_exp, x0_mnt, mode, flags);
2120}
2121
2122static uint16_t
2123fp16_muladd(uint16_t a, uint16_t b, uint16_t c, int scale,
2124 int mode, int *flags)
2125{
2126 int a_sgn, a_exp, b_sgn, b_exp, c_sgn, c_exp, x_sgn, x_exp, y_sgn, y_exp;
2127 uint16_t a_mnt, b_mnt, c_mnt, x;
2128 uint32_t x_mnt, y_mnt;
2129
2130 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2131 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
2132 fp16_unpack(&c_sgn, &c_exp, &c_mnt, c, mode, flags);
2133
2134 x = fp16_process_NaNs3(a, b, c, mode, flags);
2135
2136 if (!(mode & FPLIB_AH)) {
2137 // Quiet NaN added to product of zero and infinity:
2138 if (fp16_is_quiet_NaN(a_exp, a_mnt) &&
2139 ((!b_mnt && fp16_is_infinity(c_exp, c_mnt)) ||
2140 (!c_mnt && fp16_is_infinity(b_exp, b_mnt)))) {
2142 if (mode & FPLIB_FPEXEC)
2143 *flags |= FPLIB_IOC;
2144 }
2145 }
2146
2147 if (x) {
2148 return x;
2149 }
2150
2151 // Handle infinities and zeroes:
2152 if ((b_exp == FP16_EXP_INF && !c_mnt) ||
2153 (c_exp == FP16_EXP_INF && !b_mnt) ||
2154 (a_exp == FP16_EXP_INF &&
2155 (b_exp == FP16_EXP_INF || c_exp == FP16_EXP_INF) &&
2156 (a_sgn != (b_sgn ^ c_sgn)))) {
2157 *flags |= FPLIB_IOC;
2158 return fp16_defaultNaN(mode);
2159 }
2160 if (a_exp == FP16_EXP_INF)
2161 return fp16_infinity(a_sgn);
2162 if (b_exp == FP16_EXP_INF || c_exp == FP16_EXP_INF)
2163 return fp16_infinity(b_sgn ^ c_sgn);
2164 if (!a_mnt && (!b_mnt || !c_mnt) && a_sgn == (b_sgn ^ c_sgn))
2165 return fp16_zero(a_sgn);
2166
2167 x_sgn = a_sgn;
2168 x_exp = a_exp + 2 * FP16_EXP_BITS - 3;
2169 x_mnt = (uint32_t)a_mnt << (FP16_MANT_BITS + 4);
2170
2171 // Multiply:
2172 y_sgn = b_sgn ^ c_sgn;
2173 y_exp = b_exp + c_exp - FP16_EXP_BIAS + 2 * FP16_EXP_BITS + 1 - 3;
2174 y_mnt = (uint32_t)b_mnt * c_mnt << 3;
2175 if (!y_mnt) {
2176 y_exp = x_exp;
2177 }
2178
2179 // Add:
2180 if (x_exp >= y_exp) {
2181 y_mnt = (lsr32(y_mnt, x_exp - y_exp) |
2182 !!(y_mnt & (lsl32(1, x_exp - y_exp) - 1)));
2183 y_exp = x_exp;
2184 } else {
2185 x_mnt = (lsr32(x_mnt, y_exp - x_exp) |
2186 !!(x_mnt & (lsl32(1, y_exp - x_exp) - 1)));
2187 x_exp = y_exp;
2188 }
2189 if (x_sgn == y_sgn) {
2190 x_mnt = x_mnt + y_mnt;
2191 } else if (x_mnt >= y_mnt) {
2192 x_mnt = x_mnt - y_mnt;
2193 } else {
2194 x_sgn ^= 1;
2195 x_mnt = y_mnt - x_mnt;
2196 }
2197
2198 if (!x_mnt) {
2199 // Sign of exact zero result depends on rounding mode
2200 return fp16_zero((mode & 3) == 2);
2201 }
2202
2203 // Normalise into FP16_BITS bits, collapsing error into bottom bit:
2204 x_mnt = fp32_normalise(x_mnt, &x_exp);
2205 x_mnt = x_mnt >> (FP16_BITS - 1) | !!(uint16_t)(x_mnt << 1);
2206
2207 return fp16_round(x_sgn, x_exp + scale, x_mnt, mode, flags);
2208}
2209
2210static uint32_t
2211fp32_muladd(uint32_t a, uint32_t b, uint32_t c, int scale,
2212 int mode, int *flags, bool rm_odd=false)
2213{
2214 int a_sgn, a_exp, b_sgn, b_exp, c_sgn, c_exp, x_sgn, x_exp, y_sgn, y_exp;
2215 uint32_t a_mnt, b_mnt, c_mnt, x;
2216 uint64_t x_mnt, y_mnt;
2217
2218 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2219 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
2220 fp32_unpack(&c_sgn, &c_exp, &c_mnt, c, mode, flags);
2221
2222 x = fp32_process_NaNs3(a, b, c, mode, flags);
2223
2224 if (!(mode & FPLIB_AH)) {
2225 // Quiet NaN added to product of zero and infinity:
2226 if (fp32_is_quiet_NaN(a_exp, a_mnt) &&
2227 ((!b_mnt && fp32_is_infinity(c_exp, c_mnt)) ||
2228 (!c_mnt && fp32_is_infinity(b_exp, b_mnt)))) {
2230 if (mode & FPLIB_FPEXEC)
2231 *flags |= FPLIB_IOC;
2232 }
2233 }
2234
2235 if (x) {
2236 return x;
2237 }
2238
2239 // Handle infinities and zeroes:
2240 if ((b_exp == FP32_EXP_INF && !c_mnt) ||
2241 (c_exp == FP32_EXP_INF && !b_mnt) ||
2242 (a_exp == FP32_EXP_INF &&
2243 (b_exp == FP32_EXP_INF || c_exp == FP32_EXP_INF) &&
2244 (a_sgn != (b_sgn ^ c_sgn)))) {
2245 if (mode & FPLIB_FPEXEC)
2246 *flags |= FPLIB_IOC;
2247 return fp32_defaultNaN(mode);
2248 }
2249
2250 // FPProcessDenorms3
2251 if (mode & FPLIB_AH) {
2252 if (fp32_is_denormal(a_exp, a_mnt) || fp32_is_denormal(b_exp, b_mnt) ||
2253 fp32_is_denormal(c_exp, c_mnt)) {
2254 *flags |= FPLIB_IDC;
2255 }
2256 }
2257
2258 if (a_exp == FP32_EXP_INF)
2259 return fp32_infinity(a_sgn);
2260 if (b_exp == FP32_EXP_INF || c_exp == FP32_EXP_INF)
2261 return fp32_infinity(b_sgn ^ c_sgn);
2262 if (!a_mnt && (!b_mnt || !c_mnt) && a_sgn == (b_sgn ^ c_sgn))
2263 return fp32_zero(a_sgn);
2264
2265 x_sgn = a_sgn;
2266 x_exp = a_exp + 2 * FP32_EXP_BITS - 3;
2267 x_mnt = (uint64_t)a_mnt << (FP32_MANT_BITS + 4);
2268
2269 // Multiply:
2270 y_sgn = b_sgn ^ c_sgn;
2271 y_exp = b_exp + c_exp - FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1 - 3;
2272 y_mnt = (uint64_t)b_mnt * c_mnt << 3;
2273 if (!y_mnt) {
2274 y_exp = x_exp;
2275 }
2276
2277 // Add:
2278 if (x_exp >= y_exp) {
2279 y_mnt = (lsr64(y_mnt, x_exp - y_exp) |
2280 !!(y_mnt & (lsl64(1, x_exp - y_exp) - 1)));
2281 y_exp = x_exp;
2282 } else {
2283 x_mnt = (lsr64(x_mnt, y_exp - x_exp) |
2284 !!(x_mnt & (lsl64(1, y_exp - x_exp) - 1)));
2285 x_exp = y_exp;
2286 }
2287 if (x_sgn == y_sgn) {
2288 x_mnt = x_mnt + y_mnt;
2289 } else if (x_mnt >= y_mnt) {
2290 x_mnt = x_mnt - y_mnt;
2291 } else {
2292 x_sgn ^= 1;
2293 x_mnt = y_mnt - x_mnt;
2294 }
2295
2296 if (!x_mnt) {
2297 // Sign of exact zero result depends on rounding mode
2298 if (rm_odd) {
2299 return fp32_zero(x_sgn);
2300 } else {
2301 return fp32_zero((mode & 3) == 2);
2302 }
2303 }
2304
2305 // Normalise into FP32_BITS bits, collapsing error into bottom bit:
2306 x_mnt = fp64_normalise(x_mnt, &x_exp);
2307 x_mnt = x_mnt >> (FP32_BITS - 1) | !!(uint32_t)(x_mnt << 1);
2308
2309 if (rm_odd) {
2310 return fp32_round_(x_sgn, x_exp + scale, x_mnt,
2311 FPRounding_ODD, mode, flags, true);
2312 } else {
2313 return fp32_round(x_sgn, x_exp + scale, x_mnt, mode, flags);
2314 }
2315}
2316
2317static uint64_t
2318fp64_muladd(uint64_t a, uint64_t b, uint64_t c, int scale,
2319 int mode, int *flags)
2320{
2321 int a_sgn, a_exp, b_sgn, b_exp, c_sgn, c_exp, x_sgn, x_exp, y_sgn, y_exp;
2322 uint64_t a_mnt, b_mnt, c_mnt, x;
2323 uint64_t x0_mnt, x1_mnt, y0_mnt, y1_mnt;
2324
2325 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2326 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
2327 fp64_unpack(&c_sgn, &c_exp, &c_mnt, c, mode, flags);
2328
2329 x = fp64_process_NaNs3(a, b, c, mode, flags);
2330
2331 if (!(mode & FPLIB_AH)) {
2332 // Quiet NaN added to product of zero and infinity:
2333 if (fp64_is_quiet_NaN(a_exp, a_mnt) &&
2334 ((!b_mnt && fp64_is_infinity(c_exp, c_mnt)) ||
2335 (!c_mnt && fp64_is_infinity(b_exp, b_mnt)))) {
2337 if (mode & FPLIB_FPEXEC)
2338 *flags |= FPLIB_IOC;
2339 }
2340 }
2341
2342 if (x) {
2343 return x;
2344 }
2345
2346 // Handle infinities and zeroes:
2347 if ((b_exp == FP64_EXP_INF && !c_mnt) ||
2348 (c_exp == FP64_EXP_INF && !b_mnt) ||
2349 (a_exp == FP64_EXP_INF &&
2350 (b_exp == FP64_EXP_INF || c_exp == FP64_EXP_INF) &&
2351 (a_sgn != (b_sgn ^ c_sgn)))) {
2352 if (mode & FPLIB_FPEXEC)
2353 *flags |= FPLIB_IOC;
2354 return fp64_defaultNaN(mode);
2355 }
2356
2357 // FPProcessDenorms3
2358 if (mode & FPLIB_AH) {
2359 if (fp64_is_denormal(a_exp, a_mnt) || fp64_is_denormal(b_exp, b_mnt) ||
2360 fp64_is_denormal(c_exp, c_mnt)) {
2361 *flags |= FPLIB_IDC;
2362 }
2363 }
2364
2365 if (a_exp == FP64_EXP_INF)
2366 return fp64_infinity(a_sgn);
2367 if (b_exp == FP64_EXP_INF || c_exp == FP64_EXP_INF)
2368 return fp64_infinity(b_sgn ^ c_sgn);
2369 if (!a_mnt && (!b_mnt || !c_mnt) && a_sgn == (b_sgn ^ c_sgn))
2370 return fp64_zero(a_sgn);
2371
2372 x_sgn = a_sgn;
2373 x_exp = a_exp + FP64_EXP_BITS;
2374 x0_mnt = 0;
2375 x1_mnt = a_mnt;
2376
2377 // Multiply:
2378 y_sgn = b_sgn ^ c_sgn;
2379 y_exp = b_exp + c_exp - FP64_EXP_BIAS + 2 * FP64_EXP_BITS + 1 - 3;
2380 mul62x62(&y0_mnt, &y1_mnt, b_mnt, c_mnt << 3);
2381 if (!y0_mnt && !y1_mnt) {
2382 y_exp = x_exp;
2383 }
2384
2385 // Add:
2386 if (x_exp >= y_exp) {
2387 uint64_t t0, t1;
2388 lsl128(&t0, &t1, y0_mnt, y1_mnt,
2389 x_exp - y_exp < 128 ? 128 - (x_exp - y_exp) : 0);
2390 lsr128(&y0_mnt, &y1_mnt, y0_mnt, y1_mnt, x_exp - y_exp);
2391 y0_mnt |= !!(t0 | t1);
2392 y_exp = x_exp;
2393 } else {
2394 uint64_t t0, t1;
2395 lsl128(&t0, &t1, x0_mnt, x1_mnt,
2396 y_exp - x_exp < 128 ? 128 - (y_exp - x_exp) : 0);
2397 lsr128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, y_exp - x_exp);
2398 x0_mnt |= !!(t0 | t1);
2399 x_exp = y_exp;
2400 }
2401 if (x_sgn == y_sgn) {
2402 add128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, y0_mnt, y1_mnt);
2403 } else if (cmp128(x0_mnt, x1_mnt, y0_mnt, y1_mnt) >= 0) {
2404 sub128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, y0_mnt, y1_mnt);
2405 } else {
2406 x_sgn ^= 1;
2407 sub128(&x0_mnt, &x1_mnt, y0_mnt, y1_mnt, x0_mnt, x1_mnt);
2408 }
2409
2410 if (!x0_mnt && !x1_mnt) {
2411 // Sign of exact zero result depends on rounding mode
2412 return fp64_zero((mode & 3) == 2);
2413 }
2414
2415 // Normalise into FP64_BITS bits, collapsing error into bottom bit:
2416 fp128_normalise(&x0_mnt, &x1_mnt, &x_exp);
2417 x0_mnt = x1_mnt << 1 | !!x0_mnt;
2418
2419 return fp64_round(x_sgn, x_exp + scale, x0_mnt, mode, flags);
2420}
2421
2422static uint32_t
2423fp32_muladdh(uint32_t a, uint16_t b, uint16_t c, int scale,
2424 int mode, int *flags, bool rm_odd=false)
2425{
2426 int a_sgn, a_exp, b_sgn, b_exp, c_sgn, c_exp, x_sgn, x_exp, y_sgn, y_exp;
2427 uint16_t b_mnt, c_mnt;
2428 uint32_t a_mnt, x;
2429 uint64_t x_mnt, y_mnt;
2430
2431 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2432 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
2433 fp16_unpack(&c_sgn, &c_exp, &c_mnt, c, mode, flags);
2434
2435 x = fp32_process_NaNs3H(a, b, c, mode, flags);
2436
2437 if (!(mode & FPLIB_AH)) {
2438 // Quiet NaN added to product of zero and infinity:
2439 if (fp32_is_quiet_NaN(a_exp, a_mnt) &&
2440 ((!b_mnt && fp16_is_infinity(c_exp, c_mnt)) ||
2441 (!c_mnt && fp16_is_infinity(b_exp, b_mnt)))) {
2443 if (mode & FPLIB_FPEXEC)
2444 *flags |= FPLIB_IOC;
2445 }
2446 }
2447
2448 if (x) {
2449 return x;
2450 }
2451
2452 // Handle infinities and zeroes:
2453 if ((b_exp == FP16_EXP_INF && !c_mnt) ||
2454 (c_exp == FP16_EXP_INF && !b_mnt) ||
2455 (a_exp == FP32_EXP_INF &&
2456 (b_exp == FP16_EXP_INF || c_exp == FP16_EXP_INF) &&
2457 (a_sgn != (b_sgn ^ c_sgn)))) {
2458 if (mode & FPLIB_FPEXEC)
2459 *flags |= FPLIB_IOC;
2460 return fp32_defaultNaN(mode);
2461 }
2462
2463 // FPProcessDenorms3
2464 if (mode & FPLIB_AH) {
2465 if (fp32_is_denormal(a_exp, a_mnt)) {
2466 *flags |= FPLIB_IDC;
2467 }
2468 }
2469
2470 if (a_exp == FP32_EXP_INF)
2471 return fp32_infinity(a_sgn);
2472 if (b_exp == FP16_EXP_INF || c_exp == FP16_EXP_INF)
2473 return fp32_infinity(b_sgn ^ c_sgn);
2474 if (!a_mnt && (!b_mnt || !c_mnt) && a_sgn == (b_sgn ^ c_sgn))
2475 return fp32_zero(a_sgn);
2476
2477 x_sgn = a_sgn;
2478 x_exp = a_exp + 2 * FP32_EXP_BITS - 3;
2479 x_mnt = (uint64_t)a_mnt << (FP32_MANT_BITS + 4);
2480
2481 // Multiply:
2482 y_sgn = b_sgn ^ c_sgn;
2483 y_exp = b_exp + c_exp - 2 * FP16_EXP_BIAS + 2 * FP32_EXP_BIAS -
2484 FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1 - 3;
2485 y_mnt = (uint64_t)b_mnt * c_mnt << (3 +
2487 if (!y_mnt) {
2488 y_exp = x_exp;
2489 }
2490
2491 // Add:
2492 if (x_exp >= y_exp) {
2493 y_mnt = (lsr64(y_mnt, x_exp - y_exp) |
2494 !!(y_mnt & (lsl64(1, x_exp - y_exp) - 1)));
2495 y_exp = x_exp;
2496 } else {
2497 x_mnt = (lsr64(x_mnt, y_exp - x_exp) |
2498 !!(x_mnt & (lsl64(1, y_exp - x_exp) - 1)));
2499 x_exp = y_exp;
2500 }
2501 if (x_sgn == y_sgn) {
2502 x_mnt = x_mnt + y_mnt;
2503 } else if (x_mnt >= y_mnt) {
2504 x_mnt = x_mnt - y_mnt;
2505 } else {
2506 x_sgn ^= 1;
2507 x_mnt = y_mnt - x_mnt;
2508 }
2509
2510 if (!x_mnt) {
2511 // Sign of exact zero result depends on rounding mode
2512 if (rm_odd) {
2513 return fp32_zero(x_sgn);
2514 } else {
2515 return fp32_zero((mode & 3) == 2);
2516 }
2517 }
2518
2519 // Normalise into FP32_BITS bits, collapsing error into bottom bit:
2520 x_mnt = fp64_normalise(x_mnt, &x_exp);
2521 x_mnt = x_mnt >> (FP32_BITS - 1) | !!(uint32_t)(x_mnt << 1);
2522
2523 if (rm_odd) {
2524 return fp32_round_(x_sgn, x_exp + scale, x_mnt,
2525 FPRounding_ODD, mode, flags, true);
2526 } else {
2527 return fp32_round(x_sgn, x_exp + scale, x_mnt, mode, flags);
2528 }
2529}
2530
2531uint32_t
2532fp32_dot(uint16_t op1_a, uint16_t op1_b, uint16_t op2_a, uint16_t op2_b,
2533 int mode, int *flags)
2534{
2535 int a1_sgn, b1_sgn, a2_sgn, b2_sgn, a1_exp, b1_exp, a2_exp, b2_exp;
2536 int pa_sgn, pb_sgn, pa_exp, pb_exp, x_sgn, x_exp;
2537 uint16_t a1_mnt, b1_mnt, a2_mnt, b2_mnt;
2538 uint32_t x;
2539 uint64_t pa_mnt, pb_mnt, x_mnt;
2540
2541 // data format of a1_mnt, b1_mnt, a2_mnt, b2_mnt: Q1.10
2542 fp16_unpack(&a1_sgn, &a1_exp, &a1_mnt, op1_a, mode, flags);
2543 fp16_unpack(&b1_sgn, &b1_exp, &b1_mnt, op1_b, mode, flags);
2544 fp16_unpack(&a2_sgn, &a2_exp, &a2_mnt, op2_a, mode, flags);
2545 fp16_unpack(&b2_sgn, &b2_exp, &b2_mnt, op2_b, mode, flags);
2546
2547 x = fp16_process_NaNs4(op1_a, op1_b, op2_a, op2_b, mode, flags);
2548 if (x) {
2549 return x;
2550 }
2551
2552 bool a1_inf = fp16_is_infinity(a1_exp, a1_mnt);
2553 bool a2_inf = fp16_is_infinity(a2_exp, a2_mnt);
2554 bool b1_inf = fp16_is_infinity(b1_exp, b1_mnt);
2555 bool b2_inf = fp16_is_infinity(b2_exp, b2_mnt);
2556
2557 bool a1_zero = !a1_exp && !a1_mnt;
2558 bool a2_zero = !a2_exp && !a2_mnt;
2559 bool b1_zero = !b1_exp && !b1_mnt;
2560 bool b2_zero = !b2_exp && !b2_mnt;
2561
2562 // Determine sign and type products will have if it does not cause an
2563 // Invalid Operation.
2564 pa_sgn = a1_sgn ^ a2_sgn;
2565 pb_sgn = b1_sgn ^ b2_sgn;
2566 bool pa_inf = a1_inf || a2_inf;
2567 bool pb_inf = b1_inf || b2_inf;
2568 bool pa_zero = a1_zero || a2_zero;
2569 bool pb_zero = b1_zero || b2_zero;
2570
2571 // Non SNaN-generated Invalid Operation cases are multiplies of zero
2572 // by infinity and additions of opposite-signed infinities.
2573 bool invalidop =
2574 ((a1_inf && a2_zero) || (a1_zero && a2_inf) || (b1_inf && b2_zero) ||
2575 (b1_zero && b2_inf) || (pa_inf && pb_inf && pa_sgn != pb_sgn));
2576
2577 if (invalidop) {
2579 *flags |= FPLIB_IOC;
2580 return x;
2581 }
2582
2583 // Other cases involving infinities produce an infinity of the same sign.
2584 if ((pa_inf && !pa_sgn) || (pb_inf && !pb_sgn)) {
2585 return fp32_infinity(0);
2586 } else if ((pa_inf && pa_sgn) || (pb_inf && pb_sgn)) {
2587 return fp32_infinity(1);
2588 }
2589
2590 // Cases where the result is exactly zero and its sign is not determined by
2591 // the rounding mode are additions of same-signed zeros.
2592 if (pa_zero && pb_zero && (pa_sgn == pb_sgn)) {
2593 return fp32_zero(pa_sgn);
2594 }
2595
2596 // Otherwise calculate fused sum of products and round it.
2597 // format of pa_mnt, pb_mnt, x_mnt: Q9.23
2598 // Multiply:
2599 pa_exp = a1_exp + a2_exp - 2 * FP16_EXP_BIAS + 2 * FP32_EXP_BIAS -
2600 FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1 - 3;
2601 pa_mnt = (uint64_t)a1_mnt * a2_mnt
2602 << (3 + (FP32_MANT_BITS - FP16_MANT_BITS) * 2);
2603
2604 pb_exp = b1_exp + b2_exp - 2 * FP16_EXP_BIAS + 2 * FP32_EXP_BIAS -
2605 FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1 - 3;
2606 pb_mnt = (uint64_t)b1_mnt * b2_mnt
2607 << (3 + (FP32_MANT_BITS - FP16_MANT_BITS) * 2);
2608 if (!pb_mnt && pa_mnt) {
2609 pb_exp = pa_exp;
2610 }
2611 if (pb_mnt && !pa_mnt) {
2612 pa_exp = pb_exp;
2613 }
2614
2615 // Add:
2616 if (pa_exp >= pb_exp) {
2617 pb_mnt = (lsr64(pb_mnt, pa_exp - pb_exp) |
2618 !!(pb_mnt & (lsl64(1, pa_exp - pb_exp) - 1)));
2619 pb_exp = pa_exp;
2620 } else {
2621 pa_mnt = (lsr64(pa_mnt, pb_exp - pa_exp) |
2622 !!(pa_mnt & (lsl64(1, pb_exp - pa_exp) - 1)));
2623 pa_exp = pb_exp;
2624 }
2625 x_sgn = pa_sgn;
2626 x_exp = pa_exp;
2627 if (pa_sgn == pb_sgn) {
2628 x_mnt = pa_mnt + pb_mnt;
2629 } else if (pa_mnt >= pb_mnt) {
2630 x_mnt = pa_mnt - pb_mnt;
2631 } else {
2632 x_sgn ^= 1;
2633 x_mnt = pb_mnt - pa_mnt;
2634 }
2635
2636 if (!x_mnt) {
2637 // Sign of exact zero result depends on rounding mode
2638 return fp32_zero((mode & 3) == 2);
2639 }
2640
2641 // format of x_mnt: Q1.63
2642 x_mnt = fp64_normalise(x_mnt, &x_exp);
2643 // format of x_mnt: Q1.32
2644 x_mnt = x_mnt >> (FP32_BITS - 1) | !!(uint32_t)(x_mnt << 1);
2645
2646 return fp32_round(x_sgn, x_exp, x_mnt, mode, flags);
2647}
2648
2649static uint16_t
2650fp16_div(uint16_t a, uint16_t b, int mode, int *flags)
2651{
2652 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
2653 uint16_t a_mnt, b_mnt, x;
2654 uint32_t x_mnt;
2655
2656 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2657 fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
2658
2659 if ((x = fp16_process_NaNs(a, b, mode, flags)))
2660 return x;
2661
2662 // Handle infinities and zeroes:
2663 if ((a_exp == FP16_EXP_INF && b_exp == FP16_EXP_INF) ||
2664 (!a_mnt && !b_mnt)) {
2665 *flags |= FPLIB_IOC;
2666 return fp16_defaultNaN(mode);
2667 }
2668 if (a_exp == FP16_EXP_INF || !b_mnt) {
2669 if (a_exp != FP16_EXP_INF)
2670 *flags |= FPLIB_DZC;
2671 return fp16_infinity(a_sgn ^ b_sgn);
2672 }
2673 if (!a_mnt || b_exp == FP16_EXP_INF)
2674 return fp16_zero(a_sgn ^ b_sgn);
2675
2676 // Divide, setting bottom bit if inexact:
2677 a_mnt = fp16_normalise(a_mnt, &a_exp);
2678 x_sgn = a_sgn ^ b_sgn;
2679 x_exp = a_exp - b_exp + (FP16_EXP_BIAS + FP16_BITS + 2 * FP16_EXP_BITS - 3);
2680 x_mnt = ((uint32_t)a_mnt << (FP16_MANT_BITS - FP16_EXP_BITS + 3)) / b_mnt;
2681 x_mnt |= (x_mnt * b_mnt !=
2682 (uint32_t)a_mnt << (FP16_MANT_BITS - FP16_EXP_BITS + 3));
2683
2684 // Normalise into FP16_BITS bits, collapsing error into bottom bit:
2685 x_mnt = fp32_normalise(x_mnt, &x_exp);
2686 x_mnt = x_mnt >> (FP16_BITS - 1) | !!(uint16_t)(x_mnt << 1);
2687
2688 return fp16_round(x_sgn, x_exp, x_mnt, mode, flags);
2689}
2690
2691static uint32_t
2692fp32_div(uint32_t a, uint32_t b, int mode, int *flags)
2693{
2694 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
2695 uint32_t a_mnt, b_mnt, x;
2696 uint64_t x_mnt;
2697
2698 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2699 fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
2700
2701 if ((x = fp32_process_NaNs(a, b, mode, flags)))
2702 return x;
2703
2704 if (b_exp || b_mnt) {
2705 // FPProcessDenorms2
2706 if (mode & FPLIB_AH) {
2707 if (fp32_is_denormal(a_exp, a_mnt) ||
2708 fp32_is_denormal(b_exp, b_mnt)) {
2709 *flags |= FPLIB_IDC;
2710 }
2711 }
2712 }
2713
2714 // Handle infinities and zeroes:
2715 if ((a_exp == FP32_EXP_INF && b_exp == FP32_EXP_INF) ||
2716 (!a_mnt && !b_mnt)) {
2717 *flags |= FPLIB_IOC;
2718 return fp32_defaultNaN(mode);
2719 }
2720 if (a_exp == FP32_EXP_INF || !b_mnt) {
2721 if (a_exp != FP32_EXP_INF)
2722 *flags |= FPLIB_DZC;
2723 return fp32_infinity(a_sgn ^ b_sgn);
2724 }
2725 if (!a_mnt || b_exp == FP32_EXP_INF)
2726 return fp32_zero(a_sgn ^ b_sgn);
2727
2728 // Divide, setting bottom bit if inexact:
2729 a_mnt = fp32_normalise(a_mnt, &a_exp);
2730 x_sgn = a_sgn ^ b_sgn;
2731 x_exp = a_exp - b_exp + (FP32_EXP_BIAS + FP32_BITS + 2 * FP32_EXP_BITS - 3);
2732 x_mnt = ((uint64_t)a_mnt << (FP32_MANT_BITS - FP32_EXP_BITS + 3)) / b_mnt;
2733 x_mnt |= (x_mnt * b_mnt !=
2734 (uint64_t)a_mnt << (FP32_MANT_BITS - FP32_EXP_BITS + 3));
2735
2736 // Normalise into FP32_BITS bits, collapsing error into bottom bit:
2737 x_mnt = fp64_normalise(x_mnt, &x_exp);
2738 x_mnt = x_mnt >> (FP32_BITS - 1) | !!(uint32_t)(x_mnt << 1);
2739
2740 return fp32_round(x_sgn, x_exp, x_mnt, mode, flags);
2741}
2742
2743static uint64_t
2744fp64_div(uint64_t a, uint64_t b, int mode, int *flags)
2745{
2746 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp, c;
2747 uint64_t a_mnt, b_mnt, x, x_mnt, x0_mnt, x1_mnt;
2748
2749 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2750 fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
2751
2752 if ((x = fp64_process_NaNs(a, b, mode, flags)))
2753 return x;
2754
2755 if (b_exp || b_mnt) {
2756 // FPProcessDenorms2
2757 if (mode & FPLIB_AH) {
2758 if (fp64_is_denormal(a_exp, a_mnt) ||
2759 fp64_is_denormal(b_exp, b_mnt)) {
2760 *flags |= FPLIB_IDC;
2761 }
2762 }
2763 }
2764
2765 // Handle infinities and zeroes:
2766 if ((a_exp == FP64_EXP_INF && b_exp == FP64_EXP_INF) ||
2767 (!a_mnt && !b_mnt)) {
2768 *flags |= FPLIB_IOC;
2769 return fp64_defaultNaN(mode);
2770 }
2771 if (a_exp == FP64_EXP_INF || !b_mnt) {
2772 if (a_exp != FP64_EXP_INF)
2773 *flags |= FPLIB_DZC;
2774 return fp64_infinity(a_sgn ^ b_sgn);
2775 }
2776 if (!a_mnt || b_exp == FP64_EXP_INF)
2777 return fp64_zero(a_sgn ^ b_sgn);
2778
2779 // Find reciprocal of divisor with Newton-Raphson:
2780 a_mnt = fp64_normalise(a_mnt, &a_exp);
2781 b_mnt = fp64_normalise(b_mnt, &b_exp);
2782 x_mnt = ~(uint64_t)0 / (b_mnt >> 31);
2783 mul64x32(&x0_mnt, &x1_mnt, b_mnt, x_mnt);
2784 sub128(&x0_mnt, &x1_mnt, 0, (uint64_t)1 << 32, x0_mnt, x1_mnt);
2785 lsr128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, 32);
2786 mul64x32(&x0_mnt, &x1_mnt, x0_mnt, x_mnt);
2787 lsr128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, 33);
2788
2789 // Multiply by dividend:
2790 x_sgn = a_sgn ^ b_sgn;
2791 x_exp = a_exp - b_exp + FP64_EXP_BIAS + 8;
2792 mul62x62(&x0_mnt, &x1_mnt, x0_mnt, a_mnt >> 2);
2793 lsr128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, 4);
2794 x_mnt = x1_mnt;
2795
2796 // This is an underestimate, so try adding one:
2797 mul62x62(&x0_mnt, &x1_mnt, b_mnt >> 2, x_mnt + 1);
2798 c = cmp128(x0_mnt, x1_mnt, 0, a_mnt >> 11);
2799 if (c <= 0) {
2800 ++x_mnt;
2801 }
2802
2803 x_mnt = fp64_normalise(x_mnt, &x_exp);
2804
2805 return fp64_round(x_sgn, x_exp, x_mnt << 1 | !!c, mode, flags);
2806}
2807
2808static void
2809set_fpscr0(FPSCR &fpscr, int flags)
2810{
2811 if (flags & FPLIB_IDC) {
2812 fpscr.idc = 1;
2813 }
2814 if (flags & FPLIB_IOC) {
2815 fpscr.ioc = 1;
2816 }
2817 if (flags & FPLIB_DZC) {
2818 fpscr.dzc = 1;
2819 }
2820 if (flags & FPLIB_OFC) {
2821 fpscr.ofc = 1;
2822 }
2823 if (flags & FPLIB_UFC) {
2824 fpscr.ufc = 1;
2825 }
2826 if (flags & FPLIB_IXC) {
2827 fpscr.ixc = 1;
2828 }
2829}
2830
2831static uint16_t
2832fp16_scale(uint16_t a, int16_t b, int mode, int *flags)
2833{
2834 int a_sgn, a_exp;
2835 uint16_t a_mnt;
2836
2837 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2838
2839 // Handle NaNs:
2840 if (fp16_is_NaN(a_exp, a_mnt)) {
2841 return fp16_process_NaN(a, mode, flags);
2842 }
2843
2844 // Handle zeroes:
2845 if (!a_mnt) {
2846 return fp16_zero(a_sgn);
2847 }
2848
2849 // Handle infinities:
2850 if (a_exp == FP16_EXP_INF) {
2851 return fp16_infinity(a_sgn);
2852 }
2853
2854 b = b < -300 ? -300 : b;
2855 b = b > 300 ? 300 : b;
2856 a_exp += b;
2857 a_mnt <<= 3;
2858
2859 a_mnt = fp16_normalise(a_mnt, &a_exp);
2860
2861 return fp16_round(a_sgn, a_exp + FP16_EXP_BITS - 3, a_mnt << 1,
2862 mode, flags);
2863}
2864
2865static uint32_t
2866fp32_scale(uint32_t a, int32_t b, int mode, int *flags)
2867{
2868 int a_sgn, a_exp;
2869 uint32_t a_mnt;
2870
2871 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2872
2873 // Handle NaNs:
2874 if (fp32_is_NaN(a_exp, a_mnt)) {
2875 return fp32_process_NaN(a, mode, flags);
2876 }
2877
2878 // Handle zeroes:
2879 if (!a_mnt) {
2880 return fp32_zero(a_sgn);
2881 }
2882
2883 // Handle infinities:
2884 if (a_exp == FP32_EXP_INF) {
2885 return fp32_infinity(a_sgn);
2886 }
2887
2888 // FPProcessDenorms
2889 if (mode & FPLIB_AH) {
2890 if (fp32_is_denormal(a_exp, a_mnt)) {
2891 *flags |= FPLIB_IDC;
2892 }
2893 }
2894
2895 b = b < -300 ? -300 : b;
2896 b = b > 300 ? 300 : b;
2897 a_exp += b;
2898 a_mnt <<= 3;
2899
2900 a_mnt = fp32_normalise(a_mnt, &a_exp);
2901
2902 return fp32_round(a_sgn, a_exp + FP32_EXP_BITS - 3, a_mnt << 1,
2903 mode, flags);
2904}
2905
2906static uint64_t
2907fp64_scale(uint64_t a, int64_t b, int mode, int *flags)
2908{
2909 int a_sgn, a_exp;
2910 uint64_t a_mnt;
2911
2912 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2913
2914 // Handle NaNs:
2915 if (fp64_is_NaN(a_exp, a_mnt)) {
2916 return fp64_process_NaN(a, mode, flags);
2917 }
2918
2919 // Handle zeroes:
2920 if (!a_mnt) {
2921 return fp64_zero(a_sgn);
2922 }
2923
2924 // Handle infinities:
2925 if (a_exp == FP64_EXP_INF) {
2926 return fp64_infinity(a_sgn);
2927 }
2928
2929 // FPProcessDenorms
2930 if (mode & FPLIB_AH) {
2931 if (fp64_is_denormal(a_exp, a_mnt)) {
2932 *flags |= FPLIB_IDC;
2933 }
2934 }
2935
2936 b = b < -3000 ? -3000 : b;
2937 b = b > 3000 ? 3000 : b;
2938 a_exp += b;
2939 a_mnt <<= 3;
2940
2941 a_mnt = fp64_normalise(a_mnt, &a_exp);
2942
2943 return fp64_round(a_sgn, a_exp + FP64_EXP_BITS - 3, a_mnt << 1,
2944 mode, flags);
2945}
2946
2947static uint16_t
2948fp16_sqrt(uint16_t a, int mode, int *flags)
2949{
2950 int a_sgn, a_exp, x_sgn, x_exp;
2951 uint16_t a_mnt, x_mnt;
2952 uint32_t x, t0, t1;
2953
2954 fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
2955
2956 // Handle NaNs:
2957 if (fp16_is_NaN(a_exp, a_mnt))
2958 return fp16_process_NaN(a, mode, flags);
2959
2960 // Handle infinities and zeroes:
2961 if (!a_mnt)
2962 return fp16_zero(a_sgn);
2963 if (a_exp == FP16_EXP_INF && !a_sgn)
2964 return fp16_infinity(a_sgn);
2965 if (a_sgn) {
2966 *flags |= FPLIB_IOC;
2967 return fp16_defaultNaN(mode);
2968 }
2969
2970 a_mnt = fp16_normalise(a_mnt, &a_exp);
2971 if (a_exp & 1) {
2972 ++a_exp;
2973 a_mnt >>= 1;
2974 }
2975
2976 // x = (a * 3 + 5) / 8
2977 x = ((uint32_t)a_mnt << 14) + ((uint32_t)a_mnt << 13) + ((uint32_t)5 << 28);
2978
2979 // x = (a / x + x) / 2; // 8-bit accuracy
2980 x = (((uint32_t)a_mnt << 16) / (x >> 15) + (x >> 16)) << 15;
2981
2982 // x = (a / x + x) / 2; // 16-bit accuracy
2983 x = (((uint32_t)a_mnt << 16) / (x >> 15) + (x >> 16)) << 15;
2984
2985 x_sgn = 0;
2986 x_exp = (a_exp + 27) >> 1;
2987 x_mnt = ((x - (1 << 18)) >> 19) + 1;
2988 t1 = (uint32_t)x_mnt * x_mnt;
2989 t0 = (uint32_t)a_mnt << 9;
2990 if (t1 > t0) {
2991 --x_mnt;
2992 }
2993
2994 x_mnt = fp16_normalise(x_mnt, &x_exp);
2995
2996 return fp16_round(x_sgn, x_exp, x_mnt << 1 | (t1 != t0), mode, flags);
2997}
2998
2999static uint32_t
3000fp32_sqrt(uint32_t a, int mode, int *flags)
3001{
3002 int a_sgn, a_exp, x_sgn, x_exp;
3003 uint32_t a_mnt, x, x_mnt;
3004 uint64_t t0, t1;
3005
3006 fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
3007
3008 // Handle NaNs:
3009 if (fp32_is_NaN(a_exp, a_mnt))
3010 return fp32_process_NaN(a, mode, flags);
3011
3012 // Handle infinities and zeroes:
3013 if (!a_mnt)
3014 return fp32_zero(a_sgn);
3015 if (a_exp == FP32_EXP_INF && !a_sgn)
3016 return fp32_infinity(a_sgn);
3017 if (a_sgn) {
3018 *flags |= FPLIB_IOC;
3019 return fp32_defaultNaN(mode);
3020 }
3021
3022 // FPProcessDenorms
3023 if (mode & FPLIB_AH) {
3024 if (fp32_is_denormal(a_exp, a_mnt)) {
3025 *flags |= FPLIB_IDC;
3026 }
3027 }
3028
3029 a_mnt = fp32_normalise(a_mnt, &a_exp);
3030 if (!(a_exp & 1)) {
3031 ++a_exp;
3032 a_mnt >>= 1;
3033 }
3034
3035 // x = (a * 3 + 5) / 8
3036 x = (a_mnt >> 2) + (a_mnt >> 3) + ((uint32_t)5 << 28);
3037
3038 // x = (a / x + x) / 2; // 8-bit accuracy
3039 x = (a_mnt / (x >> 15) + (x >> 16)) << 15;
3040
3041 // x = (a / x + x) / 2; // 16-bit accuracy
3042 x = (a_mnt / (x >> 15) + (x >> 16)) << 15;
3043
3044 // x = (a / x + x) / 2; // 32-bit accuracy
3045 x = ((((uint64_t)a_mnt << 32) / x) >> 2) + (x >> 1);
3046
3047 x_sgn = 0;
3048 x_exp = (a_exp + 147) >> 1;
3049 x_mnt = ((x - (1 << 5)) >> 6) + 1;
3050 t1 = (uint64_t)x_mnt * x_mnt;
3051 t0 = (uint64_t)a_mnt << 19;
3052 if (t1 > t0) {
3053 --x_mnt;
3054 }
3055
3056 x_mnt = fp32_normalise(x_mnt, &x_exp);
3057
3058 return fp32_round(x_sgn, x_exp, x_mnt << 1 | (t1 != t0), mode, flags);
3059}
3060
3061static uint64_t
3062fp64_sqrt(uint64_t a, int mode, int *flags)
3063{
3064 int a_sgn, a_exp, x_sgn, x_exp, c;
3065 uint64_t a_mnt, x_mnt, r, x0, x1;
3066 uint32_t x;
3067
3068 fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
3069
3070 // Handle NaNs:
3071 if (fp64_is_NaN(a_exp, a_mnt))
3072 return fp64_process_NaN(a, mode, flags);
3073
3074 // Handle infinities and zeroes:
3075 if (!a_mnt)
3076 return fp64_zero(a_sgn);
3077 if (a_exp == FP64_EXP_INF && !a_sgn)
3078 return fp64_infinity(a_sgn);
3079 if (a_sgn) {
3080 *flags |= FPLIB_IOC;
3081 return fp64_defaultNaN(mode);
3082 }
3083
3084 // FPProcessDenorms2
3085 if (mode & FPLIB_AH) {
3086 if (fp64_is_denormal(a_exp, a_mnt)) {
3087 *flags |= FPLIB_IDC;
3088 }
3089 }
3090
3091 a_mnt = fp64_normalise(a_mnt, &a_exp);
3092 if (a_exp & 1) {
3093 ++a_exp;
3094 a_mnt >>= 1;
3095 }
3096
3097 // x = (a * 3 + 5) / 8
3098 x = (a_mnt >> 34) + (a_mnt >> 35) + ((uint32_t)5 << 28);
3099
3100 // x = (a / x + x) / 2; // 8-bit accuracy
3101 x = ((a_mnt >> 32) / (x >> 15) + (x >> 16)) << 15;
3102
3103 // x = (a / x + x) / 2; // 16-bit accuracy
3104 x = ((a_mnt >> 32) / (x >> 15) + (x >> 16)) << 15;
3105
3106 // x = (a / x + x) / 2; // 32-bit accuracy
3107 x = ((a_mnt / x) >> 2) + (x >> 1);
3108
3109 // r = 1 / x; // 32-bit accuracy
3110 r = ((uint64_t)1 << 62) / x;
3111
3112 // r = r * (2 - x * r); // 64-bit accuracy
3113 mul64x32(&x0, &x1, -(uint64_t)x * r << 1, r);
3114 lsr128(&x0, &x1, x0, x1, 31);
3115
3116 // x = (x + a * r) / 2; // 64-bit accuracy
3117 mul62x62(&x0, &x1, a_mnt >> 10, x0 >> 2);
3118 lsl128(&x0, &x1, x0, x1, 5);
3119 lsr128(&x0, &x1, x0, x1, 56);
3120
3121 x0 = ((uint64_t)x << 31) + (x0 >> 1);
3122
3123 x_sgn = 0;
3124 x_exp = (a_exp + 1053) >> 1;
3125 x_mnt = x0;
3126 x_mnt = ((x_mnt - (1 << 8)) >> 9) + 1;
3127 mul62x62(&x0, &x1, x_mnt, x_mnt);
3128 lsl128(&x0, &x1, x0, x1, 19);
3129 c = cmp128(x0, x1, 0, a_mnt);
3130 if (c > 0)
3131 --x_mnt;
3132
3133 x_mnt = fp64_normalise(x_mnt, &x_exp);
3134
3135 return fp64_round(x_sgn, x_exp, x_mnt << 1 | !!c, mode, flags);
3136}
3137
3138static int
3139modeConv(FPSCR fpscr)
3140{
3141 int mode = fpscr.rMode; // Round mode
3142 if (fpscr.fz)
3143 mode |= FPLIB_FZ;
3144 if (fpscr.dn)
3145 mode |= FPLIB_DN;
3146 if (fpscr.fz16)
3147 mode |= FPLIB_FZ16;
3148 mode |= FPLIB_FPEXEC;
3149 return mode;
3150 // AHP bit is ignored. Only fplibConvert uses AHP.
3151}
3152
3153static int
3154modeConv(FPSCR fpscr, FPCR fpcr)
3155{
3156 int mode = modeConv(fpscr);
3157 if (fpcr.fiz)
3158 mode |= FPLIB_FIZ;
3159 if (fpcr.ah)
3160 mode |= FPLIB_AH;
3161 if (fpcr.nep)
3162 mode |= FPLIB_NEP;
3163 return mode;
3164 // AHP bit is ignored. Only fplibConvert uses AHP.
3165 // EBF bit is ingored. Only BFDOT, BFMMLA, BFMOPA, BFMOPS uses EBF.
3166}
3167
3168static void
3169set_fpscr(FPSCR &fpscr, int flags)
3170{
3171 // translate back to FPSCR
3172 bool underflow = false;
3173 if (flags & FPLIB_IDC) {
3174 fpscr.idc = 1;
3175 }
3176 if (flags & FPLIB_IOC) {
3177 fpscr.ioc = 1;
3178 }
3179 if (flags & FPLIB_DZC) {
3180 fpscr.dzc = 1;
3181 }
3182 if (flags & FPLIB_OFC) {
3183 fpscr.ofc = 1;
3184 }
3185 if (flags & FPLIB_UFC) {
3186 underflow = true; //xx Why is this required?
3187 fpscr.ufc = 1;
3188 }
3189 if ((flags & FPLIB_IXC) && !(underflow && fpscr.fz)) {
3190 fpscr.ixc = 1;
3191 }
3192}
3193
3194template <>
3195bool
3196fplibCompareEQ(uint16_t a, uint16_t b, FPSCR &fpscr, FPCR fpcr)
3197{
3198 int flags = 0;
3199 int x = fp16_compare_eq(a, b, modeConv(fpscr, fpcr), &flags);
3200 set_fpscr(fpscr, flags);
3201 return x;
3202}
3203
3204template <>
3205bool
3206fplibCompareGE(uint16_t a, uint16_t b, FPSCR &fpscr, FPCR fpcr)
3207{
3208 int flags = 0;
3209 int x = fp16_compare_ge(a, b, modeConv(fpscr, fpcr), &flags);
3210 set_fpscr(fpscr, flags);
3211 return x;
3212}
3213
3214template <>
3215bool
3216fplibCompareGT(uint16_t a, uint16_t b, FPSCR &fpscr, FPCR fpcr)
3217{
3218 int flags = 0;
3219 int x = fp16_compare_gt(a, b, modeConv(fpscr, fpcr), &flags);
3220 set_fpscr(fpscr, flags);
3221 return x;
3222}
3223
3224template <>
3225bool
3226fplibCompareUN(uint16_t a, uint16_t b, FPSCR &fpscr, FPCR fpcr)
3227{
3228 int flags = 0;
3229 int x = fp16_compare_un(a, b, modeConv(fpscr, fpcr), &flags);
3230 set_fpscr(fpscr, flags);
3231 return x;
3232}
3233
3234template <>
3235bool
3236fplibCompareEQ(uint32_t a, uint32_t b, FPSCR &fpscr, FPCR fpcr)
3237{
3238 int flags = 0;
3239 int x = fp32_compare_eq(a, b, modeConv(fpscr, fpcr), &flags);
3240 set_fpscr(fpscr, flags);
3241 return x;
3242}
3243
3244template <>
3245bool
3246fplibCompareGE(uint32_t a, uint32_t b, FPSCR &fpscr, FPCR fpcr)
3247{
3248 int flags = 0;
3249 int x = fp32_compare_ge(a, b, modeConv(fpscr, fpcr), &flags);
3250 set_fpscr(fpscr, flags);
3251 return x;
3252}
3253
3254template <>
3255bool
3256fplibCompareGT(uint32_t a, uint32_t b, FPSCR &fpscr, FPCR fpcr)
3257{
3258 int flags = 0;
3259 int x = fp32_compare_gt(a, b, modeConv(fpscr, fpcr), &flags);
3260 set_fpscr(fpscr, flags);
3261 return x;
3262}
3263
3264template <>
3265bool
3266fplibCompareUN(uint32_t a, uint32_t b, FPSCR &fpscr, FPCR fpcr)
3267{
3268 int flags = 0;
3269 int x = fp32_compare_un(a, b, modeConv(fpscr, fpcr), &flags);
3270 set_fpscr(fpscr, flags);
3271 return x;
3272}
3273
3274template <>
3275bool
3276fplibCompareEQ(uint64_t a, uint64_t b, FPSCR &fpscr, FPCR fpcr)
3277{
3278 int flags = 0;
3279 int x = fp64_compare_eq(a, b, modeConv(fpscr, fpcr), &flags);
3280 set_fpscr(fpscr, flags);
3281 return x;
3282}
3283
3284template <>
3285bool
3286fplibCompareGE(uint64_t a, uint64_t b, FPSCR &fpscr, FPCR fpcr)
3287{
3288 int flags = 0;
3289 int x = fp64_compare_ge(a, b, modeConv(fpscr, fpcr), &flags);
3290 set_fpscr(fpscr, flags);
3291 return x;
3292}
3293
3294template <>
3295bool
3296fplibCompareGT(uint64_t a, uint64_t b, FPSCR &fpscr, FPCR fpcr)
3297{
3298 int flags = 0;
3299 int x = fp64_compare_gt(a, b, modeConv(fpscr, fpcr), &flags);
3300 set_fpscr(fpscr, flags);
3301 return x;
3302}
3303
3304template <>
3305bool
3306fplibCompareUN(uint64_t a, uint64_t b, FPSCR &fpscr, FPCR fpcr)
3307{
3308 int flags = 0;
3309 int x = fp64_compare_un(a, b, modeConv(fpscr, fpcr), &flags);
3310 set_fpscr(fpscr, flags);
3311 return x;
3312}
3313
3314template <>
3315uint16_t
3316fplibAbs(uint16_t op, FPCR fpcr)
3317{
3318 if (fpcr.ah && fp16_is_NaN(FP16_EXP(op), FP16_MANT(op))) {
3319 return op;
3320 }
3321 return op & ~(1ULL << (FP16_BITS - 1));
3322}
3323
3324template <>
3325uint32_t
3326fplibAbs(uint32_t op, FPCR fpcr)
3327{
3328 if (fpcr.ah && fp32_is_NaN(FP32_EXP(op), FP32_MANT(op))) {
3329 return op;
3330 }
3331 return op & ~(1ULL << (FP32_BITS - 1));
3332}
3333
3334template <>
3335uint64_t
3336fplibAbs(uint64_t op, FPCR fpcr)
3337{
3338 if (fpcr.ah && fp64_is_NaN(FP64_EXP(op), FP64_MANT(op))) {
3339 return op;
3340 }
3341 return op & ~(1ULL << (FP64_BITS - 1));
3342}
3343
3344template <>
3345uint16_t
3346fplibAdd(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
3347{
3348 int flags = 0;
3349 uint16_t result = fp16_add(op1, op2, 0, modeConv(fpscr, fpcr), &flags);
3350 set_fpscr0(fpscr, flags);
3351 return result;
3352}
3353
3354template <>
3355uint32_t
3356fplibAdd(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
3357{
3358 int flags = 0;
3359 uint32_t result = fp32_add(op1, op2, 0, modeConv(fpscr, fpcr), &flags);
3360 set_fpscr0(fpscr, flags);
3361 return result;
3362}
3363
3364template <>
3365uint64_t
3366fplibAdd(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
3367{
3368 int flags = 0;
3369 uint64_t result = fp64_add(op1, op2, 0, modeConv(fpscr, fpcr), &flags);
3370 set_fpscr0(fpscr, flags);
3371 return result;
3372}
3373
3374template <>
3375int
3376fplibCompare(uint16_t op1, uint16_t op2, bool signal_nans, FPSCR &fpscr,
3377 FPCR fpcr)
3378{
3379 int mode = modeConv(fpscr, fpcr);
3380 int flags = 0;
3381 int sgn1, exp1, sgn2, exp2, result;
3382 uint16_t mnt1, mnt2;
3383
3384 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3385 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3386
3387 if (fp16_is_NaN(exp1, mnt1) || fp16_is_NaN(exp2, mnt2)) {
3388 result = 3;
3389 if (fp16_is_signalling_NaN(exp1, mnt1) ||
3390 fp16_is_signalling_NaN(exp2, mnt2) || signal_nans)
3391 flags |= FPLIB_IOC;
3392 } else {
3393 if (op1 == op2 || (!mnt1 && !mnt2)) {
3394 result = 6;
3395 } else if (sgn1 != sgn2) {
3396 result = sgn1 ? 8 : 2;
3397 } else if (exp1 != exp2) {
3398 result = sgn1 ^ (exp1 < exp2) ? 8 : 2;
3399 } else {
3400 result = sgn1 ^ (mnt1 < mnt2) ? 8 : 2;
3401 }
3402 }
3403
3404 set_fpscr0(fpscr, flags);
3405
3406 return result;
3407}
3408
3409template <>
3410int
3411fplibCompare(uint32_t op1, uint32_t op2, bool signal_nans, FPSCR &fpscr,
3412 FPCR fpcr)
3413{
3414 int mode = modeConv(fpscr, fpcr);
3415 int flags = 0;
3416 int sgn1, exp1, sgn2, exp2, result;
3417 uint32_t mnt1, mnt2;
3418
3419 fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3420 fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3421
3422 if (fp32_is_NaN(exp1, mnt1) || fp32_is_NaN(exp2, mnt2)) {
3423 result = 3;
3424 if (fp32_is_signalling_NaN(exp1, mnt1) ||
3425 fp32_is_signalling_NaN(exp2, mnt2) || signal_nans)
3426 flags |= FPLIB_IOC;
3427 } else {
3428 // FPProcessDenorms2
3429 if (mode & FPLIB_AH) {
3430 if (fp32_is_denormal(exp1, mnt1) || fp32_is_denormal(exp2, mnt2)) {
3431 flags |= FPLIB_IDC;
3432 }
3433 }
3434
3435 if (op1 == op2 || (!mnt1 && !mnt2)) {
3436 result = 6;
3437 } else if (sgn1 != sgn2) {
3438 result = sgn1 ? 8 : 2;
3439 } else if (exp1 != exp2) {
3440 result = sgn1 ^ (exp1 < exp2) ? 8 : 2;
3441 } else {
3442 result = sgn1 ^ (mnt1 < mnt2) ? 8 : 2;
3443 }
3444 }
3445
3446 set_fpscr0(fpscr, flags);
3447
3448 return result;
3449}
3450
3451template <>
3452int
3453fplibCompare(uint64_t op1, uint64_t op2, bool signal_nans, FPSCR &fpscr,
3454 FPCR fpcr)
3455{
3456 int mode = modeConv(fpscr, fpcr);
3457 int flags = 0;
3458 int sgn1, exp1, sgn2, exp2, result;
3459 uint64_t mnt1, mnt2;
3460
3461 fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
3462 fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
3463
3464 if (fp64_is_NaN(exp1, mnt1) || fp64_is_NaN(exp2, mnt2)) {
3465 result = 3;
3466 if (fp64_is_signalling_NaN(exp1, mnt1) ||
3467 fp64_is_signalling_NaN(exp2, mnt2) || signal_nans)
3468 flags |= FPLIB_IOC;
3469 } else {
3470 // FPProcessDenorms2
3471 if (mode & FPLIB_AH) {
3472 if (fp64_is_denormal(exp1, mnt1) || fp64_is_denormal(exp2, mnt2)) {
3473 flags |= FPLIB_IDC;
3474 }
3475 }
3476
3477 if (op1 == op2 || (!mnt1 && !mnt2)) {
3478 result = 6;
3479 } else if (sgn1 != sgn2) {
3480 result = sgn1 ? 8 : 2;
3481 } else if (exp1 != exp2) {
3482 result = sgn1 ^ (exp1 < exp2) ? 8 : 2;
3483 } else {
3484 result = sgn1 ^ (mnt1 < mnt2) ? 8 : 2;
3485 }
3486 }
3487
3488 set_fpscr0(fpscr, flags);
3489
3490 return result;
3491}
3492
3493static uint16_t
3495{
3496 return fp16_pack(op >> (FP32_BITS - 1), FP16_EXP_INF,
3497 1ULL << (FP16_MANT_BITS - 1) |
3499}
3500
3501static uint16_t
3503{
3504 return fp16_pack(op >> (FP64_BITS - 1), FP16_EXP_INF,
3505 1ULL << (FP16_MANT_BITS - 1) |
3507}
3508
3509static uint32_t
3511{
3512 return fp32_pack(op >> (FP16_BITS - 1), FP32_EXP_INF,
3513 1ULL << (FP32_MANT_BITS - 1) |
3514 (uint32_t)op << (FP32_MANT_BITS - FP16_MANT_BITS));
3515}
3516
3517static uint32_t
3519{
3520 return fp32_pack(op >> (FP64_BITS - 1), FP32_EXP_INF,
3521 1ULL << (FP32_MANT_BITS - 1) |
3523}
3524
3525static uint64_t
3527{
3528 return fp64_pack(op >> (FP16_BITS - 1), FP64_EXP_INF,
3529 1ULL << (FP64_MANT_BITS - 1) |
3530 (uint64_t)op << (FP64_MANT_BITS - FP16_MANT_BITS));
3531}
3532
3533static uint64_t
3535{
3536 return fp64_pack(op >> (FP32_BITS - 1), FP64_EXP_INF,
3537 1ULL << (FP64_MANT_BITS - 1) |
3538 (uint64_t)op << (FP64_MANT_BITS - FP32_MANT_BITS));
3539}
3540
3541static uint16_t
3543{
3544 return fp16_pack(sgn, FP16_EXP_BIAS, 1ULL << (FP16_MANT_BITS - 1));
3545}
3546
3547static uint32_t
3549{
3550 return fp32_pack(sgn, FP32_EXP_BIAS, 1ULL << (FP32_MANT_BITS - 1));
3551}
3552
3553static uint64_t
3555{
3556 return fp64_pack(sgn, FP64_EXP_BIAS, 1ULL << (FP64_MANT_BITS - 1));
3557}
3558
3559static uint16_t
3561{
3562 return fp16_pack(sgn, FP16_EXP_BIAS + 1, 1ULL << (FP16_MANT_BITS - 1));
3563}
3564
3565static uint32_t
3567{
3568 return fp32_pack(sgn, FP32_EXP_BIAS + 1, 1ULL << (FP32_MANT_BITS - 1));
3569}
3570
3571static uint64_t
3573{
3574 return fp64_pack(sgn, FP64_EXP_BIAS + 1, 1ULL << (FP64_MANT_BITS - 1));
3575}
3576
3577static uint16_t
3579{
3580 return fp16_pack(sgn, FP16_EXP_BIAS + 1, 0);
3581}
3582
3583static uint32_t
3585{
3586 return fp32_pack(sgn, FP32_EXP_BIAS + 1, 0);
3587}
3588
3589static uint64_t
3591{
3592 return fp64_pack(sgn, FP64_EXP_BIAS + 1, 0);
3593}
3594
3595template <>
3596uint16_t
3597fplibConvert(uint32_t op, FPRounding rounding, FPSCR &fpscr, FPCR fpcr)
3598{
3599 int mode = modeConv(fpscr, fpcr);
3600 int flags = 0;
3601 int sgn, exp;
3602 uint32_t mnt;
3603 uint16_t result;
3604
3605 // Unpack floating-point operand optionally with flush-to-zero:
3606 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
3607
3608 // FPProcessDenorm
3609 if (mode & FPLIB_AH) {
3610 if (fp32_is_denormal(exp, mnt)) {
3611 flags |= FPLIB_IDC;
3612 }
3613 }
3614
3615 bool alt_hp = fpscr.ahp;
3616
3617 if (fp32_is_NaN(exp, mnt)) {
3618 if (alt_hp) {
3619 result = fp16_zero(sgn);
3620 } else if (fpscr.dn) {
3621 result = fp16_defaultNaN(mode);
3622 } else {
3623 result = fp16_FPConvertNaN_32(op);
3624 }
3625 if (!(mnt >> (FP32_MANT_BITS - 1) & 1) || alt_hp) {
3626 flags |= FPLIB_IOC;
3627 }
3628 } else if (exp == FP32_EXP_INF) {
3629 if (alt_hp) {
3630 result = ((uint16_t)sgn << (FP16_BITS - 1) |
3631 ((1ULL << (FP16_BITS - 1)) - 1));
3632 flags |= FPLIB_IOC;
3633 } else {
3634 result = fp16_infinity(sgn);
3635 }
3636 } else if (!mnt) {
3637 result = fp16_zero(sgn);
3638 } else {
3639 result =
3641 mnt >> (FP32_MANT_BITS - FP16_BITS) |
3642 !!(mnt & ((1ULL << (FP32_MANT_BITS - FP16_BITS)) - 1)),
3643 rounding, (mode & 0xfcf) | alt_hp << 4, &flags);
3644 }
3645
3646 set_fpscr0(fpscr, flags);
3647
3648 return result;
3649}
3650
3651template <>
3652uint16_t
3653fplibConvert(uint64_t op, FPRounding rounding, FPSCR &fpscr, FPCR fpcr)
3654{
3655 int mode = modeConv(fpscr, fpcr);
3656 int flags = 0;
3657 int sgn, exp;
3658 uint64_t mnt;
3659 uint16_t result;
3660
3661 // Unpack floating-point operand optionally with flush-to-zero:
3662 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
3663
3664 // FPProcessDenorm
3665 if (mode & FPLIB_AH) {
3666 if (fp64_is_denormal(exp, mnt)) {
3667 flags |= FPLIB_IDC;
3668 }
3669 }
3670
3671 bool alt_hp = fpscr.ahp;
3672
3673 if (fp64_is_NaN(exp, mnt)) {
3674 if (alt_hp) {
3675 result = fp16_zero(sgn);
3676 } else if (fpscr.dn) {
3677 result = fp16_defaultNaN(mode);
3678 } else {
3679 result = fp16_FPConvertNaN_64(op);
3680 }
3681 if (!(mnt >> (FP64_MANT_BITS - 1) & 1) || alt_hp) {
3682 flags |= FPLIB_IOC;
3683 }
3684 } else if (exp == FP64_EXP_INF) {
3685 if (alt_hp) {
3686 result = ((uint16_t)sgn << (FP16_BITS - 1) |
3687 ((1ULL << (FP16_BITS - 1)) - 1));
3688 flags |= FPLIB_IOC;
3689 } else {
3690 result = fp16_infinity(sgn);
3691 }
3692 } else if (!mnt) {
3693 result = fp16_zero(sgn);
3694 } else {
3695 result =
3697 mnt >> (FP64_MANT_BITS - FP16_BITS) |
3698 !!(mnt & ((1ULL << (FP64_MANT_BITS - FP16_BITS)) - 1)),
3699 rounding, (mode & 0xfcf) | alt_hp << 4, &flags);
3700 }
3701
3702 set_fpscr0(fpscr, flags);
3703
3704 return result;
3705}
3706
3707template <>
3708uint32_t
3709fplibConvert(uint16_t op, FPRounding rounding, FPSCR &fpscr, FPCR fpcr)
3710{
3711 int mode = modeConv(fpscr, fpcr);
3712 int flags = 0;
3713 int sgn, exp;
3714 uint16_t mnt;
3715 uint32_t result;
3716
3717 // Unpack floating-point operand optionally with flush-to-zero:
3718 fp16_unpack(&sgn, &exp, &mnt, op, mode & 0xfcf, &flags);
3719
3720 if (fp16_is_NaN(exp, mnt) && !fpscr.ahp) {
3721 if (fpscr.dn) {
3722 result = fp32_defaultNaN(mode);
3723 } else {
3724 result = fp32_FPConvertNaN_16(op);
3725 }
3726 if (!(mnt >> (FP16_MANT_BITS - 1) & 1)) {
3727 flags |= FPLIB_IOC;
3728 }
3729 } else if (exp == FP16_EXP_INF && !fpscr.ahp) {
3730 result = fp32_infinity(sgn);
3731 } else if (!mnt) {
3732 result = fp32_zero(sgn);
3733 } else {
3734 mnt = fp16_normalise(mnt, &exp);
3735 result = fp32_pack(sgn, (exp - FP16_EXP_BIAS +
3737 (uint32_t)mnt << (FP32_MANT_BITS - FP16_BITS + 1));
3738 }
3739
3740 set_fpscr0(fpscr, flags);
3741
3742 return result;
3743}
3744
3745template <>
3746uint32_t
3747fplibConvert(uint64_t op, FPRounding rounding, FPSCR &fpscr, FPCR fpcr)
3748{
3749 int mode = modeConv(fpscr, fpcr);
3750 int flags = 0;
3751 int sgn, exp;
3752 uint64_t mnt;
3753 uint32_t result;
3754
3755 // Unpack floating-point operand optionally with flush-to-zero:
3756 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
3757
3758 // FPProcessDenorm
3759 if (mode & FPLIB_AH) {
3760 if (fp64_is_denormal(exp, mnt)) {
3761 flags |= FPLIB_IDC;
3762 }
3763 }
3764
3765 if (fp64_is_NaN(exp, mnt)) {
3766 if (fpscr.dn) {
3767 result = fp32_defaultNaN(mode);
3768 } else {
3769 result = fp32_FPConvertNaN_64(op);
3770 }
3771 if (!(mnt >> (FP64_MANT_BITS - 1) & 1)) {
3772 flags |= FPLIB_IOC;
3773 }
3774 } else if (exp == FP64_EXP_INF) {
3775 result = fp32_infinity(sgn);
3776 } else if (!mnt) {
3777 result = fp32_zero(sgn);
3778 } else {
3779 result =
3781 mnt >> (FP64_MANT_BITS - FP32_BITS) |
3782 !!(mnt & ((1ULL << (FP64_MANT_BITS - FP32_BITS)) - 1)),
3783 rounding, mode, &flags);
3784 }
3785
3786 set_fpscr0(fpscr, flags);
3787
3788 return result;
3789}
3790
3791template <>
3792uint64_t
3793fplibConvert(uint16_t op, FPRounding rounding, FPSCR &fpscr, FPCR fpcr)
3794{
3795 int mode = modeConv(fpscr, fpcr);
3796 int flags = 0;
3797 int sgn, exp;
3798 uint16_t mnt;
3799 uint64_t result;
3800
3801 // Unpack floating-point operand optionally with flush-to-zero:
3802 fp16_unpack(&sgn, &exp, &mnt, op, mode & 0xfcf, &flags);
3803
3804 if (fp16_is_NaN(exp, mnt) && !fpscr.ahp) {
3805 if (fpscr.dn) {
3806 result = fp64_defaultNaN(mode);
3807 } else {
3808 result = fp64_FPConvertNaN_16(op);
3809 }
3810 if (!(mnt >> (FP16_MANT_BITS - 1) & 1)) {
3811 flags |= FPLIB_IOC;
3812 }
3813 } else if (exp == FP16_EXP_INF && !fpscr.ahp) {
3814 result = fp64_infinity(sgn);
3815 } else if (!mnt) {
3816 result = fp64_zero(sgn);
3817 } else {
3818 mnt = fp16_normalise(mnt, &exp);
3819 result = fp64_pack(sgn, (exp - FP16_EXP_BIAS +
3821 (uint64_t)mnt << (FP64_MANT_BITS - FP16_BITS + 1));
3822 }
3823
3824 set_fpscr0(fpscr, flags);
3825
3826 return result;
3827}
3828
3829template <>
3830uint64_t
3831fplibConvert(uint32_t op, FPRounding rounding, FPSCR &fpscr, FPCR fpcr)
3832{
3833 int mode = modeConv(fpscr, fpcr);
3834 int flags = 0;
3835 int sgn, exp;
3836 uint32_t mnt;
3837 uint64_t result;
3838
3839 // Unpack floating-point operand optionally with flush-to-zero:
3840 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
3841
3842 // FPProcessDenorm
3843 if (mode & FPLIB_AH) {
3844 if (fp32_is_denormal(exp, mnt)) {
3845 flags |= FPLIB_IDC;
3846 }
3847 }
3848
3849 if (fp32_is_NaN(exp, mnt)) {
3850 if (fpscr.dn) {
3851 result = fp64_defaultNaN(mode);
3852 } else {
3853 result = fp64_FPConvertNaN_32(op);
3854 }
3855 if (!(mnt >> (FP32_MANT_BITS - 1) & 1)) {
3856 flags |= FPLIB_IOC;
3857 }
3858 } else if (exp == FP32_EXP_INF) {
3859 result = fp64_infinity(sgn);
3860 } else if (!mnt) {
3861 result = fp64_zero(sgn);
3862 } else {
3863 mnt = fp32_normalise(mnt, &exp);
3864 result = fp64_pack(sgn, (exp - FP32_EXP_BIAS +
3866 (uint64_t)mnt << (FP64_MANT_BITS - FP32_BITS + 1));
3867 }
3868
3869 set_fpscr0(fpscr, flags);
3870
3871 return result;
3872}
3873
3874template <>
3875uint16_t
3876fplibMulAdd(uint16_t addend, uint16_t op1, uint16_t op2, FPSCR &fpscr,
3877 FPCR fpcr)
3878{
3879 int flags = 0;
3880 uint16_t result = fp16_muladd(addend, op1, op2, 0, modeConv(fpscr, fpcr),
3881 &flags);
3882 set_fpscr0(fpscr, flags);
3883 return result;
3884}
3885
3886template <>
3887uint32_t
3888fplibMulAdd(uint32_t addend, uint32_t op1, uint32_t op2, FPSCR &fpscr,
3889 FPCR fpcr)
3890{
3891 int flags = 0;
3892 uint32_t result = fp32_muladd(addend, op1, op2, 0, modeConv(fpscr, fpcr),
3893 &flags);
3894 set_fpscr0(fpscr, flags);
3895 return result;
3896}
3897
3898template <>
3899uint64_t
3900fplibMulAdd(uint64_t addend, uint64_t op1, uint64_t op2, FPSCR &fpscr,
3901 FPCR fpcr)
3902{
3903 int flags = 0;
3904 uint64_t result = fp64_muladd(addend, op1, op2, 0, modeConv(fpscr, fpcr),
3905 &flags);
3906 set_fpscr0(fpscr, flags);
3907 return result;
3908}
3909
3910template <>
3911uint32_t
3912fplibMulAddH(uint32_t addend, uint16_t op1, uint16_t op2, FPSCR &fpscr,
3913 FPCR fpcr)
3914{
3915 int flags = 0;
3916 uint32_t result = fp32_muladdh(addend, op1, op2, 0,
3917 modeConv(fpscr, fpcr), &flags);
3918 set_fpscr0(fpscr, flags);
3919 return result;
3920}
3921
3922template <>
3923uint16_t
3924fplibDiv(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
3925{
3926 int flags = 0;
3927 uint16_t result = fp16_div(op1, op2, modeConv(fpscr, fpcr), &flags);
3928 set_fpscr0(fpscr, flags);
3929 return result;
3930}
3931
3932template <>
3933uint32_t
3934fplibDiv(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
3935{
3936 int flags = 0;
3937 uint32_t result = fp32_div(op1, op2, modeConv(fpscr, fpcr), &flags);
3938 set_fpscr0(fpscr, flags);
3939 return result;
3940}
3941
3942template <>
3943uint64_t
3944fplibDiv(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
3945{
3946 int flags = 0;
3947 uint64_t result = fp64_div(op1, op2, modeConv(fpscr, fpcr), &flags);
3948 set_fpscr0(fpscr, flags);
3949 return result;
3950}
3951
3952template <>
3953uint32_t
3954fplibDot(uint16_t op1_a, uint16_t op1_b, uint16_t op2_a, uint16_t op2_b,
3955 FPSCR &fpscr, FPCR fpcr)
3956{
3957 int flags = 0;
3958 uint64_t result =
3959 fp32_dot(op1_a, op1_b, op2_a, op2_b, modeConv(fpscr, fpcr), &flags);
3960 set_fpscr0(fpscr, flags);
3961 return result;
3962}
3963
3964template <>
3965uint16_t
3966fplibExpA(uint16_t op)
3967{
3968 static uint16_t coeff[32] = {
3969 0x0000,
3970 0x0016,
3971 0x002d,
3972 0x0045,
3973 0x005d,
3974 0x0075,
3975 0x008e,
3976 0x00a8,
3977 0x00c2,
3978 0x00dc,
3979 0x00f8,
3980 0x0114,
3981 0x0130,
3982 0x014d,
3983 0x016b,
3984 0x0189,
3985 0x01a8,
3986 0x01c8,
3987 0x01e8,
3988 0x0209,
3989 0x022b,
3990 0x024e,
3991 0x0271,
3992 0x0295,
3993 0x02ba,
3994 0x02e0,
3995 0x0306,
3996 0x032e,
3997 0x0356,
3998 0x037f,
3999 0x03a9,
4000 0x03d4
4001 };
4002 return ((((op >> 5) & ((1 << FP16_EXP_BITS) - 1)) << FP16_MANT_BITS) |
4003 coeff[op & ((1 << 5) - 1)]);
4004}
4005
4006template <>
4007uint32_t
4008fplibExpA(uint32_t op)
4009{
4010 static uint32_t coeff[64] = {
4011 0x000000,
4012 0x0164d2,
4013 0x02cd87,
4014 0x043a29,
4015 0x05aac3,
4016 0x071f62,
4017 0x08980f,
4018 0x0a14d5,
4019 0x0b95c2,
4020 0x0d1adf,
4021 0x0ea43a,
4022 0x1031dc,
4023 0x11c3d3,
4024 0x135a2b,
4025 0x14f4f0,
4026 0x16942d,
4027 0x1837f0,
4028 0x19e046,
4029 0x1b8d3a,
4030 0x1d3eda,
4031 0x1ef532,
4032 0x20b051,
4033 0x227043,
4034 0x243516,
4035 0x25fed7,
4036 0x27cd94,
4037 0x29a15b,
4038 0x2b7a3a,
4039 0x2d583f,
4040 0x2f3b79,
4041 0x3123f6,
4042 0x3311c4,
4043 0x3504f3,
4044 0x36fd92,
4045 0x38fbaf,
4046 0x3aff5b,
4047 0x3d08a4,
4048 0x3f179a,
4049 0x412c4d,
4050 0x4346cd,
4051 0x45672a,
4052 0x478d75,
4053 0x49b9be,
4054 0x4bec15,
4055 0x4e248c,
4056 0x506334,
4057 0x52a81e,
4058 0x54f35b,
4059 0x5744fd,
4060 0x599d16,
4061 0x5bfbb8,
4062 0x5e60f5,
4063 0x60ccdf,
4064 0x633f89,
4065 0x65b907,
4066 0x68396a,
4067 0x6ac0c7,
4068 0x6d4f30,
4069 0x6fe4ba,
4070 0x728177,
4071 0x75257d,
4072 0x77d0df,
4073 0x7a83b3,
4074 0x7d3e0c
4075 };
4076 return ((((op >> 6) & ((1 << FP32_EXP_BITS) - 1)) << FP32_MANT_BITS) |
4077 coeff[op & ((1 << 6) - 1)]);
4078}
4079
4080template <>
4081uint64_t
4082fplibExpA(uint64_t op)
4083{
4084 static uint64_t coeff[64] = {
4085 0x0000000000000ULL,
4086 0x02c9a3e778061ULL,
4087 0x059b0d3158574ULL,
4088 0x0874518759bc8ULL,
4089 0x0b5586cf9890fULL,
4090 0x0e3ec32d3d1a2ULL,
4091 0x11301d0125b51ULL,
4092 0x1429aaea92de0ULL,
4093 0x172b83c7d517bULL,
4094 0x1a35beb6fcb75ULL,
4095 0x1d4873168b9aaULL,
4096 0x2063b88628cd6ULL,
4097 0x2387a6e756238ULL,
4098 0x26b4565e27cddULL,
4099 0x29e9df51fdee1ULL,
4100 0x2d285a6e4030bULL,
4101 0x306fe0a31b715ULL,
4102 0x33c08b26416ffULL,
4103 0x371a7373aa9cbULL,
4104 0x3a7db34e59ff7ULL,
4105 0x3dea64c123422ULL,
4106 0x4160a21f72e2aULL,
4107 0x44e086061892dULL,
4108 0x486a2b5c13cd0ULL,
4109 0x4bfdad5362a27ULL,
4110 0x4f9b2769d2ca7ULL,
4111 0x5342b569d4f82ULL,
4112 0x56f4736b527daULL,
4113 0x5ab07dd485429ULL,
4114 0x5e76f15ad2148ULL,
4115 0x6247eb03a5585ULL,
4116 0x6623882552225ULL,
4117 0x6a09e667f3bcdULL,
4118 0x6dfb23c651a2fULL,
4119 0x71f75e8ec5f74ULL,
4120 0x75feb564267c9ULL,
4121 0x7a11473eb0187ULL,
4122 0x7e2f336cf4e62ULL,
4123 0x82589994cce13ULL,
4124 0x868d99b4492edULL,
4125 0x8ace5422aa0dbULL,
4126 0x8f1ae99157736ULL,
4127 0x93737b0cdc5e5ULL,
4128 0x97d829fde4e50ULL,
4129 0x9c49182a3f090ULL,
4130 0xa0c667b5de565ULL,
4131 0xa5503b23e255dULL,
4132 0xa9e6b5579fdbfULL,
4133 0xae89f995ad3adULL,
4134 0xb33a2b84f15fbULL,
4135 0xb7f76f2fb5e47ULL,
4136 0xbcc1e904bc1d2ULL,
4137 0xc199bdd85529cULL,
4138 0xc67f12e57d14bULL,
4139 0xcb720dcef9069ULL,
4140 0xd072d4a07897cULL,
4141 0xd5818dcfba487ULL,
4142 0xda9e603db3285ULL,
4143 0xdfc97337b9b5fULL,
4144 0xe502ee78b3ff6ULL,
4145 0xea4afa2a490daULL,
4146 0xefa1bee615a27ULL,
4147 0xf50765b6e4540ULL,
4148 0xfa7c1819e90d8ULL
4149 };
4150 return ((((op >> 6) & ((1 << FP64_EXP_BITS) - 1)) << FP64_MANT_BITS) |
4151 coeff[op & ((1 << 6) - 1)]);
4152}
4153
4154template <>
4155uint16_t
4156fplibLogB(uint16_t op, FPSCR &fpscr, FPCR fpcr)
4157{
4158 int mode = modeConv(fpscr, fpcr);
4159 int flags = 0;
4160 int sgn, exp;
4161 uint16_t mnt, result;
4162
4163 // Unpack floating-point operand optionally with flush-to-zero:
4164 fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
4165
4166 if (fp16_is_NaN(exp, mnt)) {
4167 flags |= FPLIB_IOC;
4168 result = (uint16_t)1 << 15;
4169 } else if (exp == 0 && mnt == 0) {
4170 flags |= FPLIB_IOC;
4171 result = (uint16_t)1 << 15;
4172 } else if (fp16_is_infinity(exp, mnt)) {
4173 result = ((uint16_t)1 << 15) - 1;
4174 } else {
4175 mnt = mnt << (FP16_BITS - FP16_MANT_BITS - 1);
4176 fp16_normalise(mnt, &exp);
4177 int unbias_exp = exp - FP16_EXP_BIAS;
4178 result = static_cast<uint16_t>((int16_t)unbias_exp);
4179 }
4180
4181 set_fpscr0(fpscr, flags);
4182
4183 return result;
4184}
4185
4186template <>
4187uint32_t
4188fplibLogB(uint32_t op, FPSCR &fpscr, FPCR fpcr)
4189{
4190 int mode = modeConv(fpscr, fpcr);
4191 int flags = 0;
4192 int sgn, exp;
4193 uint32_t mnt, result;
4194
4195 // Unpack floating-point operand optionally with flush-to-zero:
4196 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
4197
4198 if (fp32_is_NaN(exp, mnt)) {
4199 flags |= FPLIB_IOC;
4200 result = (uint32_t)1 << 31;
4201 } else if (exp == 0 && mnt == 0) {
4202 flags |= FPLIB_IOC;
4203 result = (uint32_t)1 << 31;
4204 } else if (fp32_is_infinity(exp, mnt)) {
4205 result = ((uint32_t)1 << 31) - 1;
4206 } else {
4207 if (mode & FPLIB_AH) {
4208 if (fp32_is_denormal(exp, mnt)) {
4209 flags |= FPLIB_IDC;
4210 }
4211 }
4212
4213 mnt = mnt << (FP32_BITS - FP32_MANT_BITS - 1);
4214 fp32_normalise(mnt, &exp);
4215 int unbias_exp = exp - FP32_EXP_BIAS;
4216 result = static_cast<uint32_t>((int32_t)unbias_exp);
4217 }
4218
4219 set_fpscr0(fpscr, flags);
4220
4221 return result;
4222}
4223
4224template <>
4225uint64_t
4226fplibLogB(uint64_t op, FPSCR &fpscr, FPCR fpcr)
4227{
4228 int mode = modeConv(fpscr, fpcr);
4229 int flags = 0;
4230 int sgn, exp;
4231 uint64_t mnt, result;
4232
4233 // Unpack floating-point operand optionally with flush-to-zero:
4234 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
4235
4236 if (fp64_is_NaN(exp, mnt)) {
4237 flags |= FPLIB_IOC;
4238 result = (uint64_t)1 << 63;
4239 } else if (exp == 0 && mnt == 0) {
4240 flags |= FPLIB_IOC;
4241 result = (uint64_t)1 << 63;
4242 } else if (fp64_is_infinity(exp, mnt)) {
4243 result = ((uint64_t)1 << 63) - 1;
4244 } else {
4245 if (mode & FPLIB_AH) {
4246 if (fp64_is_denormal(exp, mnt)) {
4247 flags |= FPLIB_IDC;
4248 }
4249 }
4250
4251 mnt = mnt << (FP64_BITS - FP64_MANT_BITS - 1);
4252 fp64_normalise(mnt, &exp);
4253 int unbias_exp = exp - FP64_EXP_BIAS;
4254 result = static_cast<uint64_t>((int64_t)unbias_exp);
4255 }
4256
4257 set_fpscr0(fpscr, flags);
4258
4259 return result;
4260}
4261
4262static uint16_t
4263fp16_min(uint16_t op1, uint16_t op2, int mode, int *flags, bool altfpminmax)
4264{
4265 int sgn1, exp1, sgn2, exp2;
4266 uint16_t mnt1, mnt2, x, result;
4267
4268 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, flags);
4269 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, flags);
4270
4271 if (altfpminmax) {
4272 // Alternate handling of zeros with differing sign
4273 if (!exp1 && !mnt1 && !exp2 && !mnt2 && (sgn1 != sgn2)) {
4274 return fp16_zero(sgn2);
4275 }
4276 // Alternate handling of NaN inputs
4277 else if (fp16_is_NaN(exp1, mnt1) || fp16_is_NaN(exp2, mnt2)) {
4278 if (mode & FPLIB_FPEXEC)
4279 *flags |= FPLIB_IOC;
4280 if (!exp2 && !mnt2) {
4281 return fp16_zero(sgn2);
4282 } else {
4283 return op2;
4284 }
4285 }
4286 }
4287
4288 if ((x = fp16_process_NaNs(op1, op2, mode, flags))) {
4289 result = x;
4290 } else {
4291 int sgn, exp;
4292 uint16_t mnt;
4293 if (sgn1 != sgn2 ? sgn1 : sgn1 ^ (op1 < op2)) {
4294 sgn = sgn1; exp = exp1; mnt = mnt1;
4295 } else {
4296 sgn = sgn2; exp = exp2; mnt = mnt2;
4297 }
4298
4299 if (exp == FP16_EXP_INF) {
4300 result = fp16_infinity(sgn);
4301 } else if (!exp && !mnt) {
4302 result = fp16_zero(sgn1 || sgn2); // Use most negative sign
4303 } else {
4304 if (altfpminmax) {
4305 mode = mode & (~(FPLIB_FZ | FPLIB_FIZ));
4306 }
4307 mnt = fp16_normalise(mnt, &exp);
4308 result = fp16_round(sgn, exp + FP16_EXP_BITS, mnt << 1, mode,
4309 flags);
4310 }
4311 }
4312 return result;
4313}
4314
4315static uint32_t
4316fp32_min(uint32_t op1, uint32_t op2, int mode, int *flags, bool altfpminmax)
4317{
4318 int sgn1, exp1, sgn2, exp2;
4319 uint32_t mnt1, mnt2, x, result;
4320
4321 fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, flags);
4322 fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, flags);
4323
4324 if (altfpminmax) {
4325 // Alternate handling of zeros with differing sign
4326 if (!exp1 && !mnt1 && !exp2 && !mnt2 && (sgn1 != sgn2)) {
4327 return fp32_zero(sgn2);
4328 }
4329 // Alternate handling of NaN inputs
4330 else if (fp32_is_NaN(exp1, mnt1) || fp32_is_NaN(exp2, mnt2)) {
4331 if (mode & FPLIB_FPEXEC)
4332 *flags |= FPLIB_IOC;
4333 if (!exp2 && !mnt2) {
4334 return fp32_zero(sgn2);
4335 } else {
4336 return op2;
4337 }
4338 }
4339 }
4340
4341 if ((x = fp32_process_NaNs(op1, op2, mode, flags))) {
4342 result = x;
4343 } else {
4344 // FPProcessDenorms3
4345 if (mode & FPLIB_AH) {
4346 if (fp32_is_denormal(exp1, mnt1) || fp32_is_denormal(exp2, mnt2)) {
4347 *flags |= FPLIB_IDC;
4348 }
4349 }
4350
4351 int sgn, exp;
4352 uint32_t mnt;
4353 if (sgn1 != sgn2 ? sgn1 : sgn1 ^ (op1 < op2)) {
4354 sgn = sgn1; exp = exp1; mnt = mnt1;
4355 } else {
4356 sgn = sgn2; exp = exp2; mnt = mnt2;
4357 }
4358
4359 if (exp == FP32_EXP_INF) {
4360 result = fp32_infinity(sgn);
4361 } else if (!exp && !mnt) {
4362 result = fp32_zero(sgn1 || sgn2); // Use most negative sign
4363 } else {
4364 if (altfpminmax) {
4365 mode = mode & (~(FPLIB_FZ | FPLIB_FIZ));
4366 }
4367 mnt = fp32_normalise(mnt, &exp);
4368 result = fp32_round(sgn, exp + FP32_EXP_BITS, mnt << 1, mode,
4369 flags);
4370 }
4371 }
4372 return result;
4373}
4374
4375static uint64_t
4376fp64_min(uint64_t op1, uint64_t op2, int mode, int *flags, bool altfpminmax)
4377{
4378 int sgn1, exp1, sgn2, exp2;
4379 uint64_t mnt1, mnt2, x, result;
4380
4381 fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, flags);
4382 fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, flags);
4383
4384 if (altfpminmax) {
4385 // Alternate handling of zeros with differing sign
4386 if (!exp1 && !mnt1 && !exp2 && !mnt2 && (sgn1 != sgn2)) {
4387 return fp64_zero(sgn2);
4388 }
4389 // Alternate handling of NaN inputs
4390 else if (fp64_is_NaN(exp1, mnt1) || fp64_is_NaN(exp2, mnt2)) {
4391 if (mode & FPLIB_FPEXEC)
4392 *flags |= FPLIB_IOC;
4393 if (!exp2 && !mnt2) {
4394 return fp64_zero(sgn2);
4395 } else {
4396 return op2;
4397 }
4398 }
4399 }
4400
4401 if ((x = fp64_process_NaNs(op1, op2, mode, flags))) {
4402 result = x;
4403 } else {
4404 // FPProcessDenorms3
4405 if (mode & FPLIB_AH) {
4406 if (fp64_is_denormal(exp1, mnt1) || fp64_is_denormal(exp2, mnt2)) {
4407 *flags |= FPLIB_IDC;
4408 }
4409 }
4410
4411 int sgn, exp;
4412 uint64_t mnt;
4413 if (sgn1 != sgn2 ? sgn1 : sgn1 ^ (op1 < op2)) {
4414 sgn = sgn1; exp = exp1; mnt = mnt1;
4415 } else {
4416 sgn = sgn2; exp = exp2; mnt = mnt2;
4417 }
4418
4419 if (exp == FP64_EXP_INF) {
4420 result = fp64_infinity(sgn);
4421 } else if (!exp && !mnt) {
4422 result = fp64_zero(sgn1 || sgn2); // Use most negative sign
4423 } else {
4424 if (altfpminmax) {
4425 mode = mode & (~(FPLIB_FZ | FPLIB_FIZ));
4426 }
4427 mnt = fp64_normalise(mnt, &exp);
4428 result = fp64_round(sgn, exp + FP64_EXP_BITS, mnt << 1, mode,
4429 flags);
4430 }
4431 }
4432 return result;
4433}
4434
4435static uint16_t
4436fp16_max(uint16_t op1, uint16_t op2, int mode, int *flags, bool altfpminmax)
4437{
4438 int sgn1, exp1, sgn2, exp2;
4439 uint16_t mnt1, mnt2, x, result;
4440
4441 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, flags);
4442 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, flags);
4443
4444 if (altfpminmax) {
4445 // Alternate handling of zeros with differing sign
4446 if (!exp1 && !mnt1 && !exp2 && !mnt2 && (sgn1 != sgn2)) {
4447 return fp16_zero(sgn2);
4448 }
4449 // Alternate handling of NaN inputs
4450 else if (fp16_is_NaN(exp1, mnt1) || fp16_is_NaN(exp2, mnt2)) {
4451 if (mode & FPLIB_FPEXEC)
4452 *flags |= FPLIB_IOC;
4453 if (!exp2 && !mnt2) {
4454 return fp16_zero(sgn2);
4455 } else {
4456 return op2;
4457 }
4458 }
4459 }
4460
4461 if ((x = fp16_process_NaNs(op1, op2, mode, flags))) {
4462 result = x;
4463 } else {
4464 int sgn, exp;
4465 uint16_t mnt;
4466 if (sgn1 != sgn2 ? sgn2 : sgn1 ^ (op1 > op2)) {
4467 sgn = sgn1; exp = exp1; mnt = mnt1;
4468 } else {
4469 sgn = sgn2; exp = exp2; mnt = mnt2;
4470 }
4471
4472 if (exp == FP16_EXP_INF) {
4473 result = fp16_infinity(sgn);
4474 } else if (!exp && !mnt) {
4475 result = fp16_zero(sgn1 && sgn2); // Use most positive sign
4476 } else {
4477 if (altfpminmax) {
4478 mode = mode & (~(FPLIB_FZ | FPLIB_FIZ));
4479 }
4480 mnt = fp16_normalise(mnt, &exp);
4481 result = fp16_round(sgn, exp + FP16_EXP_BITS, mnt << 1, mode,
4482 flags);
4483 }
4484 }
4485 return result;
4486}
4487
4488static uint32_t
4489fp32_max(uint32_t op1, uint32_t op2, int mode, int *flags, bool altfpminmax)
4490{
4491 int sgn1, exp1, sgn2, exp2;
4492 uint32_t mnt1, mnt2, x, result;
4493
4494 fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, flags);
4495 fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, flags);
4496
4497 if (altfpminmax) {
4498 // Alternate handling of zeros with differing sign
4499 if (!exp1 && !mnt1 && !exp2 && !mnt2 && (sgn1 != sgn2)) {
4500 return fp32_zero(sgn2);
4501 }
4502 // Alternate handling of NaN inputs
4503 else if (fp32_is_NaN(exp1, mnt1) || fp32_is_NaN(exp2, mnt2)) {
4504 if (mode & FPLIB_FPEXEC)
4505 *flags |= FPLIB_IOC;
4506 if (!exp2 && !mnt2) {
4507 return fp32_zero(sgn2);
4508 } else {
4509 return op2;
4510 }
4511 }
4512 }
4513
4514 if ((x = fp32_process_NaNs(op1, op2, mode, flags))) {
4515 result = x;
4516 } else {
4517 // FPProcessDenorms3
4518 if (mode & FPLIB_AH) {
4519 if (fp32_is_denormal(exp1, mnt1) || fp32_is_denormal(exp2, mnt2)) {
4520 *flags |= FPLIB_IDC;
4521 }
4522 }
4523
4524 int sgn, exp;
4525 uint32_t mnt;
4526 if (sgn1 != sgn2 ? sgn2 : sgn1 ^ (op1 > op2)) {
4527 sgn = sgn1; exp = exp1; mnt = mnt1;
4528 } else {
4529 sgn = sgn2; exp = exp2; mnt = mnt2;
4530 }
4531
4532 if (exp == FP32_EXP_INF) {
4533 result = fp32_infinity(sgn);
4534 } else if (!exp && !mnt) {
4535 result = fp32_zero(sgn1 && sgn2); // Use most positive sign
4536 } else {
4537 if (altfpminmax) {
4538 mode = mode & (~(FPLIB_FZ | FPLIB_FIZ));
4539 }
4540 mnt = fp32_normalise(mnt, &exp);
4541 result = fp32_round(sgn, exp + FP32_EXP_BITS, mnt << 1, mode,
4542 flags);
4543 }
4544 }
4545 return result;
4546}
4547
4548static uint64_t
4549fp64_max(uint64_t op1, uint64_t op2, int mode, int *flags, bool altfpminmax)
4550{
4551 int sgn1, exp1, sgn2, exp2;
4552 uint64_t mnt1, mnt2, x, result;
4553
4554 fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, flags);
4555 fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, flags);
4556
4557 if (altfpminmax) {
4558 // Alternate handling of zeros with differing sign
4559 if (!exp1 && !mnt1 && !exp2 && !mnt2 && (sgn1 != sgn2)) {
4560 return fp64_zero(sgn2);
4561 }
4562 // Alternate handling of NaN inputs
4563 else if (fp64_is_NaN(exp1, mnt1) || fp64_is_NaN(exp2, mnt2)) {
4564 if (mode & FPLIB_FPEXEC)
4565 *flags |= FPLIB_IOC;
4566 if (!exp2 && !mnt2) {
4567 return fp64_zero(sgn2);
4568 } else {
4569 return op2;
4570 }
4571 }
4572 }
4573
4574 if ((x = fp64_process_NaNs(op1, op2, mode, flags))) {
4575 result = x;
4576 } else {
4577 // FPProcessDenorms3
4578 if (mode & FPLIB_AH) {
4579 if (fp64_is_denormal(exp1, mnt1) || fp64_is_denormal(exp2, mnt2)) {
4580 *flags |= FPLIB_IDC;
4581 }
4582 }
4583
4584 int sgn, exp;
4585 uint64_t mnt;
4586 if (sgn1 != sgn2 ? sgn2 : sgn1 ^ (op1 > op2)) {
4587 sgn = sgn1; exp = exp1; mnt = mnt1;
4588 } else {
4589 sgn = sgn2; exp = exp2; mnt = mnt2;
4590 }
4591
4592 if (exp == FP64_EXP_INF) {
4593 result = fp64_infinity(sgn);
4594 } else if (!exp && !mnt) {
4595 result = fp64_zero(sgn1 && sgn2); // Use most positive sign
4596 } else {
4597 if (altfpminmax) {
4598 mode = mode & (~(FPLIB_FZ | FPLIB_FIZ));
4599 }
4600 mnt = fp64_normalise(mnt, &exp);
4601 result = fp64_round(sgn, exp + FP64_EXP_BITS, mnt << 1, mode,
4602 flags);
4603 }
4604 }
4605 return result;
4606}
4607
4608static void
4609fp16_minmaxnum(uint16_t *op1, uint16_t *op2, int sgn)
4610{
4611 // Treat a single quiet-NaN as +Infinity/-Infinity
4612 if (!((uint16_t)~(*op1 << 1) >> FP16_MANT_BITS) &&
4613 (uint16_t)~(*op2 << 1) >> FP16_MANT_BITS)
4614 *op1 = fp16_infinity(sgn);
4615 if (!((uint16_t)~(*op2 << 1) >> FP16_MANT_BITS) &&
4616 (uint16_t)~(*op1 << 1) >> FP16_MANT_BITS)
4617 *op2 = fp16_infinity(sgn);
4618}
4619
4620static void
4621fp32_minmaxnum(uint32_t *op1, uint32_t *op2, int sgn)
4622{
4623 // Treat a single quiet-NaN as +Infinity/-Infinity
4624 if (!((uint32_t)~(*op1 << 1) >> FP32_MANT_BITS) &&
4625 (uint32_t)~(*op2 << 1) >> FP32_MANT_BITS)
4626 *op1 = fp32_infinity(sgn);
4627 if (!((uint32_t)~(*op2 << 1) >> FP32_MANT_BITS) &&
4628 (uint32_t)~(*op1 << 1) >> FP32_MANT_BITS)
4629 *op2 = fp32_infinity(sgn);
4630}
4631
4632static void
4633fp64_minmaxnum(uint64_t *op1, uint64_t *op2, int sgn)
4634{
4635 // Treat a single quiet-NaN as +Infinity/-Infinity
4636 if (!((uint64_t)~(*op1 << 1) >> FP64_MANT_BITS) &&
4637 (uint64_t)~(*op2 << 1) >> FP64_MANT_BITS)
4638 *op1 = fp64_infinity(sgn);
4639 if (!((uint64_t)~(*op2 << 1) >> FP64_MANT_BITS) &&
4640 (uint64_t)~(*op1 << 1) >> FP64_MANT_BITS)
4641 *op2 = fp64_infinity(sgn);
4642}
4643
4644template <>
4645uint16_t
4646fplibMax(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
4647{
4648 int flags = 0;
4649 uint16_t result = fp16_max(op1, op2, modeConv(fpscr, fpcr), &flags,
4650 fpcr.ah);
4651 set_fpscr0(fpscr, flags);
4652 return result;
4653}
4654
4655template <>
4656uint32_t
4657fplibMax(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
4658{
4659 int flags = 0;
4660 uint32_t result = fp32_max(op1, op2, modeConv(fpscr, fpcr), &flags,
4661 fpcr.ah);
4662 set_fpscr0(fpscr, flags);
4663 return result;
4664}
4665
4666template <>
4667uint64_t
4668fplibMax(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
4669{
4670 int flags = 0;
4671 uint64_t result = fp64_max(op1, op2, modeConv(fpscr, fpcr), &flags,
4672 fpcr.ah);
4673 set_fpscr0(fpscr, flags);
4674 return result;
4675}
4676
4677template <>
4678uint16_t
4679fplibMaxNum(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
4680{
4681 int exp1 = FP16_EXP(op1);
4682 int exp2 = FP16_EXP(op2);
4683 uint16_t mnt1 = FP16_MANT(op1);
4684 uint16_t mnt2 = FP16_MANT(op2);
4685 if (!(fpcr.ah && fp16_is_NaN(exp1, mnt1) && fp16_is_NaN(exp2, mnt2))) {
4686 fp16_minmaxnum(&op1, &op2, 1);
4687 }
4688
4689 int flags = 0;
4690 uint16_t result = fp16_max(op1, op2, modeConv(fpscr, fpcr), &flags, false);
4691 set_fpscr0(fpscr, flags);
4692 return result;
4693}
4694
4695template <>
4696uint32_t
4697fplibMaxNum(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
4698{
4699 int exp1 = FP32_EXP(op1);
4700 int exp2 = FP32_EXP(op2);
4701 uint32_t mnt1 = FP32_MANT(op1);
4702 uint32_t mnt2 = FP32_MANT(op2);
4703 if (!(fpcr.ah && fp32_is_NaN(exp1, mnt1) && fp32_is_NaN(exp2, mnt2))) {
4704 fp32_minmaxnum(&op1, &op2, 1);
4705 }
4706
4707 int flags = 0;
4708 uint32_t result = fp32_max(op1, op2, modeConv(fpscr, fpcr), &flags, false);
4709 set_fpscr0(fpscr, flags);
4710 return result;
4711}
4712
4713template <>
4714uint64_t
4715fplibMaxNum(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
4716{
4717 int exp1 = FP64_EXP(op1);
4718 int exp2 = FP64_EXP(op2);
4719 uint64_t mnt1 = FP64_MANT(op1);
4720 uint64_t mnt2 = FP64_MANT(op2);
4721 if (!(fpcr.ah && fp64_is_NaN(exp1, mnt1) && fp64_is_NaN(exp2, mnt2))) {
4722 fp64_minmaxnum(&op1, &op2, 1);
4723 }
4724
4725 int flags = 0;
4726 uint64_t result = fp64_max(op1, op2, modeConv(fpscr, fpcr), &flags, false);
4727 set_fpscr0(fpscr, flags);
4728 return result;
4729}
4730
4731template <>
4732uint16_t
4733fplibMin(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
4734{
4735 int flags = 0;
4736 uint16_t result = fp16_min(op1, op2, modeConv(fpscr, fpcr), &flags,
4737 fpcr.ah);
4738 set_fpscr0(fpscr, flags);
4739 return result;
4740}
4741
4742template <>
4743uint32_t
4744fplibMin(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
4745{
4746 int flags = 0;
4747 uint32_t result = fp32_min(op1, op2, modeConv(fpscr, fpcr), &flags,
4748 fpcr.ah);
4749 set_fpscr0(fpscr, flags);
4750 return result;
4751}
4752
4753template <>
4754uint64_t
4755fplibMin(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
4756{
4757 int flags = 0;
4758 uint64_t result = fp64_min(op1, op2, modeConv(fpscr, fpcr), &flags,
4759 fpcr.ah);
4760 set_fpscr0(fpscr, flags);
4761 return result;
4762}
4763
4764template <>
4765uint16_t
4766fplibMinNum(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
4767{
4768 int exp1 = FP16_EXP(op1);
4769 int exp2 = FP16_EXP(op2);
4770 uint16_t mnt1 = FP16_MANT(op1);
4771 uint16_t mnt2 = FP16_MANT(op2);
4772 if (!(fpcr.ah && fp16_is_NaN(exp1, mnt1) && fp16_is_NaN(exp2, mnt2))) {
4773 fp16_minmaxnum(&op1, &op2, 0);
4774 }
4775
4776 int flags = 0;
4777 uint16_t result = fp16_min(op1, op2, modeConv(fpscr, fpcr), &flags, false);
4778 set_fpscr0(fpscr, flags);
4779 return result;
4780}
4781
4782template <>
4783uint32_t
4784fplibMinNum(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
4785{
4786 int exp1 = FP32_EXP(op1);
4787 int exp2 = FP32_EXP(op2);
4788 uint32_t mnt1 = FP32_MANT(op1);
4789 uint32_t mnt2 = FP32_MANT(op2);
4790 if (!(fpcr.ah && fp32_is_NaN(exp1, mnt1) && fp32_is_NaN(exp2, mnt2))) {
4791 fp32_minmaxnum(&op1, &op2, 0);
4792 }
4793
4794 int flags = 0;
4795 uint32_t result = fp32_min(op1, op2, modeConv(fpscr, fpcr), &flags, false);
4796 set_fpscr0(fpscr, flags);
4797 return result;
4798}
4799
4800template <>
4801uint64_t
4802fplibMinNum(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
4803{
4804 int exp1 = FP64_EXP(op1);
4805 int exp2 = FP64_EXP(op2);
4806 uint64_t mnt1 = FP64_MANT(op1);
4807 uint64_t mnt2 = FP64_MANT(op2);
4808 if (!(fpcr.ah && fp64_is_NaN(exp1, mnt1) && fp64_is_NaN(exp2, mnt2))) {
4809 fp64_minmaxnum(&op1, &op2, 0);
4810 }
4811
4812 int flags = 0;
4813 uint64_t result = fp64_min(op1, op2, modeConv(fpscr, fpcr), &flags, false);
4814 set_fpscr0(fpscr, flags);
4815 return result;
4816}
4817
4818template <>
4819uint16_t
4820fplibMul(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
4821{
4822 int flags = 0;
4823 uint16_t result = fp16_mul(op1, op2, modeConv(fpscr, fpcr), &flags);
4824 set_fpscr0(fpscr, flags);
4825 return result;
4826}
4827
4828template <>
4829uint32_t
4830fplibMul(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
4831{
4832 int flags = 0;
4833 uint32_t result = fp32_mul(op1, op2, modeConv(fpscr, fpcr), &flags);
4834 set_fpscr0(fpscr, flags);
4835 return result;
4836}
4837
4838template <>
4839uint64_t
4840fplibMul(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
4841{
4842 int flags = 0;
4843 uint64_t result = fp64_mul(op1, op2, modeConv(fpscr, fpcr), &flags);
4844 set_fpscr0(fpscr, flags);
4845 return result;
4846}
4847
4848template <>
4849uint16_t
4850fplibMulX(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
4851{
4852 int mode = modeConv(fpscr, fpcr);
4853 int flags = 0;
4854 int sgn1, exp1, sgn2, exp2;
4855 uint16_t mnt1, mnt2, result;
4856
4857 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
4858 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
4859
4860 result = fp16_process_NaNs(op1, op2, mode, &flags);
4861 if (!result) {
4862 if ((exp1 == FP16_EXP_INF && !mnt2) ||
4863 (exp2 == FP16_EXP_INF && !mnt1)) {
4864 result = fp16_FPTwo(sgn1 ^ sgn2);
4865 } else if (exp1 == FP16_EXP_INF || exp2 == FP16_EXP_INF) {
4866 result = fp16_infinity(sgn1 ^ sgn2);
4867 } else if (!mnt1 || !mnt2) {
4868 result = fp16_zero(sgn1 ^ sgn2);
4869 } else {
4870 result = fp16_mul(op1, op2, mode, &flags);
4871 }
4872 }
4873
4874 set_fpscr0(fpscr, flags);
4875
4876 return result;
4877}
4878
4879template <>
4880uint32_t
4881fplibMulX(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
4882{
4883 int mode = modeConv(fpscr, fpcr);
4884 int flags = 0;
4885 int sgn1, exp1, sgn2, exp2;
4886 uint32_t mnt1, mnt2, result;
4887
4888 fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
4889 fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
4890
4891 result = fp32_process_NaNs(op1, op2, mode, &flags);
4892 if (!result) {
4893 if ((exp1 == FP32_EXP_INF && !mnt2) ||
4894 (exp2 == FP32_EXP_INF && !mnt1)) {
4895 result = fp32_FPTwo(sgn1 ^ sgn2);
4896 } else if (exp1 == FP32_EXP_INF || exp2 == FP32_EXP_INF) {
4897 result = fp32_infinity(sgn1 ^ sgn2);
4898 } else if (!mnt1 || !mnt2) {
4899 result = fp32_zero(sgn1 ^ sgn2);
4900 } else {
4901 result = fp32_mul(op1, op2, mode, &flags);
4902 }
4903
4904 // FPProcessDenorms2
4905 if (mode & FPLIB_AH) {
4906 if (fp32_is_denormal(exp1, mnt1) || fp32_is_denormal(exp2, mnt2)) {
4907 flags |= FPLIB_IDC;
4908 }
4909 }
4910 }
4911
4912 set_fpscr0(fpscr, flags);
4913
4914 return result;
4915}
4916
4917template <>
4918uint64_t
4919fplibMulX(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
4920{
4921 int mode = modeConv(fpscr, fpcr);
4922 int flags = 0;
4923 int sgn1, exp1, sgn2, exp2;
4924 uint64_t mnt1, mnt2, result;
4925
4926 fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
4927 fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
4928
4929 result = fp64_process_NaNs(op1, op2, mode, &flags);
4930 if (!result) {
4931 if ((exp1 == FP64_EXP_INF && !mnt2) ||
4932 (exp2 == FP64_EXP_INF && !mnt1)) {
4933 result = fp64_FPTwo(sgn1 ^ sgn2);
4934 } else if (exp1 == FP64_EXP_INF || exp2 == FP64_EXP_INF) {
4935 result = fp64_infinity(sgn1 ^ sgn2);
4936 } else if (!mnt1 || !mnt2) {
4937 result = fp64_zero(sgn1 ^ sgn2);
4938 } else {
4939 result = fp64_mul(op1, op2, mode, &flags);
4940 }
4941
4942 // FPProcessDenorms2
4943 if (mode & FPLIB_AH) {
4944 if (fp64_is_denormal(exp1, mnt1) || fp64_is_denormal(exp2, mnt2)) {
4945 flags |= FPLIB_IDC;
4946 }
4947 }
4948 }
4949
4950 set_fpscr0(fpscr, flags);
4951
4952 return result;
4953}
4954
4955template <>
4956uint16_t
4957fplibNeg(uint16_t op, FPCR fpcr)
4958{
4959 if (fpcr.ah && fp16_is_NaN(FP16_EXP(op), FP16_MANT(op))) {
4960 return op;
4961 }
4962 return op ^ 1ULL << (FP16_BITS - 1);
4963}
4964
4965template <>
4966uint32_t
4967fplibNeg(uint32_t op, FPCR fpcr)
4968{
4969 if (fpcr.ah && fp32_is_NaN(FP32_EXP(op), FP32_MANT(op))) {
4970 return op;
4971 }
4972 return op ^ 1ULL << (FP32_BITS - 1);
4973}
4974
4975template <>
4976uint64_t
4977fplibNeg(uint64_t op, FPCR fpcr)
4978{
4979 if (fpcr.ah && fp64_is_NaN(FP64_EXP(op), FP64_MANT(op))) {
4980 return op;
4981 }
4982 return op ^ 1ULL << (FP64_BITS - 1);
4983}
4984
4985static const uint8_t recip_sqrt_estimate[256] = {
4986 255, 253, 251, 249, 247, 245, 243, 242, 240, 238, 236, 234, 233, 231, 229, 228,
4987 226, 224, 223, 221, 219, 218, 216, 215, 213, 212, 210, 209, 207, 206, 204, 203,
4988 201, 200, 198, 197, 196, 194, 193, 192, 190, 189, 188, 186, 185, 184, 183, 181,
4989 180, 179, 178, 176, 175, 174, 173, 172, 170, 169, 168, 167, 166, 165, 164, 163,
4990 162, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146,
4991 145, 144, 143, 142, 141, 140, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131,
4992 131, 130, 129, 128, 127, 126, 126, 125, 124, 123, 122, 121, 121, 120, 119, 118,
4993 118, 117, 116, 115, 114, 114, 113, 112, 111, 111, 110, 109, 109, 108, 107, 106,
4994 105, 104, 103, 101, 100, 99, 97, 96, 95, 93, 92, 91, 90, 88, 87, 86,
4995 85, 84, 82, 81, 80, 79, 78, 77, 76, 75, 74, 72, 71, 70, 69, 68,
4996 67, 66, 65, 64, 63, 62, 61, 60, 60, 59, 58, 57, 56, 55, 54, 53,
4997 52, 51, 51, 50, 49, 48, 47, 46, 46, 45, 44, 43, 42, 42, 41, 40,
4998 39, 38, 38, 37, 36, 35, 35, 34, 33, 33, 32, 31, 30, 30, 29, 28,
4999 28, 27, 26, 26, 25, 24, 24, 23, 22, 22, 21, 20, 20, 19, 19, 18,
5000 17, 17, 16, 16, 15, 14, 14, 13, 13, 12, 11, 11, 10, 10, 9, 9,
5001 8, 8, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0
5002};
5003
5004template <>
5005uint16_t
5006fplibRSqrtEstimate(uint16_t op, FPSCR &fpscr, FPCR fpcr)
5007{
5008 int mode = modeConv(fpscr, fpcr);
5009 if (mode & FPLIB_AH) { // altfp
5010 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5011 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5012 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
5013 }
5014 int flags = 0;
5015 int sgn, exp;
5016 uint16_t mnt, result;
5017
5018 fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
5019
5020 if (fp16_is_NaN(exp, mnt)) {
5021 result = fp16_process_NaN(op, mode, &flags);
5022 } else if (!mnt) {
5023 result = fp16_infinity(sgn);
5024 if (mode & FPLIB_FPEXEC)
5025 flags |= FPLIB_DZC;
5026 } else if (sgn) {
5027 result = fp16_defaultNaN(mode);
5028 if (mode & FPLIB_FPEXEC)
5029 flags |= FPLIB_IOC;
5030 } else if (exp == FP16_EXP_INF) {
5031 result = fp16_zero(0);
5032 } else {
5033 exp += FP16_EXP_BITS;
5034 mnt = fp16_normalise(mnt, &exp);
5035 mnt = recip_sqrt_estimate[(~exp & 1) << 7 |
5036 (mnt >> (FP16_BITS - 8) & 127)];
5037 result = fp16_pack(0, (3 * FP16_EXP_BIAS - exp - 1) >> 1,
5038 mnt << (FP16_MANT_BITS - 8));
5039 }
5040
5041 set_fpscr0(fpscr, flags);
5042
5043 return result;
5044}
5045
5046template <>
5047uint32_t
5048fplibRSqrtEstimate(uint32_t op, FPSCR &fpscr, FPCR fpcr)
5049{
5050 int mode = modeConv(fpscr, fpcr);
5051 if (mode & FPLIB_AH) { // altfp
5052 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5053 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5054 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
5055 }
5056 int flags = 0;
5057 int sgn, exp;
5058 uint32_t mnt, result;
5059
5060 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
5061
5062 if (fp32_is_NaN(exp, mnt)) {
5063 result = fp32_process_NaN(op, mode, &flags);
5064 } else if (!mnt) {
5065 result = fp32_infinity(sgn);
5066 if (mode & FPLIB_FPEXEC)
5067 flags |= FPLIB_DZC;
5068 } else if (sgn) {
5069 result = fp32_defaultNaN(mode);
5070 if (mode & FPLIB_FPEXEC)
5071 flags |= FPLIB_IOC;
5072 } else if (exp == FP32_EXP_INF) {
5073 result = fp32_zero(0);
5074 } else {
5075 exp += FP32_EXP_BITS;
5076 mnt = fp32_normalise(mnt, &exp);
5077 mnt = recip_sqrt_estimate[(~exp & 1) << 7 |
5078 (mnt >> (FP32_BITS - 8) & 127)];
5079 result = fp32_pack(0, (3 * FP32_EXP_BIAS - exp - 1) >> 1,
5080 mnt << (FP32_MANT_BITS - 8));
5081 }
5082
5083 set_fpscr0(fpscr, flags);
5084
5085 return result;
5086}
5087
5088template <>
5089uint64_t
5090fplibRSqrtEstimate(uint64_t op, FPSCR &fpscr, FPCR fpcr)
5091{
5092 int mode = modeConv(fpscr, fpcr);
5093 if (mode & FPLIB_AH) { // altfp
5094 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5095 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5096 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
5097 }
5098 int flags = 0;
5099 int sgn, exp;
5100 uint64_t mnt, result;
5101
5102 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
5103
5104 if (fp64_is_NaN(exp, mnt)) {
5105 result = fp64_process_NaN(op, mode, &flags);
5106 } else if (!mnt) {
5107 result = fp64_infinity(sgn);
5108 if (mode & FPLIB_FPEXEC)
5109 flags |= FPLIB_DZC;
5110 } else if (sgn) {
5111 result = fp64_defaultNaN(mode);
5112 if (mode & FPLIB_FPEXEC)
5113 flags |= FPLIB_IOC;
5114 } else if (exp == FP64_EXP_INF) {
5115 result = fp32_zero(0);
5116 } else {
5117 exp += FP64_EXP_BITS;
5118 mnt = fp64_normalise(mnt, &exp);
5119 mnt = recip_sqrt_estimate[(~exp & 1) << 7 |
5120 (mnt >> (FP64_BITS - 8) & 127)];
5121 result = fp64_pack(0, (3 * FP64_EXP_BIAS - exp - 1) >> 1,
5122 mnt << (FP64_MANT_BITS - 8));
5123 }
5124
5125 set_fpscr0(fpscr, flags);
5126
5127 return result;
5128}
5129
5130template <>
5131uint16_t
5132fplibRSqrtStepFused(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
5133{
5134 int mode = modeConv(fpscr, fpcr);
5135 if (mode & FPLIB_AH) { // altfp
5136 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5137 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5138 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
5139 }
5140 int flags = 0;
5141 int sgn1, exp1, sgn2, exp2;
5142 uint16_t mnt1, mnt2, result;
5143
5144 op1 = fplibNeg<uint16_t>(op1, fpcr);
5145 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
5146 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
5147
5148 result = fp16_process_NaNs(op1, op2, mode, &flags);
5149 if (!result) {
5150 if ((exp1 == FP16_EXP_INF && !mnt2) ||
5151 (exp2 == FP16_EXP_INF && !mnt1)) {
5152 result = fp16_FPOnePointFive(0);
5153 } else if (exp1 == FP16_EXP_INF || exp2 == FP16_EXP_INF) {
5154 result = fp16_infinity(sgn1 ^ sgn2);
5155 } else {
5156 result = fp16_muladd(fp16_FPThree(0), op1, op2, -1, mode, &flags);
5157 }
5158 }
5159
5160 set_fpscr0(fpscr, flags);
5161
5162 return result;
5163}
5164
5165template <>
5166uint32_t
5167fplibRSqrtStepFused(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
5168{
5169 int mode = modeConv(fpscr, fpcr);
5170 if (mode & FPLIB_AH) { // altfp
5171 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5172 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5173 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
5174 }
5175 int flags = 0;
5176 int sgn1, exp1, sgn2, exp2;
5177 uint32_t mnt1, mnt2, result;
5178
5179 op1 = fplibNeg<uint32_t>(op1, fpcr);
5180 fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
5181 fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
5182
5183 result = fp32_process_NaNs(op1, op2, mode, &flags);
5184 if (!result) {
5185 if ((exp1 == FP32_EXP_INF && !mnt2) ||
5186 (exp2 == FP32_EXP_INF && !mnt1)) {
5187 result = fp32_FPOnePointFive(0);
5188 } else if (exp1 == FP32_EXP_INF || exp2 == FP32_EXP_INF) {
5189 result = fp32_infinity(sgn1 ^ sgn2);
5190 } else {
5191 result = fp32_muladd(fp32_FPThree(0), op1, op2, -1, mode, &flags);
5192 }
5193 }
5194
5195 set_fpscr0(fpscr, flags);
5196
5197 return result;
5198}
5199
5200template <>
5201uint64_t
5202fplibRSqrtStepFused(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
5203{
5204 int mode = modeConv(fpscr, fpcr);
5205 if (mode & FPLIB_AH) { // altfp
5206 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5207 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5208 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
5209 }
5210 int flags = 0;
5211 int sgn1, exp1, sgn2, exp2;
5212 uint64_t mnt1, mnt2, result;
5213
5214 op1 = fplibNeg<uint64_t>(op1, fpcr);
5215 fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
5216 fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
5217
5218 result = fp64_process_NaNs(op1, op2, mode, &flags);
5219 if (!result) {
5220 if ((exp1 == FP64_EXP_INF && !mnt2) ||
5221 (exp2 == FP64_EXP_INF && !mnt1)) {
5222 result = fp64_FPOnePointFive(0);
5223 } else if (exp1 == FP64_EXP_INF || exp2 == FP64_EXP_INF) {
5224 result = fp64_infinity(sgn1 ^ sgn2);
5225 } else {
5226 result = fp64_muladd(fp64_FPThree(0), op1, op2, -1, mode, &flags);
5227 }
5228 }
5229
5230 set_fpscr0(fpscr, flags);
5231
5232 return result;
5233}
5234
5235template <>
5236uint16_t
5237fplibRecipEstimate(uint16_t op, FPSCR &fpscr, FPCR fpcr)
5238{
5239 int mode = modeConv(fpscr, fpcr);
5240 int rm = FPCRRounding(fpscr);
5241 if (mode & FPLIB_AH) { // altfp
5242 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5243 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5244 rm = 0; // fpcr.RMode = '00'
5245 }
5246 int flags = 0;
5247 int sgn, exp;
5248 uint16_t mnt, result;
5249
5250 fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
5251
5252 if (fp16_is_NaN(exp, mnt)) {
5253 result = fp16_process_NaN(op, mode, &flags);
5254 } else if (exp == FP16_EXP_INF) {
5255 result = fp16_zero(sgn);
5256 } else if (!mnt) {
5257 result = fp16_infinity(sgn);
5258 if (mode & FPLIB_FPEXEC)
5259 flags |= FPLIB_DZC;
5260 } else if (!((uint16_t)(op << 1) >> (FP16_MANT_BITS - 1))) {
5261 bool overflow_to_inf = false;
5262 switch (rm) {
5263 case FPRounding_TIEEVEN:
5264 overflow_to_inf = true;
5265 break;
5266 case FPRounding_POSINF:
5267 overflow_to_inf = !sgn;
5268 break;
5269 case FPRounding_NEGINF:
5270 overflow_to_inf = sgn;
5271 break;
5272 case FPRounding_ZERO:
5273 overflow_to_inf = false;
5274 break;
5275 default:
5276 panic("Unrecognized FP rounding mode");
5277 }
5278 result = overflow_to_inf ? fp16_infinity(sgn) : fp16_max_normal(sgn);
5279 if (mode & FPLIB_FPEXEC)
5280 flags |= FPLIB_OFC | FPLIB_IXC;
5281 } else if ((mode & FPLIB_FZ16) && exp >= 2 * FP16_EXP_BIAS - 1) {
5282 result = fp16_zero(sgn);
5283 if (mode & FPLIB_FPEXEC)
5284 flags |= FPLIB_UFC;
5285 } else {
5286 exp += FP16_EXP_BITS;
5287 mnt = fp16_normalise(mnt, &exp);
5288 int result_exp = 2 * FP16_EXP_BIAS - 1 - exp;
5289 uint16_t fraction = (((uint32_t)1 << 19) /
5290 (mnt >> (FP16_BITS - 10) | 1) + 1) >> 1;
5291 fraction <<= FP16_MANT_BITS - 8;
5292 if (result_exp == 0) {
5293 fraction >>= 1;
5294 } else if (result_exp == -1) {
5295 fraction >>= 2;
5296 result_exp = 0;
5297 }
5298 result = fp16_pack(sgn, result_exp, fraction);
5299 }
5300
5301 set_fpscr0(fpscr, flags);
5302
5303 return result;
5304}
5305
5306template <>
5307uint32_t
5308fplibRecipEstimate(uint32_t op, FPSCR &fpscr, FPCR fpcr)
5309{
5310 int mode = modeConv(fpscr, fpcr);
5311 int rm = FPCRRounding(fpscr);
5312 if (mode & FPLIB_AH) { // altfp
5313 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5314 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5315 rm = 0; // fpcr.RMode = '00'
5316 }
5317 int flags = 0;
5318 int sgn, exp;
5319 uint32_t mnt, result;
5320
5321 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
5322
5323 if (fp32_is_NaN(exp, mnt)) {
5324 result = fp32_process_NaN(op, mode, &flags);
5325 } else if (exp == FP32_EXP_INF) {
5326 result = fp32_zero(sgn);
5327 } else if (!mnt) {
5328 result = fp32_infinity(sgn);
5329 if (mode & FPLIB_FPEXEC)
5330 flags |= FPLIB_DZC;
5331 } else if (!((uint32_t)(op << 1) >> (FP32_MANT_BITS - 1))) {
5332 bool overflow_to_inf = false;
5333 switch (rm) {
5334 case FPRounding_TIEEVEN:
5335 overflow_to_inf = true;
5336 break;
5337 case FPRounding_POSINF:
5338 overflow_to_inf = !sgn;
5339 break;
5340 case FPRounding_NEGINF:
5341 overflow_to_inf = sgn;
5342 break;
5343 case FPRounding_ZERO:
5344 overflow_to_inf = false;
5345 break;
5346 default:
5347 panic("Unrecognized FP rounding mode");
5348 }
5349 result = overflow_to_inf ? fp32_infinity(sgn) : fp32_max_normal(sgn);
5350 if (mode & FPLIB_FPEXEC)
5351 flags |= FPLIB_OFC | FPLIB_IXC;
5352 } else if ((mode & FPLIB_FZ) && exp >= 2 * FP32_EXP_BIAS - 1) {
5353 result = fp32_zero(sgn);
5354 if (mode & FPLIB_FPEXEC)
5355 flags |= FPLIB_UFC;
5356 } else {
5357 exp += FP32_EXP_BITS;
5358 mnt = fp32_normalise(mnt, &exp);
5359 int result_exp = 2 * FP32_EXP_BIAS - 1 - exp;
5360 uint32_t fraction = (((uint32_t)1 << 19) /
5361 (mnt >> (FP32_BITS - 10) | 1) + 1) >> 1;
5362 fraction <<= FP32_MANT_BITS - 8;
5363 if (result_exp == 0) {
5364 fraction >>= 1;
5365 } else if (result_exp == -1) {
5366 fraction >>= 2;
5367 result_exp = 0;
5368 }
5369 result = fp32_pack(sgn, result_exp, fraction);
5370 }
5371
5372 set_fpscr0(fpscr, flags);
5373
5374 return result;
5375}
5376
5377template <>
5378uint64_t
5379fplibRecipEstimate(uint64_t op, FPSCR &fpscr, FPCR fpcr)
5380{
5381 int mode = modeConv(fpscr, fpcr);
5382 int rm = FPCRRounding(fpscr);
5383 if (mode & FPLIB_AH) { // altfp
5384 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5385 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5386 rm = 0; // fpcr.RMode = '00'
5387 }
5388 int flags = 0;
5389 int sgn, exp;
5390 uint64_t mnt, result;
5391
5392 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
5393
5394 if (fp64_is_NaN(exp, mnt)) {
5395 result = fp64_process_NaN(op, mode, &flags);
5396 } else if (exp == FP64_EXP_INF) {
5397 result = fp64_zero(sgn);
5398 } else if (!mnt) {
5399 result = fp64_infinity(sgn);
5400 if (mode & FPLIB_FPEXEC)
5401 flags |= FPLIB_DZC;
5402 } else if (!((uint64_t)(op << 1) >> (FP64_MANT_BITS - 1))) {
5403 bool overflow_to_inf = false;
5404 switch (rm) {
5405 case FPRounding_TIEEVEN:
5406 overflow_to_inf = true;
5407 break;
5408 case FPRounding_POSINF:
5409 overflow_to_inf = !sgn;
5410 break;
5411 case FPRounding_NEGINF:
5412 overflow_to_inf = sgn;
5413 break;
5414 case FPRounding_ZERO:
5415 overflow_to_inf = false;
5416 break;
5417 default:
5418 panic("Unrecognized FP rounding mode");
5419 }
5420 result = overflow_to_inf ? fp64_infinity(sgn) : fp64_max_normal(sgn);
5421 if (mode & FPLIB_FPEXEC)
5422 flags |= FPLIB_OFC | FPLIB_IXC;
5423 } else if ((mode & FPLIB_FZ) && exp >= 2 * FP64_EXP_BIAS - 1) {
5424 result = fp64_zero(sgn);
5425 if (mode & FPLIB_FPEXEC)
5426 flags |= FPLIB_UFC;
5427 } else {
5428 exp += FP64_EXP_BITS;
5429 mnt = fp64_normalise(mnt, &exp);
5430 int result_exp = 2 * FP64_EXP_BIAS - 1 - exp;
5431 uint64_t fraction = (((uint32_t)1 << 19) /
5432 (mnt >> (FP64_BITS - 10) | 1) + 1) >> 1;
5433 fraction <<= FP64_MANT_BITS - 8;
5434 if (result_exp == 0) {
5435 fraction >>= 1;
5436 } else if (result_exp == -1) {
5437 fraction >>= 2;
5438 result_exp = 0;
5439 }
5440 result = fp64_pack(sgn, result_exp, fraction);
5441 }
5442
5443 set_fpscr0(fpscr, flags);
5444
5445 return result;
5446}
5447
5448template <>
5449uint16_t
5450fplibRecipStepFused(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
5451{
5452 int mode = modeConv(fpscr, fpcr);
5453 if (mode & FPLIB_AH) { // altfp
5454 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5455 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5456 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
5457 }
5458 int flags = 0;
5459 int sgn1, exp1, sgn2, exp2;
5460 uint16_t mnt1, mnt2, result;
5461
5462 op1 = fplibNeg<uint16_t>(op1, fpcr);
5463 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
5464 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
5465
5466 result = fp16_process_NaNs(op1, op2, mode, &flags);
5467 if (!result) {
5468 if ((exp1 == FP16_EXP_INF && !mnt2) ||
5469 (exp2 == FP16_EXP_INF && !mnt1)) {
5470 result = fp16_FPTwo(0);
5471 } else if (exp1 == FP16_EXP_INF || exp2 == FP16_EXP_INF) {
5472 result = fp16_infinity(sgn1 ^ sgn2);
5473 } else {
5474 result = fp16_muladd(fp16_FPTwo(0), op1, op2, 0, mode, &flags);
5475 }
5476 }
5477
5478 set_fpscr0(fpscr, flags);
5479
5480 return result;
5481}
5482
5483template <>
5484uint32_t
5485fplibRecipStepFused(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
5486{
5487 int mode = modeConv(fpscr, fpcr);
5488 if (mode & FPLIB_AH) { // altfp
5489 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5490 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5491 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
5492 }
5493 int flags = 0;
5494 int sgn1, exp1, sgn2, exp2;
5495 uint32_t mnt1, mnt2, result;
5496
5497 op1 = fplibNeg<uint32_t>(op1, fpcr);
5498 fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
5499 fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
5500
5501 result = fp32_process_NaNs(op1, op2, mode, &flags);
5502 if (!result) {
5503 if ((exp1 == FP32_EXP_INF && !mnt2) ||
5504 (exp2 == FP32_EXP_INF && !mnt1)) {
5505 result = fp32_FPTwo(0);
5506 } else if (exp1 == FP32_EXP_INF || exp2 == FP32_EXP_INF) {
5507 result = fp32_infinity(sgn1 ^ sgn2);
5508 } else {
5509 result = fp32_muladd(fp32_FPTwo(0), op1, op2, 0, mode, &flags);
5510 }
5511 }
5512
5513 set_fpscr0(fpscr, flags);
5514
5515 return result;
5516}
5517
5518template <>
5519uint64_t
5520fplibRecipStepFused(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
5521{
5522 int mode = modeConv(fpscr, fpcr);
5523 if (mode & FPLIB_AH) { // altfp
5524 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5525 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5526 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
5527 }
5528 int flags = 0;
5529 int sgn1, exp1, sgn2, exp2;
5530 uint64_t mnt1, mnt2, result;
5531
5532 op1 = fplibNeg<uint64_t>(op1, fpcr);
5533 fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
5534 fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
5535
5536 result = fp64_process_NaNs(op1, op2, mode, &flags);
5537 if (!result) {
5538 if ((exp1 == FP64_EXP_INF && !mnt2) ||
5539 (exp2 == FP64_EXP_INF && !mnt1)) {
5540 result = fp64_FPTwo(0);
5541 } else if (exp1 == FP64_EXP_INF || exp2 == FP64_EXP_INF) {
5542 result = fp64_infinity(sgn1 ^ sgn2);
5543 } else {
5544 result = fp64_muladd(fp64_FPTwo(0), op1, op2, 0, mode, &flags);
5545 }
5546 }
5547
5548 set_fpscr0(fpscr, flags);
5549
5550 return result;
5551}
5552
5553template <>
5554uint16_t
5555fplibRecpX(uint16_t op, FPSCR &fpscr, FPCR fpcr)
5556{
5557 int mode = modeConv(fpscr, fpcr);
5558 if (mode & FPLIB_AH) { // altfp
5559 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5560 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5561 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
5562 }
5563 int flags = 0;
5564 int sgn, exp;
5565 uint16_t mnt, result;
5566
5567 fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
5568
5569 if (fp16_is_NaN(exp, mnt)) {
5570 result = fp16_process_NaN(op, mode, &flags);
5571 }
5572 else {
5573 if (!mnt) { // Zero and denormals
5574 result = fp16_pack(sgn, FP16_EXP_INF - 1, 0);
5575 } else { // Infinities and normals
5576 result = fp16_pack(sgn, exp ^ FP16_EXP_INF, 0);
5577 }
5578 }
5579
5580 set_fpscr0(fpscr, flags);
5581
5582 return result;
5583}
5584
5585template <>
5586uint32_t
5587fplibRecpX(uint32_t op, FPSCR &fpscr, FPCR fpcr)
5588{
5589 int mode = modeConv(fpscr, fpcr);
5590 if (mode & FPLIB_AH) { // altfp
5591 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5592 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5593 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
5594 }
5595 int flags = 0;
5596 int sgn, exp;
5597 uint32_t mnt, result;
5598
5599 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
5600
5601 if (fp32_is_NaN(exp, mnt)) {
5602 result = fp32_process_NaN(op, mode, &flags);
5603 }
5604 else {
5605 if (!mnt) { // Zero and denormals
5606 result = fp32_pack(sgn, FP32_EXP_INF - 1, 0);
5607 } else { // Infinities and normals
5608 result = fp32_pack(sgn, exp ^ FP32_EXP_INF, 0);
5609 }
5610 }
5611
5612 set_fpscr0(fpscr, flags);
5613
5614 return result;
5615}
5616
5617template <>
5618uint64_t
5619fplibRecpX(uint64_t op, FPSCR &fpscr, FPCR fpcr)
5620{
5621 int mode = modeConv(fpscr, fpcr);
5622 if (mode & FPLIB_AH) { // altfp
5623 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
5624 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
5625 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
5626 }
5627 int flags = 0;
5628 int sgn, exp;
5629 uint64_t mnt, result;
5630
5631 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
5632
5633 if (fp64_is_NaN(exp, mnt)) {
5634 result = fp64_process_NaN(op, mode, &flags);
5635 }
5636 else {
5637 if (!mnt) { // Zero and denormals
5638 result = fp64_pack(sgn, FP64_EXP_INF - 1, 0);
5639 } else { // Infinities and normals
5640 result = fp64_pack(sgn, exp ^ FP64_EXP_INF, 0);
5641 }
5642 }
5643
5644 set_fpscr0(fpscr, flags);
5645
5646 return result;
5647}
5648
5649template <>
5650uint16_t
5651fplibRoundInt(uint16_t op, FPRounding rounding, bool exact, FPSCR &fpscr,
5652 FPCR fpcr)
5653{
5654 int expint = FP16_EXP_BIAS + FP16_MANT_BITS;
5655 int mode = modeConv(fpscr, fpcr);
5656 int flags = 0;
5657 int sgn, exp;
5658 uint16_t mnt, result;
5659
5660 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
5661 int unpack_mode = mode;
5662 if (unpack_mode & FPLIB_AH) {
5663 unpack_mode = unpack_mode & ~FPLIB_FPEXEC;
5664 }
5665 fp16_unpack(&sgn, &exp, &mnt, op, unpack_mode, &flags);
5666
5667 // Handle NaNs, infinities and zeroes:
5668 if (fp16_is_NaN(exp, mnt)) {
5669 result = fp16_process_NaN(op, mode, &flags);
5670 } else if (exp == FP16_EXP_INF) {
5671 result = fp16_infinity(sgn);
5672 } else if (!mnt) {
5673 result = fp16_zero(sgn);
5674 } else if (exp >= expint) {
5675 // There are no fractional bits
5676 result = op;
5677 } else {
5678 // Truncate towards zero:
5679 uint16_t x = expint - exp >= FP16_BITS ? 0 : mnt >> (expint - exp);
5680 int err = exp < expint - FP16_BITS ? 1 :
5681 ((mnt << 1 >> (expint - exp - 1) & 3) |
5682 ((uint16_t)(mnt << 2 << (FP16_BITS + exp - expint)) != 0));
5683 switch (rounding) {
5684 case FPRounding_TIEEVEN:
5685 x += (err == 3 || (err == 2 && (x & 1)));
5686 break;
5687 case FPRounding_POSINF:
5688 x += err && !sgn;
5689 break;
5690 case FPRounding_NEGINF:
5691 x += err && sgn;
5692 break;
5693 case FPRounding_ZERO:
5694 break;
5695 case FPRounding_TIEAWAY:
5696 x += err >> 1;
5697 break;
5698 default:
5699 panic("Unrecognized FP rounding mode");
5700 }
5701
5702 if (x == 0) {
5703 result = fp16_zero(sgn);
5704 } else {
5705 exp = expint;
5706 mnt = fp16_normalise(x, &exp);
5707 result = fp16_pack(sgn, exp + FP16_EXP_BITS, mnt >> FP16_EXP_BITS);
5708 }
5709
5710 if (err && exact)
5711 flags |= FPLIB_IXC;
5712 }
5713
5714 set_fpscr0(fpscr, flags);
5715
5716 return result;
5717}
5718
5719template <>
5720uint32_t
5721fplibRoundInt(uint32_t op, FPRounding rounding, bool exact, FPSCR &fpscr,
5722 FPCR fpcr)
5723{
5724 int expint = FP32_EXP_BIAS + FP32_MANT_BITS;
5725 int mode = modeConv(fpscr, fpcr);
5726 int flags = 0;
5727 int sgn, exp;
5728 uint32_t mnt, result;
5729
5730 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
5731 int unpack_mode = mode;
5732 if (unpack_mode & FPLIB_AH) {
5733 unpack_mode = unpack_mode & ~FPLIB_FPEXEC;
5734 }
5735 fp32_unpack(&sgn, &exp, &mnt, op, unpack_mode, &flags);
5736
5737 // Handle NaNs, infinities and zeroes:
5738 if (fp32_is_NaN(exp, mnt)) {
5739 result = fp32_process_NaN(op, mode, &flags);
5740 } else if (exp == FP32_EXP_INF) {
5741 result = fp32_infinity(sgn);
5742 } else if (!mnt) {
5743 result = fp32_zero(sgn);
5744 } else if (exp >= expint) {
5745 // There are no fractional bits
5746 result = op;
5747 } else {
5748 // Truncate towards zero:
5749 uint32_t x = expint - exp >= FP32_BITS ? 0 : mnt >> (expint - exp);
5750 int err = exp < expint - FP32_BITS ? 1 :
5751 ((mnt << 1 >> (expint - exp - 1) & 3) |
5752 ((uint32_t)(mnt << 2 << (FP32_BITS + exp - expint)) != 0));
5753 switch (rounding) {
5754 case FPRounding_TIEEVEN:
5755 x += (err == 3 || (err == 2 && (x & 1)));
5756 break;
5757 case FPRounding_POSINF:
5758 x += err && !sgn;
5759 break;
5760 case FPRounding_NEGINF:
5761 x += err && sgn;
5762 break;
5763 case FPRounding_ZERO:
5764 break;
5765 case FPRounding_TIEAWAY:
5766 x += err >> 1;
5767 break;
5768 default:
5769 panic("Unrecognized FP rounding mode");
5770 }
5771
5772 if (x == 0) {
5773 result = fp32_zero(sgn);
5774 } else {
5775 exp = expint;
5776 mnt = fp32_normalise(x, &exp);
5777 result = fp32_pack(sgn, exp + FP32_EXP_BITS, mnt >> FP32_EXP_BITS);
5778 }
5779
5780 if (err && exact)
5781 flags |= FPLIB_IXC;
5782 }
5783
5784 set_fpscr0(fpscr, flags);
5785
5786 return result;
5787}
5788
5789template <>
5790uint64_t
5791fplibRoundInt(uint64_t op, FPRounding rounding, bool exact, FPSCR &fpscr,
5792 FPCR fpcr)
5793{
5794 int expint = FP64_EXP_BIAS + FP64_MANT_BITS;
5795 int mode = modeConv(fpscr, fpcr);
5796 int flags = 0;
5797 int sgn, exp;
5798 uint64_t mnt, result;
5799
5800 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
5801 int unpack_mode = mode;
5802 if (unpack_mode & FPLIB_AH) {
5803 unpack_mode = unpack_mode & ~FPLIB_FPEXEC;
5804 }
5805 fp64_unpack(&sgn, &exp, &mnt, op, unpack_mode, &flags);
5806
5807 // Handle NaNs, infinities and zeroes:
5808 if (fp64_is_NaN(exp, mnt)) {
5809 result = fp64_process_NaN(op, mode, &flags);
5810 } else if (exp == FP64_EXP_INF) {
5811 result = fp64_infinity(sgn);
5812 } else if (!mnt) {
5813 result = fp64_zero(sgn);
5814 } else if (exp >= expint) {
5815 // There are no fractional bits
5816 result = op;
5817 } else {
5818 // Truncate towards zero:
5819 uint64_t x = expint - exp >= FP64_BITS ? 0 : mnt >> (expint - exp);
5820 int err = exp < expint - FP64_BITS ? 1 :
5821 ((mnt << 1 >> (expint - exp - 1) & 3) |
5822 ((uint64_t)(mnt << 2 << (FP64_BITS + exp - expint)) != 0));
5823 switch (rounding) {
5824 case FPRounding_TIEEVEN:
5825 x += (err == 3 || (err == 2 && (x & 1)));
5826 break;
5827 case FPRounding_POSINF:
5828 x += err && !sgn;
5829 break;
5830 case FPRounding_NEGINF:
5831 x += err && sgn;
5832 break;
5833 case FPRounding_ZERO:
5834 break;
5835 case FPRounding_TIEAWAY:
5836 x += err >> 1;
5837 break;
5838 default:
5839 panic("Unrecognized FP rounding mode");
5840 }
5841
5842 if (x == 0) {
5843 result = fp64_zero(sgn);
5844 } else {
5845 exp = expint;
5846 mnt = fp64_normalise(x, &exp);
5847 result = fp64_pack(sgn, exp + FP64_EXP_BITS, mnt >> FP64_EXP_BITS);
5848 }
5849
5850 if (err && exact)
5851 flags |= FPLIB_IXC;
5852 }
5853
5854 set_fpscr0(fpscr, flags);
5855
5856 return result;
5857}
5858
5859template <>
5860uint32_t
5861fplibRoundIntN(uint32_t op, FPRounding rounding, bool exact, int intsize,
5862 FPSCR &fpscr, FPCR fpcr)
5863{
5864 int expint = FP32_EXP_BIAS + FP32_MANT_BITS;
5865 int mode = modeConv(fpscr, fpcr);
5866 int flags = 0;
5867 int sgn, exp;
5868 uint32_t mnt, result;
5869
5870 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
5871 int unpack_mode = mode;
5872 if (unpack_mode & FPLIB_AH) {
5873 unpack_mode = unpack_mode & ~FPLIB_FPEXEC;
5874 }
5875 fp32_unpack(&sgn, &exp, &mnt, op, unpack_mode, &flags);
5876
5877 // Handle NaNs, infinities and zeroes:
5878 if (fp32_is_NaN(exp, mnt)) {
5879 result = fp32_pack(1, FP32_EXP_BIAS + intsize - 1, 0);
5880 flags |= FPLIB_IOC;
5881 } else if (exp == FP32_EXP_INF) {
5882 result = fp32_pack(1, FP32_EXP_BIAS + intsize - 1, 0);
5883 flags |= FPLIB_IOC;
5884 } else if (!mnt) {
5885 result = fp32_zero(sgn);
5886 } else if (exp >= expint) {
5887 // There are no fractional bits
5888 result = op;
5889 bool overflow = (exp > (FP32_EXP_BIAS + intsize - 2) && !sgn) ||
5890 (exp > (FP32_EXP_BIAS + intsize - 1) && sgn) ||
5891 (exp > (FP32_EXP_BIAS + intsize - 2) &&
5892 FP32_MANT(op) > 0 && sgn);
5893 if (overflow) {
5894 result = fp32_pack(1, FP32_EXP_BIAS + intsize - 1, 0);
5895 flags |= FPLIB_IOC;
5896 }
5897 } else {
5898 // Truncate towards zero:
5899 uint32_t x = expint - exp >= FP32_BITS ? 0 : mnt >> (expint - exp);
5900 int err = exp < expint - FP32_BITS ? 1 :
5901 ((mnt << 1 >> (expint - exp - 1) & 3) |
5902 ((uint32_t)(mnt << 2 << (FP32_BITS + exp - expint)) != 0));
5903 switch (rounding) {
5904 case FPRounding_TIEEVEN:
5905 x += (err == 3 || (err == 2 && (x & 1)));
5906 break;
5907 case FPRounding_POSINF:
5908 x += err && !sgn;
5909 break;
5910 case FPRounding_NEGINF:
5911 x += err && sgn;
5912 break;
5913 case FPRounding_ZERO:
5914 break;
5915 case FPRounding_TIEAWAY:
5916 x += err >> 1;
5917 break;
5918 default:
5919 panic("Unrecognized FP rounding mode");
5920 }
5921
5922 bool overflow = (x > (((uint32_t)1 << (intsize - 1)) - 1) && !sgn) ||
5923 (x > ((uint32_t)1 << (intsize - 1)) && sgn);
5924 if (overflow) {
5925 result = fp32_pack(1, FP32_EXP_BIAS + intsize - 1, 0);
5926 flags |= FPLIB_IOC;
5927 } else {
5928 if (x == 0) {
5929 result = fp32_zero(sgn);
5930 } else {
5931 exp = expint;
5932 mnt = fp32_normalise(x, &exp);
5933 result = fp32_pack(sgn, exp + FP32_EXP_BITS,
5934 mnt >> FP32_EXP_BITS);
5935 }
5936
5937 if (err && exact)
5938 flags |= FPLIB_IXC;
5939 }
5940 }
5941
5942 set_fpscr0(fpscr, flags);
5943
5944 return result;
5945}
5946
5947template <>
5948uint64_t
5949fplibRoundIntN(uint64_t op, FPRounding rounding, bool exact, int intsize,
5950 FPSCR &fpscr, FPCR fpcr)
5951{
5952 int expint = FP64_EXP_BIAS + FP64_MANT_BITS;
5953 int mode = modeConv(fpscr, fpcr);
5954 int flags = 0;
5955 int sgn, exp;
5956 uint64_t mnt, result;
5957
5958 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
5959 int unpack_mode = mode;
5960 if (unpack_mode & FPLIB_AH) {
5961 unpack_mode = unpack_mode & ~FPLIB_FPEXEC;
5962 }
5963 fp64_unpack(&sgn, &exp, &mnt, op, unpack_mode, &flags);
5964
5965 // Handle NaNs, infinities and zeroes:
5966 if (fp64_is_NaN(exp, mnt)) {
5967 result = fp64_pack(1, FP64_EXP_BIAS + intsize - 1, 0);
5968 flags |= FPLIB_IOC;
5969 } else if (exp == FP64_EXP_INF) {
5970 result = fp64_pack(1, FP64_EXP_BIAS + intsize - 1, 0);
5971 flags |= FPLIB_IOC;
5972 } else if (!mnt) {
5973 result = fp64_zero(sgn);
5974 } else if (exp >= expint) {
5975 // There are no fractional bits
5976 result = op;
5977 bool overflow = (exp > (FP64_EXP_BIAS + intsize - 2) && !sgn) ||
5978 (exp > (FP64_EXP_BIAS + intsize - 1) && sgn) ||
5979 (exp > (FP64_EXP_BIAS + intsize - 2) &&
5980 FP64_MANT(op) > 0 && sgn);
5981 if (overflow && intsize >= 0) {
5982 result = fp64_pack(1, FP64_EXP_BIAS + intsize - 1, 0);
5983 flags |= FPLIB_IOC;
5984 }
5985 } else {
5986 // Truncate towards zero:
5987 uint64_t x = expint - exp >= FP64_BITS ? 0 : mnt >> (expint - exp);
5988 int err = exp < expint - FP64_BITS ? 1 :
5989 ((mnt << 1 >> (expint - exp - 1) & 3) |
5990 ((uint64_t)(mnt << 2 << (FP64_BITS + exp - expint)) != 0));
5991 switch (rounding) {
5992 case FPRounding_TIEEVEN:
5993 x += (err == 3 || (err == 2 && (x & 1)));
5994 break;
5995 case FPRounding_POSINF:
5996 x += err && !sgn;
5997 break;
5998 case FPRounding_NEGINF:
5999 x += err && sgn;
6000 break;
6001 case FPRounding_ZERO:
6002 break;
6003 case FPRounding_TIEAWAY:
6004 x += err >> 1;
6005 break;
6006 default:
6007 panic("Unrecognized FP rounding mode");
6008 }
6009
6010 bool overflow = (x > (((uint64_t)1 << (intsize - 1)) - 1) && !sgn) ||
6011 (x > ((uint64_t)1 << (intsize - 1)) && sgn);
6012 if (overflow) {
6013 result = fp64_pack(1, FP64_EXP_BIAS + intsize - 1, 0);
6014 flags |= FPLIB_IOC;
6015 } else {
6016 if (x == 0) {
6017 result = fp64_zero(sgn);
6018 } else {
6019 exp = expint;
6020 mnt = fp64_normalise(x, &exp);
6021 result = fp64_pack(sgn, exp + FP64_EXP_BITS,
6022 mnt >> FP64_EXP_BITS);
6023 }
6024
6025 if (err && exact)
6026 flags |= FPLIB_IXC;
6027 }
6028 }
6029
6030 set_fpscr0(fpscr, flags);
6031
6032 return result;
6033}
6034
6035template <>
6036uint16_t
6037fplibScale(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
6038{
6039 int flags = 0;
6040 uint16_t result = fp16_scale(op1, (int16_t)op2, modeConv(fpscr, fpcr),
6041 &flags);
6042 set_fpscr0(fpscr, flags);
6043 return result;
6044}
6045
6046template <>
6047uint32_t
6048fplibScale(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
6049{
6050 int flags = 0;
6051 uint32_t result = fp32_scale(op1, (int32_t)op2, modeConv(fpscr, fpcr),
6052 &flags);
6053 set_fpscr0(fpscr, flags);
6054 return result;
6055}
6056
6057template <>
6058uint64_t
6059fplibScale(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
6060{
6061 int flags = 0;
6062 uint64_t result = fp64_scale(op1, (int64_t)op2, modeConv(fpscr, fpcr),
6063 &flags);
6064 set_fpscr0(fpscr, flags);
6065 return result;
6066}
6067
6068template <>
6069uint16_t
6070fplibSqrt(uint16_t op, FPSCR &fpscr, FPCR fpcr)
6071{
6072 int flags = 0;
6073 uint16_t result = fp16_sqrt(op, modeConv(fpscr, fpcr), &flags);
6074 set_fpscr0(fpscr, flags);
6075 return result;
6076}
6077
6078template <>
6079uint32_t
6080fplibSqrt(uint32_t op, FPSCR &fpscr, FPCR fpcr)
6081{
6082 int flags = 0;
6083 uint32_t result = fp32_sqrt(op, modeConv(fpscr, fpcr), &flags);
6084 set_fpscr0(fpscr, flags);
6085 return result;
6086}
6087
6088template <>
6089uint64_t
6090fplibSqrt(uint64_t op, FPSCR &fpscr, FPCR fpcr)
6091{
6092 int flags = 0;
6093 uint64_t result = fp64_sqrt(op, modeConv(fpscr, fpcr), &flags);
6094 set_fpscr0(fpscr, flags);
6095 return result;
6096}
6097
6098template <>
6099uint16_t
6100fplibSub(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
6101{
6102 int flags = 0;
6103 uint16_t result = fp16_add(op1, op2, 1, modeConv(fpscr, fpcr), &flags);
6104 set_fpscr0(fpscr, flags);
6105 return result;
6106}
6107
6108template <>
6109uint32_t
6110fplibSub(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
6111{
6112 int flags = 0;
6113 uint32_t result = fp32_add(op1, op2, 1, modeConv(fpscr, fpcr), &flags);
6114 set_fpscr0(fpscr, flags);
6115 return result;
6116}
6117
6118template <>
6119uint64_t
6120fplibSub(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
6121{
6122 int flags = 0;
6123 uint64_t result = fp64_add(op1, op2, 1, modeConv(fpscr, fpcr), &flags);
6124 set_fpscr0(fpscr, flags);
6125 return result;
6126}
6127
6128template <>
6129uint16_t
6130fplibTrigMulAdd(uint8_t coeff_index, uint16_t op1, uint16_t op2, FPSCR &fpscr,
6131 FPCR fpcr)
6132{
6133 static uint16_t coeff[2][8] = {
6134 {
6135 0x3c00,
6136 0xb155,
6137 0x2030,
6138 0x0000,
6139 0x0000,
6140 0x0000,
6141 0x0000,
6142 0x0000,
6143 },
6144 {
6145 0x3c00,
6146 0xb800,
6147 0x293a,
6148 0x0000,
6149 0x0000,
6150 0x0000,
6151 0x0000,
6152 0x0000
6153 }
6154 };
6155 int flags = 0;
6156 uint16_t result =
6157 fp16_muladd(coeff[op2 >> (FP16_BITS - 1)][coeff_index], op1,
6158 fplibAbs(op2, fpcr), 0, modeConv(fpscr, fpcr), &flags);
6159 set_fpscr0(fpscr, flags);
6160 return result;
6161}
6162
6163template <>
6164uint32_t
6165fplibTrigMulAdd(uint8_t coeff_index, uint32_t op1, uint32_t op2, FPSCR &fpscr,
6166 FPCR fpcr)
6167{
6168 static uint32_t coeff[2][8] = {
6169 {
6170 0x3f800000,
6171 0xbe2aaaab,
6172 0x3c088886,
6173 0xb95008b9,
6174 0x36369d6d,
6175 0x00000000,
6176 0x00000000,
6177 0x00000000
6178 },
6179 {
6180 0x3f800000,
6181 0xbf000000,
6182 0x3d2aaaa6,
6183 0xbab60705,
6184 0x37cd37cc,
6185 0x00000000,
6186 0x00000000,
6187 0x00000000
6188 }
6189 };
6190 int flags = 0;
6191 uint32_t result =
6192 fp32_muladd(coeff[op2 >> (FP32_BITS - 1)][coeff_index], op1,
6193 fplibAbs(op2, fpcr), 0, modeConv(fpscr, fpcr), &flags);
6194 set_fpscr0(fpscr, flags);
6195 return result;
6196}
6197
6198template <>
6199uint64_t
6200fplibTrigMulAdd(uint8_t coeff_index, uint64_t op1, uint64_t op2, FPSCR &fpscr,
6201 FPCR fpcr)
6202{
6203 static uint64_t coeff[2][8] = {
6204 {
6205 0x3ff0000000000000ULL,
6206 0xbfc5555555555543ULL,
6207 0x3f8111111110f30cULL,
6208 0xbf2a01a019b92fc6ULL,
6209 0x3ec71de351f3d22bULL,
6210 0xbe5ae5e2b60f7b91ULL,
6211 0x3de5d8408868552fULL,
6212 0x0000000000000000ULL
6213 },
6214 {
6215 0x3ff0000000000000ULL,
6216 0xbfe0000000000000ULL,
6217 0x3fa5555555555536ULL,
6218 0xbf56c16c16c13a0bULL,
6219 0x3efa01a019b1e8d8ULL,
6220 0xbe927e4f7282f468ULL,
6221 0x3e21ee96d2641b13ULL,
6222 0xbda8f76380fbb401ULL
6223 }
6224 };
6225 int flags = 0;
6226 uint64_t result =
6227 fp64_muladd(coeff[op2 >> (FP64_BITS - 1)][coeff_index], op1,
6228 fplibAbs(op2, fpcr), 0, modeConv(fpscr, fpcr), &flags);
6229 set_fpscr0(fpscr, flags);
6230 return result;
6231}
6232
6233template <>
6234uint16_t
6235fplibTrigSMul(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
6236{
6237 int flags = 0;
6238 int sgn, exp;
6239 uint16_t mnt;
6240
6241 int mode = modeConv(fpscr, fpcr);
6242 uint16_t result = fp16_mul(op1, op1, mode, &flags);
6243 set_fpscr0(fpscr, flags);
6244
6245 fp16_unpack(&sgn, &exp, &mnt, result, mode, &flags);
6246 if (!fp16_is_NaN(exp, mnt)) {
6247 result = (result & ~(1ULL << (FP16_BITS - 1))) |
6248 op2 << (FP16_BITS - 1);
6249 }
6250 return result;
6251}
6252
6253template <>
6254uint32_t
6255fplibTrigSMul(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
6256{
6257 int flags = 0;
6258 int sgn, exp;
6259 uint32_t mnt;
6260
6261 int mode = modeConv(fpscr, fpcr);
6262 uint32_t result = fp32_mul(op1, op1, mode, &flags);
6263 set_fpscr0(fpscr, flags);
6264
6265 fp32_unpack(&sgn, &exp, &mnt, result, mode, &flags);
6266 if (!fp32_is_NaN(exp, mnt)) {
6267 result = (result & ~(1ULL << (FP32_BITS - 1))) | op2 << (FP32_BITS - 1);
6268 }
6269 return result;
6270}
6271
6272template <>
6273uint64_t
6274fplibTrigSMul(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
6275{
6276 int flags = 0;
6277 int sgn, exp;
6278 uint64_t mnt;
6279
6280 int mode = modeConv(fpscr, fpcr);
6281 uint64_t result = fp64_mul(op1, op1, mode, &flags);
6282 set_fpscr0(fpscr, flags);
6283
6284 fp64_unpack(&sgn, &exp, &mnt, result, mode, &flags);
6285 if (!fp64_is_NaN(exp, mnt)) {
6286 result = (result & ~(1ULL << (FP64_BITS - 1))) | op2 << (FP64_BITS - 1);
6287 }
6288 return result;
6289}
6290
6291template <>
6292uint16_t
6293fplibTrigSSel(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
6294{
6295 static constexpr uint16_t fpOne =
6296 (uint16_t)FP16_EXP_BIAS << FP16_MANT_BITS; // 1.0
6297 if (op2 & 1)
6298 return fpOne ^ ((op2 >> 1) << (FP16_BITS - 1));
6299 else if (op2 & 2)
6300 return fplibNeg(op1, fpcr);
6301 else
6302 return op1;
6303}
6304
6305template <>
6306uint32_t
6307fplibTrigSSel(uint32_t op1, uint32_t op2, FPSCR &fpscr, FPCR fpcr)
6308{
6309 static constexpr uint32_t fpOne =
6310 (uint32_t)FP32_EXP_BIAS << FP32_MANT_BITS; // 1.0
6311 if (op2 & 1)
6312 return fpOne ^ ((op2 >> 1) << (FP32_BITS - 1));
6313 else if (op2 & 2)
6314 return fplibNeg(op1, fpcr);
6315 else
6316 return op1;
6317}
6318
6319template <>
6320uint64_t
6321fplibTrigSSel(uint64_t op1, uint64_t op2, FPSCR &fpscr, FPCR fpcr)
6322{
6323 static constexpr uint64_t fpOne =
6324 (uint64_t)FP64_EXP_BIAS << FP64_MANT_BITS; // 1.0
6325 if (op2 & 1)
6326 return fpOne ^ ((op2 >> 1) << (FP64_BITS - 1));
6327 else if (op2 & 2)
6328 return fplibNeg(op1, fpcr);
6329 else
6330 return op1;
6331}
6332
6333static uint64_t
6334FPToFixed_64(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding,
6335 int *flags)
6336{
6337 int expmax = FP64_EXP_BIAS + FP64_BITS - 1;
6338 uint64_t x;
6339 int err;
6340
6341 if (exp > expmax) {
6342 *flags = FPLIB_IOC;
6343 return ((uint64_t)!u << (FP64_BITS - 1)) - !sgn;
6344 }
6345
6346 x = lsr64(mnt << FP64_EXP_BITS, expmax - exp);
6347 err = (exp > expmax - 2 ? 0 :
6348 (lsr64(mnt << FP64_EXP_BITS, expmax - 2 - exp) & 3) |
6349 !!(mnt << FP64_EXP_BITS & (lsl64(1, expmax - 2 - exp) - 1)));
6350
6351 switch (rounding) {
6352 case FPRounding_TIEEVEN:
6353 x += (err == 3 || (err == 2 && (x & 1)));
6354 break;
6355 case FPRounding_POSINF:
6356 x += err && !sgn;
6357 break;
6358 case FPRounding_NEGINF:
6359 x += err && sgn;
6360 break;
6361 case FPRounding_ZERO:
6362 break;
6363 case FPRounding_TIEAWAY:
6364 x += err >> 1;
6365 break;
6366 default:
6367 panic("Unrecognized FP rounding mode");
6368 }
6369
6370 if (u ? sgn && x : x > (1ULL << (FP64_BITS - 1)) - !sgn) {
6371 *flags = FPLIB_IOC;
6372 return ((uint64_t)!u << (FP64_BITS - 1)) - !sgn;
6373 }
6374
6375 if (err) {
6376 *flags = FPLIB_IXC;
6377 }
6378
6379 return sgn ? -x : x;
6380}
6381
6382static uint32_t
6383FPToFixed_32(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding,
6384 int *flags)
6385{
6386 uint64_t x = FPToFixed_64(sgn, exp, mnt, u, rounding, flags);
6387 if (u ? x >= 1ULL << FP32_BITS :
6388 !(x < 1ULL << (FP32_BITS - 1) ||
6389 (uint64_t)-x <= (uint64_t)1 << (FP32_BITS - 1))) {
6390 *flags = FPLIB_IOC;
6391 x = ((uint32_t)!u << (FP32_BITS - 1)) - !sgn;
6392 }
6393 return x;
6394}
6395
6396static uint16_t
6397FPToFixed_16(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding,
6398 int *flags)
6399{
6400 uint64_t x = FPToFixed_64(sgn, exp, mnt, u, rounding, flags);
6401 if (u ? x >= 1ULL << FP16_BITS :
6402 !(x < 1ULL << (FP16_BITS - 1) ||
6403 (uint64_t)-x <= (uint64_t)1 << (FP16_BITS - 1))) {
6404 *flags = FPLIB_IOC;
6405 x = ((uint16_t)!u << (FP16_BITS - 1)) - !sgn;
6406 }
6407 return x;
6408}
6409
6410template <>
6411uint16_t
6412fplibFPToFixed(uint16_t op, int fbits, bool u, FPRounding rounding,
6413 FPSCR &fpscr, FPCR fpcr)
6414{
6415 int flags = 0;
6416 int sgn, exp;
6417 uint16_t mnt, result;
6418
6419 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
6420 int mode = modeConv(fpscr, fpcr);
6421 if (mode & FPLIB_AH) {
6422 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
6423 }
6424 fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
6425
6426 // If NaN, set cumulative flag or take exception:
6427 if (fp16_is_NaN(exp, mnt)) {
6428 flags = FPLIB_IOC;
6429 result = 0;
6430 } else {
6431 assert(fbits >= 0);
6432 // Infinity is treated as an ordinary normalised number that saturates.
6433 result =
6434 FPToFixed_16(sgn, exp + FP64_EXP_BIAS - FP16_EXP_BIAS + fbits,
6435 (uint64_t)mnt << (FP64_MANT_BITS - FP16_MANT_BITS),
6436 u, rounding, &flags);
6437 }
6438
6439 set_fpscr0(fpscr, flags);
6440
6441 return result;
6442}
6443
6444template <>
6445uint32_t
6446fplibFPToFixed(uint16_t op, int fbits, bool u, FPRounding rounding,
6447 FPSCR &fpscr, FPCR fpcr)
6448{
6449 int flags = 0;
6450 int sgn, exp;
6451 uint16_t mnt;
6452 uint32_t result;
6453
6454 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
6455 int mode = modeConv(fpscr, fpcr);
6456 if (mode & FPLIB_AH) {
6457 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
6458 }
6459 fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
6460
6461 // If NaN, set cumulative flag or take exception:
6462 if (fp16_is_NaN(exp, mnt)) {
6463 flags = FPLIB_IOC;
6464 result = 0;
6465 } else {
6466 assert(fbits >= 0);
6467 if (exp == FP16_EXP_INF)
6468 exp = 255; // infinity: make it big enough to saturate
6469 result =
6470 FPToFixed_32(sgn, exp + FP64_EXP_BIAS - FP16_EXP_BIAS + fbits,
6471 (uint64_t)mnt << (FP64_MANT_BITS - FP16_MANT_BITS),
6472 u, rounding, &flags);
6473 }
6474
6475 set_fpscr0(fpscr, flags);
6476
6477 return result;
6478}
6479
6480template <>
6481uint32_t
6482fplibFPToFixed(uint32_t op, int fbits, bool u, FPRounding rounding,
6483 FPSCR &fpscr, FPCR fpcr)
6484{
6485 int flags = 0;
6486 int sgn, exp;
6487 uint32_t mnt, result;
6488
6489 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
6490 int mode = modeConv(fpscr, fpcr);
6491 if (mode & FPLIB_AH) {
6492 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
6493 }
6494 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
6495
6496 // If NaN, set cumulative flag or take exception:
6497 if (fp32_is_NaN(exp, mnt)) {
6498 flags = FPLIB_IOC;
6499 result = 0;
6500 } else {
6501 assert(fbits >= 0);
6502 // Infinity is treated as an ordinary normalised number that saturates.
6503 result =
6504 FPToFixed_32(sgn, exp + FP64_EXP_BIAS - FP32_EXP_BIAS + fbits,
6505 (uint64_t)mnt << (FP64_MANT_BITS - FP32_MANT_BITS),
6506 u, rounding, &flags);
6507 }
6508
6509 set_fpscr0(fpscr, flags);
6510
6511 return result;
6512}
6513
6514template <>
6515uint32_t
6516fplibFPToFixed(uint64_t op, int fbits, bool u, FPRounding rounding,
6517 FPSCR &fpscr, FPCR fpcr)
6518{
6519 int flags = 0;
6520 int sgn, exp;
6521 uint64_t mnt;
6522 uint32_t result;
6523
6524 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
6525 int mode = modeConv(fpscr, fpcr);
6526 if (mode & FPLIB_AH) {
6527 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
6528 }
6529 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
6530
6531 // If NaN, set cumulative flag or take exception:
6532 if (fp64_is_NaN(exp, mnt)) {
6533 flags = FPLIB_IOC;
6534 result = 0;
6535 } else {
6536 assert(fbits >= 0);
6537 // Infinity is treated as an ordinary normalised number that saturates.
6538 result = FPToFixed_32(sgn, exp + fbits, mnt, u, rounding, &flags);
6539 }
6540
6541 set_fpscr0(fpscr, flags);
6542
6543 return result;
6544}
6545
6546uint32_t
6547fplibFPToFixedJS(uint64_t op, FPSCR &fpscr, bool is64, uint8_t& nz)
6548{
6549 int flags = 0;
6550 uint32_t result;
6551 bool Z = true;
6552
6553 uint32_t sgn = bits(op, 63);
6554 int32_t exp = bits(op, 62, 52);
6555 uint64_t mnt = bits(op, 51, 0);
6556
6557 if (exp == 0) {
6558 if (mnt != 0) {
6559 if (fpscr.fz) {
6560 flags |= FPLIB_IDC;
6561 } else {
6562 flags |= FPLIB_IXC;
6563 Z = 0;
6564 }
6565 }
6566 result = 0;
6567 } else if (exp == 0x7ff) {
6568 flags |= FPLIB_IOC;
6569 result = 0;
6570 Z = 0;
6571 } else {
6572 mnt |= 1ULL << FP64_MANT_BITS;
6573 int mnt_shft = exp - FP64_EXP_BIAS - 52;
6574 bool err = true;
6575
6576 if (abs(mnt_shft) >= FP64_BITS) {
6577 result = 0;
6578 Z = 0;
6579 } else if (mnt_shft >= 0) {
6580 result = lsl64(mnt, mnt_shft);
6581 } else if (mnt_shft < 0) {
6582 err = lsl64(mnt, mnt_shft+FP64_BITS) != 0;
6583 result = lsr64(mnt, abs(mnt_shft));
6584 }
6585 uint64_t max_result = (1UL << (FP32_BITS - 1)) -!sgn;
6586 if ((exp - FP64_EXP_BIAS) > 31 || result > max_result) {
6587 flags |= FPLIB_IOC;
6588 Z = false;
6589 } else if (err) {
6590 flags |= FPLIB_IXC;
6591 Z = false;
6592 }
6593 result = sgn ? -result : result;
6594 }
6595 if (sgn == 1 && result == 0)
6596 Z = false;
6597
6598 if (is64) {
6599 nz = Z? 0x1: 0x0;
6600 } else {
6601 fpscr.n = 0;
6602 fpscr.z = (int)Z;
6603 fpscr.c = 0;
6604 fpscr.v = 0;
6605 }
6606
6607 set_fpscr0(fpscr, flags);
6608 return result;
6609}
6610
6611template <>
6612uint64_t
6613fplibFPToFixed(uint16_t op, int fbits, bool u, FPRounding rounding,
6614 FPSCR &fpscr, FPCR fpcr)
6615{
6616 int flags = 0;
6617 int sgn, exp;
6618 uint16_t mnt;
6619 uint64_t result;
6620
6621 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
6622 int mode = modeConv(fpscr, fpcr);
6623 if (mode & FPLIB_AH) {
6624 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
6625 }
6626 fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
6627
6628 // If NaN, set cumulative flag or take exception:
6629 if (fp16_is_NaN(exp, mnt)) {
6630 flags = FPLIB_IOC;
6631 result = 0;
6632 } else {
6633 assert(fbits >= 0);
6634 if (exp == FP16_EXP_INF)
6635 exp = 255; // infinity: make it big enough to saturate
6636 result =
6637 FPToFixed_64(sgn, exp + FP64_EXP_BIAS - FP16_EXP_BIAS + fbits,
6638 (uint64_t)mnt << (FP64_MANT_BITS - FP16_MANT_BITS),
6639 u, rounding, &flags);
6640 }
6641
6642 set_fpscr0(fpscr, flags);
6643
6644 return result;
6645}
6646
6647template <>
6648uint64_t
6649fplibFPToFixed(uint32_t op, int fbits, bool u, FPRounding rounding,
6650 FPSCR &fpscr, FPCR fpcr)
6651{
6652 int flags = 0;
6653 int sgn, exp;
6654 uint32_t mnt;
6655 uint64_t result;
6656
6657 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
6658 int mode = modeConv(fpscr, fpcr);
6659 if (mode & FPLIB_AH) {
6660 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
6661 }
6662 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
6663
6664 // If NaN, set cumulative flag or take exception:
6665 if (fp32_is_NaN(exp, mnt)) {
6666 flags = FPLIB_IOC;
6667 result = 0;
6668 } else {
6669 assert(fbits >= 0);
6670 // Infinity is treated as an ordinary normalised number that saturates.
6671 result =
6672 FPToFixed_64(sgn, exp + FP64_EXP_BIAS - FP32_EXP_BIAS + fbits,
6673 (uint64_t)mnt << (FP64_MANT_BITS - FP32_MANT_BITS),
6674 u, rounding, &flags);
6675 }
6676
6677 set_fpscr0(fpscr, flags);
6678
6679 return result;
6680}
6681
6682template <>
6683uint64_t
6684fplibFPToFixed(uint64_t op, int fbits, bool u, FPRounding rounding,
6685 FPSCR &fpscr, FPCR fpcr)
6686{
6687 int flags = 0;
6688 int sgn, exp;
6689 uint64_t mnt, result;
6690
6691 // Unpack using FPCR to determine if subnormals are flushed-to-zero:
6692 int mode = modeConv(fpscr, fpcr);
6693 if (mode & FPLIB_AH) {
6694 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
6695 }
6696 fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
6697
6698 // If NaN, set cumulative flag or take exception:
6699 if (fp64_is_NaN(exp, mnt)) {
6700 flags = FPLIB_IOC;
6701 result = 0;
6702 } else {
6703 assert(fbits >= 0);
6704 // Infinity is treated as an ordinary normalised number that saturates.
6705 result = FPToFixed_64(sgn, exp + fbits, mnt, u, rounding, &flags);
6706 }
6707
6708 set_fpscr0(fpscr, flags);
6709
6710 return result;
6711}
6712
6713static uint16_t
6714fp16_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
6715{
6716 int x_sgn = !u && a >> (FP64_BITS - 1);
6717 int x_exp = FP16_EXP_BIAS + FP64_BITS - 1 - fbits;
6718 uint64_t x_mnt = x_sgn ? -a : a;
6719
6720 // Handle zero:
6721 if (!x_mnt) {
6722 return fp16_zero(0);
6723 }
6724
6725 // Normalise into FP16_BITS bits, collapsing error into bottom bit:
6726 x_mnt = fp64_normalise(x_mnt, &x_exp);
6727 x_mnt = (x_mnt >> (FP64_BITS - FP16_BITS - 1) |
6728 !!(x_mnt & ((1ULL << (FP64_BITS - FP16_BITS - 1)) - 1)));
6729
6730 return fp16_round(x_sgn, x_exp, x_mnt, mode, flags);
6731}
6732
6733static uint32_t
6734fp32_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
6735{
6736 int x_sgn = !u && a >> (FP64_BITS - 1);
6737 int x_exp = FP32_EXP_BIAS + FP64_BITS - 1 - fbits;
6738 uint64_t x_mnt = x_sgn ? -a : a;
6739
6740 // Handle zero:
6741 if (!x_mnt) {
6742 return fp32_zero(0);
6743 }
6744
6745 // Normalise into FP32_BITS bits, collapsing error into bottom bit:
6746 x_mnt = fp64_normalise(x_mnt, &x_exp);
6747 x_mnt = (x_mnt >> (FP64_BITS - FP32_BITS - 1) |
6748 !!(x_mnt & ((1ULL << (FP64_BITS - FP32_BITS - 1)) - 1)));
6749
6750 return fp32_round(x_sgn, x_exp, x_mnt, mode, flags);
6751}
6752
6753static uint64_t
6754fp64_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
6755{
6756 int x_sgn = !u && a >> (FP64_BITS - 1);
6757 int x_exp = FP64_EXP_BIAS + FP64_BITS - 1 - fbits;
6758 uint64_t x_mnt = x_sgn ? -a : a;
6759
6760 // Handle zero:
6761 if (!x_mnt) {
6762 return fp64_zero(0);
6763 }
6764
6765 x_mnt = fp64_normalise(x_mnt, &x_exp);
6766
6767 return fp64_round(x_sgn, x_exp, x_mnt << 1, mode, flags);
6768}
6769
6770template <>
6771uint16_t
6772fplibFixedToFP(uint64_t op, int fbits, bool u, FPRounding rounding,
6773 FPSCR &fpscr, FPCR fpcr)
6774{
6775 int flags = 0;
6776 uint16_t res = fp16_cvtf(op, fbits, u,
6777 (int)rounding | (modeConv(fpscr, fpcr) & 0xFFC),
6778 &flags);
6779 set_fpscr0(fpscr, flags);
6780 return res;
6781}
6782
6783template <>
6784uint32_t
6785fplibFixedToFP(uint64_t op, int fbits, bool u, FPRounding rounding,
6786 FPSCR &fpscr, FPCR fpcr)
6787{
6788 int flags = 0;
6789 uint32_t res = fp32_cvtf(op, fbits, u,
6790 (int)rounding | (modeConv(fpscr, fpcr) & 0xFFC),
6791 &flags);
6792 set_fpscr0(fpscr, flags);
6793 return res;
6794}
6795
6796template <>
6797uint64_t
6798fplibFixedToFP(uint64_t op, int fbits, bool u, FPRounding rounding,
6799 FPSCR &fpscr, FPCR fpcr)
6800{
6801 int flags = 0;
6802 uint64_t res = fp64_cvtf(op, fbits, u,
6803 (int)rounding | (modeConv(fpscr, fpcr) & 0xFFC),
6804 &flags);
6805 set_fpscr0(fpscr, flags);
6806 return res;
6807}
6808
6809template <>
6810uint16_t
6812{
6813 return fp16_infinity(sgn);
6814}
6815
6816template <>
6817uint32_t
6819{
6820 return fp32_infinity(sgn);
6821}
6822
6823template <>
6824uint64_t
6826{
6827 return fp64_infinity(sgn);
6828}
6829
6830template <>
6831uint16_t
6833{
6834 return fp16_defaultNaN(fpcr.ah ? FPLIB_AH : 0);
6835}
6836
6837template <>
6838uint32_t
6840{
6841 return fp32_defaultNaN(fpcr.ah ? FPLIB_AH : 0);
6842}
6843
6844template <>
6845uint64_t
6847{
6848 return fp64_defaultNaN(fpcr.ah ? FPLIB_AH : 0);
6849}
6850
6851
6852template <>
6853uint16_t
6854fplib32RSqrtStep(uint16_t op1, uint16_t op2, FPSCR &fpscr)
6855{
6856 int mode = modeConv(fpscr);
6857 int flags = 0;
6858 int sgn1, exp1, sgn2, exp2;
6859 uint16_t mnt1, mnt2, result;
6860
6861 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
6862 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
6863
6864 result = fp16_process_NaNs(op1, op2, mode, &flags);
6865 if (!result) {
6866 if ((exp1 == FP16_EXP_INF && !mnt2) ||
6867 (exp2 == FP16_EXP_INF && !mnt1)) {
6868 result = fp16_FPOnePointFive(0);
6869 } else {
6870 uint16_t product = fp16_mul(op1, op2, mode, &flags);
6871 result = fp16_halved_add(fp16_FPThree(0), product, 1, mode,
6872 &flags);
6873 }
6874 }
6875
6876 set_fpscr0(fpscr, flags);
6877
6878 return result;
6879}
6880
6881template <>
6882uint16_t
6883fplib32RecipStep(uint16_t op1, uint16_t op2, FPSCR &fpscr)
6884{
6885 int mode = modeConv(fpscr);
6886 int flags = 0;
6887 int sgn1, exp1, sgn2, exp2;
6888 uint16_t mnt1, mnt2, result;
6889
6890 fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
6891 fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
6892
6893 result = fp16_process_NaNs(op1, op2, mode, &flags);
6894 if (!result) {
6895 if ((exp1 == FP16_EXP_INF && !mnt2) ||
6896 (exp2 == FP16_EXP_INF && !mnt1)) {
6897 result = fp16_FPTwo(0);
6898 } else {
6899 uint16_t product = fp16_mul(op1, op2, mode, &flags);
6900 result = fp16_add(fp16_FPTwo(0), product, 1, mode, &flags);
6901 }
6902 }
6903
6904 set_fpscr0(fpscr, flags);
6905
6906 return result;
6907}
6908
6909static constexpr int BF16_BITS = 16;
6910static constexpr int BF16_EXP_BITS = 8;
6911static constexpr int BF16_EXP_BIAS = 127;
6912static constexpr int BF16_EXP_INF = ((1ULL << BF16_EXP_BITS) - 1);
6913static constexpr int BF16_MANT_BITS = (BF16_BITS - BF16_EXP_BITS - 1);
6914
6915static inline int
6916BF16_EXP(uint16_t x)
6917{
6918 return ((x) >> BF16_MANT_BITS & ((1ULL << BF16_EXP_BITS) - 1));
6919}
6920
6921static inline uint16_t
6922BF16_MANT(uint16_t x)
6923{
6924 return ((x) & ((1ULL << BF16_MANT_BITS) - 1));
6925}
6926
6927static inline uint16_t
6928bf16_pack(uint16_t sgn, uint16_t exp, uint16_t mnt)
6929{
6930 return sgn << (BF16_BITS - 1) | exp << BF16_MANT_BITS | BF16_MANT(mnt);
6931}
6932
6933static inline uint16_t
6935{
6936 return bf16_pack(sgn, 0, 0);
6937}
6938
6939static inline uint16_t
6941{
6942 return bf16_pack(sgn, BF16_EXP_INF - 1, -1);
6943}
6944
6945static inline uint16_t
6947{
6948 return bf16_pack(sgn, BF16_EXP_INF, 0);
6949}
6950
6951static inline uint16_t
6953{
6954 uint16_t sgn = (mode & FPLIB_AH) > 0 ? 1 : 0;
6955 return bf16_pack(sgn, BF16_EXP_INF, 1ULL << (BF16_MANT_BITS - 1));
6956}
6957[[maybe_unused]]
6958static inline void
6959bf16_unpack(int *sgn, int *exp, uint16_t *mnt, uint16_t x, int mode,
6960 int *flags)
6961{
6962 *sgn = x >> (BF16_BITS - 1);
6963 *exp = BF16_EXP(x);
6964 *mnt = BF16_MANT(x);
6965
6966 if (*exp) {
6967 *mnt |= 1ULL << BF16_MANT_BITS;
6968 } else {
6969 // Handle subnormals:
6970 // IDC (Input Denormal) is not set in this case.
6971 if (*mnt) {
6972 if (mode & FPLIB_FZ16) {
6973 *mnt = 0;
6974 } else {
6975 ++*exp;
6976 }
6977 }
6978 }
6979}
6980
6981static inline int
6982bf16_is_NaN(int exp, uint16_t mnt)
6983{
6984 return exp == BF16_EXP_INF && BF16_MANT(mnt);
6985}
6986
6987static inline int
6988bf16_is_signalling_NaN(int exp, uint16_t mnt)
6989{
6990 return bf16_is_NaN(exp, mnt) && !(mnt >> (BF16_MANT_BITS - 1) & 1);
6991}
6992
6993[[maybe_unused]]
6994static inline int
6995bf16_is_quiet_NaN(int exp, uint16_t mnt)
6996{
6997 return exp == BF16_EXP_INF && (mnt >> (BF16_MANT_BITS - 1) & 1);
6998}
6999
7000[[maybe_unused]]
7001static inline int
7002bf16_is_infinity(int exp, uint16_t mnt)
7003{
7004 return exp == BF16_EXP_INF && !BF16_MANT(mnt);
7005}
7006
7007[[maybe_unused]]
7008static inline int
7009bf16_is_denormal(int exp, uint16_t mnt)
7010{
7011 return exp == 1 && !(mnt >> BF16_MANT_BITS);
7012}
7013
7014static inline uint16_t
7015bf16_process_NaN(uint16_t a, int mode, int *flags)
7016{
7017 if (!(a >> (BF16_MANT_BITS - 1) & 1)) {
7018 *flags |= FPLIB_IOC;
7019 a |= 1ULL << (BF16_MANT_BITS - 1);
7020 }
7021 return mode & FPLIB_DN ? bf16_defaultNaN(mode) : a;
7022}
7023
7024static uint16_t
7025bf16_process_NaNs(uint16_t a, uint16_t b, int mode, int *flags)
7026{
7027 int a_exp = BF16_EXP(a);
7028 uint16_t a_mnt = BF16_MANT(a);
7029 int b_exp = BF16_EXP(b);
7030 uint16_t b_mnt = BF16_MANT(b);
7031
7032 // Handle NaN propogate when enabling FEAT_AFP.
7033 if (mode & FPLIB_AH) {
7034 if (bf16_is_NaN(a_exp, a_mnt) && bf16_is_NaN(b_exp, b_mnt)) {
7035 if (bf16_is_signalling_NaN(a_exp, a_mnt) ||
7036 bf16_is_signalling_NaN(b_exp, b_mnt)) {
7037 if (mode & FPLIB_FPEXEC)
7038 *flags |= FPLIB_IOC;
7039 a |= 1ULL << (BF16_MANT_BITS - 1);
7040 }
7041
7042 return bf16_process_NaN(a, mode, flags);
7043 }
7044 }
7045
7046 // Handle signalling NaNs:
7047 if (bf16_is_signalling_NaN(a_exp, a_mnt))
7048 return bf16_process_NaN(a, mode, flags);
7049 if (bf16_is_signalling_NaN(b_exp, b_mnt))
7050 return bf16_process_NaN(b, mode, flags);
7051
7052 // Handle quiet NaNs:
7053 if (bf16_is_NaN(a_exp, a_mnt))
7054 return bf16_process_NaN(a, mode, flags);
7055 if (bf16_is_NaN(b_exp, b_mnt))
7056 return bf16_process_NaN(b, mode, flags);
7057
7058 return 0;
7059}
7060
7061static uint16_t
7062bf16_process_NaNs3(uint16_t a, uint16_t b, uint16_t c, int mode, int *flags)
7063{
7064 int a_exp = BF16_EXP(a);
7065 uint16_t a_mnt = BF16_MANT(a);
7066 int b_exp = BF16_EXP(b);
7067 uint16_t b_mnt = BF16_MANT(b);
7068 int c_exp = BF16_EXP(c);
7069 uint16_t c_mnt = BF16_MANT(c);
7070
7071 if (mode & FPLIB_AH) {
7072 bool op1_nan = bf16_is_NaN(a_exp, a_mnt);
7073 bool op2_nan = bf16_is_NaN(b_exp, b_mnt);
7074 bool op3_nan = bf16_is_NaN(c_exp, c_mnt);
7075 bool op1_snan = bf16_is_signalling_NaN(a_exp, a_mnt);
7076 bool op2_snan = bf16_is_signalling_NaN(b_exp, b_mnt);
7077 bool op3_snan = bf16_is_signalling_NaN(c_exp, c_mnt);
7078 if (op1_nan && op2_nan && op3_nan) {
7079 if (op1_snan || op2_snan || op3_snan) {
7080 if (mode & FPLIB_FPEXEC)
7081 *flags |= FPLIB_IOC;
7082 b |= 1ULL << (BF16_MANT_BITS - 1);
7083 }
7084 return bf16_process_NaN(b, mode, flags);
7085 } else if (op2_nan && (op1_nan || op3_nan)) {
7086 if (op1_snan || op2_snan || op3_snan) {
7087 if (mode & FPLIB_FPEXEC)
7088 *flags |= FPLIB_IOC;
7089 b |= 1ULL << (BF16_MANT_BITS - 1);
7090 }
7091 return bf16_process_NaN(b, mode, flags);
7092 } else if (op3_nan && op1_nan) {
7093 if (op1_snan || op2_snan || op3_snan) {
7094 if (mode & FPLIB_FPEXEC)
7095 *flags |= FPLIB_IOC;
7096 c |= 1ULL << (BF16_MANT_BITS - 1);
7097 }
7098 return bf16_process_NaN(c, mode, flags);
7099 }
7100 }
7101
7102 // Handle signalling NaNs:
7103 if (bf16_is_signalling_NaN(a_exp, a_mnt))
7104 return bf16_process_NaN(a, mode, flags);
7105 if (bf16_is_signalling_NaN(b_exp, b_mnt))
7106 return bf16_process_NaN(b, mode, flags);
7107 if (bf16_is_signalling_NaN(c_exp, c_mnt))
7108 return bf16_process_NaN(c, mode, flags);
7109
7110 // Handle quiet NaNs:
7111 if (bf16_is_NaN(a_exp, a_mnt))
7112 return bf16_process_NaN(a, mode, flags);
7113 if (bf16_is_NaN(b_exp, b_mnt))
7114 return bf16_process_NaN(b, mode, flags);
7115 if (bf16_is_NaN(c_exp, c_mnt))
7116 return bf16_process_NaN(c, mode, flags);
7117
7118 return 0;
7119}
7120
7121static uint16_t
7122bf16_round_(int sgn, int exp, uint16_t mnt, int rm, int mode, int *flags)
7123{
7124 int biased_exp, biased_exp_afp;
7125 // mantissa for result, less than (2 << BF16_MANT_BITS)
7126 uint32_t int_mant, int_mant_afp;
7127 // 0, 1, 2 or 3, where 2 means int_mant is wrong by exactly 0.5
7128 int error, error_afp;
7129
7130 assert(rm != FPRounding_TIEAWAY);
7131
7132 // Flush to zero:
7133 // Deal with flush-to-zero before rounding if FPCR.AH != '1'.
7134 if (((mode & FPLIB_FZ) && !(mode & FPLIB_AH)) && exp < 1) {
7135 if (mode & FPLIB_FPEXEC)
7136 *flags |= FPLIB_UFC;
7137 return bf16_zero(sgn);
7138 }
7139
7140 // The bottom BF16_EXP_BITS bits of mnt are orred together:
7141 mnt = (4ULL << BF16_MANT_BITS | mnt >> (BF16_EXP_BITS - 1) |
7142 ((mnt & ((1ULL << BF16_EXP_BITS) - 1)) != 0));
7143
7144 biased_exp_afp = exp;
7145 int_mant_afp = mnt >> 2;
7146 error_afp = mnt & 3;
7147 if (exp > 0) {
7148 biased_exp = exp;
7149 int_mant = mnt >> 2;
7150 error = mnt & 3;
7151 } else {
7152 biased_exp = 0;
7153 int_mant = lsr32(mnt, 3 - exp);
7154 error = (lsr32(mnt, 1 - exp) & 3) | !!(mnt & (lsl32(1, 1 - exp) - 1));
7155 }
7156
7157 // Underflow occurs if exponent is too small before rounding, and result is
7158 // inexact or the Underflow exception is trapped. This applies before
7159 // rounding if FPCR.AH != '1'.
7160 // xx should also check fpscr_val<11>
7161 if (!(mode & FPLIB_AH) && !biased_exp && error) {
7162 if (mode & FPLIB_FPEXEC)
7163 *flags |= FPLIB_UFC;
7164 }
7165
7166 // Round up when enabling FEAT_AFP:
7167 if (mode & FPLIB_AH) {
7168 if ((rm == FPLIB_RN && (error_afp == 3 ||
7169 (error_afp == 2 && (int_mant_afp & 1)))) ||
7170 (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) &&
7171 error_afp)) {
7172 ++int_mant_afp;
7173 if (int_mant_afp == 2ULL << BF16_MANT_BITS) {
7174 // Rounded up to next exponent
7175 ++biased_exp_afp;
7176 int_mant_afp >>= 1;
7177 }
7178 }
7179 }
7180
7181 // Round up:
7182 if ((rm == FPLIB_RN && (error == 3 ||
7183 (error == 2 && (int_mant & 1)))) ||
7184 (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) && error)) {
7185 ++int_mant;
7186 if (int_mant == 1ULL << BF16_MANT_BITS) {
7187 // Rounded up from denormalized to normalized
7188 biased_exp = 1;
7189 }
7190 if (int_mant == 2ULL << BF16_MANT_BITS) {
7191 // Rounded up to next exponent
7192 ++biased_exp;
7193 int_mant >>= 1;
7194 }
7195 }
7196
7197 // Handle rounding to odd aka Von Neumann rounding:
7198 if (error && rm == FPRounding_ODD)
7199 int_mant |= 1;
7200
7201 // Flush to zero:
7202 // Deal with overflow and generate result.
7203 // Deal with flush-to-zero and underflow after rounding if FPCR.AH == '1'.
7204 if (biased_exp_afp < 1) {
7205 if ((mode & FPLIB_FZ) && (mode & FPLIB_AH)) {
7206 if (mode & FPLIB_FPEXEC)
7207 *flags |= FPLIB_UFC | FPLIB_IXC;
7208 return bf16_zero(sgn);
7209 } else if (error) {
7210 if (mode & FPLIB_FPEXEC)
7211 *flags |= FPLIB_UFC;
7212 }
7213 }
7214
7215 // Handle overflow:
7216 if (biased_exp >= (int)BF16_EXP_INF) {
7217 if (mode & FPLIB_FPEXEC)
7218 *flags |= FPLIB_OFC | FPLIB_IXC;
7219 if (rm == FPLIB_RN || (rm == FPLIB_RP && !sgn) ||
7220 (rm == FPLIB_RM && sgn)) {
7221 return bf16_infinity(sgn);
7222 } else {
7223 return bf16_max_normal(sgn);
7224 }
7225 }
7226
7227 if (error) {
7228 if (mode & FPLIB_FPEXEC)
7229 *flags |= FPLIB_IXC;
7230 }
7231
7232 return bf16_pack(sgn, biased_exp, int_mant);
7233}
7234
7235static uint32_t
7236bf16_round(int sgn, int exp, uint32_t mnt, int mode, int *flags)
7237{
7238 return bf16_round_(sgn, exp, mnt, mode & 3, mode, flags);
7239}
7240
7241static uint16_t
7242bf16_add(uint16_t a, uint16_t b, int neg, int mode, int *flags)
7243{
7244 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
7245 uint32_t a_mnt, b_mnt, x, x_mnt;
7246
7247 fp32_unpack(&a_sgn, &a_exp, &a_mnt, (uint32_t)a << 16, mode, flags);
7248 fp32_unpack(&b_sgn, &b_exp, &b_mnt, (uint32_t)b << 16, mode, flags);
7249
7250 if ((x = bf16_process_NaNs(a, b, mode, flags))) {
7251 return x;
7252 }
7253
7254 // FPProcessDenorms2
7255 if (mode & FPLIB_AH) {
7256 if (fp32_is_denormal(a_exp, a_mnt) || fp32_is_denormal(b_exp, b_mnt)) {
7257 *flags |= FPLIB_IDC;
7258 }
7259 }
7260
7261 b_sgn ^= neg;
7262
7263 // Handle infinities and zeroes:
7264 if (a_exp == FP32_EXP_INF && b_exp == FP32_EXP_INF && a_sgn != b_sgn) {
7265 *flags |= FPLIB_IOC;
7266 return bf16_defaultNaN(mode);
7267 } else if (a_exp == FP32_EXP_INF) {
7268 return bf16_infinity(a_sgn);
7269 } else if (b_exp == FP32_EXP_INF) {
7270 return bf16_infinity(b_sgn);
7271 } else if (!a_mnt && !b_mnt && a_sgn == b_sgn) {
7272 return bf16_zero(a_sgn);
7273 }
7274
7275 a_mnt <<= 3;
7276 b_mnt <<= 3;
7277 if (a_exp >= b_exp) {
7278 b_mnt = (lsr32(b_mnt, a_exp - b_exp) |
7279 !!(b_mnt & (lsl32(1, a_exp - b_exp) - 1)));
7280 b_exp = a_exp;
7281 } else {
7282 a_mnt = (lsr32(a_mnt, b_exp - a_exp) |
7283 !!(a_mnt & (lsl32(1, b_exp - a_exp) - 1)));
7284 a_exp = b_exp;
7285 }
7286 x_sgn = a_sgn;
7287 x_exp = a_exp;
7288 if (a_sgn == b_sgn) {
7289 x_mnt = a_mnt + b_mnt;
7290 } else if (a_mnt >= b_mnt) {
7291 x_mnt = a_mnt - b_mnt;
7292 } else {
7293 x_sgn ^= 1;
7294 x_mnt = b_mnt - a_mnt;
7295 }
7296
7297 if (!x_mnt) {
7298 // Sign of exact zero result depends on rounding mode
7299 return bf16_zero((mode & 3) == 2);
7300 }
7301
7302 x_mnt = fp32_normalise(x_mnt, &x_exp);
7303
7304 return bf16_round(
7305 x_sgn, x_exp + FP32_EXP_BITS - 3,
7306 x_mnt >> (FP32_BITS - 1 - BF16_BITS) |
7307 !!(x_mnt & ((1ULL << (FP32_BITS - 1 - BF16_BITS)) - 1)),
7308 mode, flags);
7309}
7310
7311static uint16_t
7312bf16_mul(uint16_t a, uint16_t b, int mode, int *flags)
7313{
7314 int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
7315 uint32_t a_mnt, b_mnt, x;
7316 uint64_t x_mnt;
7317
7318 fp32_unpack(&a_sgn, &a_exp, &a_mnt, (uint32_t)a << 16, mode, flags);
7319 fp32_unpack(&b_sgn, &b_exp, &b_mnt, (uint32_t)b << 16, mode, flags);
7320
7321 if ((x = bf16_process_NaNs(a, b, mode, flags))) {
7322 return x;
7323 }
7324
7325 // FPProcessDenorms2
7326 if (mode & FPLIB_AH) {
7327 if (fp32_is_denormal(a_exp, a_mnt) || fp32_is_denormal(b_exp, b_mnt)) {
7328 *flags |= FPLIB_IDC;
7329 }
7330 }
7331
7332 // Handle infinities and zeroes:
7333 if ((a_exp == FP32_EXP_INF && !b_mnt) ||
7334 (b_exp == FP32_EXP_INF && !a_mnt)) {
7335 *flags |= FPLIB_IOC;
7336 return bf16_defaultNaN(mode);
7337 } else if (a_exp == FP32_EXP_INF || b_exp == FP32_EXP_INF) {
7338 return bf16_infinity(a_sgn ^ b_sgn);
7339 } else if (!a_mnt || !b_mnt) {
7340 return bf16_zero(a_sgn ^ b_sgn);
7341 }
7342
7343 // Multiply and normalise:
7344 x_sgn = a_sgn ^ b_sgn;
7345 x_exp = a_exp + b_exp - FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1;
7346 x_mnt = (uint64_t)a_mnt * b_mnt;
7347 x_mnt = fp64_normalise(x_mnt, &x_exp);
7348
7349 // Convert to FP32_BITS bits, collapsing error into bottom bit:
7350 x_mnt = lsr64(x_mnt, FP32_BITS - 1) | !!lsl64(x_mnt, FP32_BITS + 1);
7351
7352 return bf16_round(x_sgn, x_exp,
7353 x_mnt >> (FP32_BITS - BF16_BITS) |
7354 !!(x_mnt & ((1ULL << (FP32_BITS - BF16_BITS)) - 1)),
7355 mode, flags);
7356}
7357
7358static uint16_t
7359bf16_muladd(uint16_t a, uint16_t b, uint16_t c, int scale,
7360 int mode, int *flags)
7361{
7362 int a_sgn, a_exp, b_sgn, b_exp, c_sgn, c_exp, x_sgn, x_exp, y_sgn, y_exp;
7363 uint32_t a_mnt, b_mnt, c_mnt, x;
7364 uint64_t x_mnt, y_mnt;
7365
7366 fp32_unpack(&a_sgn, &a_exp, &a_mnt, (uint32_t)a << 16, mode, flags);
7367 fp32_unpack(&b_sgn, &b_exp, &b_mnt, (uint32_t)b << 16, mode, flags);
7368 fp32_unpack(&c_sgn, &c_exp, &c_mnt, (uint32_t)c << 16, mode, flags);
7369
7370 x = bf16_process_NaNs3(a, b, c, mode, flags);
7371
7372 if (!(mode & FPLIB_AH)) {
7373 // Quiet NaN added to product of zero and infinity:
7374 if (fp32_is_quiet_NaN(a_exp, a_mnt) &&
7375 ((!b_mnt && fp32_is_infinity(c_exp, c_mnt)) ||
7376 (!c_mnt && fp32_is_infinity(b_exp, b_mnt)))) {
7378 if (mode & FPLIB_FPEXEC)
7379 *flags |= FPLIB_IOC;
7380 }
7381 }
7382
7383 if (x) {
7384 return x;
7385 }
7386
7387 // Handle infinities and zeroes:
7388 if ((b_exp == FP32_EXP_INF && !c_mnt) ||
7389 (c_exp == FP32_EXP_INF && !b_mnt) ||
7390 (a_exp == FP32_EXP_INF &&
7391 (b_exp == FP32_EXP_INF || c_exp == FP32_EXP_INF) &&
7392 (a_sgn != (b_sgn ^ c_sgn)))) {
7393 if (mode & FPLIB_FPEXEC)
7394 *flags |= FPLIB_IOC;
7395 return bf16_defaultNaN(mode);
7396 }
7397
7398 // FPProcessDenorms3
7399 if (mode & FPLIB_AH) {
7400 if (fp32_is_denormal(a_exp, a_mnt) || fp32_is_denormal(b_exp, b_mnt) ||
7401 fp32_is_denormal(c_exp, c_mnt)) {
7402 *flags |= FPLIB_IDC;
7403 }
7404 }
7405
7406 if (a_exp == FP32_EXP_INF)
7407 return bf16_infinity(a_sgn);
7408 if (b_exp == FP32_EXP_INF || c_exp == FP32_EXP_INF)
7409 return bf16_infinity(b_sgn ^ c_sgn);
7410 if (!a_mnt && (!b_mnt || !c_mnt) && a_sgn == (b_sgn ^ c_sgn))
7411 return bf16_zero(a_sgn);
7412
7413 x_sgn = a_sgn;
7414 x_exp = a_exp + 2 * FP32_EXP_BITS - 3;
7415 x_mnt = (uint64_t)a_mnt << (FP32_MANT_BITS + 4);
7416
7417 // Multiply:
7418 y_sgn = b_sgn ^ c_sgn;
7419 y_exp = b_exp + c_exp - FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1 - 3;
7420 y_mnt = (uint64_t)b_mnt * c_mnt << 3;
7421 if (!y_mnt) {
7422 y_exp = x_exp;
7423 }
7424
7425 // Add:
7426 if (x_exp >= y_exp) {
7427 y_mnt = (lsr64(y_mnt, x_exp - y_exp) |
7428 !!(y_mnt & (lsl64(1, x_exp - y_exp) - 1)));
7429 y_exp = x_exp;
7430 } else {
7431 x_mnt = (lsr64(x_mnt, y_exp - x_exp) |
7432 !!(x_mnt & (lsl64(1, y_exp - x_exp) - 1)));
7433 x_exp = y_exp;
7434 }
7435 if (x_sgn == y_sgn) {
7436 x_mnt = x_mnt + y_mnt;
7437 } else if (x_mnt >= y_mnt) {
7438 x_mnt = x_mnt - y_mnt;
7439 } else {
7440 x_sgn ^= 1;
7441 x_mnt = y_mnt - x_mnt;
7442 }
7443
7444 if (!x_mnt) {
7445 // Sign of exact zero result depends on rounding mode
7446 return bf16_zero((mode & 3) == 2);
7447 }
7448
7449 // Normalise into FP32_BITS bits, collapsing error into bottom bit:
7450 x_mnt = fp64_normalise(x_mnt, &x_exp);
7451 x_mnt = x_mnt >> (FP32_BITS - 1) | !!(uint32_t)(x_mnt << 1);
7452
7453 return bf16_round(x_sgn, x_exp + scale,
7454 x_mnt >> (FP32_BITS - BF16_BITS) |
7455 !!(x_mnt & ((1ULL << (FP32_BITS - BF16_BITS)) - 1)),
7456 mode, flags);
7457}
7458
7459uint32_t
7460bf16_dot(uint32_t op1_a, uint32_t op1_b, uint32_t op2_a, uint32_t op2_b,
7461 int mode, int* flags)
7462{
7463 int a1_sgn, b1_sgn, a2_sgn, b2_sgn, a1_exp, b1_exp, a2_exp, b2_exp;
7464 int pa_sgn, pb_sgn, pa_exp, pb_exp, x_sgn, x_exp;
7465 uint32_t a1_mnt, b1_mnt, a2_mnt, b2_mnt;
7466 uint64_t pa_mnt, pb_mnt, x_mnt, x;
7467
7468 fp32_unpack(&a1_sgn, &a1_exp, &a1_mnt, op1_a, mode, flags);
7469 fp32_unpack(&b1_sgn, &b1_exp, &b1_mnt, op1_b, mode, flags);
7470 fp32_unpack(&a2_sgn, &a2_exp, &a2_mnt, op2_a, mode, flags);
7471 fp32_unpack(&b2_sgn, &b2_exp, &b2_mnt, op2_b, mode, flags);
7472
7473 x = fp32_process_NaNs4(op1_a, op1_b, op2_a, op2_b, mode, flags);
7474 if (x) {
7475 return x;
7476 }
7477
7478 bool a1_inf = fp32_is_infinity(a1_exp, a1_mnt);
7479 bool a2_inf = fp32_is_infinity(a2_exp, a2_mnt);
7480 bool b1_inf = fp32_is_infinity(b1_exp, b1_mnt);
7481 bool b2_inf = fp32_is_infinity(b2_exp, b2_mnt);
7482
7483 bool a1_zero = !a1_exp && !a1_mnt;
7484 bool a2_zero = !a2_exp && !a2_mnt;
7485 bool b1_zero = !b1_exp && !b1_mnt;
7486 bool b2_zero = !b2_exp && !b2_mnt;
7487
7488 // Determine sign and type products will have if it does not cause an
7489 // Invalid Operation.
7490 pa_sgn = a1_sgn ^ a2_sgn;
7491 pb_sgn = b1_sgn ^ b2_sgn;
7492 bool pa_inf = a1_inf || a2_inf;
7493 bool pb_inf = b1_inf || b2_inf;
7494 bool pa_zero = a1_zero || a2_zero;
7495 bool pb_zero = b1_zero || b2_zero;
7496
7497 // Non SNaN-generated Invalid Operation cases are multiplies of zero
7498 // by infinity and additions of opposite-signed infinities.
7499 bool invalidop = ((a1_inf && a2_zero) || (a1_zero && a2_inf) ||
7500 (b1_inf && b2_zero) || (b1_zero && b2_inf) ||
7501 (pa_inf && pb_inf && pa_sgn != pb_sgn));
7502
7503 if (invalidop) {
7505 *flags |= FPLIB_IOC;
7506 return x;
7507 }
7508
7509 // Other cases involving infinities produce an infinity of the same sign.
7510 if ((pa_inf && !pa_sgn) || (pb_inf && !pb_sgn)) {
7511 return fp32_infinity(0);
7512 } else if ((pa_inf && pa_sgn) || (pb_inf && pb_sgn)) {
7513 return fp32_infinity(1);
7514 }
7515
7516 // Cases where the result is exactly zero and its sign is not determined by
7517 // the rounding mode are additions of same-signed zeros.
7518 if (pa_zero && pb_zero && (pa_sgn == pb_sgn)) {
7519 return fp32_zero(pa_sgn);
7520 }
7521
7522 // Otherwise calculate fused sum of products and round it.
7523 // Multiply:
7524 pa_exp = a1_exp + a2_exp - FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1 - 3;
7525 pa_mnt = (uint64_t)a1_mnt * a2_mnt << 3;
7526
7527 pb_exp = b1_exp + b2_exp - FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1 - 3;
7528 pb_mnt = (uint64_t)b1_mnt * b2_mnt << 3;
7529 if (!pb_mnt && pa_mnt) {
7530 pb_exp = pa_exp;
7531 }
7532 if (pb_mnt && !pa_mnt) {
7533 pa_exp = pb_exp;
7534 }
7535
7536 // Add:
7537 if (pa_exp >= pb_exp) {
7538 pb_mnt = (lsr64(pb_mnt, pa_exp - pb_exp) |
7539 !!(pb_mnt & (lsl64(1, pa_exp - pb_exp) - 1)));
7540 pb_exp = pa_exp;
7541 } else {
7542 pa_mnt = (lsr64(pa_mnt, pb_exp - pa_exp) |
7543 !!(pa_mnt & (lsl64(1, pb_exp - pa_exp) - 1)));
7544 pa_exp = pb_exp;
7545 }
7546 x_sgn = pa_sgn;
7547 x_exp = pa_exp;
7548 if (pa_sgn == pb_sgn) {
7549 x_mnt = pa_mnt + pb_mnt;
7550 } else if (pa_mnt >= pb_mnt) {
7551 x_mnt = pa_mnt - pb_mnt;
7552 } else {
7553 x_sgn ^= 1;
7554 x_mnt = pb_mnt - pa_mnt;
7555 }
7556
7557 if (!x_mnt) {
7558 // Sign of exact zero result depends on rounding mode
7559 return fp32_zero((mode & 3) == 2);
7560 }
7561
7562 x_mnt = fp64_normalise(x_mnt, &x_exp);
7563 x_mnt = x_mnt >> (FP32_BITS - 1) | !!(uint32_t)(x_mnt << 1);
7564
7565 return fp32_round(x_sgn, x_exp, x_mnt, mode, flags);
7566}
7567
7568static void
7569bf16_minmaxnum(uint16_t *op1, uint16_t *op2, int sgn)
7570{
7571 // Treat a single quiet-NaN as +Infinity/-Infinity
7572 if (!((uint16_t)~(*op1 << 1) >> BF16_MANT_BITS) &&
7573 (uint16_t)~(*op2 << 1) >> BF16_MANT_BITS)
7574 *op1 = bf16_infinity(sgn);
7575 if (!((uint16_t)~(*op2 << 1) >> BF16_MANT_BITS) &&
7576 (uint16_t)~(*op1 << 1) >> BF16_MANT_BITS)
7577 *op2 = bf16_infinity(sgn);
7578}
7579
7580uint16_t
7581fplibConvertBF(uint32_t op, FPRounding rounding, FPSCR &fpscr, FPCR fpcr)
7582{
7583 int mode = modeConv(fpscr, fpcr);
7584 int flags = 0;
7585 int sgn, exp;
7586 uint32_t mnt;
7587 uint16_t result;
7588
7589 // Alternate BFloat16 behaviors
7590 if (mode & FPLIB_AH) {
7591 // Produce the expected IEEE 754 default result but do not update the
7592 // FPSR cumulative exception flag bits.
7594 // Use Round to Nearest Even, ignoring FPCR.RMode.
7595 rounding = FPRounding_TIEEVEN;
7596 // Flush denormalized inputs and outputs to zero, as if FPCR.{FZ, FIZ}
7597 // is {1, 1}.
7598 mode |= FPLIB_FIZ | FPLIB_FZ;
7599 }
7600
7601 // Unpack floating-point operand optionally with flush-to-zero:
7602 fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
7603
7604 if (fp32_is_NaN(exp, mnt)) {
7605 if (fpscr.dn) {
7606 result = bf16_defaultNaN(mode);
7607 } else {
7608 result = (op >> (FP32_MANT_BITS - BF16_MANT_BITS)) |
7609 (1ULL << (BF16_MANT_BITS - 1));
7610 }
7611 if (!(mnt >> (FP32_MANT_BITS - 1) & 1)) {
7612 if (mode & FPLIB_FPEXEC)
7613 flags |= FPLIB_IOC;
7614 }
7615 } else if (exp == FP32_EXP_INF) {
7616 result = bf16_infinity(sgn);
7617 } else if (!mnt) {
7618 result = bf16_zero(sgn);
7619 } else {
7620 mnt = fp32_normalise(mnt, &exp);
7621 result = bf16_round_(
7623 mnt >> (FP32_BITS - 1 - BF16_BITS) |
7624 !!(mnt & ((1ULL << (FP32_BITS - 1 - BF16_BITS)) - 1)),
7625 rounding, mode, &flags);
7626 }
7627
7628 set_fpscr0(fpscr, flags);
7629
7630 return result;
7631}
7632
7633uint16_t
7634fplibBfAdd(uint16_t op1, uint16_t op2, FPSCR& fpscr, FPCR fpcr)
7635{
7636 int flags = 0;
7637 uint16_t result = bf16_add(op1, op2, 0, modeConv(fpscr, fpcr), &flags);
7638 set_fpscr0(fpscr, flags);
7639 return result;
7640}
7641
7642uint16_t
7643fplibBfMax(uint16_t op1, uint16_t op2, FPSCR& fpscr, FPCR fpcr)
7644{
7645 int flags = 0;
7646 uint32_t result = fp32_max((uint32_t)op1 << 16, (uint32_t)op2 << 16,
7647 modeConv(fpscr, fpcr), &flags, fpcr.ah);
7648 result = result >> 16;
7649 set_fpscr0(fpscr, flags);
7650 return result;
7651}
7652
7653uint16_t
7654fplibBfMaxNum(uint16_t op1, uint16_t op2, FPSCR& fpscr, FPCR fpcr)
7655{
7656 int exp1 = BF16_EXP(op1);
7657 int exp2 = BF16_EXP(op2);
7658 uint16_t mnt1 = BF16_MANT(op1);
7659 uint16_t mnt2 = BF16_MANT(op2);
7660 if (!(fpcr.ah && bf16_is_NaN(exp1, mnt1) && bf16_is_NaN(exp2, mnt2))) {
7661 bf16_minmaxnum(&op1, &op2, 1);
7662 }
7663
7664 int flags = 0;
7665 uint32_t result = fp32_max((uint32_t)op1 << 16, (uint32_t)op2 << 16,
7666 modeConv(fpscr, fpcr), &flags, false);
7667 result = result >> 16;
7668 set_fpscr0(fpscr, flags);
7669 return result;
7670}
7671
7672uint16_t
7673fplibBfMin(uint16_t op1, uint16_t op2, FPSCR& fpscr, FPCR fpcr)
7674{
7675 int flags = 0;
7676 uint32_t result = fp32_min((uint32_t)op1 << 16, (uint32_t)op2 << 16,
7677 modeConv(fpscr, fpcr), &flags, fpcr.ah);
7678 result = result >> 16;
7679 set_fpscr0(fpscr, flags);
7680 return result;
7681}
7682
7683uint16_t
7684fplibBfMinNum(uint16_t op1, uint16_t op2, FPSCR& fpscr, FPCR fpcr)
7685{
7686 int exp1 = BF16_EXP(op1);
7687 int exp2 = BF16_EXP(op2);
7688 uint32_t mnt1 = BF16_MANT(op1);
7689 uint32_t mnt2 = BF16_MANT(op2);
7690 if (!(fpcr.ah && bf16_is_NaN(exp1, mnt1) && bf16_is_NaN(exp2, mnt2))) {
7691 bf16_minmaxnum(&op1, &op2, 0);
7692 }
7693
7694 int flags = 0;
7695 uint32_t result = fp32_min((uint32_t)op1 << 16, (uint32_t)op2 << 16,
7696 modeConv(fpscr, fpcr), &flags, false);
7697 result = result >> 16;
7698 set_fpscr0(fpscr, flags);
7699 return result;
7700}
7701
7702uint16_t
7703fplibBfMul(uint16_t op1, uint16_t op2, FPSCR& fpscr, FPCR fpcr)
7704{
7705 int flags = 0;
7706 uint16_t result = bf16_mul(op1, op2, modeConv(fpscr, fpcr), &flags);
7707 set_fpscr0(fpscr, flags);
7708 return result;
7709}
7710
7711uint32_t
7712fplibBfMulH(uint16_t op1, uint16_t op2, FPSCR &fpscr)
7713{
7714 int flags = 0;
7715 uint32_t result = fp32_mul((uint32_t)op1 << 16, (uint32_t)op2 << 16,
7716 modeConv(fpscr), &flags, true);
7717 set_fpscr0(fpscr, flags);
7718 return result;
7719}
7720
7721uint16_t
7722fplibBfMulAdd(uint16_t addend, uint16_t op1, uint16_t op2,
7723 FPSCR &fpscr, FPCR fpcr)
7724{
7725 int flags = 0;
7726 uint16_t result = bf16_muladd(addend, op1, op2, 0, modeConv(fpscr, fpcr),
7727 &flags);
7728 set_fpscr0(fpscr, flags);
7729 return result;
7730}
7731
7732uint32_t
7733fplibBfMulAddH(uint32_t addend, uint16_t op1, uint16_t op2,
7734 FPSCR &fpscr, FPCR fpcr)
7735{
7736 int flags = 0;
7737 int mode = modeConv(fpscr, fpcr);
7738 if (mode & FPLIB_AH) { // altfp
7739 mode = mode & (~(int)FPLIB_FPEXEC); // fpexc = !altfp
7740 mode = mode | FPLIB_FIZ | FPLIB_FZ; // fpcr.<FIZ.FZ> = '11'
7741 mode = mode & (~(int)0x3); // fpcr.RMode = '00'
7742 }
7743 uint32_t result = fp32_muladd(
7744 addend, (uint32_t)op1 << 16, (uint32_t)op2 << 16, 0, mode, &flags);
7745 set_fpscr0(fpscr, flags);
7746 return result;
7747}
7748
7749uint16_t
7750fplibBfNeg(uint16_t op, FPCR fpcr)
7751{
7752 if (fpcr.ah) {
7753 int exp = BF16_EXP(op);
7754 uint16_t mnt = BF16_MANT(op);
7755 if (bf16_is_NaN(exp, mnt)) {
7756 return op;
7757 }
7758 }
7759 return op ^ 1ULL << (BF16_BITS - 1);
7760}
7761
7762uint16_t
7763fplibBfSub(uint16_t op1, uint16_t op2, FPSCR& fpscr, FPCR fpcr)
7764{
7765 int flags = 0;
7766 uint16_t result = bf16_add(op1, op2, 1, modeConv(fpscr, fpcr), &flags);
7767 set_fpscr0(fpscr, flags);
7768 return result;
7769}
7770
7771uint32_t
7772fplibAdd_Bf16(uint32_t op1, uint32_t op2, FPSCR &fpscr)
7773{
7774 int flags = 0;
7775 uint32_t result = fp32_add(op1, op2, 0, modeConv(fpscr), &flags, true);
7776 set_fpscr0(fpscr, flags);
7777 return result;
7778}
7779
7780uint32_t
7781fplibBfdotAdd(uint32_t addend, uint16_t op1_a, uint16_t op1_b,
7782 uint16_t op2_a, uint16_t op2_b, FPSCR &fpscr, FPCR fpcr)
7783{
7784 // Extended BFloat16 behaviors
7785 if (fpcr.ebf) {
7786 int mode = modeConv(fpscr, fpcr) | FPLIB_DN;
7787 int flags = 0;
7788 uint32_t product = bf16_dot(
7789 (uint32_t)op1_a << 16, (uint32_t)op1_b << 16,
7790 (uint32_t)op2_a << 16, (uint32_t)op2_b << 16, mode, &flags);
7791 uint32_t result = fp32_add(addend, product, 0, mode, &flags);
7792 set_fpscr0(fpscr, flags);
7793 return result;
7794 }
7795 // Standard BFloat16 behaviors
7796 else {
7797 int mode = modeConv(fpscr, fpcr) | FPLIB_DN | FPLIB_FZ | FPLIB_FIZ;
7798 int flags = 0;
7799 uint32_t product1 = fp32_mul(
7800 (uint32_t)op1_a << 16, (uint32_t)op2_a << 16, mode, &flags, true);
7801 uint32_t product2 = fp32_mul(
7802 (uint32_t)op1_b << 16, (uint32_t)op2_b << 16, mode, &flags, true);
7803 uint32_t product = fp32_add(product1, product2, 0, mode, &flags, true);
7804 uint32_t result = fp32_add(addend, product, 0, mode, &flags, true);
7805 set_fpscr0(fpscr, flags);
7806 return result;
7807 }
7808}
7809
7810} // namespace ArmISA
7811} // 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_NEP
Definition fplib.cc:63
#define FPLIB_DZC
Definition fplib.cc:70
#define FP32_EXP_BITS
Definition fplib.cc:78
#define FP16_MANT(x)
Definition fplib.cc:97
#define FP32_BITS
Definition fplib.cc:74
#define FP64_EXP_INF
Definition fplib.cc:87
#define FPLIB_FPEXEC
Definition fplib.cc:64
#define FP32_MANT_BITS
Definition fplib.cc:90
#define FPLIB_RP
Definition fplib.cc:54
#define FPLIB_IOC
Definition fplib.cc:71
#define FP16_MANT_BITS
Definition fplib.cc:89
#define FP16_EXP_BITS
Definition fplib.cc:77
#define FP64_EXP_BITS
Definition fplib.cc:79
#define FP64_MANT_BITS
Definition fplib.cc:91
#define FPLIB_FIZ
Definition fplib.cc:61
#define FPLIB_AHP
Definition fplib.cc:59
#define FPLIB_OFC
Definition fplib.cc:69
#define FP64_MANT(x)
Definition fplib.cc:99
#define FP16_EXP_INF
Definition fplib.cc:85
#define FP32_EXP(x)
Definition fplib.cc:94
#define FP64_EXP_BIAS
Definition fplib.cc:83
#define FP16_EXP(x)
Definition fplib.cc:93
#define FPLIB_IDC
Definition fplib.cc:66
#define FPLIB_FZ
Definition fplib.cc:57
#define FP16_BITS
Definition fplib.cc:73
#define FP32_MANT(x)
Definition fplib.cc:98
#define FP32_EXP_BIAS
Definition fplib.cc:82
#define FPLIB_IXC
Definition fplib.cc:67
#define FPLIB_AH
Definition fplib.cc:62
#define FP32_EXP_INF
Definition fplib.cc:86
#define FP64_EXP(x)
Definition fplib.cc:95
#define FPLIB_UFC
Definition fplib.cc:68
#define FP64_BITS
Definition fplib.cc:75
#define FP16_EXP_BIAS
Definition fplib.cc:81
#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
static uint64_t fp64_FPOnePointFive(int sgn)
Definition fplib.cc:3554
uint16_t fplib32RSqrtStep(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:6854
static uint16_t bf16_process_NaNs(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:7025
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:6547
uint16_t fplib32RecipStep(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:6883
static int fp64_is_infinity(int exp, uint64_t mnt)
Definition fplib.cc:540
static uint32_t fp32_FPConvertNaN_16(uint16_t op)
Definition fplib.cc:3510
static constexpr int BF16_EXP_INF
Definition fplib.cc:6912
static FPRounding FPCRRounding(FPSCR &fpscr)
Definition fplib.hh:71
uint32_t fplibMulAddH(uint32_t addend, uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:3912
static uint64_t fp64_process_NaNs(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:672
static uint16_t fp16_normalise(uint16_t mnt, int *exp)
Definition fplib.cc:223
static uint16_t bf16_process_NaN(uint16_t a, int mode, int *flags)
Definition fplib.cc:7015
static int fp32_compare_un(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:1585
static uint32_t fp32_add(uint32_t a, uint32_t b, int neg, int mode, int *flags, bool rm_odd=false)
Definition fplib.cc:1792
static uint32_t fp32_scale(uint32_t a, int32_t b, int mode, int *flags)
Definition fplib.cc:2866
static void fp32_unpack(int *sgn, int *exp, uint32_t *mnt, uint32_t x, int mode, int *flags)
Definition fplib.cc:422
static uint16_t BF16_MANT(uint16_t x)
Definition fplib.cc:6922
static uint64_t fp64_FPConvertNaN_32(uint32_t op)
Definition fplib.cc:3534
static int modeConv(FPSCR fpscr)
Definition fplib.cc:3139
static uint64_t fp64_round(int sgn, int exp, uint64_t mnt, int mode, int *flags)
Definition fplib.cc:1398
uint16_t fplibTrigMulAdd(uint8_t coeff_index, uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:6130
uint32_t fplibBfMulH(uint16_t op1, uint16_t op2, FPSCR &fpscr)
Definition fplib.cc:7712
static uint16_t bf16_add(uint16_t a, uint16_t b, int neg, int mode, int *flags)
Definition fplib.cc:7242
uint16_t fplibBfMaxNum(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:7654
static int fp16_compare_ge(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:1423
Bitfield< 22 > a1
static uint32_t fp32_FPThree(int sgn)
Definition fplib.cc:3566
static uint16_t bf16_muladd(uint16_t a, uint16_t b, uint16_t c, int scale, int mode, int *flags)
Definition fplib.cc:7359
static uint32_t fp16_process_NaNs4(uint16_t a, uint16_t b, uint16_t c, uint16_t d, int mode, int *flags)
Definition fplib.cc:900
static uint64_t fp64_process_NaN(uint64_t a, int mode, int *flags)
Definition fplib.cc:587
static uint64_t fp64_pack(uint64_t sgn, uint64_t exp, uint64_t mnt)
Definition fplib.cc:318
static void fp64_unpack(int *sgn, int *exp, uint64_t *mnt, uint64_t x, int mode, int *flags)
Definition fplib.cc:448
static uint16_t fp16_scale(uint16_t a, int16_t b, int mode, int *flags)
Definition fplib.cc:2832
static uint16_t bf16_infinity(int sgn)
Definition fplib.cc:6946
static uint64_t fp64_process_NaNs3(uint64_t a, uint64_t b, uint64_t c, int mode, int *flags)
Definition fplib.cc:829
static constexpr int BF16_BITS
Definition fplib.cc:6909
uint32_t fplibAdd_Bf16(uint32_t op1, uint32_t op2, FPSCR &fpscr)
Definition fplib.cc:7772
static uint16_t fp16_zero(int sgn)
Definition fplib.cc:324
static uint16_t fp16_defaultNaN(int mode)
Definition fplib.cc:378
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
static uint32_t fp32_round_(int sgn, int exp, uint32_t mnt, int rm, int mode, int *flags, bool rm_odd=false)
Definition fplib.cc:1166
static uint16_t fp16_max_normal(int sgn)
Definition fplib.cc:342
uint16_t fplibBfMin(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:7673
static uint16_t lsl16(uint16_t x, uint32_t shift)
Definition fplib.cc:102
Bitfield< 4, 0 > mode
Definition misc_types.hh:74
uint16_t fplibRSqrtEstimate(uint16_t op, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:5006
uint16_t fplibMulX(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:4850
bool fplibCompareEQ(uint16_t a, uint16_t b, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:3196
static int fp64_compare_un(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:1705
static void bf16_unpack(int *sgn, int *exp, uint16_t *mnt, uint16_t x, int mode, int *flags)
Definition fplib.cc:6959
Bitfield< 3, 0 > rm
Definition types.hh:118
static uint32_t fp32_muladd(uint32_t a, uint32_t b, uint32_t c, int scale, int mode, int *flags, bool rm_odd=false)
Definition fplib.cc:2211
static uint16_t fp16_process_NaN(uint16_t a, int mode, int *flags)
Definition fplib.cc:565
static uint16_t bf16_round_(int sgn, int exp, uint16_t mnt, int rm, int mode, int *flags)
Definition fplib.cc:7122
bool fplibCompareGE(uint16_t a, uint16_t b, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:3206
static uint16_t fp16_FPConvertNaN_32(uint32_t op)
Definition fplib.cc:3494
static int fp16_is_quiet_NaN(int exp, uint16_t mnt)
Definition fplib.cc:510
static uint16_t fp16_max(uint16_t op1, uint16_t op2, int mode, int *flags, bool altfpminmax)
Definition fplib.cc:4436
static void fp16_unpack(int *sgn, int *exp, uint16_t *mnt, uint16_t x, int mode, int *flags)
Definition fplib.cc:399
uint16_t fplibBfMul(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:7703
static uint32_t FPToFixed_32(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding, int *flags)
Definition fplib.cc:6383
static int fp64_compare_ge(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:1639
int fplibCompare(uint16_t op1, uint16_t op2, bool signal_nans, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:3376
static uint32_t lsr32(uint32_t x, uint32_t shift)
Definition fplib.cc:120
static uint64_t FPToFixed_64(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding, int *flags)
Definition fplib.cc:6334
static uint32_t fp32_convert_default_nan(uint16_t op)
Definition fplib.cc:889
static uint16_t fp16_div(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:2650
uint16_t fplibConvert(uint32_t op, FPRounding rounding, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:3597
static int bf16_is_denormal(int exp, uint16_t mnt)
Definition fplib.cc:7009
static uint64_t fp64_defaultNaN(int mode)
Definition fplib.cc:392
Bitfield< 7 > b
uint16_t fplibExpA(uint16_t op)
Definition fplib.cc:3966
uint16_t fplibMaxNum(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:4679
static uint32_t fp32_FPTwo(int sgn)
Definition fplib.cc:3584
static int fp32_compare_gt(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:1552
uint32_t fp32_dot(uint16_t op1_a, uint16_t op1_b, uint16_t op2_a, uint16_t op2_b, int mode, int *flags)
Definition fplib.cc:2532
static uint64_t fp64_FPConvertNaN_16(uint16_t op)
Definition fplib.cc:3526
bool fplibCompareUN(uint16_t a, uint16_t b, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:3226
static uint32_t fp32_max(uint32_t op1, uint32_t op2, int mode, int *flags, bool altfpminmax)
Definition fplib.cc:4489
static uint32_t fp32_muladdh(uint32_t a, uint16_t b, uint16_t c, int scale, int mode, int *flags, bool rm_odd=false)
Definition fplib.cc:2423
uint16_t fplibTrigSMul(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:6235
static uint16_t bf16_pack(uint16_t sgn, uint16_t exp, uint16_t mnt)
Definition fplib.cc:6928
Bitfield< 6 > err
uint16_t fplibMul(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:4820
static uint16_t fp16_FPOnePointFive(int sgn)
Definition fplib.cc:3542
uint16_t fplibMulAdd(uint16_t addend, uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:3876
uint16_t fplibScale(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:6037
static uint16_t fp16_add(uint16_t a, uint16_t b, int neg, int mode, int *flags)
Definition fplib.cc:1732
static int fp32_compare_eq(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:1492
static uint16_t fp16_min(uint16_t op1, uint16_t op2, int mode, int *flags, bool altfpminmax)
Definition fplib.cc:4263
static uint16_t fp16_pack(uint16_t sgn, uint16_t exp, uint16_t mnt)
Definition fplib.cc:306
uint16_t fplibLogB(uint16_t op, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:4156
static uint64_t fp64_div(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:2744
static uint32_t fp32_normalise(uint32_t mnt, int *exp)
Definition fplib.cc:241
static uint32_t fp32_infinity(int sgn)
Definition fplib.cc:366
static uint64_t lsr64(uint64_t x, uint32_t shift)
Definition fplib.cc:132
static uint32_t fp32_mul(uint32_t a, uint32_t b, int mode, int *flags, bool rm_odd=false)
Definition fplib.cc:2030
static uint16_t bf16_max_normal(int sgn)
Definition fplib.cc:6940
static uint32_t fp32_process_NaNs3(uint32_t a, uint32_t b, uint32_t c, int mode, int *flags)
Definition fplib.cc:769
static int fp64_is_NaN(int exp, uint64_t mnt)
Definition fplib.cc:486
static uint16_t fp16_FPTwo(int sgn)
Definition fplib.cc:3578
static uint16_t fp16_sqrt(uint16_t a, int mode, int *flags)
Definition fplib.cc:2948
static int fp32_is_NaN(int exp, uint32_t mnt)
Definition fplib.cc:480
static uint64_t fp64_FPTwo(int sgn)
Definition fplib.cc:3590
static uint16_t lsr16(uint16_t x, uint32_t shift)
Definition fplib.cc:108
static uint32_t bf16_round(int sgn, int exp, uint32_t mnt, int mode, int *flags)
Definition fplib.cc:7236
uint16_t fplibConvertBF(uint32_t op, FPRounding rounding, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:7581
static int fp64_compare_eq(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:1612
static uint16_t fp16_infinity(int sgn)
Definition fplib.cc:360
static int bf16_is_infinity(int exp, uint16_t mnt)
Definition fplib.cc:7002
static uint32_t fp32_FPConvertNaN_64(uint64_t op)
Definition fplib.cc:3518
static uint16_t fp16_muladd(uint16_t a, uint16_t b, uint16_t c, int scale, int mode, int *flags)
Definition fplib.cc:2123
uint16_t fplibFixedToFP(uint64_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:6772
static void set_fpscr0(FPSCR &fpscr, int flags)
Definition fplib.cc:2809
static uint64_t fp64_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
Definition fplib.cc:6754
static uint16_t FPToFixed_16(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding, int *flags)
Definition fplib.cc:6397
static uint32_t lsl32(uint32_t x, uint32_t shift)
Definition fplib.cc:114
static void add128(uint64_t *x0, uint64_t *x1, uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
Definition fplib.cc:201
uint16_t fplibRecpX(uint16_t op, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:5555
static uint32_t fp32_FPOnePointFive(int sgn)
Definition fplib.cc:3548
uint32_t fplibBfdotAdd(uint32_t addend, uint16_t op1_a, uint16_t op1_b, uint16_t op2_a, uint16_t op2_b, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:7781
static constexpr int BF16_EXP_BITS
Definition fplib.cc:6910
uint16_t fplibRoundInt(uint16_t op, FPRounding rounding, bool exact, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:5651
static int fp32_is_denormal(int exp, uint32_t mnt)
Definition fplib.cc:553
uint16_t fplibBfMulAdd(uint16_t addend, uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:7722
static uint64_t fp64_infinity(int sgn)
Definition fplib.cc:372
static int BF16_EXP(uint16_t x)
Definition fplib.cc:6916
static int fp64_compare_gt(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:1672
static int fp16_is_infinity(int exp, uint16_t mnt)
Definition fplib.cc:528
static uint64_t fp64_FPThree(int sgn)
Definition fplib.cc:3572
static constexpr int BF16_EXP_BIAS
Definition fplib.cc:6911
static int fp16_is_denormal(int exp, uint16_t mnt)
Definition fplib.cc:547
static uint64_t fp64_sqrt(uint64_t a, int mode, int *flags)
Definition fplib.cc:3062
static void fp64_minmaxnum(uint64_t *op1, uint64_t *op2, int sgn)
Definition fplib.cc:4633
static int fp16_compare_eq(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:1404
static uint16_t fp16_process_NaNs(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:598
static uint16_t bf16_defaultNaN(int mode)
Definition fplib.cc:6952
uint32_t bf16_dot(uint32_t op1_a, uint32_t op1_b, uint32_t op2_a, uint32_t op2_b, int mode, int *flags)
Definition fplib.cc:7460
static int fp32_is_signalling_NaN(int exp, uint32_t mnt)
Definition fplib.cc:498
static int bf16_is_signalling_NaN(int exp, uint16_t mnt)
Definition fplib.cc:6988
static int fp32_compare_ge(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:1519
static uint16_t fp16_round_(int sgn, int exp, uint16_t mnt, int rm, int mode, int *flags)
Definition fplib.cc:1040
static int fp16_is_NaN(int exp, uint16_t mnt)
Definition fplib.cc:474
uint16_t fplibBfAdd(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:7634
static uint64_t fp64_max(uint64_t op1, uint64_t op2, int mode, int *flags, bool altfpminmax)
Definition fplib.cc:4549
Bitfield< 29 > c
Definition misc_types.hh:53
static void fp16_minmaxnum(uint16_t *op1, uint16_t *op2, int sgn)
Definition fplib.cc:4609
uint16_t fplibDiv(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:3924
static uint16_t fp16_mul(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:1993
static void lsl128(uint64_t *r0, uint64_t *r1, uint64_t x0, uint64_t x1, uint32_t shift)
Definition fplib.cc:138
static uint32_t fp32_round(int sgn, int exp, uint32_t mnt, int mode, int *flags)
Definition fplib.cc:1282
Bitfield< 8 > a
Definition misc_types.hh:66
uint32_t fplibBfMulAddH(uint32_t addend, uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:7733
uint16_t fplibMinNum(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:4766
static uint32_t fp32_zero(int sgn)
Definition fplib.cc:330
static void lsr128(uint64_t *r0, uint64_t *r1, uint64_t x0, uint64_t x1, uint32_t shift)
Definition fplib.cc:156
static uint32_t fp32_pack(uint32_t sgn, uint32_t exp, uint32_t mnt)
Definition fplib.cc:312
static void mul64x32(uint64_t *x0, uint64_t *x1, uint64_t a, uint32_t b)
Definition fplib.cc:192
uint16_t fplibRecipStepFused(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:5450
Bitfield< 22 > u
uint16_t fplibMax(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:4646
static uint64_t fp64_scale(uint64_t a, int64_t b, int mode, int *flags)
Definition fplib.cc:2907
static int fp16_is_signalling_NaN(int exp, uint16_t mnt)
Definition fplib.cc:492
Bitfield< 24 > fz
uint16_t fplibSqrt(uint16_t op, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:6070
static uint16_t bf16_mul(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:7312
static int fp64_is_denormal(int exp, uint64_t mnt)
Definition fplib.cc:559
static void fp32_minmaxnum(uint32_t *op1, uint32_t *op2, int sgn)
Definition fplib.cc:4621
uint16_t fplibMin(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:4733
uint16_t fplibBfSub(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:7763
uint16_t fplibAbs(uint16_t op, FPCR fpcr)
Definition fplib.cc:3316
static uint64_t fp64_add(uint64_t a, uint64_t b, int neg, int mode, int *flags)
Definition fplib.cc:1865
static uint32_t fp32_process_NaNs(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:635
static const uint8_t recip_sqrt_estimate[256]
Definition fplib.cc:4985
static uint32_t fp32_process_NaN(uint32_t a, int mode, int *flags)
Definition fplib.cc:576
uint16_t fplibAdd(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:3346
static int fp16_compare_gt(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:1448
static uint16_t fp16_process_NaNs3(uint16_t a, uint16_t b, uint16_t c, int mode, int *flags)
Definition fplib.cc:709
static uint32_t fp32_min(uint32_t op1, uint32_t op2, int mode, int *flags, bool altfpminmax)
Definition fplib.cc:4316
static uint32_t fp32_defaultNaN(int mode)
Definition fplib.cc:385
static uint32_t fp32_process_NaNs4(uint32_t a, uint32_t b, uint32_t c, uint32_t d, int mode, int *flags)
Definition fplib.cc:944
static uint64_t lsl64(uint64_t x, uint32_t shift)
Definition fplib.cc:126
uint16_t fplibSub(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:6100
static int fp32_is_infinity(int exp, uint32_t mnt)
Definition fplib.cc:534
Bitfield< 1 > t1
uint16_t fplibFPToFixed(uint16_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:6412
static uint64_t fp64_zero(int sgn)
Definition fplib.cc:336
static uint32_t fp32_sqrt(uint32_t a, int mode, int *flags)
Definition fplib.cc:3000
static int fp64_is_quiet_NaN(int exp, uint64_t mnt)
Definition fplib.cc:522
uint16_t fplibRecipEstimate(uint16_t op, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:5237
static uint16_t fp16_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
Definition fplib.cc:6714
uint16_t fplibBfMax(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:7643
static int fp16_compare_un(uint16_t a, uint16_t b, int mode, int *flags)
Definition fplib.cc:1473
static uint16_t fp16_FPThree(int sgn)
Definition fplib.cc:3560
uint32_t fplibRoundIntN(uint32_t op, FPRounding rounding, bool exact, int intsize, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:5861
static uint16_t bf16_zero(int sgn)
Definition fplib.cc:6934
static uint32_t fp32_process_NaNs3H(uint32_t a, uint16_t b, uint16_t c, int mode, int *flags)
Definition fplib.cc:980
uint16_t fplibTrigSSel(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:6293
static void bf16_minmaxnum(uint16_t *op1, uint16_t *op2, int sgn)
Definition fplib.cc:7569
uint32_t fplibDot(uint16_t op1_a, uint16_t op1_b, uint16_t op2_a, uint16_t op2_b, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:3954
static void sub128(uint64_t *x0, uint64_t *x1, uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
Definition fplib.cc:209
static int bf16_is_NaN(int exp, uint16_t mnt)
Definition fplib.cc:6982
static uint16_t fp16_halved_add(uint16_t a, uint16_t b, int neg, int mode, int *flags)
Definition fplib.cc:1932
static int fp32_is_quiet_NaN(int exp, uint32_t mnt)
Definition fplib.cc:516
bool fplibCompareGT(uint16_t a, uint16_t b, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:3216
static uint64_t fp64_max_normal(int sgn)
Definition fplib.cc:354
uint16_t fplibBfNeg(uint16_t op, FPCR fpcr)
Definition fplib.cc:7750
static uint32_t fp32_div(uint32_t a, uint32_t b, int mode, int *flags)
Definition fplib.cc:2692
uint16_t fplibInfinity(int sgn)
Definition fplib.cc:6811
uint16_t fplibRSqrtStepFused(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:5132
uint16_t fplibDefaultNaN(FPCR fpcr)
Definition fplib.cc:6832
static int bf16_is_quiet_NaN(int exp, uint16_t mnt)
Definition fplib.cc:6995
static uint16_t bf16_process_NaNs3(uint16_t a, uint16_t b, uint16_t c, int mode, int *flags)
Definition fplib.cc:7062
Bitfield< 9 > d
Definition misc_types.hh:64
static uint16_t fp16_round(int sgn, int exp, uint16_t mnt, int mode, int *flags)
Definition fplib.cc:1160
static uint64_t fp64_min(uint64_t op1, uint64_t op2, int mode, int *flags, bool altfpminmax)
Definition fplib.cc:4376
static void set_fpscr(FPSCR &fpscr, int flags)
Definition fplib.cc:3169
static uint64_t fp64_mul(uint64_t a, uint64_t b, int mode, int *flags)
Definition fplib.cc:2079
Bitfield< 6, 5 > shift
Definition types.hh:117
static uint16_t fp16_FPConvertNaN_64(uint64_t op)
Definition fplib.cc:3502
static uint64_t fp64_round_(int sgn, int exp, uint64_t mnt, int rm, int mode, int *flags)
Definition fplib.cc:1288
@ 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
static uint64_t fp64_muladd(uint64_t a, uint64_t b, uint64_t c, int scale, int mode, int *flags)
Definition fplib.cc:2318
static constexpr int BF16_MANT_BITS
Definition fplib.cc:6913
static int fp64_is_signalling_NaN(int exp, uint64_t mnt)
Definition fplib.cc:504
static uint32_t fp32_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
Definition fplib.cc:6734
uint16_t fplibNeg(uint16_t op, FPCR fpcr)
Definition fplib.cc:4957
static void fp128_normalise(uint64_t *mnt0, uint64_t *mnt1, int *exp)
Definition fplib.cc:277
static uint64_t fp64_normalise(uint64_t mnt, int *exp)
Definition fplib.cc:259
uint16_t fplibBfMinNum(uint16_t op1, uint16_t op2, FPSCR &fpscr, FPCR fpcr)
Definition fplib.cc:7684
Bitfield< 0 > t0
static uint32_t fp32_max_normal(int sgn)
Definition fplib.cc:348
static void mul62x62(uint64_t *x0, uint64_t *x1, uint64_t a, uint64_t b)
Definition fplib.cc:174
static int cmp128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
Definition fplib.cc:217
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:78
Bitfield< 4 > op
Definition types.hh:83
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36

Generated on Mon Oct 27 2025 04:12:54 for gem5 by doxygen 1.14.0