blob: f7a5cf5e19bf965af410b159e3722ef175fef052 [file] [log] [blame]
Thomas Gleixner9d5a6342019-05-31 01:09:55 -07001// SPDX-License-Identifier: GPL-2.0-only
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/* IEEE754 floating point arithmetic
3 * single precision
4 */
5/*
6 * MIPS floating point support
7 * Copyright (C) 1994-2000 Algorithmics Ltd.
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 */
9
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include "ieee754sp.h"
11
Ralf Baechle2209bcb2014-04-16 01:31:11 +020012int ieee754sp_tint(union ieee754sp x)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013{
Ralf Baechle3f7cac42014-04-26 01:49:14 +020014 u32 residue;
15 int round;
16 int sticky;
17 int odd;
18
Linus Torvalds1da177e2005-04-16 15:20:36 -070019 COMPXSP;
20
Ralf Baechle9e8bad12014-04-19 00:36:32 +020021 ieee754_clearcx();
Linus Torvalds1da177e2005-04-16 15:20:36 -070022
23 EXPLODEXSP;
24 FLUSHXSP;
25
26 switch (xc) {
27 case IEEE754_CLASS_SNAN:
28 case IEEE754_CLASS_QNAN:
Ralf Baechle9e8bad12014-04-19 00:36:32 +020029 ieee754_setcx(IEEE754_INVALID_OPERATION);
Ralf Baechle90efba32014-04-25 03:19:57 +020030 return ieee754si_indef();
Ralf Baechle3f7cac42014-04-26 01:49:14 +020031
Maciej W. Rozycki90d53a92015-11-13 00:47:28 +000032 case IEEE754_CLASS_INF:
33 ieee754_setcx(IEEE754_INVALID_OPERATION);
34 return ieee754si_overflow(xs);
35
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 case IEEE754_CLASS_ZERO:
37 return 0;
Ralf Baechle3f7cac42014-04-26 01:49:14 +020038
Linus Torvalds1da177e2005-04-16 15:20:36 -070039 case IEEE754_CLASS_DNORM:
40 case IEEE754_CLASS_NORM:
41 break;
42 }
43 if (xe >= 31) {
44 /* look for valid corner case */
45 if (xe == 31 && xs && xm == SP_HIDDEN_BIT)
46 return -0x80000000;
47 /* Set invalid. We will only use overflow for floating
48 point overflow */
Ralf Baechle9e8bad12014-04-19 00:36:32 +020049 ieee754_setcx(IEEE754_INVALID_OPERATION);
Maciej W. Rozycki90d53a92015-11-13 00:47:28 +000050 return ieee754si_overflow(xs);
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 }
52 /* oh gawd */
Ralf Baechlead8fb5532014-04-22 15:51:55 +020053 if (xe > SP_FBITS) {
54 xm <<= xe - SP_FBITS;
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 if (xe < -1) {
57 residue = xm;
58 round = 0;
59 sticky = residue != 0;
60 xm = 0;
Andrea Gelmini3e4088a2010-05-23 21:52:09 +020061 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 /* Shifting a u32 32 times does not work,
63 * so we do it in two steps. Be aware that xe
64 * may be -1 */
65 residue = xm << (xe + 1);
Ralf Baechlead8fb5532014-04-22 15:51:55 +020066 residue <<= 31 - SP_FBITS;
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 round = (residue >> 31) != 0;
68 sticky = (residue << 1) != 0;
Ralf Baechlead8fb5532014-04-22 15:51:55 +020069 xm >>= SP_FBITS - xe;
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 }
71 odd = (xm & 0x1) != 0x0;
72 switch (ieee754_csr.rm) {
Ralf Baechle56a64732014-04-30 11:21:55 +020073 case FPU_CSR_RN:
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 if (round && (sticky || odd))
75 xm++;
76 break;
Ralf Baechle56a64732014-04-30 11:21:55 +020077 case FPU_CSR_RZ:
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 break;
Ralf Baechle56a64732014-04-30 11:21:55 +020079 case FPU_CSR_RU: /* toward +Infinity */
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 if ((round || sticky) && !xs)
81 xm++;
82 break;
Ralf Baechle56a64732014-04-30 11:21:55 +020083 case FPU_CSR_RD: /* toward -Infinity */
Linus Torvalds1da177e2005-04-16 15:20:36 -070084 if ((round || sticky) && xs)
85 xm++;
86 break;
87 }
88 if ((xm >> 31) != 0) {
89 /* This can happen after rounding */
Ralf Baechle9e8bad12014-04-19 00:36:32 +020090 ieee754_setcx(IEEE754_INVALID_OPERATION);
Maciej W. Rozycki90d53a92015-11-13 00:47:28 +000091 return ieee754si_overflow(xs);
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 }
93 if (round || sticky)
Ralf Baechle9e8bad12014-04-19 00:36:32 +020094 ieee754_setcx(IEEE754_INEXACT);
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 }
96 if (xs)
97 return -xm;
98 else
99 return xm;
100}