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