shithub: opus

Download patch

ref: 510e1029b45aa01a7047e5b3b82169be40911b96
parent: a80e9e9533d4edeaae282b82f77b8bd8a4903eca
author: Marcus Asteborg <maastebo@microsoft.com>
date: Wed Jul 6 17:35:16 EDT 2022

cmake - fix rtcd detection on x86 non windows

Signed-off-by: Mark Harris <mark.hsj@gmail.com>

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -366,11 +366,21 @@
 endif()
 
 if(NOT OPUS_DISABLE_INTRINSICS)
-  if((OPUS_X86_MAY_HAVE_SSE AND NOT OPUS_X86_PRESUME_SSE) OR
+  if(((OPUS_X86_MAY_HAVE_SSE AND NOT OPUS_X86_PRESUME_SSE) OR
      (OPUS_X86_MAY_HAVE_SSE2 AND NOT OPUS_X86_PRESUME_SSE2) OR
      (OPUS_X86_MAY_HAVE_SSE4_1 AND NOT OPUS_X86_PRESUME_SSE4_1) OR
-     (OPUS_X86_MAY_HAVE_AVX AND NOT OPUS_X86_PRESUME_AVX))
+     (OPUS_X86_MAY_HAVE_AVX AND NOT OPUS_X86_PRESUME_AVX)) AND
+      RUNTIME_CPU_CAPABILITY_DETECTION)
     target_compile_definitions(opus PRIVATE OPUS_HAVE_RTCD)
+    if(NOT MSVC)
+      if(CPU_INFO_BY_ASM_SUPPORTED)
+        target_compile_definitions(opus PRIVATE CPU_INFO_BY_ASM)
+      elseif(CPU_INFO_BY_C_SUPPORTED)
+        target_compile_definitions(opus PRIVATE CPU_INFO_BY_C)
+      else()
+        message(ERROR "Runtime cpu capability detection is enabled while CPU_INFO is not supported")
+      endif()
+    endif()
   endif()
 
   if(SSE1_SUPPORTED)
--- a/Makefile.am
+++ b/Makefile.am
@@ -225,6 +225,8 @@
              cmake/RunTest.cmake \
              cmake/config.h.cmake.in \
              cmake/vla.c \
+             cmake/cpu_info_by_asm.c \
+             cmake/cpu_info_by_c.c \
              meson/get-version.py \
              meson/read-sources-list.py \
              meson.build \
--- a/cmake/OpusFunctions.cmake
+++ b/cmake/OpusFunctions.cmake
@@ -142,14 +142,28 @@
 endfunction()
 
 function(opus_supports_cpu_detection RUNTIME_CPU_CAPABILITY_DETECTION)
-  if(MSVC)
-    check_include_file(intrin.h HAVE_INTRIN_H)
-  else()
-    check_include_file(cpuid.h HAVE_CPUID_H)
-  endif()
-  if(HAVE_INTRIN_H OR HAVE_CPUID_H)
-    set(RUNTIME_CPU_CAPABILITY_DETECTION 1 PARENT_SCOPE)
-  elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(arm|aarch64)")
+  set(RUNTIME_CPU_CAPABILITY_DETECTION 0 PARENT_SCOPE)
+  if(OPUS_CPU_X86 OR OPUS_CPU_X64)
+    if(MSVC)
+      check_include_file(intrin.h HAVE_INTRIN_H)
+      if(HAVE_INTRIN_H)
+        # if intrin.h is available we assume __cpuid is there
+        set(RUNTIME_CPU_CAPABILITY_DETECTION 1 PARENT_SCOPE)
+      endif()
+    else()
+      include(CFeatureCheck)
+      c_feature_check(CPU_INFO_BY_ASM)
+      set(CPU_INFO_BY_ASM_SUPPORTED ${CPU_INFO_BY_ASM_SUPPORTED} PARENT_SCOPE)
+      check_include_file(cpuid.h HAVE_CPUID_H)
+      if(HAVE_CPUID_H)
+        c_feature_check(CPU_INFO_BY_C)
+        set(CPU_INFO_BY_C_SUPPORTED ${CPU_INFO_BY_C_SUPPORTED} PARENT_SCOPE)
+      endif()
+      if(CPU_INFO_BY_ASM_SUPPORTED OR CPU_INFO_BY_C_SUPPORTED)
+        set(RUNTIME_CPU_CAPABILITY_DETECTION 1 PARENT_SCOPE)
+      endif()
+    endif()
+  elseif(OPUS_CPU_ARM)
     # ARM cpu detection is implemented for Windows and anything
     # using a Linux kernel (such as Android).
     if (CMAKE_SYSTEM_NAME MATCHES "(Windows|Linux|Android)")
--- /dev/null
+++ b/cmake/cpu_info_by_asm.c
@@ -1,0 +1,31 @@
+#include <stdio.h>
+int main() {
+    unsigned int CPUInfo0;
+    unsigned int CPUInfo1;
+    unsigned int CPUInfo2;
+    unsigned int CPUInfo3;
+    unsigned int InfoType;
+#if defined(__i386__) && defined(__PIC__)
+/* %ebx is PIC register in 32-bit, so mustn't clobber it. */
+    __asm__ __volatile__ (
+        "xchg %%ebx, %1\n"
+        "cpuid\n"
+        "xchg %%ebx, %1\n":
+        "=a" (CPUInfo0),
+        "=r" (CPUInfo1),
+        "=c" (CPUInfo2),
+        "=d" (CPUInfo3) :
+        "0" (InfoType), "2" (0)
+    );
+#else
+    __asm__ __volatile__ (
+        "cpuid":
+        "=a" (CPUInfo0),
+        "=b" (CPUInfo1),
+        "=c" (CPUInfo2),
+        "=d" (CPUInfo3) :
+        "0" (InfoType), "2" (0)
+    );
+#endif
+    return 0;
+}
--- /dev/null
+++ b/cmake/cpu_info_by_c.c
@@ -1,0 +1,9 @@
+#include <cpuid.h>
+int main() {
+    unsigned int CPUInfo0;
+    unsigned int CPUInfo1;
+    unsigned int CPUInfo2;
+    unsigned int CPUInfo3;
+    unsigned int InfoType;
+    return __get_cpuid_count(InfoType, 0, &CPUInfo0, &CPUInfo1, &CPUInfo2, &CPUInfo3);
+}