2012-05-11  Andreas Jaeger  <aj@suse.de>
	    Carlos O'Donell  <carlos_odonell@mentor.com>

	[BZ #14059]
	* sysdeps/x86_64/multiarch/init-arch.h 
	(bit_AVX_Usable): New macro.
	(bit_FMA4_Usable): New macro.
	(bit_XMM_state): New macro.
	(bit_YMM_state): New macro.
	[__ASSEMBLER__] (index_YMM_Usable): Rename to...
	[__ASSEMBLER__] (index_AVX_Usable): ... this.
	[__ASSEMBLER__] (index_FMA4_Usable): New macro.
	(CPUID_OSXSAVE): New macro.
	(CPUID_AVX): New macro.
	(CPUID_FMA4): New macro.
	(index_YMM_Usable): Rename to...
	(index_AVX_Usable): ... this.
	(HAS_AVX): Use HAS_ARCH_FEATURE.
	(HAS_FMA4): Likewise.
	(HAS_YMM_USABLE): Remove.
	* sysdeps/x86_64/multiarch/init-arch.c (__init_cpu_features):
	Fix check for AVX, enable FMA4 only if it exists and if AVX is
	usable.
	* sysdeps/x86_64/multiarch/strcmp.S: Use bit_AVX_Usable.

diff --git a/sysdeps/x86_64/multiarch/init-arch.c b/sysdeps/x86_64/multiarch/init-arch.c
index 80527ec..e68e5fa 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,18 +143,23 @@ __init_cpu_features (void)
   else
     kind = arch_kind_other;
 
-  if (__cpu_features.cpuid[COMMON_CPUID_INDEX_1].ecx & bit_AVX)
+  if (CPUID_AVX)
     {
-      /* Reset the AVX bit in case OSXSAVE is disabled.  */
-      if ((__cpu_features.cpuid[COMMON_CPUID_INDEX_1].ecx & bit_OSXSAVE) != 0
+      /* Determine if AVX is usable.  */
+      if (CPUID_OSXSAVE
 	  && ({ 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;
+		(xcrlow & (bit_YMM_state | bit_XMM_state)) ==
+		 (bit_YMM_state | bit_XMM_state); }))
+	__cpu_features.feature[index_AVX_Usable] = 1;
     }
 
+  /* FMA4 depends on AVX support.  */
+  if (CPUID_FMA4 && HAS_AVX)
+	__cpu_features.feature[index_FMA4_Usable] = 1;
+
   __cpu_features.family = family;
   __cpu_features.model = model;
   atomic_write_barrier ();
diff --git a/sysdeps/x86_64/multiarch/init-arch.h b/sysdeps/x86_64/multiarch/init-arch.h
index 5054e46..e6a10bb 100644
--- a/sysdeps/x86_64/multiarch/init-arch.h
+++ b/sysdeps/x86_64/multiarch/init-arch.h
@@ -1,5 +1,5 @@
 /* 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.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -21,8 +21,10 @@
 #define bit_Prefer_SSE_for_memop	(1 << 3)
 #define bit_Fast_Unaligned_Load		(1 << 4)
 #define bit_Prefer_PMINUB_for_stringop	(1 << 5)
-#define bit_YMM_Usable			(1 << 6)
+#define bit_AVX_Usable			(1 << 6)
+#define bit_FMA4_Usable			(1 << 7)
 
+/* CPUID Feature flags.  */
 #define bit_SSE2	(1 << 26)
 #define bit_SSSE3	(1 << 9)
 #define bit_SSE4_1	(1 << 19)
@@ -33,6 +35,10 @@
 #define bit_FMA		(1 << 12)
 #define bit_FMA4	(1 << 16)
 
+/* XCR0 Feature flags.  */
+#define bit_XMM_state  (1 << 1)
+#define bit_YMM_state  (2 << 1)
+
 #ifdef	__ASSEMBLER__
 
 # include <ifunc-defines.h>
@@ -49,7 +55,8 @@
 # define index_Prefer_SSE_for_memop	FEATURE_INDEX_1*FEATURE_SIZE
 # define index_Fast_Unaligned_Load	FEATURE_INDEX_1*FEATURE_SIZE
 # define index_Prefer_PMINUB_for_stringop FEATURE_INDEX_1*FEATURE_SIZE
-# define index_YMM_Usable		FEATURE_INDEX_1*FEATURE_SIZE
+# define index_AVX_Usable		FEATURE_INDEX_1*FEATURE_SIZE
+# define index_FMA4_Usable		FEATURE_INDEX_1*FEATURE_SIZE
 
 #else	/* __ASSEMBLER__ */
 
@@ -113,35 +120,36 @@ extern const struct cpu_features *__get_cpu_features (void)
 
 /* Following are the feature tests used throughout libc.  */
 
+/* CPUID_* evaluates to true if the feature flag is enabled.  */
+# define CPUID_OSXSAVE	HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, ecx, bit_OSXSAVE)
+# define CPUID_AVX	HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, ecx, bit_AVX)
+# define CPUID_FMA4	HAS_CPU_FEATURE (COMMON_CPUID_INDEX_80000001, ecx, bit_FMA4)
+
+/* HAS_* evaluates to true if we may use the feature at runtime.  */
 # define HAS_SSE2	HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, edx, bit_SSE2)
 # define HAS_POPCOUNT	HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, ecx, bit_POPCOUNT)
 # define HAS_SSSE3	HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, ecx, bit_SSSE3)
 # define HAS_SSE4_1	HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, ecx, bit_SSE4_1)
 # define HAS_SSE4_2	HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, ecx, bit_SSE4_2)
 # define HAS_FMA	HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, ecx, bit_FMA)
-# define HAS_AVX	HAS_CPU_FEATURE (COMMON_CPUID_INDEX_1, ecx, bit_AVX)
-# define HAS_FMA4	HAS_CPU_FEATURE (COMMON_CPUID_INDEX_80000001, ecx, bit_FMA4)
 
 # define index_Fast_Rep_String		FEATURE_INDEX_1
 # define index_Fast_Copy_Backward	FEATURE_INDEX_1
 # define index_Slow_BSF			FEATURE_INDEX_1
 # define index_Prefer_SSE_for_memop	FEATURE_INDEX_1
 # define index_Fast_Unaligned_Load	FEATURE_INDEX_1
-# define index_YMM_Usable		FEATURE_INDEX_1
+# define index_AVX_Usable		FEATURE_INDEX_1
+# define index_FMA4_Usable		FEATURE_INDEX_1
 
 # define HAS_ARCH_FEATURE(name) \
   ((__get_cpu_features ()->feature[index_##name] & (bit_##name)) != 0)
 
-# define HAS_FAST_REP_STRING	HAS_ARCH_FEATURE (Fast_Rep_String)
-
-# define HAS_FAST_COPY_BACKWARD	HAS_ARCH_FEATURE (Fast_Copy_Backward)
-
-# define HAS_SLOW_BSF		HAS_ARCH_FEATURE (Slow_BSF)
-
-# define HAS_PREFER_SSE_FOR_MEMOP HAS_ARCH_FEATURE (Prefer_SSE_for_memop)
-
-# define HAS_FAST_UNALIGNED_LOAD HAS_ARCH_FEATURE (Fast_Unaligned_Load)
-
-# define HAS_YMM_USABLE		HAS_ARCH_FEATURE (YMM_Usable)
+# define HAS_FAST_REP_STRING		HAS_ARCH_FEATURE (Fast_Rep_String)
+# define HAS_FAST_COPY_BACKWARD		HAS_ARCH_FEATURE (Fast_Copy_Backward)
+# define HAS_SLOW_BSF			HAS_ARCH_FEATURE (Slow_BSF)
+# define HAS_PREFER_SSE_FOR_MEMOP	HAS_ARCH_FEATURE (Prefer_SSE_for_memop)
+# define HAS_FAST_UNALIGNED_LOAD	HAS_ARCH_FEATURE (Fast_Unaligned_Load)
+# define HAS_AVX			HAS_ARCH_FEATURE (AVX_Usable)
+# define HAS_FMA4			HAS_ARCH_FEATURE (FMA4_Usable)
 
 #endif	/* __ASSEMBLER__ */
diff --git a/sysdeps/x86_64/multiarch/strcmp.S b/sysdeps/x86_64/multiarch/strcmp.S
index 2b9870b..d76e55b 100644
--- a/sysdeps/x86_64/multiarch/strcmp.S
+++ b/sysdeps/x86_64/multiarch/strcmp.S
@@ -1,5 +1,5 @@
 /* strcmp with SSE4.2
-   Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2009-2012 Free Software Foundation, Inc.
    Contributed by Intel Corporation.
    This file is part of the GNU C Library.
 
@@ -106,7 +106,7 @@ ENTRY(__strcasecmp)
 1:
 #  ifdef HAVE_AVX_SUPPORT
 	leaq	__strcasecmp_avx(%rip), %rax
-	testl	$bit_AVX, __cpu_features+CPUID_OFFSET+index_AVX(%rip)
+	testl	$bit_AVX_Usable, __cpu_features+FEATURE_OFFSET+index_AVX_Usable(%rip)
 	jnz	2f
 #  endif
 	leaq	__strcasecmp_sse42(%rip), %rax
@@ -129,7 +129,7 @@ ENTRY(__strncasecmp)
 1:
 #  ifdef HAVE_AVX_SUPPORT
 	leaq	__strncasecmp_avx(%rip), %rax
-	testl	$bit_AVX, __cpu_features+CPUID_OFFSET+index_AVX(%rip)
+	testl	$bit_AVX_Usable, __cpu_features+FEATURE_OFFSET+index_AVX_Usable(%rip)
 	jnz	2f
 #  endif
 	leaq	__strncasecmp_sse42(%rip), %rax
