Utils-vixl.h (51048B)
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 <limits> 33 #include <type_traits> 34 #include <vector> 35 36 #include "jit/arm64/vixl/CompilerIntrinsics-vixl.h" 37 #include "jit/arm64/vixl/Globals-vixl.h" 38 39 namespace vixl { 40 41 // Macros for compile-time format checking. 42 #if GCC_VERSION_OR_NEWER(4, 4, 0) 43 #define PRINTF_CHECK(format_index, varargs_index) \ 44 __attribute__((format(gnu_printf, format_index, varargs_index))) 45 #else 46 #define PRINTF_CHECK(format_index, varargs_index) 47 #endif 48 49 #ifdef __has_extension 50 # if __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 template <typename T, size_t n> 69 constexpr size_t ArrayLength(const T (&)[n]) { 70 return n; 71 } 72 73 inline uint64_t GetUintMask(unsigned bits) { 74 VIXL_ASSERT(bits <= 64); 75 uint64_t base = (bits >= 64) ? 0 : (UINT64_C(1) << bits); 76 return base - 1; 77 } 78 79 inline uint64_t GetSignMask(unsigned bits) { 80 VIXL_ASSERT(bits <= 64); 81 return UINT64_C(1) << (bits - 1); 82 } 83 84 // Check number width. 85 // TODO: Refactor these using templates. 86 inline bool IsIntN(unsigned n, uint32_t x) { 87 VIXL_ASSERT((0 < n) && (n <= 32)); 88 return x <= static_cast<uint32_t>(INT32_MAX >> (32 - n)); 89 } 90 inline bool IsIntN(unsigned n, int32_t x) { 91 VIXL_ASSERT((0 < n) && (n <= 32)); 92 if (n == 32) return true; 93 int32_t limit = INT32_C(1) << (n - 1); 94 return (-limit <= x) && (x < limit); 95 } 96 inline bool IsIntN(unsigned n, uint64_t x) { 97 VIXL_ASSERT((0 < n) && (n <= 64)); 98 return x <= static_cast<uint64_t>(INT64_MAX >> (64 - n)); 99 } 100 inline bool IsIntN(unsigned n, int64_t x) { 101 VIXL_ASSERT((0 < n) && (n <= 64)); 102 if (n == 64) return true; 103 int64_t limit = INT64_C(1) << (n - 1); 104 return (-limit <= x) && (x < limit); 105 } 106 VIXL_DEPRECATED("IsIntN", inline bool is_intn(unsigned n, int64_t x)) { 107 return IsIntN(n, x); 108 } 109 110 inline bool IsUintN(unsigned n, uint32_t x) { 111 VIXL_ASSERT((0 < n) && (n <= 32)); 112 if (n >= 32) return true; 113 return !(x >> n); 114 } 115 inline bool IsUintN(unsigned n, int32_t x) { 116 VIXL_ASSERT((0 < n) && (n < 32)); 117 // Convert to an unsigned integer to avoid implementation-defined behavior. 118 return !(static_cast<uint32_t>(x) >> n); 119 } 120 inline bool IsUintN(unsigned n, uint64_t x) { 121 VIXL_ASSERT((0 < n) && (n <= 64)); 122 if (n >= 64) return true; 123 return !(x >> n); 124 } 125 inline bool IsUintN(unsigned n, int64_t x) { 126 VIXL_ASSERT((0 < n) && (n < 64)); 127 // Convert to an unsigned integer to avoid implementation-defined behavior. 128 return !(static_cast<uint64_t>(x) >> n); 129 } 130 VIXL_DEPRECATED("IsUintN", inline bool is_uintn(unsigned n, int64_t x)) { 131 return IsUintN(n, x); 132 } 133 134 inline uint64_t TruncateToUintN(unsigned n, uint64_t x) { 135 VIXL_ASSERT((0 < n) && (n < 64)); 136 return static_cast<uint64_t>(x) & ((UINT64_C(1) << n) - 1); 137 } 138 VIXL_DEPRECATED("TruncateToUintN", 139 inline uint64_t truncate_to_intn(unsigned n, int64_t x)) { 140 return TruncateToUintN(n, x); 141 } 142 143 // clang-format off 144 #define INT_1_TO_32_LIST(V) \ 145 V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) \ 146 V(9) V(10) V(11) V(12) V(13) V(14) V(15) V(16) \ 147 V(17) V(18) V(19) V(20) V(21) V(22) V(23) V(24) \ 148 V(25) V(26) V(27) V(28) V(29) V(30) V(31) V(32) 149 150 #define INT_33_TO_63_LIST(V) \ 151 V(33) V(34) V(35) V(36) V(37) V(38) V(39) V(40) \ 152 V(41) V(42) V(43) V(44) V(45) V(46) V(47) V(48) \ 153 V(49) V(50) V(51) V(52) V(53) V(54) V(55) V(56) \ 154 V(57) V(58) V(59) V(60) V(61) V(62) V(63) 155 156 #define INT_1_TO_63_LIST(V) INT_1_TO_32_LIST(V) INT_33_TO_63_LIST(V) 157 158 // clang-format on 159 160 #define DECLARE_IS_INT_N(N) \ 161 inline bool IsInt##N(int64_t x) { return IsIntN(N, x); } \ 162 VIXL_DEPRECATED("IsInt" #N, inline bool is_int##N(int64_t x)) { \ 163 return IsIntN(N, x); \ 164 } 165 166 #define DECLARE_IS_UINT_N(N) \ 167 inline bool IsUint##N(int64_t x) { return IsUintN(N, x); } \ 168 VIXL_DEPRECATED("IsUint" #N, inline bool is_uint##N(int64_t x)) { \ 169 return IsUintN(N, x); \ 170 } 171 172 #define DECLARE_TRUNCATE_TO_UINT_32(N) \ 173 inline uint32_t TruncateToUint##N(uint64_t x) { \ 174 return static_cast<uint32_t>(TruncateToUintN(N, x)); \ 175 } \ 176 VIXL_DEPRECATED("TruncateToUint" #N, \ 177 inline uint32_t truncate_to_int##N(int64_t x)) { \ 178 return TruncateToUint##N(x); \ 179 } 180 181 INT_1_TO_63_LIST(DECLARE_IS_INT_N) 182 INT_1_TO_63_LIST(DECLARE_IS_UINT_N) 183 INT_1_TO_32_LIST(DECLARE_TRUNCATE_TO_UINT_32) 184 185 #undef DECLARE_IS_INT_N 186 #undef DECLARE_IS_UINT_N 187 #undef DECLARE_TRUNCATE_TO_INT_N 188 189 // Bit field extraction. 190 inline uint64_t ExtractUnsignedBitfield64(int msb, int lsb, uint64_t x) { 191 VIXL_ASSERT((static_cast<size_t>(msb) < sizeof(x) * 8) && (lsb >= 0) && 192 (msb >= lsb)); 193 if ((msb == 63) && (lsb == 0)) return x; 194 return (x >> lsb) & ((static_cast<uint64_t>(1) << (1 + msb - lsb)) - 1); 195 } 196 197 198 inline uint32_t ExtractUnsignedBitfield32(int msb, int lsb, uint64_t x) { 199 VIXL_ASSERT((static_cast<size_t>(msb) < sizeof(x) * 8) && (lsb >= 0) && 200 (msb >= lsb)); 201 return TruncateToUint32(ExtractUnsignedBitfield64(msb, lsb, x)); 202 } 203 204 205 inline int64_t ExtractSignedBitfield64(int msb, int lsb, uint64_t x) { 206 VIXL_ASSERT((static_cast<size_t>(msb) < sizeof(x) * 8) && (lsb >= 0) && 207 (msb >= lsb)); 208 uint64_t temp = ExtractUnsignedBitfield64(msb, lsb, x); 209 // If the highest extracted bit is set, sign extend. 210 if ((temp >> (msb - lsb)) == 1) { 211 temp |= ~UINT64_C(0) << (msb - lsb); 212 } 213 int64_t result; 214 memcpy(&result, &temp, sizeof(result)); 215 return result; 216 } 217 218 inline int32_t ExtractSignedBitfield32(int msb, int lsb, uint64_t x) { 219 VIXL_ASSERT((static_cast<size_t>(msb) < sizeof(x) * 8) && (lsb >= 0) && 220 (msb >= lsb)); 221 uint32_t temp = TruncateToUint32(ExtractSignedBitfield64(msb, lsb, x)); 222 int32_t result; 223 memcpy(&result, &temp, sizeof(result)); 224 return result; 225 } 226 227 inline uint64_t RotateRight(uint64_t value, 228 unsigned int rotate, 229 unsigned int width) { 230 VIXL_ASSERT((width > 0) && (width <= 64)); 231 uint64_t width_mask = ~UINT64_C(0) >> (64 - width); 232 rotate &= 63; 233 if (rotate > 0) { 234 value &= width_mask; 235 value = (value << (width - rotate)) | (value >> rotate); 236 } 237 return value & width_mask; 238 } 239 240 inline uint64_t RotateLeft(uint64_t value, 241 unsigned int rotate, 242 unsigned int width) { 243 return RotateRight(value, width - rotate, width); 244 } 245 246 // Wrapper class for passing FP16 values through the assembler. 247 // This is purely to aid with type checking/casting. 248 class Float16 { 249 public: 250 explicit Float16(double dvalue); 251 Float16() : rawbits_(0x0) {} 252 friend uint16_t Float16ToRawbits(Float16 value); 253 friend Float16 RawbitsToFloat16(uint16_t bits); 254 255 protected: 256 uint16_t rawbits_; 257 }; 258 259 // Floating point representation. 260 uint16_t Float16ToRawbits(Float16 value); 261 262 263 uint32_t FloatToRawbits(float value); 264 VIXL_DEPRECATED("FloatToRawbits", 265 inline uint32_t float_to_rawbits(float value)) { 266 return FloatToRawbits(value); 267 } 268 269 uint64_t DoubleToRawbits(double value); 270 VIXL_DEPRECATED("DoubleToRawbits", 271 inline uint64_t double_to_rawbits(double value)) { 272 return DoubleToRawbits(value); 273 } 274 275 Float16 RawbitsToFloat16(uint16_t bits); 276 277 float RawbitsToFloat(uint32_t bits); 278 VIXL_DEPRECATED("RawbitsToFloat", 279 inline float rawbits_to_float(uint32_t bits)) { 280 return RawbitsToFloat(bits); 281 } 282 283 double RawbitsToDouble(uint64_t bits); 284 VIXL_DEPRECATED("RawbitsToDouble", 285 inline double rawbits_to_double(uint64_t bits)) { 286 return RawbitsToDouble(bits); 287 } 288 289 // Some compilers dislike negating unsigned integers, 290 // so we provide an equivalent. 291 template <typename T> 292 T UnsignedNegate(T value) { 293 VIXL_STATIC_ASSERT(std::is_unsigned<T>::value); 294 return ~value + 1; 295 } 296 297 template <typename T> 298 bool CanBeNegated(T value) { 299 VIXL_STATIC_ASSERT(std::is_signed<T>::value); 300 return (value == std::numeric_limits<T>::min()) ? false : true; 301 } 302 303 // An absolute operation for signed integers that is defined for results outside 304 // the representable range. Specifically, Abs(MIN_INT) is MIN_INT. 305 template <typename T> 306 T Abs(T val) { 307 // TODO: this static assertion is for signed integer inputs, as that's the 308 // only type tested. However, the code should work for all numeric inputs. 309 // Remove the assertion and this comment when more tests are available. 310 VIXL_STATIC_ASSERT(std::is_signed<T>::value && std::is_integral<T>::value); 311 return ((val >= -std::numeric_limits<T>::max()) && (val < 0)) ? -val : val; 312 } 313 314 // Convert unsigned to signed numbers in a well-defined way (using two's 315 // complement representations). 316 inline int64_t RawbitsToInt64(uint64_t bits) { 317 return (bits >= UINT64_C(0x8000000000000000)) 318 ? (-static_cast<int64_t>(UnsignedNegate(bits) - 1) - 1) 319 : static_cast<int64_t>(bits); 320 } 321 322 inline int32_t RawbitsToInt32(uint32_t bits) { 323 return (bits >= UINT64_C(0x80000000)) 324 ? (-static_cast<int32_t>(UnsignedNegate(bits) - 1) - 1) 325 : static_cast<int32_t>(bits); 326 } 327 328 namespace internal { 329 330 // Internal simulation class used solely by the simulator to 331 // provide an abstraction layer for any half-precision arithmetic. 332 class SimFloat16 : public Float16 { 333 public: 334 // TODO: We should investigate making this constructor explicit. 335 // This is currently difficult to do due to a number of templated 336 // functions in the simulator which rely on returning double values. 337 SimFloat16(double dvalue) : Float16(dvalue) {} // NOLINT(runtime/explicit) 338 SimFloat16(Float16 f) { // NOLINT(runtime/explicit) 339 this->rawbits_ = Float16ToRawbits(f); 340 } 341 SimFloat16() : Float16() {} 342 SimFloat16 operator-() const; 343 SimFloat16 operator+(SimFloat16 rhs) const; 344 SimFloat16 operator-(SimFloat16 rhs) const; 345 SimFloat16 operator*(SimFloat16 rhs) const; 346 SimFloat16 operator/(SimFloat16 rhs) const; 347 bool operator<(SimFloat16 rhs) const; 348 bool operator>(SimFloat16 rhs) const; 349 bool operator==(SimFloat16 rhs) const; 350 bool operator!=(SimFloat16 rhs) const; 351 // This is necessary for conversions performed in (macro asm) Fmov. 352 bool operator==(double rhs) const; 353 operator double() const; 354 }; 355 } // namespace internal 356 357 uint32_t Float16Sign(internal::SimFloat16 value); 358 359 uint32_t Float16Exp(internal::SimFloat16 value); 360 361 uint32_t Float16Mantissa(internal::SimFloat16 value); 362 363 uint32_t FloatSign(float value); 364 VIXL_DEPRECATED("FloatSign", inline uint32_t float_sign(float value)) { 365 return FloatSign(value); 366 } 367 368 uint32_t FloatExp(float value); 369 VIXL_DEPRECATED("FloatExp", inline uint32_t float_exp(float value)) { 370 return FloatExp(value); 371 } 372 373 uint32_t FloatMantissa(float value); 374 VIXL_DEPRECATED("FloatMantissa", inline uint32_t float_mantissa(float value)) { 375 return FloatMantissa(value); 376 } 377 378 uint32_t DoubleSign(double value); 379 VIXL_DEPRECATED("DoubleSign", inline uint32_t double_sign(double value)) { 380 return DoubleSign(value); 381 } 382 383 uint32_t DoubleExp(double value); 384 VIXL_DEPRECATED("DoubleExp", inline uint32_t double_exp(double value)) { 385 return DoubleExp(value); 386 } 387 388 uint64_t DoubleMantissa(double value); 389 VIXL_DEPRECATED("DoubleMantissa", 390 inline uint64_t double_mantissa(double value)) { 391 return DoubleMantissa(value); 392 } 393 394 internal::SimFloat16 Float16Pack(uint16_t sign, 395 uint16_t exp, 396 uint16_t mantissa); 397 398 float FloatPack(uint32_t sign, uint32_t exp, uint32_t mantissa); 399 VIXL_DEPRECATED("FloatPack", 400 inline float float_pack(uint32_t sign, 401 uint32_t exp, 402 uint32_t mantissa)) { 403 return FloatPack(sign, exp, mantissa); 404 } 405 406 double DoublePack(uint64_t sign, uint64_t exp, uint64_t mantissa); 407 VIXL_DEPRECATED("DoublePack", 408 inline double double_pack(uint32_t sign, 409 uint32_t exp, 410 uint64_t mantissa)) { 411 return DoublePack(sign, exp, mantissa); 412 } 413 414 // An fpclassify() function for 16-bit half-precision floats. 415 int Float16Classify(Float16 value); 416 VIXL_DEPRECATED("Float16Classify", inline int float16classify(uint16_t value)) { 417 return Float16Classify(RawbitsToFloat16(value)); 418 } 419 420 bool IsZero(Float16 value); 421 422 inline bool IsPositiveZero(double value) { 423 return (value == 0.0) && (copysign(1.0, value) > 0.0); 424 } 425 426 inline bool IsNaN(float value) { return std::isnan(value); } 427 428 inline bool IsNaN(double value) { return std::isnan(value); } 429 430 inline bool IsNaN(Float16 value) { return Float16Classify(value) == FP_NAN; } 431 432 inline bool IsInf(float value) { return std::isinf(value); } 433 434 inline bool IsInf(double value) { return std::isinf(value); } 435 436 inline bool IsInf(Float16 value) { 437 return Float16Classify(value) == FP_INFINITE; 438 } 439 440 441 // NaN tests. 442 inline bool IsSignallingNaN(double num) { 443 const uint64_t kFP64QuietNaNMask = UINT64_C(0x0008000000000000); 444 uint64_t raw = DoubleToRawbits(num); 445 if (IsNaN(num) && ((raw & kFP64QuietNaNMask) == 0)) { 446 return true; 447 } 448 return false; 449 } 450 451 452 inline bool IsSignallingNaN(float num) { 453 const uint32_t kFP32QuietNaNMask = 0x00400000; 454 uint32_t raw = FloatToRawbits(num); 455 if (IsNaN(num) && ((raw & kFP32QuietNaNMask) == 0)) { 456 return true; 457 } 458 return false; 459 } 460 461 462 inline bool IsSignallingNaN(Float16 num) { 463 const uint16_t kFP16QuietNaNMask = 0x0200; 464 return IsNaN(num) && ((Float16ToRawbits(num) & kFP16QuietNaNMask) == 0); 465 } 466 467 468 template <typename T> 469 inline bool IsQuietNaN(T num) { 470 return IsNaN(num) && !IsSignallingNaN(num); 471 } 472 473 474 // Convert the NaN in 'num' to a quiet NaN. 475 inline double ToQuietNaN(double num) { 476 const uint64_t kFP64QuietNaNMask = UINT64_C(0x0008000000000000); 477 VIXL_ASSERT(IsNaN(num)); 478 return RawbitsToDouble(DoubleToRawbits(num) | kFP64QuietNaNMask); 479 } 480 481 482 inline float ToQuietNaN(float num) { 483 const uint32_t kFP32QuietNaNMask = 0x00400000; 484 VIXL_ASSERT(IsNaN(num)); 485 return RawbitsToFloat(FloatToRawbits(num) | kFP32QuietNaNMask); 486 } 487 488 489 inline internal::SimFloat16 ToQuietNaN(internal::SimFloat16 num) { 490 const uint16_t kFP16QuietNaNMask = 0x0200; 491 VIXL_ASSERT(IsNaN(num)); 492 return internal::SimFloat16( 493 RawbitsToFloat16(Float16ToRawbits(num) | kFP16QuietNaNMask)); 494 } 495 496 497 // Fused multiply-add. 498 inline double FusedMultiplyAdd(double op1, double op2, double a) { 499 return fma(op1, op2, a); 500 } 501 502 503 inline float FusedMultiplyAdd(float op1, float op2, float a) { 504 return fmaf(op1, op2, a); 505 } 506 507 508 inline uint64_t LowestSetBit(uint64_t value) { 509 return value & UnsignedNegate(value); 510 } 511 512 513 template <typename T> 514 inline int HighestSetBitPosition(T value) { 515 VIXL_ASSERT(value != 0); 516 return (sizeof(value) * 8 - 1) - CountLeadingZeros(value); 517 } 518 519 520 template <typename V> 521 inline int WhichPowerOf2(V value) { 522 VIXL_ASSERT(IsPowerOf2(value)); 523 return CountTrailingZeros(value); 524 } 525 526 527 unsigned CountClearHalfWords(uint64_t imm, unsigned reg_size); 528 529 530 int BitCount(uint64_t value); 531 532 533 template <typename T> 534 T ReverseBits(T value) { 535 VIXL_ASSERT((sizeof(value) == 1) || (sizeof(value) == 2) || 536 (sizeof(value) == 4) || (sizeof(value) == 8)); 537 T result = 0; 538 for (unsigned i = 0; i < (sizeof(value) * 8); i++) { 539 result = (result << 1) | (value & 1); 540 value >>= 1; 541 } 542 return result; 543 } 544 545 546 template <typename T> 547 inline T SignExtend(T val, int size_in_bits) { 548 VIXL_ASSERT(size_in_bits > 0); 549 T mask = (T(2) << (size_in_bits - 1)) - T(1); 550 val &= mask; 551 T sign_bits = -((val >> (size_in_bits - 1)) << size_in_bits); 552 val |= sign_bits; 553 return val; 554 } 555 556 557 template <typename T> 558 T ReverseBytes(T value, int block_bytes_log2) { 559 VIXL_ASSERT((sizeof(value) == 4) || (sizeof(value) == 8)); 560 VIXL_ASSERT((uint64_t{1} << block_bytes_log2) <= sizeof(value)); 561 // Split the 64-bit value into an 8-bit array, where b[0] is the least 562 // significant byte, and b[7] is the most significant. 563 uint8_t bytes[8]; 564 uint64_t mask = UINT64_C(0xff00000000000000); 565 for (int i = 7; i >= 0; i--) { 566 bytes[i] = 567 static_cast<uint8_t>((static_cast<uint64_t>(value) & mask) >> (i * 8)); 568 mask >>= 8; 569 } 570 571 // Permutation tables for REV instructions. 572 // permute_table[0] is used by REV16_x, REV16_w 573 // permute_table[1] is used by REV32_x, REV_w 574 // permute_table[2] is used by REV_x 575 VIXL_ASSERT((0 < block_bytes_log2) && (block_bytes_log2 < 4)); 576 static const uint8_t permute_table[3][8] = {{6, 7, 4, 5, 2, 3, 0, 1}, 577 {4, 5, 6, 7, 0, 1, 2, 3}, 578 {0, 1, 2, 3, 4, 5, 6, 7}}; 579 uint64_t temp = 0; 580 for (int i = 0; i < 8; i++) { 581 temp <<= 8; 582 temp |= bytes[permute_table[block_bytes_log2 - 1][i]]; 583 } 584 585 T result; 586 VIXL_STATIC_ASSERT(sizeof(result) <= sizeof(temp)); 587 memcpy(&result, &temp, sizeof(result)); 588 return result; 589 } 590 591 template <unsigned MULTIPLE, typename T> 592 inline bool IsMultiple(T value) { 593 VIXL_ASSERT(IsPowerOf2(MULTIPLE)); 594 return (value & (MULTIPLE - 1)) == 0; 595 } 596 597 template <typename T> 598 inline bool IsMultiple(T value, unsigned multiple) { 599 VIXL_ASSERT(IsPowerOf2(multiple)); 600 return (value & (multiple - 1)) == 0; 601 } 602 603 template <typename T> 604 inline bool IsAligned(T pointer, int alignment) { 605 VIXL_ASSERT(IsPowerOf2(alignment)); 606 return (pointer & (alignment - 1)) == 0; 607 } 608 609 // Pointer alignment 610 // TODO: rename/refactor to make it specific to instructions. 611 template <unsigned ALIGN, typename T> 612 inline bool IsAligned(T pointer) { 613 VIXL_ASSERT(sizeof(pointer) == sizeof(intptr_t)); // NOLINT(runtime/sizeof) 614 // Use C-style casts to get static_cast behaviour for integral types (T), and 615 // reinterpret_cast behaviour for other types. 616 return IsAligned((intptr_t)(pointer), ALIGN); 617 } 618 619 template <typename T> 620 bool IsWordAligned(T pointer) { 621 return IsAligned<4>(pointer); 622 } 623 624 template <unsigned BITS, typename T> 625 bool IsRepeatingPattern(T value) { 626 VIXL_STATIC_ASSERT(std::is_unsigned<T>::value); 627 VIXL_ASSERT(IsMultiple(sizeof(value) * kBitsPerByte, BITS)); 628 VIXL_ASSERT(IsMultiple(BITS, 2)); 629 VIXL_STATIC_ASSERT(BITS >= 2); 630 #if (defined(__x86_64__) || defined(__i386)) && __clang_major__ >= 17 && \ 631 __clang_major__ <= 19 632 // Workaround for https://github.com/llvm/llvm-project/issues/108722 633 unsigned hbits = BITS / 2; 634 T midmask = (~static_cast<T>(0) >> BITS) << hbits; 635 // E.g. for bytes in a word (0xb3b2b1b0): .b3b2b1. == .b2b1b0. 636 return (((value >> hbits) & midmask) == ((value << hbits) & midmask)); 637 #else 638 return value == RotateRight(value, BITS, sizeof(value) * kBitsPerByte); 639 #endif 640 } 641 642 template <typename T> 643 bool AllBytesMatch(T value) { 644 return IsRepeatingPattern<kBitsPerByte>(value); 645 } 646 647 template <typename T> 648 bool AllHalfwordsMatch(T value) { 649 return IsRepeatingPattern<kBitsPerByte * 2>(value); 650 } 651 652 template <typename T> 653 bool AllWordsMatch(T value) { 654 return IsRepeatingPattern<kBitsPerByte * 4>(value); 655 } 656 657 // Increment a pointer until it has the specified alignment. The alignment must 658 // be a power of two. 659 template <class T> 660 T AlignUp(T pointer, 661 typename Unsigned<sizeof(T) * kBitsPerByte>::type alignment) { 662 VIXL_ASSERT(IsPowerOf2(alignment)); 663 // Use C-style casts to get static_cast behaviour for integral types (T), and 664 // reinterpret_cast behaviour for other types. 665 666 typename Unsigned<sizeof(T)* kBitsPerByte>::type pointer_raw = 667 (typename Unsigned<sizeof(T) * kBitsPerByte>::type) pointer; 668 VIXL_STATIC_ASSERT(sizeof(pointer) <= sizeof(pointer_raw)); 669 670 size_t mask = alignment - 1; 671 T result = (T)((pointer_raw + mask) & ~mask); 672 VIXL_ASSERT(result >= pointer); 673 674 return result; 675 } 676 677 // Decrement a pointer until it has the specified alignment. The alignment must 678 // be a power of two. 679 template <class T> 680 T AlignDown(T pointer, 681 typename Unsigned<sizeof(T) * kBitsPerByte>::type alignment) { 682 VIXL_ASSERT(IsPowerOf2(alignment)); 683 // Use C-style casts to get static_cast behaviour for integral types (T), and 684 // reinterpret_cast behaviour for other types. 685 686 typename Unsigned<sizeof(T)* kBitsPerByte>::type pointer_raw = 687 (typename Unsigned<sizeof(T) * kBitsPerByte>::type) pointer; 688 VIXL_STATIC_ASSERT(sizeof(pointer) <= sizeof(pointer_raw)); 689 690 size_t mask = alignment - 1; 691 return (T)(pointer_raw & ~mask); 692 } 693 694 695 template <typename T> 696 inline T ExtractBit(T value, unsigned bit) { 697 return (value >> bit) & T(1); 698 } 699 700 template <typename Ts, typename Td> 701 inline Td ExtractBits(Ts value, int least_significant_bit, Td mask) { 702 return Td((value >> least_significant_bit) & Ts(mask)); 703 } 704 705 template <typename Ts, typename Td> 706 inline void AssignBit(Td& dst, // NOLINT(runtime/references) 707 int bit, 708 Ts value) { 709 VIXL_ASSERT((value == Ts(0)) || (value == Ts(1))); 710 VIXL_ASSERT(bit >= 0); 711 VIXL_ASSERT(bit < static_cast<int>(sizeof(Td) * 8)); 712 Td mask(1); 713 dst &= ~(mask << bit); 714 dst |= Td(value) << bit; 715 } 716 717 template <typename Td, typename Ts> 718 inline void AssignBits(Td& dst, // NOLINT(runtime/references) 719 int least_significant_bit, 720 Ts mask, 721 Ts value) { 722 VIXL_ASSERT(least_significant_bit >= 0); 723 VIXL_ASSERT(least_significant_bit < static_cast<int>(sizeof(Td) * 8)); 724 VIXL_ASSERT(((Td(mask) << least_significant_bit) >> least_significant_bit) == 725 Td(mask)); 726 VIXL_ASSERT((value & mask) == value); 727 dst &= ~(Td(mask) << least_significant_bit); 728 dst |= Td(value) << least_significant_bit; 729 } 730 731 class VFP { 732 public: 733 static uint32_t FP32ToImm8(float imm) { 734 // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000 735 uint32_t bits = FloatToRawbits(imm); 736 // bit7: a000.0000 737 uint32_t bit7 = ((bits >> 31) & 0x1) << 7; 738 // bit6: 0b00.0000 739 uint32_t bit6 = ((bits >> 29) & 0x1) << 6; 740 // bit5_to_0: 00cd.efgh 741 uint32_t bit5_to_0 = (bits >> 19) & 0x3f; 742 return static_cast<uint32_t>(bit7 | bit6 | bit5_to_0); 743 } 744 static uint32_t FP64ToImm8(double imm) { 745 // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 746 // 0000.0000.0000.0000.0000.0000.0000.0000 747 uint64_t bits = DoubleToRawbits(imm); 748 // bit7: a000.0000 749 uint64_t bit7 = ((bits >> 63) & 0x1) << 7; 750 // bit6: 0b00.0000 751 uint64_t bit6 = ((bits >> 61) & 0x1) << 6; 752 // bit5_to_0: 00cd.efgh 753 uint64_t bit5_to_0 = (bits >> 48) & 0x3f; 754 755 return static_cast<uint32_t>(bit7 | bit6 | bit5_to_0); 756 } 757 static float Imm8ToFP32(uint32_t imm8) { 758 // Imm8: abcdefgh (8 bits) 759 // Single: aBbb.bbbc.defg.h000.0000.0000.0000.0000 (32 bits) 760 // where B is b ^ 1 761 uint32_t bits = imm8; 762 uint32_t bit7 = (bits >> 7) & 0x1; 763 uint32_t bit6 = (bits >> 6) & 0x1; 764 uint32_t bit5_to_0 = bits & 0x3f; 765 uint32_t result = (bit7 << 31) | ((32 - bit6) << 25) | (bit5_to_0 << 19); 766 767 return RawbitsToFloat(result); 768 } 769 static double Imm8ToFP64(uint32_t imm8) { 770 // Imm8: abcdefgh (8 bits) 771 // Double: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 772 // 0000.0000.0000.0000.0000.0000.0000.0000 (64 bits) 773 // where B is b ^ 1 774 uint32_t bits = imm8; 775 uint64_t bit7 = (bits >> 7) & 0x1; 776 uint64_t bit6 = (bits >> 6) & 0x1; 777 uint64_t bit5_to_0 = bits & 0x3f; 778 uint64_t result = (bit7 << 63) | ((256 - bit6) << 54) | (bit5_to_0 << 48); 779 return RawbitsToDouble(result); 780 } 781 static bool IsImmFP32(float imm) { 782 // Valid values will have the form: 783 // aBbb.bbbc.defg.h000.0000.0000.0000.0000 784 uint32_t bits = FloatToRawbits(imm); 785 // bits[19..0] are cleared. 786 if ((bits & 0x7ffff) != 0) { 787 return false; 788 } 789 790 791 // bits[29..25] are all set or all cleared. 792 uint32_t b_pattern = (bits >> 16) & 0x3e00; 793 if (b_pattern != 0 && b_pattern != 0x3e00) { 794 return false; 795 } 796 // bit[30] and bit[29] are opposite. 797 if (((bits ^ (bits << 1)) & 0x40000000) == 0) { 798 return false; 799 } 800 return true; 801 } 802 static bool IsImmFP64(double imm) { 803 // Valid values will have the form: 804 // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 805 // 0000.0000.0000.0000.0000.0000.0000.0000 806 uint64_t bits = DoubleToRawbits(imm); 807 // bits[47..0] are cleared. 808 if ((bits & 0x0000ffffffffffff) != 0) { 809 return false; 810 } 811 // bits[61..54] are all set or all cleared. 812 uint32_t b_pattern = (bits >> 48) & 0x3fc0; 813 if ((b_pattern != 0) && (b_pattern != 0x3fc0)) { 814 return false; 815 } 816 // bit[62] and bit[61] are opposite. 817 if (((bits ^ (bits << 1)) & (UINT64_C(1) << 62)) == 0) { 818 return false; 819 } 820 return true; 821 } 822 }; 823 824 class BitField { 825 // ForEachBitHelper is a functor that will call 826 // bool ForEachBitHelper::execute(ElementType id) const 827 // and expects a boolean in return whether to continue (if true) 828 // or stop (if false) 829 // check_set will check if the bits are on (true) or off(false) 830 template <typename ForEachBitHelper, bool check_set> 831 bool ForEachBit(const ForEachBitHelper& helper) { 832 for (int i = 0; static_cast<size_t>(i) < bitfield_.size(); i++) { 833 if (bitfield_[i] == check_set) 834 if (!helper.execute(i)) return false; 835 } 836 return true; 837 } 838 839 public: 840 explicit BitField(unsigned size) : bitfield_(size, 0) {} 841 842 void Set(int i) { 843 VIXL_ASSERT((i >= 0) && (static_cast<size_t>(i) < bitfield_.size())); 844 bitfield_[i] = true; 845 } 846 847 void Unset(int i) { 848 VIXL_ASSERT((i >= 0) && (static_cast<size_t>(i) < bitfield_.size())); 849 bitfield_[i] = true; 850 } 851 852 bool IsSet(int i) const { return bitfield_[i]; } 853 854 // For each bit not set in the bitfield call the execute functor 855 // execute. 856 // ForEachBitSetHelper::execute returns true if the iteration through 857 // the bits can continue, otherwise it will stop. 858 // struct ForEachBitSetHelper { 859 // bool execute(int /*id*/) { return false; } 860 // }; 861 template <typename ForEachBitNotSetHelper> 862 bool ForEachBitNotSet(const ForEachBitNotSetHelper& helper) { 863 return ForEachBit<ForEachBitNotSetHelper, false>(helper); 864 } 865 866 // For each bit set in the bitfield call the execute functor 867 // execute. 868 template <typename ForEachBitSetHelper> 869 bool ForEachBitSet(const ForEachBitSetHelper& helper) { 870 return ForEachBit<ForEachBitSetHelper, true>(helper); 871 } 872 873 private: 874 std::vector<bool> bitfield_; 875 }; 876 877 namespace internal { 878 879 typedef int64_t Int64; 880 class Uint64; 881 class Uint128; 882 883 class Uint32 { 884 uint32_t data_; 885 886 public: 887 // Unlike uint32_t, Uint32 has a default constructor. 888 Uint32() { data_ = 0; } 889 explicit Uint32(uint32_t data) : data_(data) {} 890 inline explicit Uint32(Uint64 data); 891 uint32_t Get() const { return data_; } 892 template <int N> 893 int32_t GetSigned() const { 894 return ExtractSignedBitfield32(N - 1, 0, data_); 895 } 896 int32_t GetSigned() const { return data_; } 897 Uint32 operator~() const { return Uint32(~data_); } 898 Uint32 operator-() const { return Uint32(UnsignedNegate(data_)); } 899 bool operator==(Uint32 value) const { return data_ == value.data_; } 900 bool operator!=(Uint32 value) const { return data_ != value.data_; } 901 bool operator>(Uint32 value) const { return data_ > value.data_; } 902 Uint32 operator+(Uint32 value) const { return Uint32(data_ + value.data_); } 903 Uint32 operator-(Uint32 value) const { return Uint32(data_ - value.data_); } 904 Uint32 operator&(Uint32 value) const { return Uint32(data_ & value.data_); } 905 Uint32 operator&=(Uint32 value) { 906 data_ &= value.data_; 907 return *this; 908 } 909 Uint32 operator^(Uint32 value) const { return Uint32(data_ ^ value.data_); } 910 Uint32 operator^=(Uint32 value) { 911 data_ ^= value.data_; 912 return *this; 913 } 914 Uint32 operator|(Uint32 value) const { return Uint32(data_ | value.data_); } 915 Uint32 operator|=(Uint32 value) { 916 data_ |= value.data_; 917 return *this; 918 } 919 // Unlike uint32_t, the shift functions can accept negative shift and 920 // return 0 when the shift is too big. 921 Uint32 operator>>(int shift) const { 922 if (shift == 0) return *this; 923 if (shift < 0) { 924 int tmp = -shift; 925 if (tmp >= 32) return Uint32(0); 926 return Uint32(data_ << tmp); 927 } 928 int tmp = shift; 929 if (tmp >= 32) return Uint32(0); 930 return Uint32(data_ >> tmp); 931 } 932 Uint32 operator<<(int shift) const { 933 if (shift == 0) return *this; 934 if (shift < 0) { 935 int tmp = -shift; 936 if (tmp >= 32) return Uint32(0); 937 return Uint32(data_ >> tmp); 938 } 939 int tmp = shift; 940 if (tmp >= 32) return Uint32(0); 941 return Uint32(data_ << tmp); 942 } 943 }; 944 945 class Uint64 { 946 uint64_t data_; 947 948 public: 949 // Unlike uint64_t, Uint64 has a default constructor. 950 Uint64() { data_ = 0; } 951 explicit Uint64(uint64_t data) : data_(data) {} 952 explicit Uint64(Uint32 data) : data_(data.Get()) {} 953 inline explicit Uint64(Uint128 data); 954 uint64_t Get() const { return data_; } 955 int64_t GetSigned(int N) const { 956 return ExtractSignedBitfield64(N - 1, 0, data_); 957 } 958 int64_t GetSigned() const { return data_; } 959 Uint32 ToUint32() const { 960 VIXL_ASSERT((data_ >> 32) == 0); 961 return Uint32(static_cast<uint32_t>(data_)); 962 } 963 Uint32 GetHigh32() const { return Uint32(data_ >> 32); } 964 Uint32 GetLow32() const { return Uint32(data_ & 0xffffffff); } 965 Uint64 operator~() const { return Uint64(~data_); } 966 Uint64 operator-() const { return Uint64(UnsignedNegate(data_)); } 967 bool operator==(Uint64 value) const { return data_ == value.data_; } 968 bool operator!=(Uint64 value) const { return data_ != value.data_; } 969 Uint64 operator+(Uint64 value) const { return Uint64(data_ + value.data_); } 970 Uint64 operator-(Uint64 value) const { return Uint64(data_ - value.data_); } 971 Uint64 operator&(Uint64 value) const { return Uint64(data_ & value.data_); } 972 Uint64 operator&=(Uint64 value) { 973 data_ &= value.data_; 974 return *this; 975 } 976 Uint64 operator^(Uint64 value) const { return Uint64(data_ ^ value.data_); } 977 Uint64 operator^=(Uint64 value) { 978 data_ ^= value.data_; 979 return *this; 980 } 981 Uint64 operator|(Uint64 value) const { return Uint64(data_ | value.data_); } 982 Uint64 operator|=(Uint64 value) { 983 data_ |= value.data_; 984 return *this; 985 } 986 // Unlike uint64_t, the shift functions can accept negative shift and 987 // return 0 when the shift is too big. 988 Uint64 operator>>(int shift) const { 989 if (shift == 0) return *this; 990 if (shift < 0) { 991 int tmp = -shift; 992 if (tmp >= 64) return Uint64(0); 993 return Uint64(data_ << tmp); 994 } 995 int tmp = shift; 996 if (tmp >= 64) return Uint64(0); 997 return Uint64(data_ >> tmp); 998 } 999 Uint64 operator<<(int shift) const { 1000 if (shift == 0) return *this; 1001 if (shift < 0) { 1002 int tmp = -shift; 1003 if (tmp >= 64) return Uint64(0); 1004 return Uint64(data_ >> tmp); 1005 } 1006 int tmp = shift; 1007 if (tmp >= 64) return Uint64(0); 1008 return Uint64(data_ << tmp); 1009 } 1010 }; 1011 1012 class Uint128 { 1013 uint64_t data_high_; 1014 uint64_t data_low_; 1015 1016 public: 1017 Uint128() : data_high_(0), data_low_(0) {} 1018 explicit Uint128(uint64_t data_low) : data_high_(0), data_low_(data_low) {} 1019 explicit Uint128(Uint64 data_low) 1020 : data_high_(0), data_low_(data_low.Get()) {} 1021 Uint128(uint64_t data_high, uint64_t data_low) 1022 : data_high_(data_high), data_low_(data_low) {} 1023 Uint64 ToUint64() const { 1024 VIXL_ASSERT(data_high_ == 0); 1025 return Uint64(data_low_); 1026 } 1027 Uint64 GetHigh64() const { return Uint64(data_high_); } 1028 Uint64 GetLow64() const { return Uint64(data_low_); } 1029 Uint128 operator~() const { return Uint128(~data_high_, ~data_low_); } 1030 bool operator==(Uint128 value) const { 1031 return (data_high_ == value.data_high_) && (data_low_ == value.data_low_); 1032 } 1033 Uint128 operator&(Uint128 value) const { 1034 return Uint128(data_high_ & value.data_high_, data_low_ & value.data_low_); 1035 } 1036 Uint128 operator&=(Uint128 value) { 1037 data_high_ &= value.data_high_; 1038 data_low_ &= value.data_low_; 1039 return *this; 1040 } 1041 Uint128 operator|=(Uint128 value) { 1042 data_high_ |= value.data_high_; 1043 data_low_ |= value.data_low_; 1044 return *this; 1045 } 1046 Uint128 operator>>(int shift) const { 1047 VIXL_ASSERT((shift >= 0) && (shift < 128)); 1048 if (shift == 0) return *this; 1049 if (shift >= 64) { 1050 return Uint128(0, data_high_ >> (shift - 64)); 1051 } 1052 uint64_t tmp = (data_high_ << (64 - shift)) | (data_low_ >> shift); 1053 return Uint128(data_high_ >> shift, tmp); 1054 } 1055 Uint128 operator<<(int shift) const { 1056 VIXL_ASSERT((shift >= 0) && (shift < 128)); 1057 if (shift == 0) return *this; 1058 if (shift >= 64) { 1059 return Uint128(data_low_ << (shift - 64), 0); 1060 } 1061 uint64_t tmp = (data_high_ << shift) | (data_low_ >> (64 - shift)); 1062 return Uint128(tmp, data_low_ << shift); 1063 } 1064 }; 1065 1066 Uint32::Uint32(Uint64 data) : data_(data.ToUint32().Get()) {} 1067 Uint64::Uint64(Uint128 data) : data_(data.ToUint64().Get()) {} 1068 1069 Int64 BitCount(Uint32 value); 1070 1071 // The algorithm used is adapted from the one described in section 8.2 of 1072 // Hacker's Delight, by Henry S. Warren, Jr. 1073 template <unsigned N, typename T> 1074 int64_t MultiplyHigh(T u, T v) { 1075 uint64_t u0, v0, w0, u1, v1, w1, w2, t; 1076 VIXL_STATIC_ASSERT((N == 8) || (N == 16) || (N == 32) || (N == 64)); 1077 uint64_t sign_mask = UINT64_C(1) << (N - 1); 1078 uint64_t sign_ext = 0; 1079 unsigned half_bits = N / 2; 1080 uint64_t half_mask = GetUintMask(half_bits); 1081 if (std::numeric_limits<T>::is_signed) { 1082 sign_ext = UINT64_C(0xffffffffffffffff) << half_bits; 1083 } 1084 1085 VIXL_ASSERT(sizeof(u) == sizeof(uint64_t)); 1086 VIXL_ASSERT(sizeof(u) == sizeof(u0)); 1087 1088 u0 = u & half_mask; 1089 u1 = u >> half_bits | (((u & sign_mask) != 0) ? sign_ext : 0); 1090 v0 = v & half_mask; 1091 v1 = v >> half_bits | (((v & sign_mask) != 0) ? sign_ext : 0); 1092 1093 w0 = u0 * v0; 1094 t = u1 * v0 + (w0 >> half_bits); 1095 1096 w1 = t & half_mask; 1097 w2 = t >> half_bits | (((t & sign_mask) != 0) ? sign_ext : 0); 1098 w1 = u0 * v1 + w1; 1099 w1 = w1 >> half_bits | (((w1 & sign_mask) != 0) ? sign_ext : 0); 1100 1101 uint64_t value = u1 * v1 + w2 + w1; 1102 int64_t result; 1103 memcpy(&result, &value, sizeof(result)); 1104 return result; 1105 } 1106 1107 } // namespace internal 1108 1109 // The default NaN values (for FPCR.DN=1). 1110 extern const double kFP64DefaultNaN; 1111 extern const float kFP32DefaultNaN; 1112 extern const Float16 kFP16DefaultNaN; 1113 1114 // Floating-point infinity values. 1115 extern const Float16 kFP16PositiveInfinity; 1116 extern const Float16 kFP16NegativeInfinity; 1117 extern const float kFP32PositiveInfinity; 1118 extern const float kFP32NegativeInfinity; 1119 extern const double kFP64PositiveInfinity; 1120 extern const double kFP64NegativeInfinity; 1121 1122 // Floating-point zero values. 1123 extern const Float16 kFP16PositiveZero; 1124 extern const Float16 kFP16NegativeZero; 1125 1126 // AArch64 floating-point specifics. These match IEEE-754. 1127 const unsigned kDoubleMantissaBits = 52; 1128 const unsigned kDoubleExponentBits = 11; 1129 const unsigned kFloatMantissaBits = 23; 1130 const unsigned kFloatExponentBits = 8; 1131 const unsigned kFloat16MantissaBits = 10; 1132 const unsigned kFloat16ExponentBits = 5; 1133 1134 enum FPRounding { 1135 // The first four values are encodable directly by FPCR<RMode>. 1136 FPTieEven = 0x0, 1137 FPPositiveInfinity = 0x1, 1138 FPNegativeInfinity = 0x2, 1139 FPZero = 0x3, 1140 1141 // The final rounding modes are only available when explicitly specified by 1142 // the instruction (such as with fcvta). It cannot be set in FPCR. 1143 FPTieAway, 1144 FPRoundOdd 1145 }; 1146 1147 enum UseDefaultNaN { kUseDefaultNaN, kIgnoreDefaultNaN }; 1148 1149 // Assemble the specified IEEE-754 components into the target type and apply 1150 // appropriate rounding. 1151 // sign: 0 = positive, 1 = negative 1152 // exponent: Unbiased IEEE-754 exponent. 1153 // mantissa: The mantissa of the input. The top bit (which is not encoded for 1154 // normal IEEE-754 values) must not be omitted. This bit has the 1155 // value 'pow(2, exponent)'. 1156 // 1157 // The input value is assumed to be a normalized value. That is, the input may 1158 // not be infinity or NaN. If the source value is subnormal, it must be 1159 // normalized before calling this function such that the highest set bit in the 1160 // mantissa has the value 'pow(2, exponent)'. 1161 // 1162 // Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than 1163 // calling a templated FPRound. 1164 template <class T, int ebits, int mbits> 1165 T FPRound(int64_t sign, 1166 int64_t exponent, 1167 uint64_t mantissa, 1168 FPRounding round_mode) { 1169 VIXL_ASSERT((sign == 0) || (sign == 1)); 1170 1171 // Only FPTieEven and FPRoundOdd rounding modes are implemented. 1172 VIXL_ASSERT((round_mode == FPTieEven) || (round_mode == FPRoundOdd)); 1173 1174 // Rounding can promote subnormals to normals, and normals to infinities. For 1175 // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be 1176 // encodable as a float, but rounding based on the low-order mantissa bits 1177 // could make it overflow. With ties-to-even rounding, this value would become 1178 // an infinity. 1179 1180 // ---- Rounding Method ---- 1181 // 1182 // The exponent is irrelevant in the rounding operation, so we treat the 1183 // lowest-order bit that will fit into the result ('onebit') as having 1184 // the value '1'. Similarly, the highest-order bit that won't fit into 1185 // the result ('halfbit') has the value '0.5'. The 'point' sits between 1186 // 'onebit' and 'halfbit': 1187 // 1188 // These bits fit into the result. 1189 // |---------------------| 1190 // mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1191 // || 1192 // / | 1193 // / halfbit 1194 // onebit 1195 // 1196 // For subnormal outputs, the range of representable bits is smaller and 1197 // the position of onebit and halfbit depends on the exponent of the 1198 // input, but the method is otherwise similar. 1199 // 1200 // onebit(frac) 1201 // | 1202 // | halfbit(frac) halfbit(adjusted) 1203 // | / / 1204 // | | | 1205 // 0b00.0 (exact) -> 0b00.0 (exact) -> 0b00 1206 // 0b00.0... -> 0b00.0... -> 0b00 1207 // 0b00.1 (exact) -> 0b00.0111..111 -> 0b00 1208 // 0b00.1... -> 0b00.1... -> 0b01 1209 // 0b01.0 (exact) -> 0b01.0 (exact) -> 0b01 1210 // 0b01.0... -> 0b01.0... -> 0b01 1211 // 0b01.1 (exact) -> 0b01.1 (exact) -> 0b10 1212 // 0b01.1... -> 0b01.1... -> 0b10 1213 // 0b10.0 (exact) -> 0b10.0 (exact) -> 0b10 1214 // 0b10.0... -> 0b10.0... -> 0b10 1215 // 0b10.1 (exact) -> 0b10.0111..111 -> 0b10 1216 // 0b10.1... -> 0b10.1... -> 0b11 1217 // 0b11.0 (exact) -> 0b11.0 (exact) -> 0b11 1218 // ... / | / | 1219 // / | / | 1220 // / | 1221 // adjusted = frac - (halfbit(mantissa) & ~onebit(frac)); / | 1222 // 1223 // mantissa = (mantissa >> shift) + halfbit(adjusted); 1224 1225 static const int mantissa_offset = 0; 1226 static const int exponent_offset = mantissa_offset + mbits; 1227 static const int sign_offset = exponent_offset + ebits; 1228 VIXL_ASSERT(sign_offset == (sizeof(T) * 8 - 1)); 1229 1230 // Bail out early for zero inputs. 1231 if (mantissa == 0) { 1232 return static_cast<T>(sign << sign_offset); 1233 } 1234 1235 // If all bits in the exponent are set, the value is infinite or NaN. 1236 // This is true for all binary IEEE-754 formats. 1237 static const int infinite_exponent = (1 << ebits) - 1; 1238 static const int max_normal_exponent = infinite_exponent - 1; 1239 1240 // Apply the exponent bias to encode it for the result. Doing this early makes 1241 // it easy to detect values that will be infinite or subnormal. 1242 exponent += max_normal_exponent >> 1; 1243 1244 if (exponent > max_normal_exponent) { 1245 // Overflow: the input is too large for the result type to represent. 1246 if (round_mode == FPTieEven) { 1247 // FPTieEven rounding mode handles overflows using infinities. 1248 exponent = infinite_exponent; 1249 mantissa = 0; 1250 } else { 1251 VIXL_ASSERT(round_mode == FPRoundOdd); 1252 // FPRoundOdd rounding mode handles overflows using the largest magnitude 1253 // normal number. 1254 exponent = max_normal_exponent; 1255 mantissa = (UINT64_C(1) << exponent_offset) - 1; 1256 } 1257 return static_cast<T>((sign << sign_offset) | 1258 (exponent << exponent_offset) | 1259 (mantissa << mantissa_offset)); 1260 } 1261 1262 // Calculate the shift required to move the top mantissa bit to the proper 1263 // place in the destination type. 1264 const int highest_significant_bit = 63 - CountLeadingZeros(mantissa); 1265 int shift = highest_significant_bit - mbits; 1266 1267 if (exponent <= 0) { 1268 // The output will be subnormal (before rounding). 1269 // For subnormal outputs, the shift must be adjusted by the exponent. The +1 1270 // is necessary because the exponent of a subnormal value (encoded as 0) is 1271 // the same as the exponent of the smallest normal value (encoded as 1). 1272 shift += static_cast<int>(-exponent + 1); 1273 1274 // Handle inputs that would produce a zero output. 1275 // 1276 // Shifts higher than highest_significant_bit+1 will always produce a zero 1277 // result. A shift of exactly highest_significant_bit+1 might produce a 1278 // non-zero result after rounding. 1279 if (shift > (highest_significant_bit + 1)) { 1280 if (round_mode == FPTieEven) { 1281 // The result will always be +/-0.0. 1282 return static_cast<T>(sign << sign_offset); 1283 } else { 1284 VIXL_ASSERT(round_mode == FPRoundOdd); 1285 VIXL_ASSERT(mantissa != 0); 1286 // For FPRoundOdd, if the mantissa is too small to represent and 1287 // non-zero return the next "odd" value. 1288 return static_cast<T>((sign << sign_offset) | 1); 1289 } 1290 } 1291 1292 // Properly encode the exponent for a subnormal output. 1293 exponent = 0; 1294 } else { 1295 // Clear the topmost mantissa bit, since this is not encoded in IEEE-754 1296 // normal values. 1297 mantissa &= ~(UINT64_C(1) << highest_significant_bit); 1298 } 1299 1300 // The casts below are only well-defined for unsigned integers. 1301 VIXL_STATIC_ASSERT(std::numeric_limits<T>::is_integer); 1302 VIXL_STATIC_ASSERT(!std::numeric_limits<T>::is_signed); 1303 1304 if (shift > 0) { 1305 if (round_mode == FPTieEven) { 1306 // We have to shift the mantissa to the right. Some precision is lost, so 1307 // we need to apply rounding. 1308 uint64_t onebit_mantissa = (mantissa >> (shift)) & 1; 1309 uint64_t halfbit_mantissa = (mantissa >> (shift - 1)) & 1; 1310 uint64_t adjustment = (halfbit_mantissa & ~onebit_mantissa); 1311 uint64_t adjusted = mantissa - adjustment; 1312 T halfbit_adjusted = (adjusted >> (shift - 1)) & 1; 1313 1314 T result = 1315 static_cast<T>((sign << sign_offset) | (exponent << exponent_offset) | 1316 ((mantissa >> shift) << mantissa_offset)); 1317 1318 // A very large mantissa can overflow during rounding. If this happens, 1319 // the exponent should be incremented and the mantissa set to 1.0 1320 // (encoded as 0). Applying halfbit_adjusted after assembling the float 1321 // has the nice side-effect that this case is handled for free. 1322 // 1323 // This also handles cases where a very large finite value overflows to 1324 // infinity, or where a very large subnormal value overflows to become 1325 // normal. 1326 return result + halfbit_adjusted; 1327 } else { 1328 VIXL_ASSERT(round_mode == FPRoundOdd); 1329 // If any bits at position halfbit or below are set, onebit (ie. the 1330 // bottom bit of the resulting mantissa) must be set. 1331 uint64_t fractional_bits = mantissa & ((UINT64_C(1) << shift) - 1); 1332 if (fractional_bits != 0) { 1333 mantissa |= UINT64_C(1) << shift; 1334 } 1335 1336 return static_cast<T>((sign << sign_offset) | 1337 (exponent << exponent_offset) | 1338 ((mantissa >> shift) << mantissa_offset)); 1339 } 1340 } else { 1341 // We have to shift the mantissa to the left (or not at all). The input 1342 // mantissa is exactly representable in the output mantissa, so apply no 1343 // rounding correction. 1344 return static_cast<T>((sign << sign_offset) | 1345 (exponent << exponent_offset) | 1346 ((mantissa << -shift) << mantissa_offset)); 1347 } 1348 } 1349 1350 1351 // See FPRound for a description of this function. 1352 inline double FPRoundToDouble(int64_t sign, 1353 int64_t exponent, 1354 uint64_t mantissa, 1355 FPRounding round_mode) { 1356 uint64_t bits = 1357 FPRound<uint64_t, kDoubleExponentBits, kDoubleMantissaBits>(sign, 1358 exponent, 1359 mantissa, 1360 round_mode); 1361 return RawbitsToDouble(bits); 1362 } 1363 1364 1365 // See FPRound for a description of this function. 1366 inline Float16 FPRoundToFloat16(int64_t sign, 1367 int64_t exponent, 1368 uint64_t mantissa, 1369 FPRounding round_mode) { 1370 return RawbitsToFloat16( 1371 FPRound<uint16_t, kFloat16ExponentBits, kFloat16MantissaBits>( 1372 sign, exponent, mantissa, round_mode)); 1373 } 1374 1375 1376 // See FPRound for a description of this function. 1377 static inline float FPRoundToFloat(int64_t sign, 1378 int64_t exponent, 1379 uint64_t mantissa, 1380 FPRounding round_mode) { 1381 uint32_t bits = 1382 FPRound<uint32_t, kFloatExponentBits, kFloatMantissaBits>(sign, 1383 exponent, 1384 mantissa, 1385 round_mode); 1386 return RawbitsToFloat(bits); 1387 } 1388 1389 1390 float FPToFloat(Float16 value, UseDefaultNaN DN, bool* exception = NULL); 1391 float FPToFloat(double value, 1392 FPRounding round_mode, 1393 UseDefaultNaN DN, 1394 bool* exception = NULL); 1395 1396 double FPToDouble(Float16 value, UseDefaultNaN DN, bool* exception = NULL); 1397 double FPToDouble(float value, UseDefaultNaN DN, bool* exception = NULL); 1398 1399 Float16 FPToFloat16(float value, 1400 FPRounding round_mode, 1401 UseDefaultNaN DN, 1402 bool* exception = NULL); 1403 1404 Float16 FPToFloat16(double value, 1405 FPRounding round_mode, 1406 UseDefaultNaN DN, 1407 bool* exception = NULL); 1408 1409 // Like static_cast<T>(value), but with specialisations for the Float16 type. 1410 template <typename T, typename F> 1411 T StaticCastFPTo(F value) { 1412 return static_cast<T>(value); 1413 } 1414 1415 template <> 1416 inline float StaticCastFPTo<float, Float16>(Float16 value) { 1417 return FPToFloat(value, kIgnoreDefaultNaN); 1418 } 1419 1420 template <> 1421 inline double StaticCastFPTo<double, Float16>(Float16 value) { 1422 return FPToDouble(value, kIgnoreDefaultNaN); 1423 } 1424 1425 template <> 1426 inline Float16 StaticCastFPTo<Float16, float>(float value) { 1427 return FPToFloat16(value, FPTieEven, kIgnoreDefaultNaN); 1428 } 1429 1430 template <> 1431 inline Float16 StaticCastFPTo<Float16, double>(double value) { 1432 return FPToFloat16(value, FPTieEven, kIgnoreDefaultNaN); 1433 } 1434 1435 template <typename T> 1436 uint64_t FPToRawbitsWithSize(unsigned size_in_bits, T value) { 1437 switch (size_in_bits) { 1438 case 16: 1439 return Float16ToRawbits(StaticCastFPTo<Float16>(value)); 1440 case 32: 1441 return FloatToRawbits(StaticCastFPTo<float>(value)); 1442 case 64: 1443 return DoubleToRawbits(StaticCastFPTo<double>(value)); 1444 } 1445 VIXL_UNREACHABLE(); 1446 return 0; 1447 } 1448 1449 template <typename T> 1450 T RawbitsWithSizeToFP(unsigned size_in_bits, uint64_t value) { 1451 VIXL_ASSERT(IsUintN(size_in_bits, value)); 1452 switch (size_in_bits) { 1453 case 16: 1454 return StaticCastFPTo<T>(RawbitsToFloat16(static_cast<uint16_t>(value))); 1455 case 32: 1456 return StaticCastFPTo<T>(RawbitsToFloat(static_cast<uint32_t>(value))); 1457 case 64: 1458 return StaticCastFPTo<T>(RawbitsToDouble(value)); 1459 } 1460 VIXL_UNREACHABLE(); 1461 return 0; 1462 } 1463 1464 // Jenkins one-at-a-time hash, based on 1465 // https://en.wikipedia.org/wiki/Jenkins_hash_function citing 1466 // https://www.drdobbs.com/database/algorithm-alley/184410284. 1467 constexpr uint32_t Hash(const char* str, uint32_t hash = 0) { 1468 if (*str == '\0') { 1469 hash += hash << 3; 1470 hash ^= hash >> 11; 1471 hash += hash << 15; 1472 return hash; 1473 } else { 1474 hash += *str; 1475 hash += hash << 10; 1476 hash ^= hash >> 6; 1477 return Hash(str + 1, hash); 1478 } 1479 } 1480 1481 constexpr uint32_t operator""_h(const char* x, size_t) { return Hash(x); } 1482 1483 } // namespace vixl 1484 1485 #endif // VIXL_UTILS_H