summary refs log tree commit diff
path: root/sysdeps/x86_64/multiarch/init-arch.c
diff options
context:
space:
mode:
authorCarlos O'Donell <carlos_odonell@mentor.com>2012-05-16 20:14:24 -0700
committerCarlos O'Donell <carlos_odonell@mentor.com>2012-05-17 06:59:28 -0700
commit1a0994f5356214e8af8a1c1cc33fbf74a7ac8993 (patch)
tree99ce1f919a2509868a71f4262f055b5eec9accb0 /sysdeps/x86_64/multiarch/init-arch.c
parent0af797def371ceb4f05586d7bcd25841653d2082 (diff)
downloadglibc-1a0994f5356214e8af8a1c1cc33fbf74a7ac8993.tar.gz
glibc-1a0994f5356214e8af8a1c1cc33fbf74a7ac8993.tar.xz
glibc-1a0994f5356214e8af8a1c1cc33fbf74a7ac8993.zip
BZ#14059: Fix AVX and FMA4 detection.
Fix AVX and FMA4 detection by following the guidelines
set out by Intel and AMD for detecting these features.
Diffstat (limited to 'sysdeps/x86_64/multiarch/init-arch.c')
-rw-r--r--sysdeps/x86_64/multiarch/init-arch.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/sysdeps/x86_64/multiarch/init-arch.c b/sysdeps/x86_64/multiarch/init-arch.c
index 80527ec59d..fb44dcfcf6 100644
--- a/sysdeps/x86_64/multiarch/init-arch.c
+++ b/sysdeps/x86_64/multiarch/init-arch.c
@@ -1,6 +1,6 @@
 /* Initialize CPU feature data.
    This file is part of the GNU C Library.
-   Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+   Copyright (C) 2008-2012 Free Software Foundation, Inc.
    Contributed by Ulrich Drepper <drepper@redhat.com>.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -143,16 +143,23 @@ __init_cpu_features (void)
   else
     kind = arch_kind_other;
 
-  if (__cpu_features.cpuid[COMMON_CPUID_INDEX_1].ecx & bit_AVX)
+  /* Can we call xgetbv?  */
+  if (CPUID_OSXSAVE)
     {
-      /* Reset the AVX bit in case OSXSAVE is disabled.  */
-      if ((__cpu_features.cpuid[COMMON_CPUID_INDEX_1].ecx & bit_OSXSAVE) != 0
-	  && ({ unsigned int xcrlow;
-		unsigned int xcrhigh;
-		asm ("xgetbv"
-		     : "=a" (xcrlow), "=d" (xcrhigh) : "c" (0));
-		(xcrlow & 6) == 6; }))
-	__cpu_features.feature[index_YMM_Usable] |= bit_YMM_Usable;
+      unsigned int xcrlow;
+      unsigned int xcrhigh;
+      asm ("xgetbv" : "=a" (xcrlow), "=d" (xcrhigh) : "c" (0));
+      /* Is YMM and XMM state usable?  */
+      if ((xcrlow & (bit_YMM_state | bit_XMM_state)) ==
+	  (bit_YMM_state | bit_XMM_state))
+	{
+	  /* Determine if AVX is usable.  */
+	  if (CPUID_AVX)
+	    __cpu_features.feature[index_AVX_Usable] |= bit_AVX_Usable;
+	  /* Determine if FMA4 is usable.  */
+	  if (CPUID_FMA4)
+	    __cpu_features.feature[index_FMA4_Usable] |= bit_FMA4_Usable;
+	}
     }
 
   __cpu_features.family = family;