| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- using namespace Wasm;
- template<typename T>
- inline T WasmMath::Shl( T aLeft, T aRight )
- {
- return aLeft << (aRight & (sizeof(T)*8-1));
- }
- template<typename T>
- inline T WasmMath::Shr( T aLeft, T aRight )
- {
- return aLeft >> (aRight & (sizeof(T)*8-1));
- }
- template<typename T>
- inline T WasmMath::ShrU( T aLeft, T aRight )
- {
- return aLeft >> (aRight & (sizeof(T)*8-1));
- }
- template<>
- inline int WasmMath::Ctz(int value)
- {
- DWORD index;
- if (_BitScanForward(&index, value))
- {
- return index;
- }
- return 32;
- }
- template<>
- inline int64 WasmMath::Ctz(int64 value)
- {
- DWORD index;
- #if TARGET_64
- if (_BitScanForward64(&index, value))
- {
- return index;
- }
- #else
- if (_BitScanForward(&index, (int32)value))
- {
- return index;
- }
- if (_BitScanForward(&index, (int32)(value >> 32)))
- {
- return index + 32;
- }
- #endif
- return 64;
- }
- template<>
- inline int64 WasmMath::Clz(int64 value)
- {
- DWORD index;
- #if TARGET_64
- if (_BitScanReverse64(&index, value))
- {
- return 63 - index;
- }
- #else
- if (_BitScanReverse(&index, (int32)(value >> 32)))
- {
- return 31 - index;
- }
- if (_BitScanReverse(&index, (int32)value))
- {
- return 63 - index;
- }
- #endif
- return 64;
- }
- template<>
- inline int WasmMath::PopCnt(int value)
- {
- return ::Math::PopCnt32(value);
- }
- template<>
- inline int64 WasmMath::PopCnt(int64 value)
- {
- uint64 v = (uint64)value;
- // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
- v = v - ((v >> 1) & 0x5555555555555555LL);
- v = (v & 0x3333333333333333LL) + ((v >> 2) & 0x3333333333333333LL);
- v = (v + (v >> 4)) & 0x0f0f0f0f0f0f0f0f;
- v = (uint64)(v * 0x0101010101010101LL) >> (sizeof(uint64) - 1) * CHAR_BIT;
- return (int64)v;
- }
- template<typename T>
- inline int WasmMath::Eqz(T value)
- {
- return value == 0;
- }
- template<>
- inline double WasmMath::Copysign(double aLeft, double aRight)
- {
- uint64 aLeftI64 = *(uint64*)(&aLeft);
- uint64 aRightI64 = *(uint64*)(&aRight);
- uint64 res = ((aLeftI64 & 0x7fffffffffffffffull) | (aRightI64 & 0x8000000000000000ull));
- return *(double*)(&res);
- }
- template<>
- inline float WasmMath::Copysign(float aLeft, float aRight)
- {
- uint32 aLeftI32 = *(uint32*)(&aLeft);
- uint32 aRightI32 = *(uint32*)(&aRight);
- uint32 res = ((aLeftI32 & 0x7fffffffu) | (aRightI32 & 0x80000000u));
- return *(float*)(&res);
- }
- template <typename T> bool WasmMath::LessThan(T aLeft, T aRight)
- {
- return aLeft < aRight;
- }
- template <typename T> bool WasmMath::LessOrEqual(T aLeft, T aRight)
- {
- return aLeft <= aRight;
- }
- template <
- typename SrcType,
- typename DstType,
- typename ReinterpretType,
- ReinterpretType Max,
- ReinterpretType NegZero,
- ReinterpretType NegOne,
- WasmMath::CmpPtr<ReinterpretType> MaxCmp,
- WasmMath::CmpPtr<ReinterpretType> NegOneCmp,
- bool Saturate,
- DstType MinResult,
- DstType MaxResult>
- DstType WasmMath::ConvertFloatToInt(SrcType srcVal, _In_ Js::ScriptContext * scriptContext)
- {
- CompileAssert(sizeof(SrcType) == sizeof(ReinterpretType));
- if (IsNaN(srcVal))
- {
- if (!Saturate)
- {
- Js::JavascriptError::ThrowWebAssemblyRuntimeError(scriptContext, VBSERR_Overflow);
- }
- return 0;
- }
- // TODO NumberUtilities::ToSpecial
- ReinterpretType val = *reinterpret_cast<ReinterpretType*> (&srcVal);
- if (MaxCmp(val, Max) || (val >= NegZero && NegOneCmp(val, NegOne)))
- {
- return static_cast<DstType>(srcVal);
- }
- if (!Saturate)
- {
- Js::JavascriptError::ThrowWebAssemblyRuntimeError(scriptContext, VBSERR_Overflow);
- }
- return (srcVal < 0) ? MinResult : MaxResult;
- }
- template <typename STYPE> bool WasmMath::IsNaN(STYPE src)
- {
- return src != src;
- }
- template<typename T>
- inline T WasmMath::Trunc(T value)
- {
- if (value == 0.0)
- {
- return value;
- }
- else
- {
- T result;
- if (value < 0.0)
- {
- result = ceil(value);
- }
- else
- {
- result = floor(value);
- }
- // TODO: Propagating NaN sign for now awaiting consensus on semantics
- return result;
- }
- }
- template<typename T>
- inline T WasmMath::Nearest(T value)
- {
- if (value == 0.0)
- {
- return value;
- }
- else
- {
- T result;
- T u = ceil(value);
- T d = floor(value);
- T um = fabs(value - u);
- T dm = fabs(value - d);
- if (um < dm || (um == dm && floor(u / 2) == u / 2))
- {
- result = u;
- }
- else
- {
- result = d;
- }
- // TODO: Propagating NaN sign for now awaiting consensus on semantics
- return result;
- }
- }
- template<>
- inline int WasmMath::Rol(int aLeft, int aRight)
- {
- return _rotl(aLeft, aRight);
- }
- template<>
- inline int64 WasmMath::Rol(int64 aLeft, int64 aRight)
- {
- return _rotl64(aLeft, (int)aRight);
- }
- template<>
- inline int WasmMath::Ror(int aLeft, int aRight)
- {
- return _rotr(aLeft, aRight);
- }
- template<>
- inline int64 WasmMath::Ror(int64 aLeft, int64 aRight)
- {
- return _rotr64(aLeft, (int)aRight);
- }
- template<typename To, typename From>
- To WasmMath::SignExtend(To value)
- {
- return static_cast<To>(static_cast<From>(value));
- }
- template <bool Saturate>
- int32 WasmMath::F32ToI32(float src, _In_ Js::ScriptContext* scriptContext)
- {
- return WasmMath::ConvertFloatToInt<
- float, // SrcType
- int32, // DstType
- uint32, // ReinterpretType
- Js::NumberConstants::k_Float32TwoTo31,
- Js::NumberConstants::k_Float32NegZero,
- Js::NumberConstants::k_Float32NegTwoTo31,
- &WasmMath::LessThan<uint32>,
- &WasmMath::LessOrEqual<uint32>,
- Saturate,
- INT32_MIN,
- INT32_MAX>(
- src,
- scriptContext);
- }
- template <bool Saturate>
- uint32 WasmMath::F32ToU32(float src, _In_ Js::ScriptContext* scriptContext)
- {
- return WasmMath::ConvertFloatToInt<
- float, // SrcType
- uint32, // DstType
- uint32, // ReinterpretType
- Js::NumberConstants::k_Float32TwoTo32,
- Js::NumberConstants::k_Float32NegZero,
- Js::NumberConstants::k_Float32NegOne,
- &WasmMath::LessThan<uint32>,
- &WasmMath::LessThan<uint32>,
- Saturate,
- 0,
- UINT32_MAX>(
- src,
- scriptContext);
- }
- template <bool Saturate>
- int32 WasmMath::F64ToI32(double src, _In_ Js::ScriptContext* scriptContext)
- {
- return WasmMath::ConvertFloatToInt<
- double, // SrcType
- int32, // DstType
- uint64, // ReinterpretType
- Js::NumberConstants::k_TwoTo31,
- Js::NumberConstants::k_NegZero,
- Js::NumberConstants::k_NegTwoTo31,
- &WasmMath::LessOrEqual<uint64>,
- &WasmMath::LessOrEqual<uint64>,
- Saturate,
- INT32_MIN,
- INT32_MAX>(
- src,
- scriptContext);
- }
- template <bool Saturate>
- uint32 WasmMath::F64ToU32(double src, _In_ Js::ScriptContext* scriptContext)
- {
- return WasmMath::ConvertFloatToInt<
- double, // SrcType
- uint32, // DstType
- uint64, // ReinterpretType
- Js::NumberConstants::k_TwoTo32,
- Js::NumberConstants::k_NegZero,
- Js::NumberConstants::k_NegOne,
- &WasmMath::LessOrEqual<uint64>,
- &WasmMath::LessThan<uint64>,
- Saturate,
- 0,
- UINT32_MAX>(
- src,
- scriptContext);
- }
- template <bool Saturate>
- int64 WasmMath::F32ToI64(float src, _In_ Js::ScriptContext* scriptContext)
- {
- return WasmMath::ConvertFloatToInt<
- float, // SrcType
- int64, // DstType
- uint32, // ReinterpretType
- Js::NumberConstants::k_Float32TwoTo63,
- Js::NumberConstants::k_Float32NegZero,
- Js::NumberConstants::k_Float32NegTwoTo63,
- &WasmMath::LessThan<uint32>,
- &WasmMath::LessOrEqual<uint32>,
- Saturate,
- INT64_MIN,
- INT64_MAX>(
- src,
- scriptContext);
- }
- template <bool Saturate>
- uint64 WasmMath::F32ToU64(float src, _In_ Js::ScriptContext* scriptContext)
- {
- return WasmMath::ConvertFloatToInt<
- float, // SrcType
- uint64, // DstType
- uint32, // ReinterpretType
- Js::NumberConstants::k_Float32TwoTo64,
- Js::NumberConstants::k_Float32NegZero,
- Js::NumberConstants::k_Float32NegOne,
- &WasmMath::LessThan<uint32>,
- &WasmMath::LessThan<uint32>,
- Saturate,
- 0,
- UINT64_MAX>(
- src,
- scriptContext);
- }
- template <bool Saturate>
- int64 WasmMath::F64ToI64(double src, _In_ Js::ScriptContext* scriptContext)
- {
- return WasmMath::ConvertFloatToInt<
- double, // SrcType
- int64, // DstType
- uint64, // ReinterpretType
- Js::NumberConstants::k_TwoTo63,
- Js::NumberConstants::k_NegZero,
- Js::NumberConstants::k_NegTwoTo63,
- &WasmMath::LessThan<uint64>,
- &WasmMath::LessOrEqual<uint64>,
- Saturate,
- INT64_MIN,
- INT64_MAX>(
- src,
- scriptContext);
- }
- template <bool Saturate>
- uint64 WasmMath::F64ToU64(double src, _In_ Js::ScriptContext* scriptContext)
- {
- return WasmMath::ConvertFloatToInt<
- double, // SrcType
- uint64, // DstType
- uint64, // ReinterpretType
- Js::NumberConstants::k_TwoTo64,
- Js::NumberConstants::k_NegZero,
- Js::NumberConstants::k_NegOne,
- &WasmMath::LessThan<uint64>,
- &WasmMath::LessThan<uint64>,
- Saturate,
- 0,
- UINT64_MAX>(
- src,
- scriptContext);
- }
|