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