1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <math.h> 6 #include <stdint.h> 7 #include <stdlib.h> 8 #include <limits> 9 10 #include "include/v8config.h" 11 12 #include "src/base/bits.h" 13 #include "src/wasm/wasm-external-refs.h" 14 15 namespace v8 { 16 namespace internal { 17 namespace wasm { 18 19 void f32_trunc_wrapper(float* param) { *param = truncf(*param); } 20 21 void f32_floor_wrapper(float* param) { *param = floorf(*param); } 22 23 void f32_ceil_wrapper(float* param) { *param = ceilf(*param); } 24 25 void f32_nearest_int_wrapper(float* param) { *param = nearbyintf(*param); } 26 27 void f64_trunc_wrapper(double* param) { *param = trunc(*param); } 28 29 void f64_floor_wrapper(double* param) { *param = floor(*param); } 30 31 void f64_ceil_wrapper(double* param) { *param = ceil(*param); } 32 33 void f64_nearest_int_wrapper(double* param) { *param = nearbyint(*param); } 34 35 void int64_to_float32_wrapper(int64_t* input, float* output) { 36 *output = static_cast<float>(*input); 37 } 38 39 void uint64_to_float32_wrapper(uint64_t* input, float* output) { 40 #if V8_CC_MSVC 41 // With MSVC we use static_cast<float>(uint32_t) instead of 42 // static_cast<float>(uint64_t) to achieve round-to-nearest-ties-even 43 // semantics. The idea is to calculate 44 // static_cast<float>(high_word) * 2^32 + static_cast<float>(low_word). To 45 // achieve proper rounding in all cases we have to adjust the high_word 46 // with a "rounding bit" sometimes. The rounding bit is stored in the LSB of 47 // the high_word if the low_word may affect the rounding of the high_word. 48 uint32_t low_word = static_cast<uint32_t>(*input & 0xffffffff); 49 uint32_t high_word = static_cast<uint32_t>(*input >> 32); 50 51 float shift = static_cast<float>(1ull << 32); 52 // If the MSB of the high_word is set, then we make space for a rounding bit. 53 if (high_word < 0x80000000) { 54 high_word <<= 1; 55 shift = static_cast<float>(1ull << 31); 56 } 57 58 if ((high_word & 0xfe000000) && low_word) { 59 // Set the rounding bit. 60 high_word |= 1; 61 } 62 63 float result = static_cast<float>(high_word); 64 result *= shift; 65 result += static_cast<float>(low_word); 66 *output = result; 67 68 #else 69 *output = static_cast<float>(*input); 70 #endif 71 } 72 73 void int64_to_float64_wrapper(int64_t* input, double* output) { 74 *output = static_cast<double>(*input); 75 } 76 77 void uint64_to_float64_wrapper(uint64_t* input, double* output) { 78 #if V8_CC_MSVC 79 // With MSVC we use static_cast<double>(uint32_t) instead of 80 // static_cast<double>(uint64_t) to achieve round-to-nearest-ties-even 81 // semantics. The idea is to calculate 82 // static_cast<double>(high_word) * 2^32 + static_cast<double>(low_word). 83 uint32_t low_word = static_cast<uint32_t>(*input & 0xffffffff); 84 uint32_t high_word = static_cast<uint32_t>(*input >> 32); 85 86 double shift = static_cast<double>(1ull << 32); 87 88 double result = static_cast<double>(high_word); 89 result *= shift; 90 result += static_cast<double>(low_word); 91 *output = result; 92 93 #else 94 *output = static_cast<double>(*input); 95 #endif 96 } 97 98 int32_t float32_to_int64_wrapper(float* input, int64_t* output) { 99 // We use "<" here to check the upper bound because of rounding problems: With 100 // "<=" some inputs would be considered within int64 range which are actually 101 // not within int64 range. 102 if (*input >= static_cast<float>(std::numeric_limits<int64_t>::min()) && 103 *input < static_cast<float>(std::numeric_limits<int64_t>::max())) { 104 *output = static_cast<int64_t>(*input); 105 return 1; 106 } 107 return 0; 108 } 109 110 int32_t float32_to_uint64_wrapper(float* input, uint64_t* output) { 111 // We use "<" here to check the upper bound because of rounding problems: With 112 // "<=" some inputs would be considered within uint64 range which are actually 113 // not within uint64 range. 114 if (*input > -1.0 && 115 *input < static_cast<float>(std::numeric_limits<uint64_t>::max())) { 116 *output = static_cast<uint64_t>(*input); 117 return 1; 118 } 119 return 0; 120 } 121 122 int32_t float64_to_int64_wrapper(double* input, int64_t* output) { 123 // We use "<" here to check the upper bound because of rounding problems: With 124 // "<=" some inputs would be considered within int64 range which are actually 125 // not within int64 range. 126 if (*input >= static_cast<double>(std::numeric_limits<int64_t>::min()) && 127 *input < static_cast<double>(std::numeric_limits<int64_t>::max())) { 128 *output = static_cast<int64_t>(*input); 129 return 1; 130 } 131 return 0; 132 } 133 134 int32_t float64_to_uint64_wrapper(double* input, uint64_t* output) { 135 // We use "<" here to check the upper bound because of rounding problems: With 136 // "<=" some inputs would be considered within uint64 range which are actually 137 // not within uint64 range. 138 if (*input > -1.0 && 139 *input < static_cast<double>(std::numeric_limits<uint64_t>::max())) { 140 *output = static_cast<uint64_t>(*input); 141 return 1; 142 } 143 return 0; 144 } 145 146 int32_t int64_div_wrapper(int64_t* dst, int64_t* src) { 147 if (*src == 0) { 148 return 0; 149 } 150 if (*src == -1 && *dst == std::numeric_limits<int64_t>::min()) { 151 return -1; 152 } 153 *dst /= *src; 154 return 1; 155 } 156 157 int32_t int64_mod_wrapper(int64_t* dst, int64_t* src) { 158 if (*src == 0) { 159 return 0; 160 } 161 *dst %= *src; 162 return 1; 163 } 164 165 int32_t uint64_div_wrapper(uint64_t* dst, uint64_t* src) { 166 if (*src == 0) { 167 return 0; 168 } 169 *dst /= *src; 170 return 1; 171 } 172 173 int32_t uint64_mod_wrapper(uint64_t* dst, uint64_t* src) { 174 if (*src == 0) { 175 return 0; 176 } 177 *dst %= *src; 178 return 1; 179 } 180 181 uint32_t word32_ctz_wrapper(uint32_t* input) { 182 return static_cast<uint32_t>(base::bits::CountTrailingZeros32(*input)); 183 } 184 185 uint32_t word64_ctz_wrapper(uint64_t* input) { 186 return static_cast<uint32_t>(base::bits::CountTrailingZeros64(*input)); 187 } 188 189 uint32_t word32_popcnt_wrapper(uint32_t* input) { 190 return static_cast<uint32_t>(base::bits::CountPopulation(*input)); 191 } 192 193 uint32_t word64_popcnt_wrapper(uint64_t* input) { 194 return static_cast<uint32_t>(base::bits::CountPopulation(*input)); 195 } 196 197 } // namespace wasm 198 } // namespace internal 199 } // namespace v8 200