1474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org/* 2474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * 4474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * Use of this source code is governed by a BSD-style license 5474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * that can be found in the LICENSE file in the root of the source 6474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * tree. An additional intellectual property rights grant can be found 7474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * in the file PATENTS. All contributing project authors may 8474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org * be found in the AUTHORS file in the root of the source tree. 9474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org */ 10474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 11474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include <stdlib.h> 12474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include <string.h> 1387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#include "vpx_ports/arm.h" 1487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#include "./vpx_config.h" 15474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 16810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org#ifdef WINAPI_FAMILY 17810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org#include <winapifamily.h> 18810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) 19810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org#define getenv(x) NULL 20810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org#endif 21810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org#endif 22810cf1767dc8df4783e02ba8a712072f50ddc99efgalligan@chromium.org 2361a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.orgstatic int arm_cpu_env_flags(int *flags) { 2461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org char *env; 2561a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org env = getenv("VPX_SIMD_CAPS"); 2661a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (env && *env) { 2761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org *flags = (int)strtol(env, NULL, 0); 2861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org return 0; 2961a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 3061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org *flags = 0; 3161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org return -1; 32474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 33474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 3461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.orgstatic int arm_cpu_env_mask(void) { 3561a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org char *env; 3661a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org env = getenv("VPX_SIMD_CAPS_MASK"); 3761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org return env && *env ? (int)strtol(env, NULL, 0) : ~0; 38474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 39474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 40ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#if !CONFIG_RUNTIME_CPU_DETECT 41474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 4261a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.orgint arm_cpu_caps(void) { 43ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org /* This function should actually be a no-op. There is no way to adjust any of 44ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org * these because the RTCD tables do not exist: the functions are called 45ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org * statically */ 4661a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org int flags; 4761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org int mask; 4861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (!arm_cpu_env_flags(&flags)) { 4961a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org return flags; 5061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 5161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org mask = arm_cpu_env_mask(); 52ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#if HAVE_EDSP 5361a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org flags |= HAS_EDSP; 54ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#endif /* HAVE_EDSP */ 55ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#if HAVE_MEDIA 5661a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org flags |= HAS_MEDIA; 57ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#endif /* HAVE_MEDIA */ 5887997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if HAVE_NEON || HAVE_NEON_ASM 5961a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org flags |= HAS_NEON; 6087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif /* HAVE_NEON || HAVE_NEON_ASM */ 6161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org return flags & mask; 62ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org} 63ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org 64ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#elif defined(_MSC_VER) /* end !CONFIG_RUNTIME_CPU_DETECT */ 65474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org/*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/ 66474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#define WIN32_LEAN_AND_MEAN 67474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#define WIN32_EXTRA_LEAN 68474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include <windows.h> 69474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 7061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.orgint arm_cpu_caps(void) { 7161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org int flags; 7261a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org int mask; 7361a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (!arm_cpu_env_flags(&flags)) { 7461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org return flags; 7561a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 7661a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org mask = arm_cpu_env_mask(); 7761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org /* MSVC has no inline __asm support for ARM, but it does let you __emit 7861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org * instructions via their assembled hex code. 7961a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org * All of these instructions should be essentially nops. 8061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org */ 81ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#if HAVE_EDSP 8261a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (mask & HAS_EDSP) { 8361a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org __try { 8461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org /*PLD [r13]*/ 8561a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org __emit(0xF5DDF000); 8661a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org flags |= HAS_EDSP; 8761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } __except (GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) { 8861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org /*Ignore exception.*/ 89474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 9061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 9187997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif /* HAVE_EDSP */ 92ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#if HAVE_MEDIA 9361a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (mask & HAS_MEDIA) 9461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org __try { 9561a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org /*SHADD8 r3,r3,r3*/ 9661a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org __emit(0xE6333F93); 9761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org flags |= HAS_MEDIA; 9861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } __except (GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) { 9961a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org /*Ignore exception.*/ 10061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 10161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org} 10287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif /* HAVE_MEDIA */ 10387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if HAVE_NEON || HAVE_NEON_ASM 10461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.orgif (mask &HAS_NEON) { 10561a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org __try { 10661a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org /*VORR q0,q0,q0*/ 10761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org __emit(0xF2200150); 10861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org flags |= HAS_NEON; 10961a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } __except (GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) { 11061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org /*Ignore exception.*/ 11161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 11261a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org} 11387997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif /* HAVE_NEON || HAVE_NEON_ASM */ 11461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.orgreturn flags & mask; 115474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 116474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 117ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#elif defined(__ANDROID__) /* end _MSC_VER */ 118167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org#include <cpu-features.h> 119167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org 12061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.orgint arm_cpu_caps(void) { 12161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org int flags; 12261a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org int mask; 12361a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org uint64_t features; 12461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (!arm_cpu_env_flags(&flags)) { 12561a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org return flags; 12661a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 12761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org mask = arm_cpu_env_mask(); 12861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org features = android_getCpuFeatures(); 129167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org 130ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#if HAVE_EDSP 13161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org flags |= HAS_EDSP; 132ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#endif /* HAVE_EDSP */ 133ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#if HAVE_MEDIA 13461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org flags |= HAS_MEDIA; 135ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#endif /* HAVE_MEDIA */ 13687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if HAVE_NEON || HAVE_NEON_ASM 13761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (features & ANDROID_CPU_ARM_FEATURE_NEON) 13861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org flags |= HAS_NEON; 13987997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif /* HAVE_NEON || HAVE_NEON_ASM */ 14061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org return flags & mask; 141167514562bbce1eb0566271d6cb41d90d2b5ffa0hclam@chromium.org} 142ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org 143ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#elif defined(__linux__) /* end __ANDROID__ */ 14461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org 145474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#include <stdio.h> 146474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org 14761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.orgint arm_cpu_caps(void) { 14861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org FILE *fin; 14961a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org int flags; 15061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org int mask; 15161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (!arm_cpu_env_flags(&flags)) { 15261a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org return flags; 15361a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 15461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org mask = arm_cpu_env_mask(); 15561a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org /* Reading /proc/self/auxv would be easier, but that doesn't work reliably 15661a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org * on Android. 15761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org * This also means that detection will fail in Scratchbox. 15861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org */ 15961a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org fin = fopen("/proc/cpuinfo", "r"); 16061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (fin != NULL) { 16161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org /* 512 should be enough for anybody (it's even enough for all the flags 16261a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org * that x86 has accumulated... so far). 163474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org */ 16461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org char buf[512]; 16561a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org while (fgets(buf, 511, fin) != NULL) { 16687997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if HAVE_EDSP || HAVE_NEON || HAVE_NEON_ASM 16761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (memcmp(buf, "Features", 8) == 0) { 16861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org char *p; 169ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#if HAVE_EDSP 17061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org p = strstr(buf, " edsp"); 17161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (p != NULL && (p[5] == ' ' || p[5] == '\n')) { 17261a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org flags |= HAS_EDSP; 17361a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 17487997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif /* HAVE_EDSP */ 17587997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#if HAVE_NEON || HAVE_NEON_ASM 17661a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org p = strstr(buf, " neon"); 17761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (p != NULL && (p[5] == ' ' || p[5] == '\n')) { 17861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org flags |= HAS_NEON; 17961a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 18087997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif /* HAVE_NEON || HAVE_NEON_ASM */ 18161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 18287997d490ae52aa962a985c95b3cddf7f8832641johannkoenig@chromium.org#endif /* HAVE_EDSP || HAVE_NEON || HAVE_NEON_ASM */ 183ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#if HAVE_MEDIA 18461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (memcmp(buf, "CPU architecture:", 17) == 0) { 18561a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org int version; 18661a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org version = atoi(buf + 17); 18761a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org if (version >= 6) { 18861a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org flags |= HAS_MEDIA; 189474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 19061a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 19161a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org#endif /* HAVE_MEDIA */ 192474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org } 19361a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org fclose(fin); 19461a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org } 19561a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org return flags & mask; 196474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org} 197ed759d81a39febed3a8a395386639d54307504aagrunell@chromium.org#else /* end __linux__ */ 198474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#error "--enable-runtime-cpu-detect selected, but no CPU detection method " \ 19961a121c21a665ca9697a7984a3a031bb07e05cd5fgalligan@chromium.org"available for your platform. Reconfigure with --disable-runtime-cpu-detect." 200474eb7536515fb785e925cc9375d22817c416851hclam@chromium.org#endif 201