1 // fp.h - Floating point number class using host integer ops. -*- C++ -*-
3 // Copyright 1997, 1998, 2002, 2005, 2006 Free Software Foundation, Inc.
4 // Copyright 2002 Red Hat, Inc.
5 // This file is part of SID.
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2, or (at your option)
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License along
18 // with this program; if not, write to the Free Software Foundation, Inc.,
19 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 // This file is heavily lifted from the GDB simulators' sim-fpu.{h,c},
22 // which in turn is heavily lifted from GCC's fp-bit library.
29 #include "cgen-types.h"
31 using sid::host_int_4;
32 using sid::host_int_8;
33 using sid::signed_host_int_8;
35 // XXX: more of this cruft should be C++-ed.
37 #define FRAC32MASK LSMASK64 (63, NR_FRAC_GUARD - 32 + 1)
38 #define MAX_UINT32() LSMASK64 (31, 0)
39 #define MAX_UINT64() LSMASK64 (63, 0)
40 #define MAX_INT (is_64bit ? MAX_INT64 () : MAX_INT32 ())
41 #define MIN_INT (is_64bit ? MIN_INT64 () : MIN_INT32 ())
42 #define MAX_UINT (is_64bit ? MAX_UINT64 () : MAX_UINT32 ())
43 #define QUIET_NAN LSBIT64 (NR_FRACBITS (double_p) - 1)
44 #define IMPLICIT_1 LSBIT64 (NR_FRAC_GUARD)
45 #define IMPLICIT_2 LSBIT64 (NR_FRAC_GUARD + 1)
46 #define IMPLICIT_4 LSBIT64 (NR_FRAC_GUARD + 2)
47 #define NORMAL_EXPMIN (-(EXPBIAS (double_p) )+1)
48 #define NORMAL_EXPMAX (EXPBIAS (double_p))
50 #if (WITH_TARGET_WORD_MSB == 0)
51 #define _LSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS)
53 #define _LSB_SHIFT(WIDTH, POS) (POS)
56 #if (WITH_TARGET_WORD_MSB == 0)
57 #define _MSB_SHIFT(WIDTH, POS) (POS)
59 #define _MSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS)
62 #define _MASK64(WIDTH, START, STOP) (((static_cast<host_int_8>(-1)) \
63 >> (_MSB_SHIFT (WIDTH, START) \
64 + _LSB_SHIFT (WIDTH, STOP))) \
65 << _LSB_SHIFT (WIDTH, STOP))
67 #if (WITH_TARGET_WORD_MSB == 0)
68 #define _LSB_POS(WIDTH, SHIFT) (WIDTH - 1 - SHIFT)
70 #define _LSB_POS(WIDTH, SHIFT) (SHIFT)
73 #define _LSMASK64(WIDTH, FIRST, LAST) _MASK64 (WIDTH, \
74 _LSB_POS (WIDTH, FIRST), \
75 _LSB_POS (WIDTH, LAST))
77 #define LSMASK64(FIRST, LAST) _LSMASK64 (64, (FIRST), (LAST))
79 #define GUARDMSB LSBIT64 (NR_GUARDS (double_p) - 1)
80 #define GUARDLSB LSBIT64 (NR_PADS (double_p))
81 #define GUARDMASK LSMASK64 (NR_GUARDS (double_p) - 1, 0)
82 #define GUARDROUND LSMASK64 (NR_GUARDS (double_p) - 2, 0)
84 #define PADMASK LSMASK64 (NR_PADS (double_p) - 1, 0)
86 static const int NR_SPARE = 2;
87 static const int EXPMAX32 = 255;
88 static const int EXPMAX64 = 2047;
89 static const int NR_FRAC_GUARD = 60;
90 static const int EXPBIAS32 = 127;
91 static const int EXPBIAS64 = 1023;
92 static const int NR_PAD32 = 30;
93 static const int NR_PAD64 = 0;
94 static const int NR_GUARDS32 = 7 + NR_PAD32;
95 static const int NR_GUARDS64 = 8 + NR_PAD64;
96 static const int NORMAL_EXPMAX32 = EXPBIAS32;
97 static const int NORMAL_EXPMAX64 = EXPBIAS64;
100 signed_host_int_8 MAX_INT32 ()
102 return LSMASK64 (30, 0);
106 signed_host_int_8 MIN_INT32 ()
108 return LSMASK64 (63, 31);
112 signed_host_int_8 MAX_INT64 ()
114 return LSMASK64 (62, 0);
118 signed_host_int_8 MIN_INT64 ()
120 return LSMASK64 (63, 63);
124 unsigned EXPMAX (bool double_p)
126 return double_p ? EXPMAX64 : EXPMAX32;
130 int EXPBIAS (bool double_p)
132 return double_p ? EXPBIAS64 : EXPBIAS32;
136 int NR_GUARDS (bool double_p)
138 return double_p ? NR_GUARDS64 : NR_GUARDS32;
142 int NR_PADS (bool double_p)
144 return double_p ? NR_PAD64 : NR_PAD32;
148 int NR_EXPBITS (bool double_p)
150 return double_p ? 11 : 8;
154 int NR_FRACBITS (bool double_p)
156 return double_p ? 52 : 23;
160 int NR_INTBITS (bool is_64bit)
162 return is_64bit ? 64 : 32;
166 host_int_8 LSBIT64 (int pos)
168 return host_int_8 (1) << pos;
172 host_int_8 MSBIT64 (int pos)
174 return host_int_8 (1) << (64 - 1 - pos);
178 host_int_8 SIGNBIT (bool double_p)
180 return double_p ? MSBIT64 (0) : MSBIT64 (32);
188 typedef int status_t;
190 typedef sid::host_int_8 fraction_t;
204 denorm_underflow_inexact,
218 // Type thrown by operators.
222 error (fp::status_t s) :status (s) {}
223 operator int() { return static_cast<int> (status); }
228 // Construct a float from packed registers.
229 fp (const cgen::SF&);
230 fp (const cgen::DF&);
231 fp (const cgen::SF& high, const cgen::SF& low);
234 :status (ok), fp_class (class_zero), sign (0), fraction (0), normal_exp (0) {}
236 :status (ok), fp_class (c), sign (0), fraction (0), normal_exp (0) {}
237 fp (enum class_t c, int s, sid::host_int_8 f, exp_t exp)
238 :status (ok), fp_class (c), sign (s), fraction (f), normal_exp (exp) {}
241 bool is_nan () const;
243 // Is this fp a signalling NaN?
244 bool is_snan () const;
246 // Is this fp a quiet NaN?
247 bool is_qnan () const;
249 bool is_denorm () const;
250 bool is_zero () const;
251 bool is_infinity () const;
252 bool is_number () const;
253 bool is_inexact () const;
254 bool is_negative () const;
256 status_t get_status () const { return status; }
257 class_t get_class () const { return fp_class; }
259 // Conversions to integers.
260 virtual void integer (int&, round_mode_t = round_default);
261 virtual void integer (long&, round_mode_t = round_default);
262 virtual void integer (long long&, round_mode_t = round_default);
263 virtual void integer (unsigned int&, round_mode_t = round_default);
264 virtual void integer (unsigned long&, round_mode_t = round_default);
265 virtual void integer (unsigned long long&, round_mode_t = round_default);
267 // Pack an fp into registers of various sizes.
268 void pack (cgen::SF&) const;
269 void pack (cgen::DF&) const;
270 void pack (cgen::SF& upper, cgen::SF& lower) const;
272 virtual host_int_8 qnan_exponent (bool double_p) const
274 return EXPMAX (double_p);
277 virtual host_int_8 qnan_fraction (bool double_p) const
279 // Force fraction to correct class.
280 host_int_8 frac = fraction;
281 frac >>= NR_GUARDS (double_p);
286 virtual host_int_8 snan_exponent (bool double_p) const
288 return EXPMAX (double_p);
291 virtual host_int_8 snan_fraction (bool double_p) const
293 // Force fraction to correct class.
294 host_int_8 frac = fraction;
295 frac >>= NR_GUARDS (double_p);
300 virtual bool is_qnan_fraction (host_int_8 frac, bool double_p) const { return frac >= QUIET_NAN; }
302 // Round an fp suitable for packing.
303 void round_32 (round_mode_t = round_default, enum denorm_t = denorm_default);
304 void round_64 (round_mode_t = round_default, enum denorm_t = denorm_default);
306 template <typename T> static fp from_int (T i);
307 template <typename T> static fp from_uint (T u);
309 static fp max (const fp& l, const fp& r);
310 static fp min (const fp& l, const fp& r);
311 static fp neg (const fp& f);
312 static fp abs (const fp& f);
313 static fp inv (const fp& f);
314 static fp sqrt (const fp& f);
316 // Status codes (can be bitwise ORed).
329 invalid_sqrt = 0x200,
339 enum class_t fp_class;
344 virtual void do_round (bool double_p, round_mode_t round, enum denorm_t denorm);
345 virtual status_t do_normal_round (int nr_guards, enum round_mode_t round);
346 virtual status_t do_normal_overflow (bool double_p, enum round_mode_t round);
347 virtual status_t do_normal_underflow (bool double_p, enum round_mode_t round);
349 void int_to_fp (cgen::SI i);
350 void uint_to_fp (cgen::USI i);
351 template <typename T> void fp_to_int (T& t, round_mode_t round);
352 template <typename T> void fp_to_uint (T& t);
353 template <typename T> void unpack (const T& t);
354 template <typename T> void pack_any (T& t) const;
357 fp operator+ (const fp& r) const;
358 fp operator- (const fp& r) const;
359 fp operator* (const fp& r) const;
360 fp operator/ (const fp& r) const;
362 bool operator< (const fp& r) const;
363 bool operator<= (const fp& r) const;
364 bool operator== (const fp& r) const;
365 bool operator!= (const fp& r) const;
366 bool operator>= (const fp& r) const;
367 bool operator> (const fp& r) const;
369 friend std::ostream& operator<< (std::ostream& out, const fp& f);
372 std::ostream& operator<< (std::ostream& op, const fp& f);
374 // A number of useful constants.
375 extern const fp constant_zero;
376 extern const fp constant_one;
377 extern const fp constant_two;
378 extern const fp constant_qnan;
379 extern const fp constant_max32;
380 extern const fp constant_max64;
385 return fp_class == class_qnan || fp_class == class_snan;
391 return fp_class == class_snan;
397 return fp_class == class_qnan;
403 return fp_class == class_zero;
407 fp::is_infinity () const
409 return fp_class == class_infinity;
413 fp::is_number () const
415 return fp_class == class_denorm || fp_class == class_number;
419 fp::is_negative () const
421 return (is_number () || is_zero ()) && sign;
425 fp::is_inexact () const
427 return status == inexact;
431 fp::is_denorm () const
433 return fp_class == class_denorm;
437 fp::pack (cgen::SF& sf) const
443 fp::pack (cgen::DF& df) const
449 fp::pack (cgen::SF& high, cgen::SF& low) const
451 sid::host_int_8 temp = high;
452 temp = (temp << 32) | low;
456 template <typename T>
465 template <typename T>