1 // $Id: long.h,v 1.25 2004/02/17 10:34:43 elliott-oss Exp $ -*- c++ -*-
2 //
3 // This software is subject to the terms of the IBM Jikes Compiler
4 // License Agreement available at the following URL:
5 // http://ibm.com/developerworks/opensource/jikes.
6 // Copyright (C) 1996, 2003 IBM Corporation and others.  All Rights Reserved.
7 // You must accept the terms of that agreement to use this software.
8 //
9 
10 #ifndef long_INCLUDED
11 #define long_INCLUDED
12 
13 #include "platform.h"
14 
15 #ifdef HAVE_JIKES_NAMESPACE
16 namespace Jikes { // Open namespace Jikes block
17 #endif
18 
19 class IEEEdouble;
20 class IEEEfloat;
21 
22 class LongInt;
23 class ULongInt;
24 
25 class Int
26 {
27 public:
28     // Max value of i4
MAX_INT()29     static inline const i4 MAX_INT()
30     {
31         return 0x7FFFFFFF;
32     }
33 
34     // Min value of i4
MIN_INT()35     static inline const i4 MIN_INT()
36     {
37         return 0x80000000;
38     }
39 };
40 
41 class BaseLong
42 {
43 protected:
44     enum
45     {
46         SHORT_MASK = 0xFFFF, // mask for lower half of i4
47         SIGN_BIT = 0x80000000 // sign bit
48     };
49 
50     union
51     {
52         double double_value;
53 #ifndef HAVE_64BIT_TYPES
54         u4 word[2];
55 #else
56         u8 words;
57 #endif // HAVE_64BIT_TYPES
58     } value;
59 
60     // Set the high word only. Does not modify the low word!
setHighWord(u4 high)61     inline void setHighWord(u4 high)
62     {
63 #ifndef HAVE_64BIT_TYPES
64 # ifndef WORDS_BIGENDIAN
65         value.word[1] = high;
66 # else
67         value.word[0] = high;
68 # endif
69 #else
70         setHighAndLowWords(high, LowWord());
71 #endif // HAVE_64BIT_TYPES
72     }
73 
74     // Set the low word only. Does not modify the high word!
setLowWord(u4 low)75     inline void setLowWord(u4 low)
76     {
77 #ifndef HAVE_64BIT_TYPES
78 # ifndef WORDS_BIGENDIAN
79         value.word[0] = low;
80 # else
81         value.word[1] = low;
82 # endif
83 #else
84         setHighAndLowWords(HighWord(), low);
85 #endif // HAVE_64BIT_TYPES
86     }
87 
88     // Set the value for both words.
setHighAndLowWords(u4 high,u4 low)89     inline void setHighAndLowWords(u4 high, u4 low)
90     {
91 #ifndef HAVE_64BIT_TYPES
92 # ifndef WORDS_BIGENDIAN
93         value.word[1] = high;
94         value.word[0] = low;
95 # else
96         value.word[0] = high;
97         value.word[1] = low;
98 # endif
99 #else
100         value.words = (((u8) high) << 32) | low;
101 #endif // HAVE_64BIT_TYPES
102     }
103 
104     // Set the value for both words.
setHighAndLowWords(const BaseLong & op)105     inline void setHighAndLowWords(const BaseLong& op)
106     {
107 #ifndef HAVE_64BIT_TYPES
108         value.word[0] = op.value.word[0];
109         value.word[1] = op.value.word[1];
110 #else
111         value.words = op.value.words;
112 #endif // HAVE_64BIT_TYPES
113     }
114 
115 public:
116 
117 #ifndef HAVE_64BIT_TYPES
118 # ifndef WORDS_BIGENDIAN
HighWord()119     inline u4 HighWord() const { return value.word[1]; }
LowWord()120     inline u4 LowWord() const { return value.word[0]; }
121 # else
122     inline u4 HighWord() const { return value.word[0]; }
123     inline u4 LowWord() const { return value.word[1]; }
124 # endif
125 #else
126     inline u4 HighWord() const { return (u4) (value.words >> 32); }
127     inline u4 LowWord() const { return (u4) value.words; }
128     inline u8 Words() const { return value.words; }
129 #endif // HAVE_64BIT_TYPES
130 
DoubleView()131     double DoubleView() const { return value.double_value; }
132 
133     BaseLong(u4 high, u4 low);
134     BaseLong(u4 a); // no sign extension
135     BaseLong(i4 a); // sign extends
136     // Forwarding constructor, if needed, so that BaseLong(0) works.
137 #ifndef TYPE_I4_IS_INT
BaseLong(int i)138     inline BaseLong(int i) { *this = BaseLong((i4) i); }
139 #endif // TYPE_I4_IS_INT
BaseLong()140     inline BaseLong() {} // construct without initializing
141 #ifdef HAVE_64BIT_TYPES
BaseLong(u8 a)142     inline BaseLong(u8 a) { value.words = a; } // construct in one step
143 #endif // HAVE_64BIT_TYPES
144 
145     BaseLong operator+(const BaseLong) const; // binary addition
146     BaseLong operator+() const;     // unary plus
147     BaseLong& operator+=(const BaseLong); // add and assign
148     BaseLong operator++(int);      // postfix increment
149     BaseLong operator++();     // prefix increment
150 
151     BaseLong operator-(const BaseLong) const; // binary subtraction
152     BaseLong operator-() const;     // unary minus
153     BaseLong& operator-=(const BaseLong); // subtract and assign
154     BaseLong operator--(int);      // postfix decrement
155     BaseLong operator--();     // prefix decrement
156 
157     BaseLong operator*(const BaseLong) const; // multiplication
158     BaseLong& operator*=(const BaseLong); // multiply and assign
159 
160     //
161     // NOTE: To match the JLS, mask the argument with
162     // Semantic::LONG_SHIFT_MASK (0x3f)
163     //
164     BaseLong operator<<(int) const;      // left shift
165     BaseLong& operator<<=(int);      // left shift and assign
166 
167     bool operator==(const BaseLong) const; // equal
168     bool operator!=(const BaseLong) const; // not equal
169     bool operator!() const;     // logical complement
170 
171     BaseLong operator~() const;     // bitwise complement
172     BaseLong operator^(const BaseLong) const; // bitwise XOR
173     BaseLong& operator^=(const BaseLong); // bitwise XOR and assign
174     BaseLong operator|(const BaseLong) const; // bitwise OR
175     BaseLong& operator|=(const BaseLong); // bitwise OR and assign
176     BaseLong operator&(const BaseLong) const; // bitwise AND
177     BaseLong& operator&=(const BaseLong); // bitwise AND and assign
178 
179     bool operator&&(const BaseLong) const; // logical AND (not short-circuit)
180     bool operator||(const BaseLong) const; // logical OR (not short circuit)
181 
182     static void Divide(const BaseLong&, const BaseLong&, BaseLong&, BaseLong&);
183 
184     operator LongInt() const;          // Cast to LongInt
185     operator ULongInt() const;         // Cast to ULongInt
186 
187     // mirrors java.lang.Long, useful in hashing
hashCode()188     inline i4 hashCode() const { return HighWord() ^ LowWord(); }
189 };
190 
191 
192 class LongInt : public BaseLong
193 {
194 public:
195 
LongInt(u4 a,u4 b)196     inline LongInt(u4 a, u4 b) : BaseLong(a, b) {}
LongInt(u4 a)197     inline LongInt(u4 a) : BaseLong(a) {} // no sign extension
LongInt(i4 a)198     inline LongInt(i4 a) : BaseLong(a) {} // sign extends
199     // Forwarding constructor, if needed, so that LongInt(0) works.
200 #ifndef TYPE_I4_IS_INT
LongInt(int i)201     inline LongInt(int i) { *this = LongInt((i4) i); }
202 #endif // TYPE_I4_IS_INT
203 #ifdef HAVE_EXPLICIT
204     explicit
205 #endif
LongInt(const BaseLong & a)206              inline LongInt(const BaseLong& a) : BaseLong(a) {}
LongInt()207     inline LongInt() : BaseLong() {} // uninitialized
208     // narrowing conversion of double to long
209 #ifdef HAVE_EXPLICIT
210     explicit
211 #endif
212              LongInt(const IEEEdouble&);
213 
214 #ifdef HAVE_EXPLICIT
215     explicit
216 #endif
217     LongInt(const IEEEfloat&); // narrowing conversion of float to long
218 
219 #ifdef HAVE_64BIT_TYPES
LongInt(u8 a)220     inline LongInt(u8 a) : BaseLong(a) {} // construct in one step
221 #endif // HAVE_64BIT_TYPES
222 
223     //
224     // These constants are generated when first used.  The memory they
225     // use can be reclaimed with ConstantCleanup().
226     //
MAX_LONG()227     static inline const LongInt MAX_LONG()
228     {
229         return max_long_const ? *max_long_const
230             : *(max_long_const = new LongInt(0x7FFFFFFF, 0xFFFFFFFF));
231     }
MIN_LONG()232     static inline const LongInt MIN_LONG()
233     {
234         return min_long_const ? *min_long_const
235             : *(min_long_const = new LongInt(0x80000000, 0x00000000));
236     }
ConstantCleanup()237     static void ConstantCleanup()
238     {
239         // The explicit casts are there to workaround a MSVC
240         // behaviour which doesn't allow an implicit cast
241         // from const X* to void* for the delete operator.
242         delete (LongInt*) max_long_const;
243         delete (LongInt*) min_long_const;
244     }
245 
246 
247 private:
248     static const LongInt* max_long_const;
249     static const LongInt* min_long_const;
250 
251 public:
252     LongInt operator/(const LongInt) const; // divide
253     LongInt& operator/=(const LongInt); // divide and assign
254 
255     LongInt operator%(const LongInt) const; // modulus
256     LongInt& operator%=(const LongInt); // modulus and assign
257 
258     //
259     // NOTE: To match the JLS, mask the argument with
260     // Semantic::LONG_SHIFT_MASK (0x3f)
261     //
262     LongInt operator>>(int) const;     // right shift
263     LongInt& operator>>=(int);     // right shift and assign
264 
265     bool operator<(const LongInt) const; // less-than
266     bool operator>(const LongInt) const; // greater-than
267     bool operator<=(const LongInt) const; // less-than or equal
268     bool operator>=(const LongInt) const; // greater-than or equal
269 };
270 
271 
272 class ULongInt : public BaseLong
273 {
274 public:
275 
ULongInt(u4 a,u4 b)276     inline ULongInt(u4 a, u4 b) : BaseLong(a, b) {}
ULongInt(u4 a)277     inline ULongInt(u4 a) : BaseLong(a) {} // no sign extension
ULongInt(i4 a)278     inline ULongInt(i4 a) : BaseLong(a) {} // sign extended
279     // Forwarding constructor, if needed, so that ULongInt(0) works.
280 #ifndef TYPE_I4_IS_INT
ULongInt(int i)281     inline ULongInt(int i) { *this = ULongInt((i4) i); }
282 #endif // TYPE_I4_IS_INT
ULongInt()283     inline ULongInt() : BaseLong() {} // uninitialized
284 #ifdef HAVE_64BIT_TYPES
ULongInt(u8 a)285     inline ULongInt(u8 a) : BaseLong(a) {} // construct in one step
286 #endif // HAVE_64BIT_TYPES
287 
288     ULongInt operator/(const ULongInt) const; // divide
289     ULongInt& operator/=(const ULongInt); // divide and assign
290 
291     ULongInt operator%(const ULongInt) const; // modulus
292     ULongInt& operator%=(const ULongInt); // modulus and assign
293 
294     //
295     // NOTE: To match the JLS, mask the argument with
296     // Semantic::LONG_SHIFT_MASK (0x3f)
297     //
298     ULongInt operator>>(int) const;      // right shift
299     ULongInt& operator>>=(int);      // right shift and assign
300 
301     bool operator<(const ULongInt) const; // less-than
302     bool operator>(const ULongInt) const; // greater-than
303     bool operator<=(const ULongInt) const; // less-than or equal
304     bool operator>=(const ULongInt) const; // greater-than or equal
305 };
306 
307 #ifdef HAVE_JIKES_NAMESPACE
308 } // Close namespace Jikes block
309 #endif
310 
311 #endif // long_INCLUDED
312