cpu.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // Copyright 2011 Google Inc. All Rights Reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style license
  4. // that can be found in the COPYING file in the root of the source
  5. // tree. An additional intellectual property rights grant can be found
  6. // in the file PATENTS. All contributing project authors may
  7. // be found in the AUTHORS file in the root of the source tree.
  8. // -----------------------------------------------------------------------------
  9. //
  10. // CPU detection
  11. //
  12. // Author: Christian Duvivier (cduvivier@google.com)
  13. #include "./dsp.h"
  14. #if defined(__ANDROID__)
  15. #include <cpu-features.h>
  16. #endif
  17. //------------------------------------------------------------------------------
  18. // SSE2 detection.
  19. //
  20. // apple/darwin gcc-4.0.1 defines __PIC__, but not __pic__ with -fPIC.
  21. #if (defined(__pic__) || defined(__PIC__)) && defined(__i386__)
  22. static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
  23. __asm__ volatile (
  24. "mov %%ebx, %%edi\n"
  25. "cpuid\n"
  26. "xchg %%edi, %%ebx\n"
  27. : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
  28. : "a"(info_type));
  29. }
  30. #elif defined(__i386__) || defined(__x86_64__)
  31. static WEBP_INLINE void GetCPUInfo(int cpu_info[4], int info_type) {
  32. __asm__ volatile (
  33. "cpuid\n"
  34. : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
  35. : "a"(info_type));
  36. }
  37. #elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729 // >= VS2008 SP1
  38. #define GetCPUInfo(info, type) __cpuidex(info, type, 0) // set ecx=0
  39. #elif defined(WEBP_MSC_SSE2)
  40. #define GetCPUInfo __cpuid
  41. #endif
  42. // NaCl has no support for xgetbv or the raw opcode.
  43. #if !defined(__native_client__) && (defined(__i386__) || defined(__x86_64__))
  44. static WEBP_INLINE uint64_t xgetbv(void) {
  45. const uint32_t ecx = 0;
  46. uint32_t eax, edx;
  47. // Use the raw opcode for xgetbv for compatibility with older toolchains.
  48. __asm__ volatile (
  49. ".byte 0x0f, 0x01, 0xd0\n"
  50. : "=a"(eax), "=d"(edx) : "c" (ecx));
  51. return ((uint64_t)edx << 32) | eax;
  52. }
  53. #elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 160040219 // >= VS2010 SP1
  54. #define xgetbv() _xgetbv(0)
  55. #elif defined(_MSC_VER) && defined(_M_IX86)
  56. static WEBP_INLINE uint64_t xgetbv(void) {
  57. uint32_t eax_, edx_;
  58. __asm {
  59. xor ecx, ecx // ecx = 0
  60. // Use the raw opcode for xgetbv for compatibility with older toolchains.
  61. __asm _emit 0x0f __asm _emit 0x01 __asm _emit 0xd0
  62. mov eax_, eax
  63. mov edx_, edx
  64. }
  65. return ((uint64_t)edx_ << 32) | eax_;
  66. }
  67. #else
  68. #define xgetbv() 0U // no AVX for older x64 or unrecognized toolchains.
  69. #endif
  70. #if defined(__i386__) || defined(__x86_64__) || defined(WEBP_MSC_SSE2)
  71. static int x86CPUInfo(CPUFeature feature) {
  72. int cpu_info[4];
  73. GetCPUInfo(cpu_info, 1);
  74. if (feature == kSSE2) {
  75. return 0 != (cpu_info[3] & 0x04000000);
  76. }
  77. if (feature == kSSE3) {
  78. return 0 != (cpu_info[2] & 0x00000001);
  79. }
  80. if (feature == kAVX) {
  81. // bits 27 (OSXSAVE) & 28 (256-bit AVX)
  82. if ((cpu_info[2] & 0x18000000) == 0x18000000) {
  83. // XMM state and YMM state enabled by the OS.
  84. return (xgetbv() & 0x6) == 0x6;
  85. }
  86. }
  87. if (feature == kAVX2) {
  88. if (x86CPUInfo(kAVX)) {
  89. GetCPUInfo(cpu_info, 7);
  90. return ((cpu_info[1] & 0x00000020) == 0x00000020);
  91. }
  92. }
  93. return 0;
  94. }
  95. VP8CPUInfo VP8GetCPUInfo = x86CPUInfo;
  96. #elif defined(WEBP_ANDROID_NEON) // NB: needs to be before generic NEON test.
  97. static int AndroidCPUInfo(CPUFeature feature) {
  98. const AndroidCpuFamily cpu_family = android_getCpuFamily();
  99. const uint64_t cpu_features = android_getCpuFeatures();
  100. if (feature == kNEON) {
  101. return (cpu_family == ANDROID_CPU_FAMILY_ARM &&
  102. 0 != (cpu_features & ANDROID_CPU_ARM_FEATURE_NEON));
  103. }
  104. return 0;
  105. }
  106. VP8CPUInfo VP8GetCPUInfo = AndroidCPUInfo;
  107. #elif defined(WEBP_USE_NEON)
  108. // define a dummy function to enable turning off NEON at runtime by setting
  109. // VP8DecGetCPUInfo = NULL
  110. static int armCPUInfo(CPUFeature feature) {
  111. (void)feature;
  112. return 1;
  113. }
  114. VP8CPUInfo VP8GetCPUInfo = armCPUInfo;
  115. #elif defined(WEBP_USE_MIPS32)
  116. static int mipsCPUInfo(CPUFeature feature) {
  117. (void)feature;
  118. return 1;
  119. }
  120. VP8CPUInfo VP8GetCPUInfo = mipsCPUInfo;
  121. #else
  122. VP8CPUInfo VP8GetCPUInfo = NULL;
  123. #endif