123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- // SPDX-License-Identifier: Apache-2.0
- // ----------------------------------------------------------------------------
- // Copyright 2020-2022 Arm Limited
- //
- // Licensed under the Apache License, Version 2.0 (the "License"); you may not
- // use this file except in compliance with the License. You may obtain a copy
- // of the License at:
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- // License for the specific language governing permissions and limitations
- // under the License.
- // ----------------------------------------------------------------------------
- /**
- * @brief Platform-specific function implementations.
- *
- * This module contains functions for querying the host extended ISA support.
- */
- // Include before the defines below to pick up any auto-setup based on compiler
- // built-in config, if not being set explicitly by the build system
- #include "astcenc_internal.h"
- #if (ASTCENC_SSE > 0) || (ASTCENC_AVX > 0) || \
- (ASTCENC_POPCNT > 0) || (ASTCENC_F16C > 0)
- static bool g_init { false };
- /** Does this CPU support SSE 4.1? Set to -1 if not yet initialized. */
- static bool g_cpu_has_sse41 { false };
- /** Does this CPU support AVX2? Set to -1 if not yet initialized. */
- static bool g_cpu_has_avx2 { false };
- /** Does this CPU support POPCNT? Set to -1 if not yet initialized. */
- static bool g_cpu_has_popcnt { false };
- /** Does this CPU support F16C? Set to -1 if not yet initialized. */
- static bool g_cpu_has_f16c { false };
- /* ============================================================================
- Platform code for Visual Studio
- ============================================================================ */
- #if !defined(__clang__) && defined(_MSC_VER)
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #include <intrin.h>
- /**
- * @brief Detect platform CPU ISA support and update global trackers.
- */
- static void detect_cpu_isa()
- {
- int data[4];
- __cpuid(data, 0);
- int num_id = data[0];
- if (num_id >= 1)
- {
- __cpuidex(data, 1, 0);
- // SSE41 = Bank 1, ECX, bit 19
- g_cpu_has_sse41 = data[2] & (1 << 19) ? true : false;
- // POPCNT = Bank 1, ECX, bit 23
- g_cpu_has_popcnt = data[2] & (1 << 23) ? true : false;
- // F16C = Bank 1, ECX, bit 29
- g_cpu_has_f16c = data[2] & (1 << 29) ? true : false;
- }
- if (num_id >= 7)
- {
- __cpuidex(data, 7, 0);
- // AVX2 = Bank 7, EBX, bit 5
- g_cpu_has_avx2 = data[1] & (1 << 5) ? true : false;
- }
- // Ensure state bits are updated before init flag is updated
- MemoryBarrier();
- g_init = true;
- }
- /* ============================================================================
- Platform code for GCC and Clang
- ============================================================================ */
- #else
- #include <cpuid.h>
- /**
- * @brief Detect platform CPU ISA support and update global trackers.
- */
- static void detect_cpu_isa()
- {
- unsigned int data[4];
- if (__get_cpuid_count(1, 0, &data[0], &data[1], &data[2], &data[3]))
- {
- // SSE41 = Bank 1, ECX, bit 19
- g_cpu_has_sse41 = data[2] & (1 << 19) ? true : false;
- // POPCNT = Bank 1, ECX, bit 23
- g_cpu_has_popcnt = data[2] & (1 << 23) ? true : false;
- // F16C = Bank 1, ECX, bit 29
- g_cpu_has_f16c = data[2] & (1 << 29) ? true : false;
- }
- g_cpu_has_avx2 = 0;
- if (__get_cpuid_count(7, 0, &data[0], &data[1], &data[2], &data[3]))
- {
- // AVX2 = Bank 7, EBX, bit 5
- g_cpu_has_avx2 = data[1] & (1 << 5) ? true : false;
- }
- // Ensure state bits are updated before init flag is updated
- __sync_synchronize();
- g_init = true;
- }
- #endif
- /* See header for documentation. */
- bool cpu_supports_popcnt()
- {
- if (!g_init)
- {
- detect_cpu_isa();
- }
- return g_cpu_has_popcnt;
- }
- /* See header for documentation. */
- bool cpu_supports_f16c()
- {
- if (!g_init)
- {
- detect_cpu_isa();
- }
- return g_cpu_has_f16c;
- }
- /* See header for documentation. */
- bool cpu_supports_sse41()
- {
- if (!g_init)
- {
- detect_cpu_isa();
- }
- return g_cpu_has_sse41;
- }
- /* See header for documentation. */
- bool cpu_supports_avx2()
- {
- if (!g_init)
- {
- detect_cpu_isa();
- }
- return g_cpu_has_avx2;
- }
- #endif
|