Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sp_tlong.c
Go to the documentation of this file.
1 /* IEEE754 floating point arithmetic
2  * single precision
3  */
4 /*
5  * MIPS floating point support
6  * Copyright (C) 1994-2000 Algorithmics Ltd.
7  *
8  * ########################################################################
9  *
10  * This program is free software; you can distribute it and/or modify it
11  * under the terms of the GNU General Public License (Version 2) as
12  * published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17  * for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  *
23  * ########################################################################
24  */
25 
26 
27 #include "ieee754sp.h"
28 
29 s64 ieee754sp_tlong(ieee754sp x)
30 {
31  COMPXDP; /* <-- need 64-bit mantissa tmp */
32 
33  CLEARCX;
34 
35  EXPLODEXSP;
36  FLUSHXSP;
37 
38  switch (xc) {
39  case IEEE754_CLASS_SNAN:
40  case IEEE754_CLASS_QNAN:
41  case IEEE754_CLASS_INF:
43  return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
44  case IEEE754_CLASS_ZERO:
45  return 0;
47  case IEEE754_CLASS_NORM:
48  break;
49  }
50  if (xe >= 63) {
51  /* look for valid corner case */
52  if (xe == 63 && xs && xm == SP_HIDDEN_BIT)
53  return -0x8000000000000000LL;
54  /* Set invalid. We will only use overflow for floating
55  point overflow */
57  return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
58  }
59  /* oh gawd */
60  if (xe > SP_MBITS) {
61  xm <<= xe - SP_MBITS;
62  } else if (xe < SP_MBITS) {
63  u32 residue;
64  int round;
65  int sticky;
66  int odd;
67 
68  if (xe < -1) {
69  residue = xm;
70  round = 0;
71  sticky = residue != 0;
72  xm = 0;
73  } else {
74  residue = xm << (32 - SP_MBITS + xe);
75  round = (residue >> 31) != 0;
76  sticky = (residue << 1) != 0;
77  xm >>= SP_MBITS - xe;
78  }
79  odd = (xm & 0x1) != 0x0;
80  switch (ieee754_csr.rm) {
81  case IEEE754_RN:
82  if (round && (sticky || odd))
83  xm++;
84  break;
85  case IEEE754_RZ:
86  break;
87  case IEEE754_RU: /* toward +Infinity */
88  if ((round || sticky) && !xs)
89  xm++;
90  break;
91  case IEEE754_RD: /* toward -Infinity */
92  if ((round || sticky) && xs)
93  xm++;
94  break;
95  }
96  if ((xm >> 63) != 0) {
97  /* This can happen after rounding */
99  return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
100  }
101  if (round || sticky)
103  }
104  if (xs)
105  return -xm;
106  else
107  return xm;
108 }
109 
110 
112 {
113  ieee754sp hb = ieee754sp_1e63();
114 
115  /* what if x < 0 ?? */
116  if (ieee754sp_lt(x, hb))
117  return (u64) ieee754sp_tlong(x);
118 
119  return (u64) ieee754sp_tlong(ieee754sp_sub(x, hb)) |
120  (1ULL << 63);
121 }