mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-21 07:15:40 -04:00
Common: Add intrin.h
This commit is contained in:
@ -19,6 +19,7 @@ add_library(common
|
||||
file_system.h
|
||||
image.cpp
|
||||
image.h
|
||||
intrin.h
|
||||
hash_combine.h
|
||||
heap_array.h
|
||||
heterogeneous_containers.h
|
||||
|
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
@ -8,6 +8,130 @@
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
// Zero-extending helper
|
||||
template<typename TReturn, typename TValue>
|
||||
ALWAYS_INLINE constexpr TReturn ZeroExtend(TValue value)
|
||||
{
|
||||
return static_cast<TReturn>(static_cast<typename std::make_unsigned<TReturn>::type>(
|
||||
static_cast<typename std::make_unsigned<TValue>::type>(value)));
|
||||
}
|
||||
// Sign-extending helper
|
||||
template<typename TReturn, typename TValue>
|
||||
ALWAYS_INLINE constexpr TReturn SignExtend(TValue value)
|
||||
{
|
||||
return static_cast<TReturn>(
|
||||
static_cast<typename std::make_signed<TReturn>::type>(static_cast<typename std::make_signed<TValue>::type>(value)));
|
||||
}
|
||||
|
||||
// Type-specific helpers
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u16 ZeroExtend16(TValue value)
|
||||
{
|
||||
return ZeroExtend<u16, TValue>(value);
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u32 ZeroExtend32(TValue value)
|
||||
{
|
||||
return ZeroExtend<u32, TValue>(value);
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u64 ZeroExtend64(TValue value)
|
||||
{
|
||||
return ZeroExtend<u64, TValue>(value);
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u16 SignExtend16(TValue value)
|
||||
{
|
||||
return SignExtend<u16, TValue>(value);
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u32 SignExtend32(TValue value)
|
||||
{
|
||||
return SignExtend<u32, TValue>(value);
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u64 SignExtend64(TValue value)
|
||||
{
|
||||
return SignExtend<u64, TValue>(value);
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u8 Truncate8(TValue value)
|
||||
{
|
||||
return static_cast<u8>(static_cast<typename std::make_unsigned<decltype(value)>::type>(value));
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u16 Truncate16(TValue value)
|
||||
{
|
||||
return static_cast<u16>(static_cast<typename std::make_unsigned<decltype(value)>::type>(value));
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u32 Truncate32(TValue value)
|
||||
{
|
||||
return static_cast<u32>(static_cast<typename std::make_unsigned<decltype(value)>::type>(value));
|
||||
}
|
||||
|
||||
// BCD helpers
|
||||
ALWAYS_INLINE constexpr u8 BinaryToBCD(u8 value)
|
||||
{
|
||||
return ((value / 10) << 4) + (value % 10);
|
||||
}
|
||||
ALWAYS_INLINE constexpr u8 PackedBCDToBinary(u8 value)
|
||||
{
|
||||
return ((value >> 4) * 10) + (value % 16);
|
||||
}
|
||||
ALWAYS_INLINE constexpr u8 IsValidBCDDigit(u8 digit)
|
||||
{
|
||||
return (digit <= 9);
|
||||
}
|
||||
ALWAYS_INLINE constexpr u8 IsValidPackedBCD(u8 value)
|
||||
{
|
||||
return IsValidBCDDigit(value & 0x0F) && IsValidBCDDigit(value >> 4);
|
||||
}
|
||||
|
||||
// Boolean to integer
|
||||
ALWAYS_INLINE constexpr u8 BoolToUInt8(bool value)
|
||||
{
|
||||
return static_cast<u8>(value);
|
||||
}
|
||||
ALWAYS_INLINE constexpr u16 BoolToUInt16(bool value)
|
||||
{
|
||||
return static_cast<u16>(value);
|
||||
}
|
||||
ALWAYS_INLINE constexpr u32 BoolToUInt32(bool value)
|
||||
{
|
||||
return static_cast<u32>(value);
|
||||
}
|
||||
ALWAYS_INLINE constexpr u64 BoolToUInt64(bool value)
|
||||
{
|
||||
return static_cast<u64>(value);
|
||||
}
|
||||
|
||||
// Integer to boolean
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr bool ConvertToBool(TValue value)
|
||||
{
|
||||
return static_cast<bool>(value);
|
||||
}
|
||||
|
||||
// Unsafe integer to boolean
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE bool ConvertToBoolUnchecked(TValue value)
|
||||
{
|
||||
// static_assert(sizeof(uint8) == sizeof(bool));
|
||||
bool ret;
|
||||
std::memcpy(&ret, &value, sizeof(bool));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Generic sign extension
|
||||
template<int NBITS, typename T>
|
||||
ALWAYS_INLINE constexpr T SignExtendN(T value)
|
||||
{
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend
|
||||
constexpr int shift = 8 * sizeof(T) - NBITS;
|
||||
return static_cast<T>((static_cast<std::make_signed_t<T>>(value) << shift) >> shift);
|
||||
}
|
||||
|
||||
/// Returns the number of zero bits before the first set bit, going MSB->LSB.
|
||||
template<typename T>
|
||||
ALWAYS_INLINE unsigned CountLeadingZeros(T value)
|
||||
|
@ -20,6 +20,7 @@
|
||||
<ClInclude Include="http_downloader.h" />
|
||||
<ClInclude Include="http_downloader_winhttp.h" />
|
||||
<ClInclude Include="image.h" />
|
||||
<ClInclude Include="intrin.h" />
|
||||
<ClInclude Include="layered_settings_interface.h" />
|
||||
<ClInclude Include="log.h" />
|
||||
<ClInclude Include="lru_cache.h" />
|
||||
|
@ -43,6 +43,7 @@
|
||||
<ClInclude Include="sha1_digest.h" />
|
||||
<ClInclude Include="fastjmp.h" />
|
||||
<ClInclude Include="memmap.h" />
|
||||
<ClInclude Include="intrin.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="small_string.cpp" />
|
||||
|
26
src/common/intrin.h
Normal file
26
src/common/intrin.h
Normal file
@ -0,0 +1,26 @@
|
||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
// Includes appropriate intrinsic header based on platform.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#if defined(CPU_ARCH_X86) || defined(CPU_ARCH_X64)
|
||||
#define CPU_ARCH_SSE 1
|
||||
#include <emmintrin.h>
|
||||
#elif defined(CPU_ARCH_ARM64)
|
||||
#define CPU_ARCH_NEON 1
|
||||
#ifdef _MSC_VER
|
||||
#include <arm64_neon.h>
|
||||
#else
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <stdlib.h> // alloca
|
||||
#else
|
||||
#include <malloc.h> // alloca
|
||||
#endif
|
@ -180,130 +180,6 @@ static constexpr u32 HOST_PAGE_MASK = HOST_PAGE_SIZE - 1;
|
||||
static constexpr u32 HOST_PAGE_SHIFT = 12;
|
||||
#endif
|
||||
|
||||
// Zero-extending helper
|
||||
template<typename TReturn, typename TValue>
|
||||
ALWAYS_INLINE constexpr TReturn ZeroExtend(TValue value)
|
||||
{
|
||||
return static_cast<TReturn>(static_cast<typename std::make_unsigned<TReturn>::type>(
|
||||
static_cast<typename std::make_unsigned<TValue>::type>(value)));
|
||||
}
|
||||
// Sign-extending helper
|
||||
template<typename TReturn, typename TValue>
|
||||
ALWAYS_INLINE constexpr TReturn SignExtend(TValue value)
|
||||
{
|
||||
return static_cast<TReturn>(
|
||||
static_cast<typename std::make_signed<TReturn>::type>(static_cast<typename std::make_signed<TValue>::type>(value)));
|
||||
}
|
||||
|
||||
// Type-specific helpers
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u16 ZeroExtend16(TValue value)
|
||||
{
|
||||
return ZeroExtend<u16, TValue>(value);
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u32 ZeroExtend32(TValue value)
|
||||
{
|
||||
return ZeroExtend<u32, TValue>(value);
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u64 ZeroExtend64(TValue value)
|
||||
{
|
||||
return ZeroExtend<u64, TValue>(value);
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u16 SignExtend16(TValue value)
|
||||
{
|
||||
return SignExtend<u16, TValue>(value);
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u32 SignExtend32(TValue value)
|
||||
{
|
||||
return SignExtend<u32, TValue>(value);
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u64 SignExtend64(TValue value)
|
||||
{
|
||||
return SignExtend<u64, TValue>(value);
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u8 Truncate8(TValue value)
|
||||
{
|
||||
return static_cast<u8>(static_cast<typename std::make_unsigned<decltype(value)>::type>(value));
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u16 Truncate16(TValue value)
|
||||
{
|
||||
return static_cast<u16>(static_cast<typename std::make_unsigned<decltype(value)>::type>(value));
|
||||
}
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr u32 Truncate32(TValue value)
|
||||
{
|
||||
return static_cast<u32>(static_cast<typename std::make_unsigned<decltype(value)>::type>(value));
|
||||
}
|
||||
|
||||
// BCD helpers
|
||||
ALWAYS_INLINE constexpr u8 BinaryToBCD(u8 value)
|
||||
{
|
||||
return ((value / 10) << 4) + (value % 10);
|
||||
}
|
||||
ALWAYS_INLINE constexpr u8 PackedBCDToBinary(u8 value)
|
||||
{
|
||||
return ((value >> 4) * 10) + (value % 16);
|
||||
}
|
||||
ALWAYS_INLINE constexpr u8 IsValidBCDDigit(u8 digit)
|
||||
{
|
||||
return (digit <= 9);
|
||||
}
|
||||
ALWAYS_INLINE constexpr u8 IsValidPackedBCD(u8 value)
|
||||
{
|
||||
return IsValidBCDDigit(value & 0x0F) && IsValidBCDDigit(value >> 4);
|
||||
}
|
||||
|
||||
// Boolean to integer
|
||||
ALWAYS_INLINE constexpr u8 BoolToUInt8(bool value)
|
||||
{
|
||||
return static_cast<u8>(value);
|
||||
}
|
||||
ALWAYS_INLINE constexpr u16 BoolToUInt16(bool value)
|
||||
{
|
||||
return static_cast<u16>(value);
|
||||
}
|
||||
ALWAYS_INLINE constexpr u32 BoolToUInt32(bool value)
|
||||
{
|
||||
return static_cast<u32>(value);
|
||||
}
|
||||
ALWAYS_INLINE constexpr u64 BoolToUInt64(bool value)
|
||||
{
|
||||
return static_cast<u64>(value);
|
||||
}
|
||||
|
||||
// Integer to boolean
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE constexpr bool ConvertToBool(TValue value)
|
||||
{
|
||||
return static_cast<bool>(value);
|
||||
}
|
||||
|
||||
// Unsafe integer to boolean
|
||||
template<typename TValue>
|
||||
ALWAYS_INLINE bool ConvertToBoolUnchecked(TValue value)
|
||||
{
|
||||
// static_assert(sizeof(uint8) == sizeof(bool));
|
||||
bool ret;
|
||||
std::memcpy(&ret, &value, sizeof(bool));
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Generic sign extension
|
||||
template<int NBITS, typename T>
|
||||
ALWAYS_INLINE constexpr T SignExtendN(T value)
|
||||
{
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend
|
||||
constexpr int shift = 8 * sizeof(T) - NBITS;
|
||||
return static_cast<T>((static_cast<std::make_signed_t<T>>(value) << shift) >> shift);
|
||||
}
|
||||
|
||||
// Enum class bitwise operators
|
||||
#define IMPLEMENT_ENUM_CLASS_BITWISE_OPERATORS(type_) \
|
||||
ALWAYS_INLINE constexpr type_ operator&(type_ lhs, type_ rhs) \
|
||||
|
Reference in New Issue
Block a user