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