1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_ARM64_UTILS_ARM64_H_ 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_ARM64_UTILS_ARM64_H_ 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <cmath> 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/constants-arm64.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// These are global assumptions in v8. 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSTATIC_ASSERT((static_cast<int32_t>(-1) >> 1) == -1); 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSTATIC_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7FFFFFFF); 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Floating point representation. 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline uint32_t float_to_rawbits(float value) { 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t bits = 0; 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch memcpy(&bits, &value, 4); 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return bits; 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline uint64_t double_to_rawbits(double value) { 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t bits = 0; 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch memcpy(&bits, &value, 8); 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return bits; 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline float rawbits_to_float(uint32_t bits) { 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch float value = 0.0; 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch memcpy(&value, &bits, 4); 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return value; 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic inline double rawbits_to_double(uint64_t bits) { 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double value = 0.0; 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch memcpy(&value, &bits, 8); 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return value; 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Bit counting. 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint CountLeadingZeros(uint64_t value, int width); 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint CountLeadingSignBits(int64_t value, int width); 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint CountTrailingZeros(uint64_t value, int width); 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint CountSetBits(uint64_t value, int width); 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochuint64_t LargestPowerOf2Divisor(uint64_t value); 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint MaskToBit(uint64_t mask); 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <typename T> 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochT ReverseBytes(T value, int block_bytes_log2) { 59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK((sizeof(value) == 4) || (sizeof(value) == 8)); 60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK((1U << block_bytes_log2) <= sizeof(value)); 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Split the 64-bit value into an 8-bit array, where b[0] is the least 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // significant byte, and b[7] is the most significant. 63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint8_t bytes[8]; 64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint64_t mask = 0xff00000000000000; 65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 7; i >= 0; i--) { 66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bytes[i] = (static_cast<uint64_t>(value) & mask) >> (i * 8); 67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mask >>= 8; 68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Permutation tables for REV instructions. 71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // permute_table[0] is used by REV16_x, REV16_w 72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // permute_table[1] is used by REV32_x, REV_w 73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // permute_table[2] is used by REV_x 74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK((0 < block_bytes_log2) && (block_bytes_log2 < 4)); 75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static const uint8_t permute_table[3][8] = {{6, 7, 4, 5, 2, 3, 0, 1}, 76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch {4, 5, 6, 7, 0, 1, 2, 3}, 77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch {0, 1, 2, 3, 4, 5, 6, 7}}; 78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch T result = 0; 79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < 8; i++) { 80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result <<= 8; 81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result |= bytes[permute_table[block_bytes_log2 - 1][i]]; 82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return result; 84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// NaN tests. 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline bool IsSignallingNaN(double num) { 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t raw = double_to_rawbits(num); 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (std::isnan(num) && ((raw & kDQuietNanMask) == 0)) { 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline bool IsSignallingNaN(float num) { 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t raw = float_to_rawbits(num); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (std::isnan(num) && ((raw & kSQuietNanMask) == 0)) { 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T> 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline bool IsQuietNaN(T num) { 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return std::isnan(num) && !IsSignallingNaN(num); 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Convert the NaN in 'num' to a quiet NaN. 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline double ToQuietNaN(double num) { 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(std::isnan(num)); 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return rawbits_to_double(double_to_rawbits(num) | kDQuietNanMask); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline float ToQuietNaN(float num) { 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(std::isnan(num)); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return rawbits_to_float(float_to_rawbits(num) | kSQuietNanMask); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Fused multiply-add. 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline double FusedMultiplyAdd(double op1, double op2, double a) { 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return fma(op1, op2, a); 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline float FusedMultiplyAdd(float op1, float op2, float a) { 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return fmaf(op1, op2, a); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_ARM64_UTILS_ARM64_H_ 139