1 // Copyright 2015, VIXL authors 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are met: 6 // 7 // * Redistributions of source code must retain the above copyright notice, 8 // this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above copyright notice, 10 // this list of conditions and the following disclaimer in the documentation 11 // and/or other materials provided with the distribution. 12 // * Neither the name of ARM Limited nor the names of its contributors may be 13 // used to endorse or promote products derived from this software without 14 // specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND 17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27 #ifndef VIXL_UTILS_H 28 #define VIXL_UTILS_H 29 30 #include <cmath> 31 #include <cstring> 32 #include <vector> 33 34 #include "compiler-intrinsics-vixl.h" 35 #include "globals-vixl.h" 36 37 namespace vixl { 38 39 // Macros for compile-time format checking. 40 #if GCC_VERSION_OR_NEWER(4, 4, 0) 41 #define PRINTF_CHECK(format_index, varargs_index) \ 42 __attribute__((format(gnu_printf, format_index, varargs_index))) 43 #else 44 #define PRINTF_CHECK(format_index, varargs_index) 45 #endif 46 47 #ifdef __GNUC__ 48 #define VIXL_HAS_DEPRECATED_WITH_MSG 49 #elif defined(__clang__) 50 #ifdef __has_extension(attribute_deprecated_with_message) 51 #define VIXL_HAS_DEPRECATED_WITH_MSG 52 #endif 53 #endif 54 55 #ifdef VIXL_HAS_DEPRECATED_WITH_MSG 56 #define VIXL_DEPRECATED(replaced_by, declarator) \ 57 __attribute__((deprecated("Use \"" replaced_by "\" instead"))) declarator 58 #else 59 #define VIXL_DEPRECATED(replaced_by, declarator) declarator 60 #endif 61 62 #ifdef VIXL_DEBUG 63 #define VIXL_UNREACHABLE_OR_FALLTHROUGH() VIXL_UNREACHABLE() 64 #else 65 #define VIXL_UNREACHABLE_OR_FALLTHROUGH() VIXL_FALLTHROUGH() 66 #endif 67 68 // Check number width. 69 // TODO: Refactor these using templates. 70 inline bool IsIntN(unsigned n, uint32_t x) { 71 VIXL_ASSERT((0 < n) && (n < 32)); 72 uint32_t limit = UINT32_C(1) << (n - 1); 73 return x < limit; 74 } 75 inline bool IsIntN(unsigned n, int32_t x) { 76 VIXL_ASSERT((0 < n) && (n < 32)); 77 int32_t limit = INT32_C(1) << (n - 1); 78 return (-limit <= x) && (x < limit); 79 } 80 inline bool IsIntN(unsigned n, uint64_t x) { 81 VIXL_ASSERT((0 < n) && (n < 64)); 82 uint64_t limit = UINT64_C(1) << (n - 1); 83 return x < limit; 84 } 85 inline bool IsIntN(unsigned n, int64_t x) { 86 VIXL_ASSERT((0 < n) && (n < 64)); 87 int64_t limit = INT64_C(1) << (n - 1); 88 return (-limit <= x) && (x < limit); 89 } 90 VIXL_DEPRECATED("IsIntN", inline bool is_intn(unsigned n, int64_t x)) { 91 return IsIntN(n, x); 92 } 93 94 inline bool IsUintN(unsigned n, uint32_t x) { 95 VIXL_ASSERT((0 < n) && (n < 32)); 96 return !(x >> n); 97 } 98 inline bool IsUintN(unsigned n, int32_t x) { 99 VIXL_ASSERT((0 < n) && (n < 32)); 100 // Convert to an unsigned integer to avoid implementation-defined behavior. 101 return !(static_cast<uint32_t>(x) >> n); 102 } 103 inline bool IsUintN(unsigned n, uint64_t x) { 104 VIXL_ASSERT((0 < n) && (n < 64)); 105 return !(x >> n); 106 } 107 inline bool IsUintN(unsigned n, int64_t x) { 108 VIXL_ASSERT((0 < n) && (n < 64)); 109 // Convert to an unsigned integer to avoid implementation-defined behavior. 110 return !(static_cast<uint64_t>(x) >> n); 111 } 112 VIXL_DEPRECATED("IsUintN", inline bool is_uintn(unsigned n, int64_t x)) { 113 return IsUintN(n, x); 114 } 115 116 inline uint64_t TruncateToUintN(unsigned n, uint64_t x) { 117 VIXL_ASSERT((0 < n) && (n < 64)); 118 return static_cast<uint64_t>(x) & ((UINT64_C(1) << n) - 1); 119 } 120 VIXL_DEPRECATED("TruncateToUintN", 121 inline uint64_t truncate_to_intn(unsigned n, int64_t x)) { 122 return TruncateToUintN(n, x); 123 } 124 125 // clang-format off 126 #define INT_1_TO_32_LIST(V) \ 127 V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) \ 128 V(9) V(10) V(11) V(12) V(13) V(14) V(15) V(16) \ 129 V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) \ 130 V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32) 131 132 #define INT_33_TO_63_LIST(V) \ 133 V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \ 134 V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) \ 135 V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56) \ 136 V(57) V(58) V(59) V(60) V(61) V(62) V(63) 137 138 #define INT_1_TO_63_LIST(V) INT_1_TO_32_LIST(V) INT_33_TO_63_LIST(V) 139 140 // clang-format on 141 142 #define DECLARE_IS_INT_N(N) \ 143 inline bool IsInt##N(int64_t x) { return IsIntN(N, x); } \ 144 VIXL_DEPRECATED("IsInt" #N, inline bool is_int##N(int64_t x)) { \ 145 return IsIntN(N, x); \ 146 } 147 148 #define DECLARE_IS_UINT_N(N) \ 149 inline bool IsUint##N(int64_t x) { return IsUintN(N, x); } \ 150 VIXL_DEPRECATED("IsUint" #N, inline bool is_uint##N(int64_t x)) { \ 151 return IsUintN(N, x); \ 152 } 153 154 #define DECLARE_TRUNCATE_TO_UINT_32(N) \ 155 inline uint32_t TruncateToUint##N(uint64_t x) { \ 156 return static_cast<uint32_t>(TruncateToUintN(N, x)); \ 157 } \ 158 VIXL_DEPRECATED("TruncateToUint" #N, \ 159 inline uint32_t truncate_to_int##N(int64_t x)) { \ 160 return TruncateToUint##N(x); \ 161 } 162 163 INT_1_TO_63_LIST(DECLARE_IS_INT_N) 164 INT_1_TO_63_LIST(DECLARE_IS_UINT_N) 165 INT_1_TO_32_LIST(DECLARE_TRUNCATE_TO_UINT_32) 166 167 #undef DECLARE_IS_INT_N 168 #undef DECLARE_IS_UINT_N 169 #undef DECLARE_TRUNCATE_TO_INT_N 170 171 // Bit field extraction. 172 inline uint64_t ExtractUnsignedBitfield64(int msb, int lsb, uint64_t x) { 173 VIXL_ASSERT((static_cast<size_t>(msb) < sizeof(x) * 8) && (lsb >= 0) && 174 (msb >= lsb)); 175 if ((msb == 63) && (lsb == 0)) return x; 176 return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1); 177 } 178 179 180 inline uint32_t ExtractUnsignedBitfield32(int msb, int lsb, uint32_t x) { 181 VIXL_ASSERT((static_cast<size_t>(msb) < sizeof(x) * 8) && (lsb >= 0) && 182 (msb >= lsb)); 183 return TruncateToUint32(ExtractUnsignedBitfield64(msb, lsb, x)); 184 } 185 186 187 inline int64_t ExtractSignedBitfield64(int msb, int lsb, int64_t x) { 188 VIXL_ASSERT((static_cast<size_t>(msb) < sizeof(x) * 8) && (lsb >= 0) && 189 (msb >= lsb)); 190 uint64_t temp = ExtractUnsignedBitfield64(msb, lsb, x); 191 // If the highest extracted bit is set, sign extend. 192 if ((temp >> (msb - lsb)) == 1) { 193 temp |= ~UINT64_C(0) << (msb - lsb); 194 } 195 int64_t result; 196 memcpy(&result, &temp, sizeof(result)); 197 return result; 198 } 199 200 201 inline int32_t ExtractSignedBitfield32(int msb, int lsb, int32_t x) { 202 VIXL_ASSERT((static_cast<size_t>(msb) < sizeof(x) * 8) && (lsb >= 0) && 203 (msb >= lsb)); 204 uint32_t temp = TruncateToUint32(ExtractSignedBitfield64(msb, lsb, x)); 205 int32_t result; 206 memcpy(&result, &temp, sizeof(result)); 207 return result; 208 } 209 210 211 inline uint64_t RotateRight(uint64_t value, 212 unsigned int rotate, 213 unsigned int width) { 214 VIXL_ASSERT((width > 0) && (width <= 64)); 215 uint64_t width_mask = ~UINT64_C(0) >> (64 - width); 216 rotate &= 63; 217 if (rotate > 0) { 218 value &= width_mask; 219 value = (value << (width - rotate)) | (value >> rotate); 220 } 221 return value & width_mask; 222 } 223 224 225 // Floating point representation. 226 uint32_t FloatToRawbits(float value); 227 VIXL_DEPRECATED("FloatToRawbits", 228 inline uint32_t float_to_rawbits(float value)) { 229 return FloatToRawbits(value); 230 } 231 232 uint64_t DoubleToRawbits(double value); 233 VIXL_DEPRECATED("DoubleToRawbits", 234 inline uint64_t double_to_rawbits(double value)) { 235 return DoubleToRawbits(value); 236 } 237 238 float RawbitsToFloat(uint32_t bits); 239 VIXL_DEPRECATED("RawbitsToFloat", 240 inline float rawbits_to_float(uint32_t bits)) { 241 return RawbitsToFloat(bits); 242 } 243 244 double RawbitsToDouble(uint64_t bits); 245 VIXL_DEPRECATED("RawbitsToDouble", 246 inline double rawbits_to_double(uint64_t bits)) { 247 return RawbitsToDouble(bits); 248 } 249 250 uint32_t FloatSign(float value); 251 VIXL_DEPRECATED("FloatSign", inline uint32_t float_sign(float value)) { 252 return FloatSign(value); 253 } 254 255 uint32_t FloatExp(float value); 256 VIXL_DEPRECATED("FloatExp", inline uint32_t float_exp(float value)) { 257 return FloatExp(value); 258 } 259 260 uint32_t FloatMantissa(float value); 261 VIXL_DEPRECATED("FloatMantissa", inline uint32_t float_mantissa(float value)) { 262 return FloatMantissa(value); 263 } 264 265 uint32_t DoubleSign(double value); 266 VIXL_DEPRECATED("DoubleSign", inline uint32_t double_sign(double value)) { 267 return DoubleSign(value); 268 } 269 270 uint32_t DoubleExp(double value); 271 VIXL_DEPRECATED("DoubleExp", inline uint32_t double_exp(double value)) { 272 return DoubleExp(value); 273 } 274 275 uint64_t DoubleMantissa(double value); 276 VIXL_DEPRECATED("DoubleMantissa", 277 inline uint64_t double_mantissa(double value)) { 278 return DoubleMantissa(value); 279 } 280 281 float FloatPack(uint32_t sign, uint32_t exp, uint32_t mantissa); 282 VIXL_DEPRECATED("FloatPack", 283 inline float float_pack(uint32_t sign, 284 uint32_t exp, 285 uint32_t mantissa)) { 286 return FloatPack(sign, exp, mantissa); 287 } 288 289 double DoublePack(uint64_t sign, uint64_t exp, uint64_t mantissa); 290 VIXL_DEPRECATED("DoublePack", 291 inline double double_pack(uint32_t sign, 292 uint32_t exp, 293 uint64_t mantissa)) { 294 return DoublePack(sign, exp, mantissa); 295 } 296 297 // An fpclassify() function for 16-bit half-precision floats. 298 int Float16Classify(float16 value); 299 VIXL_DEPRECATED("Float16Classify", inline int float16classify(float16 value)) { 300 return Float16Classify(value); 301 } 302 303 // NaN tests. 304 inline bool IsSignallingNaN(double num) { 305 const uint64_t kFP64QuietNaNMask = UINT64_C(0x0008000000000000); 306 uint64_t raw = DoubleToRawbits(num); 307 if (std::isnan(num) && ((raw & kFP64QuietNaNMask) == 0)) { 308 return true; 309 } 310 return false; 311 } 312 313 314 inline bool IsSignallingNaN(float num) { 315 const uint32_t kFP32QuietNaNMask = 0x00400000; 316 uint32_t raw = FloatToRawbits(num); 317 if (std::isnan(num) && ((raw & kFP32QuietNaNMask) == 0)) { 318 return true; 319 } 320 return false; 321 } 322 323 324 inline bool IsSignallingNaN(float16 num) { 325 const uint16_t kFP16QuietNaNMask = 0x0200; 326 return (Float16Classify(num) == FP_NAN) && ((num & kFP16QuietNaNMask) == 0); 327 } 328 329 330 template <typename T> 331 inline bool IsQuietNaN(T num) { 332 return std::isnan(num) && !IsSignallingNaN(num); 333 } 334 335 336 // Convert the NaN in 'num' to a quiet NaN. 337 inline double ToQuietNaN(double num) { 338 const uint64_t kFP64QuietNaNMask = UINT64_C(0x0008000000000000); 339 VIXL_ASSERT(std::isnan(num)); 340 return RawbitsToDouble(DoubleToRawbits(num) | kFP64QuietNaNMask); 341 } 342 343 344 inline float ToQuietNaN(float num) { 345 const uint32_t kFP32QuietNaNMask = 0x00400000; 346 VIXL_ASSERT(std::isnan(num)); 347 return RawbitsToFloat(FloatToRawbits(num) | kFP32QuietNaNMask); 348 } 349 350 351 // Fused multiply-add. 352 inline double FusedMultiplyAdd(double op1, double op2, double a) { 353 return fma(op1, op2, a); 354 } 355 356 357 inline float FusedMultiplyAdd(float op1, float op2, float a) { 358 return fmaf(op1, op2, a); 359 } 360 361 362 inline uint64_t LowestSetBit(uint64_t value) { return value & -value; } 363 364 365 template <typename T> 366 inline int HighestSetBitPosition(T value) { 367 VIXL_ASSERT(value != 0); 368 return (sizeof(value) * 8 - 1) - CountLeadingZeros(value); 369 } 370 371 372 template <typename V> 373 inline int WhichPowerOf2(V value) { 374 VIXL_ASSERT(IsPowerOf2(value)); 375 return CountTrailingZeros(value); 376 } 377 378 379 unsigned CountClearHalfWords(uint64_t imm, unsigned reg_size); 380 381 382 int BitCount(uint64_t value); 383 384 385 template <typename T> 386 T ReverseBits(T value) { 387 VIXL_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || 388 (sizeof(value) == 4) || (sizeof(value) == 8)); 389 T result = 0; 390 for (unsigned i = 0; i < (sizeof(value) * 8); i++) { 391 result = (result << 1) | (value & 1); 392 value >>= 1; 393 } 394 return result; 395 } 396 397 398 template <typename T> 399 inline T SignExtend(T val, int bitSize) { 400 VIXL_ASSERT(bitSize > 0); 401 T mask = (T(2) << (bitSize - 1)) - T(1); 402 val &= mask; 403 T sign = -(val >> (bitSize - 1)); 404 val |= (sign << bitSize); 405 return val; 406 } 407 408 409 template <typename T> 410 T ReverseBytes(T value, int block_bytes_log2) { 411 VIXL_ASSERT((sizeof(value) == 4) || (sizeof(value) == 8)); 412 VIXL_ASSERT((1U << block_bytes_log2) <= sizeof(value)); 413 // Split the 64-bit value into an 8-bit array, where b[0] is the least 414 // significant byte, and b[7] is the most significant. 415 uint8_t bytes[8]; 416 uint64_t mask = UINT64_C(0xff00000000000000); 417 for (int i = 7; i >= 0; i--) { 418 bytes[i] = (static_cast<uint64_t>(value) & mask) >> (i * 8); 419 mask >>= 8; 420 } 421 422 // Permutation tables for REV instructions. 423 // permute_table[0] is used by REV16_x, REV16_w 424 // permute_table[1] is used by REV32_x, REV_w 425 // permute_table[2] is used by REV_x 426 VIXL_ASSERT((0 < block_bytes_log2) && (block_bytes_log2 < 4)); 427 static const uint8_t permute_table[3][8] = {{6, 7, 4, 5, 2, 3, 0, 1}, 428 {4, 5, 6, 7, 0, 1, 2, 3}, 429 {0, 1, 2, 3, 4, 5, 6, 7}}; 430 uint64_t temp = 0; 431 for (int i = 0; i < 8; i++) { 432 temp <<= 8; 433 temp |= bytes[permute_table[block_bytes_log2 - 1][i]]; 434 } 435 436 T result; 437 VIXL_STATIC_ASSERT(sizeof(result) <= sizeof(temp)); 438 memcpy(&result, &temp, sizeof(result)); 439 return result; 440 } 441 442 template <unsigned MULTIPLE, typename T> 443 inline bool IsMultiple(T value) { 444 VIXL_ASSERT(IsPowerOf2(MULTIPLE)); 445 return (value & (MULTIPLE - 1)) == 0; 446 } 447 448 template <typename T> 449 inline bool IsMultiple(T value, unsigned multiple) { 450 VIXL_ASSERT(IsPowerOf2(multiple)); 451 return (value & (multiple - 1)) == 0; 452 } 453 454 // Pointer alignment 455 // TODO: rename/refactor to make it specific to instructions. 456 template <unsigned ALIGN, typename T> 457 inline bool IsAligned(T pointer) { 458 VIXL_ASSERT(sizeof(pointer) == sizeof(intptr_t)); // NOLINT(runtime/sizeof) 459 VIXL_ASSERT(IsPowerOf2(ALIGN)); 460 // Use C-style casts to get static_cast behaviour for integral types (T), and 461 // reinterpret_cast behaviour for other types. 462 return ((intptr_t)(pointer) & (ALIGN - 1)) == 0; 463 } 464 465 template <typename T> 466 bool IsWordAligned(T pointer) { 467 return IsAligned<4>(pointer); 468 } 469 470 // Increment a pointer (up to 64 bits) until it has the specified alignment. 471 template <class T> 472 T AlignUp(T pointer, size_t alignment) { 473 // Use C-style casts to get static_cast behaviour for integral types (T), and 474 // reinterpret_cast behaviour for other types. 475 476 uint64_t pointer_raw = (uint64_t)pointer; 477 VIXL_STATIC_ASSERT(sizeof(pointer) <= sizeof(pointer_raw)); 478 479 size_t align_step = (alignment - pointer_raw) % alignment; 480 VIXL_ASSERT((pointer_raw + align_step) % alignment == 0); 481 482 T result = (T)(pointer_raw + align_step); 483 484 VIXL_ASSERT(result >= pointer); 485 486 return result; 487 } 488 489 // Decrement a pointer (up to 64 bits) until it has the specified alignment. 490 template <class T> 491 T AlignDown(T pointer, size_t alignment) { 492 // Use C-style casts to get static_cast behaviour for integral types (T), and 493 // reinterpret_cast behaviour for other types. 494 495 uint64_t pointer_raw = (uint64_t)pointer; 496 VIXL_STATIC_ASSERT(sizeof(pointer) <= sizeof(pointer_raw)); 497 498 size_t align_step = pointer_raw % alignment; 499 VIXL_ASSERT((pointer_raw - align_step) % alignment == 0); 500 501 return (T)(pointer_raw - align_step); 502 } 503 504 template <typename T> 505 inline T ExtractBit(T value, unsigned bit) { 506 return (value >> bit) & T(1); 507 } 508 509 template <typename Ts, typename Td> 510 inline Td ExtractBits(Ts value, int least_significant_bit, Td mask) { 511 return Td((value >> least_significant_bit) & Ts(mask)); 512 } 513 514 template <typename Ts, typename Td> 515 inline void AssignBit(Td& dst, // NOLINT(runtime/references) 516 int bit, 517 Ts value) { 518 VIXL_ASSERT((value == Ts(0)) || (value == Ts(1))); 519 VIXL_ASSERT(bit >= 0); 520 VIXL_ASSERT(bit < static_cast<int>(sizeof(Td) * 8)); 521 Td mask(1); 522 dst &= ~(mask << bit); 523 dst |= Td(value) << bit; 524 } 525 526 template <typename Td, typename Ts> 527 inline void AssignBits(Td& dst, // NOLINT(runtime/references) 528 int least_significant_bit, 529 Ts mask, 530 Ts value) { 531 VIXL_ASSERT(least_significant_bit >= 0); 532 VIXL_ASSERT(least_significant_bit < static_cast<int>(sizeof(Td) * 8)); 533 VIXL_ASSERT(((Td(mask) << least_significant_bit) >> least_significant_bit) == 534 Td(mask)); 535 VIXL_ASSERT((value & mask) == value); 536 dst &= ~(Td(mask) << least_significant_bit); 537 dst |= Td(value) << least_significant_bit; 538 } 539 540 class VFP { 541 public: 542 static uint32_t FP32ToImm8(float imm) { 543 // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000 544 uint32_t bits = FloatToRawbits(imm); 545 // bit7: a000.0000 546 uint32_t bit7 = ((bits >> 31) & 0x1) << 7; 547 // bit6: 0b00.0000 548 uint32_t bit6 = ((bits >> 29) & 0x1) << 6; 549 // bit5_to_0: 00cd.efgh 550 uint32_t bit5_to_0 = (bits >> 19) & 0x3f; 551 return static_cast<uint32_t>(bit7 | bit6 | bit5_to_0); 552 } 553 static uint32_t FP64ToImm8(double imm) { 554 // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 555 // 0000.0000.0000.0000.0000.0000.0000.0000 556 uint64_t bits = DoubleToRawbits(imm); 557 // bit7: a000.0000 558 uint64_t bit7 = ((bits >> 63) & 0x1) << 7; 559 // bit6: 0b00.0000 560 uint64_t bit6 = ((bits >> 61) & 0x1) << 6; 561 // bit5_to_0: 00cd.efgh 562 uint64_t bit5_to_0 = (bits >> 48) & 0x3f; 563 564 return static_cast<uint32_t>(bit7 | bit6 | bit5_to_0); 565 } 566 static float Imm8ToFP32(uint32_t imm8) { 567 // Imm8: abcdefgh (8 bits) 568 // Single: aBbb.bbbc.defg.h000.0000.0000.0000.0000 (32 bits) 569 // where B is b ^ 1 570 uint32_t bits = imm8; 571 uint32_t bit7 = (bits >> 7) & 0x1; 572 uint32_t bit6 = (bits >> 6) & 0x1; 573 uint32_t bit5_to_0 = bits & 0x3f; 574 uint32_t result = (bit7 << 31) | ((32 - bit6) << 25) | (bit5_to_0 << 19); 575 576 return RawbitsToFloat(result); 577 } 578 static double Imm8ToFP64(uint32_t imm8) { 579 // Imm8: abcdefgh (8 bits) 580 // Double: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 581 // 0000.0000.0000.0000.0000.0000.0000.0000 (64 bits) 582 // where B is b ^ 1 583 uint32_t bits = imm8; 584 uint64_t bit7 = (bits >> 7) & 0x1; 585 uint64_t bit6 = (bits >> 6) & 0x1; 586 uint64_t bit5_to_0 = bits & 0x3f; 587 uint64_t result = (bit7 << 63) | ((256 - bit6) << 54) | (bit5_to_0 << 48); 588 return RawbitsToDouble(result); 589 } 590 static bool IsImmFP32(float imm) { 591 // Valid values will have the form: 592 // aBbb.bbbc.defg.h000.0000.0000.0000.0000 593 uint32_t bits = FloatToRawbits(imm); 594 // bits[19..0] are cleared. 595 if ((bits & 0x7ffff) != 0) { 596 return false; 597 } 598 599 600 // bits[29..25] are all set or all cleared. 601 uint32_t b_pattern = (bits >> 16) & 0x3e00; 602 if (b_pattern != 0 && b_pattern != 0x3e00) { 603 return false; 604 } 605 // bit[30] and bit[29] are opposite. 606 if (((bits ^ (bits << 1)) & 0x40000000) == 0) { 607 return false; 608 } 609 return true; 610 } 611 static bool IsImmFP64(double imm) { 612 // Valid values will have the form: 613 // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 614 // 0000.0000.0000.0000.0000.0000.0000.0000 615 uint64_t bits = DoubleToRawbits(imm); 616 // bits[47..0] are cleared. 617 if ((bits & 0x0000ffffffffffff) != 0) { 618 return false; 619 } 620 // bits[61..54] are all set or all cleared. 621 uint32_t b_pattern = (bits >> 48) & 0x3fc0; 622 if ((b_pattern != 0) && (b_pattern != 0x3fc0)) { 623 return false; 624 } 625 // bit[62] and bit[61] are opposite. 626 if (((bits ^ (bits << 1)) & (UINT64_C(1) << 62)) == 0) { 627 return false; 628 } 629 return true; 630 } 631 }; 632 633 class BitField { 634 // ForEachBitHelper is a functor that will call 635 // bool ForEachBitHelper::execute(ElementType id) const 636 // and expects a boolean in return whether to continue (if true) 637 // or stop (if false) 638 // check_set will check if the bits are on (true) or off(false) 639 template <typename ForEachBitHelper, bool check_set> 640 bool ForEachBit(const ForEachBitHelper& helper) { 641 for (int i = 0; static_cast<size_t>(i) < bitfield_.size(); i++) { 642 if (bitfield_[i] == check_set) 643 if (!helper.execute(i)) return false; 644 } 645 return true; 646 } 647 648 public: 649 explicit BitField(unsigned size) : bitfield_(size, 0) {} 650 651 void Set(int i) { 652 VIXL_ASSERT((i >= 0) && (static_cast<size_t>(i) < bitfield_.size())); 653 bitfield_[i] = true; 654 } 655 656 void Unset(int i) { 657 VIXL_ASSERT((i >= 0) && (static_cast<size_t>(i) < bitfield_.size())); 658 bitfield_[i] = true; 659 } 660 661 bool IsSet(int i) const { return bitfield_[i]; } 662 663 // For each bit not set in the bitfield call the execute functor 664 // execute. 665 // ForEachBitSetHelper::execute returns true if the iteration through 666 // the bits can continue, otherwise it will stop. 667 // struct ForEachBitSetHelper { 668 // bool execute(int /*id*/) { return false; } 669 // }; 670 template <typename ForEachBitNotSetHelper> 671 bool ForEachBitNotSet(const ForEachBitNotSetHelper& helper) { 672 return ForEachBit<ForEachBitNotSetHelper, false>(helper); 673 } 674 675 // For each bit set in the bitfield call the execute functor 676 // execute. 677 template <typename ForEachBitSetHelper> 678 bool ForEachBitSet(const ForEachBitSetHelper& helper) { 679 return ForEachBit<ForEachBitSetHelper, true>(helper); 680 } 681 682 private: 683 std::vector<bool> bitfield_; 684 }; 685 686 typedef int64_t Int64; 687 class Uint64; 688 class Uint128; 689 690 class Uint32 { 691 uint32_t data_; 692 693 public: 694 // Unlike uint32_t, Uint32 has a default constructor. 695 Uint32() { data_ = 0; } 696 explicit Uint32(uint32_t data) : data_(data) {} 697 inline explicit Uint32(Uint64 data); 698 uint32_t Get() const { return data_; } 699 template <int N> 700 int32_t GetSigned() const { 701 return ExtractSignedBitfield32(N - 1, 0, data_); 702 } 703 int32_t GetSigned() const { return data_; } 704 Uint32 operator~() const { return Uint32(~data_); } 705 Uint32 operator-() const { return Uint32(-data_); } 706 bool operator==(Uint32 value) const { return data_ == value.data_; } 707 bool operator!=(Uint32 value) const { return data_ != value.data_; } 708 bool operator>(Uint32 value) const { return data_ > value.data_; } 709 Uint32 operator+(Uint32 value) const { return Uint32(data_ + value.data_); } 710 Uint32 operator-(Uint32 value) const { return Uint32(data_ - value.data_); } 711 Uint32 operator&(Uint32 value) const { return Uint32(data_ & value.data_); } 712 Uint32 operator&=(Uint32 value) { 713 data_ &= value.data_; 714 return *this; 715 } 716 Uint32 operator^(Uint32 value) const { return Uint32(data_ ^ value.data_); } 717 Uint32 operator^=(Uint32 value) { 718 data_ ^= value.data_; 719 return *this; 720 } 721 Uint32 operator|(Uint32 value) const { return Uint32(data_ | value.data_); } 722 Uint32 operator|=(Uint32 value) { 723 data_ |= value.data_; 724 return *this; 725 } 726 // Unlike uint32_t, the shift functions can accept negative shift and 727 // return 0 when the shift is too big. 728 Uint32 operator>>(int shift) const { 729 if (shift == 0) return *this; 730 if (shift < 0) { 731 int tmp = -shift; 732 if (tmp >= 32) return Uint32(0); 733 return Uint32(data_ << tmp); 734 } 735 int tmp = shift; 736 if (tmp >= 32) return Uint32(0); 737 return Uint32(data_ >> tmp); 738 } 739 Uint32 operator<<(int shift) const { 740 if (shift == 0) return *this; 741 if (shift < 0) { 742 int tmp = -shift; 743 if (tmp >= 32) return Uint32(0); 744 return Uint32(data_ >> tmp); 745 } 746 int tmp = shift; 747 if (tmp >= 32) return Uint32(0); 748 return Uint32(data_ << tmp); 749 } 750 }; 751 752 class Uint64 { 753 uint64_t data_; 754 755 public: 756 // Unlike uint64_t, Uint64 has a default constructor. 757 Uint64() { data_ = 0; } 758 explicit Uint64(uint64_t data) : data_(data) {} 759 explicit Uint64(Uint32 data) : data_(data.Get()) {} 760 inline explicit Uint64(Uint128 data); 761 uint64_t Get() const { return data_; } 762 int64_t GetSigned(int N) const { 763 return ExtractSignedBitfield64(N - 1, 0, data_); 764 } 765 int64_t GetSigned() const { return data_; } 766 Uint32 ToUint32() const { 767 VIXL_ASSERT((data_ >> 32) == 0); 768 return Uint32(static_cast<uint32_t>(data_)); 769 } 770 Uint32 GetHigh32() const { return Uint32(data_ >> 32); } 771 Uint32 GetLow32() const { return Uint32(data_ & 0xffffffff); } 772 Uint64 operator~() const { return Uint64(~data_); } 773 Uint64 operator-() const { return Uint64(-data_); } 774 bool operator==(Uint64 value) const { return data_ == value.data_; } 775 bool operator!=(Uint64 value) const { return data_ != value.data_; } 776 Uint64 operator+(Uint64 value) const { return Uint64(data_ + value.data_); } 777 Uint64 operator-(Uint64 value) const { return Uint64(data_ - value.data_); } 778 Uint64 operator&(Uint64 value) const { return Uint64(data_ & value.data_); } 779 Uint64 operator&=(Uint64 value) { 780 data_ &= value.data_; 781 return *this; 782 } 783 Uint64 operator^(Uint64 value) const { return Uint64(data_ ^ value.data_); } 784 Uint64 operator^=(Uint64 value) { 785 data_ ^= value.data_; 786 return *this; 787 } 788 Uint64 operator|(Uint64 value) const { return Uint64(data_ | value.data_); } 789 Uint64 operator|=(Uint64 value) { 790 data_ |= value.data_; 791 return *this; 792 } 793 // Unlike uint64_t, the shift functions can accept negative shift and 794 // return 0 when the shift is too big. 795 Uint64 operator>>(int shift) const { 796 if (shift == 0) return *this; 797 if (shift < 0) { 798 int tmp = -shift; 799 if (tmp >= 64) return Uint64(0); 800 return Uint64(data_ << tmp); 801 } 802 int tmp = shift; 803 if (tmp >= 64) return Uint64(0); 804 return Uint64(data_ >> tmp); 805 } 806 Uint64 operator<<(int shift) const { 807 if (shift == 0) return *this; 808 if (shift < 0) { 809 int tmp = -shift; 810 if (tmp >= 64) return Uint64(0); 811 return Uint64(data_ >> tmp); 812 } 813 int tmp = shift; 814 if (tmp >= 64) return Uint64(0); 815 return Uint64(data_ << tmp); 816 } 817 }; 818 819 class Uint128 { 820 uint64_t data_high_; 821 uint64_t data_low_; 822 823 public: 824 Uint128() : data_high_(0), data_low_(0) {} 825 explicit Uint128(uint64_t data_low) : data_high_(0), data_low_(data_low) {} 826 explicit Uint128(Uint64 data_low) 827 : data_high_(0), data_low_(data_low.Get()) {} 828 Uint128(uint64_t data_high, uint64_t data_low) 829 : data_high_(data_high), data_low_(data_low) {} 830 Uint64 ToUint64() const { 831 VIXL_ASSERT(data_high_ == 0); 832 return Uint64(data_low_); 833 } 834 Uint64 GetHigh64() const { return Uint64(data_high_); } 835 Uint64 GetLow64() const { return Uint64(data_low_); } 836 Uint128 operator~() const { return Uint128(~data_high_, ~data_low_); } 837 bool operator==(Uint128 value) const { 838 return (data_high_ == value.data_high_) && (data_low_ == value.data_low_); 839 } 840 Uint128 operator&(Uint128 value) const { 841 return Uint128(data_high_ & value.data_high_, data_low_ & value.data_low_); 842 } 843 Uint128 operator&=(Uint128 value) { 844 data_high_ &= value.data_high_; 845 data_low_ &= value.data_low_; 846 return *this; 847 } 848 Uint128 operator|=(Uint128 value) { 849 data_high_ |= value.data_high_; 850 data_low_ |= value.data_low_; 851 return *this; 852 } 853 Uint128 operator>>(int shift) const { 854 VIXL_ASSERT((shift >= 0) && (shift < 128)); 855 if (shift == 0) return *this; 856 if (shift >= 64) { 857 return Uint128(0, data_high_ >> (shift - 64)); 858 } 859 uint64_t tmp = (data_high_ << (64 - shift)) | (data_low_ >> shift); 860 return Uint128(data_high_ >> shift, tmp); 861 } 862 Uint128 operator<<(int shift) const { 863 VIXL_ASSERT((shift >= 0) && (shift < 128)); 864 if (shift == 0) return *this; 865 if (shift >= 64) { 866 return Uint128(data_low_ << (shift - 64), 0); 867 } 868 uint64_t tmp = (data_high_ << shift) | (data_low_ >> (64 - shift)); 869 return Uint128(tmp, data_low_ << shift); 870 } 871 }; 872 873 Uint32::Uint32(Uint64 data) : data_(data.ToUint32().Get()) {} 874 Uint64::Uint64(Uint128 data) : data_(data.ToUint64().Get()) {} 875 876 Int64 BitCount(Uint32 value); 877 878 } // namespace vixl 879 880 #endif // VIXL_UTILS_H 881