• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/utils.h"
14 #include "src/wasm/wasm-external-refs.h"
15 
16 namespace v8 {
17 namespace internal {
18 namespace wasm {
19 
f32_trunc_wrapper(float * param)20 void f32_trunc_wrapper(float* param) { *param = truncf(*param); }
21 
f32_floor_wrapper(float * param)22 void f32_floor_wrapper(float* param) { *param = floorf(*param); }
23 
f32_ceil_wrapper(float * param)24 void f32_ceil_wrapper(float* param) { *param = ceilf(*param); }
25 
f32_nearest_int_wrapper(float * param)26 void f32_nearest_int_wrapper(float* param) { *param = nearbyintf(*param); }
27 
f64_trunc_wrapper(double * param)28 void f64_trunc_wrapper(double* param) {
29   WriteDoubleValue(param, trunc(ReadDoubleValue(param)));
30 }
31 
f64_floor_wrapper(double * param)32 void f64_floor_wrapper(double* param) {
33   WriteDoubleValue(param, floor(ReadDoubleValue(param)));
34 }
35 
f64_ceil_wrapper(double * param)36 void f64_ceil_wrapper(double* param) {
37   WriteDoubleValue(param, ceil(ReadDoubleValue(param)));
38 }
39 
f64_nearest_int_wrapper(double * param)40 void f64_nearest_int_wrapper(double* param) {
41   WriteDoubleValue(param, nearbyint(ReadDoubleValue(param)));
42 }
43 
int64_to_float32_wrapper(int64_t * input,float * output)44 void int64_to_float32_wrapper(int64_t* input, float* output) {
45   *output = static_cast<float>(*input);
46 }
47 
uint64_to_float32_wrapper(uint64_t * input,float * output)48 void uint64_to_float32_wrapper(uint64_t* input, float* output) {
49 #if V8_CC_MSVC
50   // With MSVC we use static_cast<float>(uint32_t) instead of
51   // static_cast<float>(uint64_t) to achieve round-to-nearest-ties-even
52   // semantics. The idea is to calculate
53   // static_cast<float>(high_word) * 2^32 + static_cast<float>(low_word). To
54   // achieve proper rounding in all cases we have to adjust the high_word
55   // with a "rounding bit" sometimes. The rounding bit is stored in the LSB of
56   // the high_word if the low_word may affect the rounding of the high_word.
57   uint32_t low_word = static_cast<uint32_t>(*input & 0xffffffff);
58   uint32_t high_word = static_cast<uint32_t>(*input >> 32);
59 
60   float shift = static_cast<float>(1ull << 32);
61   // If the MSB of the high_word is set, then we make space for a rounding bit.
62   if (high_word < 0x80000000) {
63     high_word <<= 1;
64     shift = static_cast<float>(1ull << 31);
65   }
66 
67   if ((high_word & 0xfe000000) && low_word) {
68     // Set the rounding bit.
69     high_word |= 1;
70   }
71 
72   float result = static_cast<float>(high_word);
73   result *= shift;
74   result += static_cast<float>(low_word);
75   *output = result;
76 
77 #else
78   *output = static_cast<float>(*input);
79 #endif
80 }
81 
int64_to_float64_wrapper(int64_t * input,double * output)82 void int64_to_float64_wrapper(int64_t* input, double* output) {
83   *output = static_cast<double>(*input);
84 }
85 
uint64_to_float64_wrapper(uint64_t * input,double * output)86 void uint64_to_float64_wrapper(uint64_t* input, double* output) {
87 #if V8_CC_MSVC
88   // With MSVC we use static_cast<double>(uint32_t) instead of
89   // static_cast<double>(uint64_t) to achieve round-to-nearest-ties-even
90   // semantics. The idea is to calculate
91   // static_cast<double>(high_word) * 2^32 + static_cast<double>(low_word).
92   uint32_t low_word = static_cast<uint32_t>(*input & 0xffffffff);
93   uint32_t high_word = static_cast<uint32_t>(*input >> 32);
94 
95   double shift = static_cast<double>(1ull << 32);
96 
97   double result = static_cast<double>(high_word);
98   result *= shift;
99   result += static_cast<double>(low_word);
100   *output = result;
101 
102 #else
103   *output = static_cast<double>(*input);
104 #endif
105 }
106 
float32_to_int64_wrapper(float * input,int64_t * output)107 int32_t float32_to_int64_wrapper(float* input, int64_t* output) {
108   // We use "<" here to check the upper bound because of rounding problems: With
109   // "<=" some inputs would be considered within int64 range which are actually
110   // not within int64 range.
111   if (*input >= static_cast<float>(std::numeric_limits<int64_t>::min()) &&
112       *input < static_cast<float>(std::numeric_limits<int64_t>::max())) {
113     *output = static_cast<int64_t>(*input);
114     return 1;
115   }
116   return 0;
117 }
118 
float32_to_uint64_wrapper(float * input,uint64_t * output)119 int32_t float32_to_uint64_wrapper(float* input, uint64_t* output) {
120   // We use "<" here to check the upper bound because of rounding problems: With
121   // "<=" some inputs would be considered within uint64 range which are actually
122   // not within uint64 range.
123   if (*input > -1.0 &&
124       *input < static_cast<float>(std::numeric_limits<uint64_t>::max())) {
125     *output = static_cast<uint64_t>(*input);
126     return 1;
127   }
128   return 0;
129 }
130 
float64_to_int64_wrapper(double * input,int64_t * output)131 int32_t float64_to_int64_wrapper(double* input, int64_t* output) {
132   // We use "<" here to check the upper bound because of rounding problems: With
133   // "<=" some inputs would be considered within int64 range which are actually
134   // not within int64 range.
135   if (*input >= static_cast<double>(std::numeric_limits<int64_t>::min()) &&
136       *input < static_cast<double>(std::numeric_limits<int64_t>::max())) {
137     *output = static_cast<int64_t>(*input);
138     return 1;
139   }
140   return 0;
141 }
142 
float64_to_uint64_wrapper(double * input,uint64_t * output)143 int32_t float64_to_uint64_wrapper(double* input, uint64_t* output) {
144   // We use "<" here to check the upper bound because of rounding problems: With
145   // "<=" some inputs would be considered within uint64 range which are actually
146   // not within uint64 range.
147   if (*input > -1.0 &&
148       *input < static_cast<double>(std::numeric_limits<uint64_t>::max())) {
149     *output = static_cast<uint64_t>(*input);
150     return 1;
151   }
152   return 0;
153 }
154 
int64_div_wrapper(int64_t * dst,int64_t * src)155 int32_t int64_div_wrapper(int64_t* dst, int64_t* src) {
156   if (*src == 0) {
157     return 0;
158   }
159   if (*src == -1 && *dst == std::numeric_limits<int64_t>::min()) {
160     return -1;
161   }
162   *dst /= *src;
163   return 1;
164 }
165 
int64_mod_wrapper(int64_t * dst,int64_t * src)166 int32_t int64_mod_wrapper(int64_t* dst, int64_t* src) {
167   if (*src == 0) {
168     return 0;
169   }
170   *dst %= *src;
171   return 1;
172 }
173 
uint64_div_wrapper(uint64_t * dst,uint64_t * src)174 int32_t uint64_div_wrapper(uint64_t* dst, uint64_t* src) {
175   if (*src == 0) {
176     return 0;
177   }
178   *dst /= *src;
179   return 1;
180 }
181 
uint64_mod_wrapper(uint64_t * dst,uint64_t * src)182 int32_t uint64_mod_wrapper(uint64_t* dst, uint64_t* src) {
183   if (*src == 0) {
184     return 0;
185   }
186   *dst %= *src;
187   return 1;
188 }
189 
word32_ctz_wrapper(uint32_t * input)190 uint32_t word32_ctz_wrapper(uint32_t* input) {
191   return static_cast<uint32_t>(base::bits::CountTrailingZeros32(*input));
192 }
193 
word64_ctz_wrapper(uint64_t * input)194 uint32_t word64_ctz_wrapper(uint64_t* input) {
195   return static_cast<uint32_t>(base::bits::CountTrailingZeros64(*input));
196 }
197 
word32_popcnt_wrapper(uint32_t * input)198 uint32_t word32_popcnt_wrapper(uint32_t* input) {
199   return static_cast<uint32_t>(base::bits::CountPopulation(*input));
200 }
201 
word64_popcnt_wrapper(uint64_t * input)202 uint32_t word64_popcnt_wrapper(uint64_t* input) {
203   return static_cast<uint32_t>(base::bits::CountPopulation(*input));
204 }
205 
float64_pow_wrapper(double * param0,double * param1)206 void float64_pow_wrapper(double* param0, double* param1) {
207   double x = ReadDoubleValue(param0);
208   double y = ReadDoubleValue(param1);
209   WriteDoubleValue(param0, Pow(x, y));
210 }
211 
212 static WasmTrapCallbackForTesting wasm_trap_callback_for_testing = nullptr;
213 
set_trap_callback_for_testing(WasmTrapCallbackForTesting callback)214 void set_trap_callback_for_testing(WasmTrapCallbackForTesting callback) {
215   wasm_trap_callback_for_testing = callback;
216 }
217 
call_trap_callback_for_testing()218 void call_trap_callback_for_testing() {
219   if (wasm_trap_callback_for_testing) {
220     wasm_trap_callback_for_testing();
221   }
222 }
223 
224 }  // namespace wasm
225 }  // namespace internal
226 }  // namespace v8
227