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