| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- //-------------------------------------------------------------------------------------------------------
- // 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
- namespace Wasm
- {
- const uint64 specialDivLeftValue = (uint64)1 << 63;
- template<>
- inline int64 WasmMath::Rem( int64 aLeft, int64 aRight )
- {
- return (aLeft == specialDivLeftValue && aRight == -1) ? 0 : aLeft % aRight;
- }
- template<>
- inline uint64 WasmMath::Rem( uint64 aLeft, uint64 aRight )
- {
- return (aLeft == specialDivLeftValue && aRight == -1) ? specialDivLeftValue : aLeft % aRight;
- }
- 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)
- {
- return _copysign(aLeft, aRight);
- }
- template<>
- inline float WasmMath::Copysign(float aLeft, float aRight)
- {
- uint32 res = ((*(uint32*)(&aLeft) & 0x7fffffffu) | (*(uint32*)(&aRight) & 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 STYPE,
- typename UTYPE,
- UTYPE MAX,
- UTYPE NEG_ZERO,
- UTYPE NEG_ONE,
- WasmMath::CmpPtr<UTYPE> CMP1,
- WasmMath::CmpPtr<UTYPE> CMP2>
- bool WasmMath::isInRange(STYPE srcVal)
- {
- Assert(sizeof(STYPE) == sizeof(UTYPE));
- UTYPE val = *reinterpret_cast<UTYPE*> (&srcVal);
- return (CMP1(val, MAX)) || (val >= NEG_ZERO && CMP2(val, NEG_ONE));
- }
- 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);
- }
- }
|