OSDN Git Service

2008-11-07 Frank Ch. Eigler <fche@redhat.com>
[pf3gnuchains/pf3gnuchains4x.git] / sid / component / cgen-cpu / fp.h
1 // fp.h - Floating point number class using host integer ops.  -*- C++ -*-
2
3 // Copyright 1997, 1998, 2002, 2005, 2006 Free Software Foundation, Inc.
4 // Copyright 2002 Red Hat, Inc.
5 // This file is part of SID.
6
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)
10 // any later version.
11
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.
16
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.  */
20
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.
23
24 #ifndef FP_H
25 #define FP_H
26
27 #include <stdlib.h>
28 #include "sidtypes.h"
29 #include "cgen-types.h"
30
31 using sid::host_int_4;
32 using sid::host_int_8;
33 using sid::signed_host_int_8;
34
35 // XXX: more of this cruft should be C++-ed.
36
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))
49
50 #if (WITH_TARGET_WORD_MSB == 0)
51 #define _LSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS)
52 #else
53 #define _LSB_SHIFT(WIDTH, POS) (POS)
54 #endif
55
56 #if (WITH_TARGET_WORD_MSB == 0)
57 #define _MSB_SHIFT(WIDTH, POS) (POS)
58 #else
59 #define _MSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS)
60 #endif
61
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))
66
67 #if (WITH_TARGET_WORD_MSB == 0)
68 #define _LSB_POS(WIDTH, SHIFT) (WIDTH - 1 - SHIFT)
69 #else
70 #define _LSB_POS(WIDTH, SHIFT) (SHIFT)
71 #endif
72
73 #define _LSMASK64(WIDTH, FIRST, LAST) _MASK64 (WIDTH, \
74                                              _LSB_POS (WIDTH, FIRST), \
75                                              _LSB_POS (WIDTH, LAST))
76
77 #define LSMASK64(FIRST, LAST)  _LSMASK64 (64, (FIRST), (LAST))
78
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)
83
84 #define PADMASK    LSMASK64 (NR_PADS (double_p) - 1, 0)
85
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;
98
99 static inline
100 signed_host_int_8 MAX_INT32 ()
101 {
102   return LSMASK64 (30, 0);
103 }
104
105 static inline
106 signed_host_int_8 MIN_INT32 ()
107 {
108   return LSMASK64 (63, 31);
109 }
110
111 static inline
112 signed_host_int_8 MAX_INT64 ()
113 {
114   return LSMASK64 (62, 0);
115 }
116
117 static inline
118 signed_host_int_8 MIN_INT64 ()
119 {
120   return LSMASK64 (63, 63);
121 }
122
123 static inline
124 unsigned EXPMAX (bool double_p)
125 {
126   return double_p ? EXPMAX64 : EXPMAX32;
127
128
129 static inline
130 int EXPBIAS (bool double_p)
131 {
132   return double_p ? EXPBIAS64 : EXPBIAS32;
133 }
134
135 static inline
136 int NR_GUARDS (bool double_p)
137 {
138   return double_p ? NR_GUARDS64 : NR_GUARDS32;
139 }
140
141 static inline
142 int NR_PADS (bool double_p)
143 {
144   return double_p ? NR_PAD64 : NR_PAD32;
145 }
146
147 static inline
148 int NR_EXPBITS (bool double_p)
149 {
150   return double_p ? 11 : 8;
151 }
152
153 static inline
154 int NR_FRACBITS (bool double_p)
155 {
156   return double_p ? 52 : 23;
157 }
158
159 static inline
160 int NR_INTBITS (bool is_64bit)
161 {
162   return is_64bit ? 64 : 32;
163 }
164
165 static inline
166 host_int_8 LSBIT64 (int pos)
167 {
168   return host_int_8 (1) << pos;
169 }
170
171 static inline
172 host_int_8 MSBIT64 (int pos)
173 {
174   return host_int_8 (1) << (64 - 1 - pos);
175 }
176
177 static inline
178 host_int_8 SIGNBIT (bool double_p)
179 {
180   return double_p ? MSBIT64 (0) : MSBIT64 (32);
181 }
182
183 namespace sidutil
184 {
185   class fp
186     {
187     public:
188       typedef int status_t;
189       typedef int exp_t;
190       typedef sid::host_int_8 fraction_t;
191       
192       enum round_mode_t
193         {
194           round_default,
195           round_near,
196           round_zero,
197           round_up,
198           round_down
199         };
200       
201       enum denorm_t
202         {
203           denorm_default,
204           denorm_underflow_inexact,
205           denorm_zero
206         };
207       
208       enum class_t
209         {
210           class_zero,
211           class_snan,
212           class_qnan,
213           class_number,
214           class_denorm,
215           class_infinity
216         };
217
218       // Type thrown by operators.
219       class error
220       {
221       public:
222         error (fp::status_t s) :status (s) {}
223         operator int() { return static_cast<int> (status); }
224       private:
225         fp::status_t status;
226       };
227
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);
232
233       fp ()
234         :status (ok), fp_class (class_zero), sign (0), fraction (0), normal_exp (0) {}
235       fp (enum class_t c)
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) {}
239
240       // Is this fp NaN?
241       bool is_nan () const;
242
243       // Is this fp a signalling NaN?
244       bool is_snan () const;
245       
246       // Is this fp a quiet NaN?
247       bool is_qnan () const;
248
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;
255
256       status_t get_status () const { return status; }
257       class_t get_class () const { return fp_class; }
258
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);
266
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;
271
272       virtual host_int_8 qnan_exponent (bool double_p) const
273       {
274         return EXPMAX (double_p);
275       }
276
277       virtual host_int_8 qnan_fraction (bool double_p) const
278       {
279         // Force fraction to correct class.
280         host_int_8 frac = fraction;
281         frac >>= NR_GUARDS (double_p);
282         frac |= QUIET_NAN;
283         return frac;
284       }
285
286       virtual host_int_8 snan_exponent (bool double_p) const
287       {
288         return EXPMAX (double_p);
289       }
290
291       virtual host_int_8 snan_fraction (bool double_p) const
292       {
293         // Force fraction to correct class.
294         host_int_8 frac = fraction;
295         frac >>= NR_GUARDS (double_p);
296         frac &= ~QUIET_NAN;
297         return frac;
298       }
299
300       virtual bool is_qnan_fraction (host_int_8 frac, bool double_p) const { return frac >= QUIET_NAN; }
301
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);
305
306       template <typename T> static fp from_int (T i);
307       template <typename T> static fp from_uint (T u);
308
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);
315
316       // Status codes (can be bitwise ORed).
317       enum
318         {
319           ok = 0x0,
320           invalid_snan = 0x1,
321           invalid_qnan = 0x2,
322           invalid_isi = 0x4,
323           invalid_idi = 0x8,
324           invalid_zdz = 0x10,
325           invalid_imz = 0x20,
326           invalid_cvi = 0x40,
327           invalid_div0 = 0x80,
328           invalid_cmp = 0x100,
329           invalid_sqrt = 0x200,
330           rounded = 0x400,
331           inexact = 0x800,
332           overflow = 0x1000,
333           underflow = 0x2000,
334           denorm = 0x4000
335         };
336
337     protected:
338       status_t status;
339       enum class_t fp_class;
340       int sign;
341       fraction_t fraction;
342       exp_t normal_exp;
343
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);
348
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;
355
356     public:
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;
361
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;
368
369       friend std::ostream& operator<< (std::ostream& out, const fp& f);
370     };
371
372   std::ostream& operator<< (std::ostream& op, const fp& f);
373   
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;
381
382   inline bool
383   fp::is_nan () const 
384     {
385       return fp_class == class_qnan || fp_class == class_snan;
386     }
387
388   inline bool
389   fp::is_snan () const
390     {
391       return fp_class == class_snan;
392     }
393
394   inline bool
395   fp::is_qnan () const
396     {
397       return fp_class == class_qnan;
398     }
399
400   inline bool
401   fp::is_zero () const
402     {
403       return fp_class == class_zero;
404     }
405
406   inline bool
407   fp::is_infinity () const
408     {
409       return fp_class == class_infinity;
410     }
411
412   inline bool
413   fp::is_number () const
414     {
415       return fp_class == class_denorm || fp_class == class_number;
416     }
417
418   inline bool
419   fp::is_negative () const
420     {
421       return (is_number () || is_zero ()) && sign;
422     }
423
424   inline bool
425   fp::is_inexact () const
426     {
427       return status == inexact;
428     }
429
430   inline bool
431   fp::is_denorm () const
432     {
433       return fp_class == class_denorm;
434     }
435
436   inline void
437   fp::pack (cgen::SF& sf) const
438     { 
439       pack_any (sf);
440     }
441
442   inline void
443   fp::pack (cgen::DF& df) const
444     {
445       pack_any (df);
446     }
447
448   inline void
449   fp::pack (cgen::SF& high, cgen::SF& low) const
450     {
451       sid::host_int_8 temp = high;
452       temp = (temp << 32) | low;
453       pack_any (temp);
454     }
455
456   template <typename T>
457   fp
458   fp::from_int (T i)
459   {
460     fp f;
461     f.int_to_fp (i);
462     return f;
463   }
464   
465   template <typename T>
466   fp
467   fp::from_uint (T u)
468   {
469     fp f;
470     f.uint_to_fp (u);
471     return f;
472   }
473 };
474
475 #endif // FP_H