[PATCH, i386]: Fix PR 77756, _-get_cpuid() returns wrong values for level 7 (extended features)

Uros Bizjak ubizjak@gmail.com
Thu Sep 29 18:58:00 GMT 2016


On Wed, Sep 28, 2016 at 11:32 PM, Uros Bizjak <ubizjak@gmail.com> wrote:

> 2016-09-28  Uros Bizjak  <ubizjak@gmail.com>

I have reverted my previous patch and committed the following:

2016-09-29  Uros Bizjak  <ubizjak@gmail.com>

    PR target/77756
    * config/i386/cpuid.h (__get_cpuid_count): New.
    (__get_cpuid): Rename __level to __leaf.

testsuite/ChangeLog:

2016-09-29  Uros Bizjak  <ubizjak@gmail.com>

    PR target/77756
    * gcc.target/i386/pr77756.c: New test.

Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.

Committed to mainline, will be backported to release branches.

Uros.
-------------- next part --------------
Index: config/i386/cpuid.h
===================================================================
--- config/i386/cpuid.h	(revision 240626)
+++ config/i386/cpuid.h	(working copy)
@@ -229,31 +229,37 @@
   return __eax;
 }
 
-/* Return cpuid data for requested cpuid level, as found in returned
+/* Return cpuid data for requested cpuid leaf, as found in returned
    eax, ebx, ecx and edx registers.  The function checks if cpuid is
    supported and returns 1 for valid cpuid information or 0 for
-   unsupported cpuid level.  All pointers are required to be non-null.  */
+   unsupported cpuid leaf.  All pointers are required to be non-null.  */
 
 static __inline int
-__get_cpuid (unsigned int __level,
+__get_cpuid (unsigned int __leaf,
 	     unsigned int *__eax, unsigned int *__ebx,
 	     unsigned int *__ecx, unsigned int *__edx)
 {
-  unsigned int __ext = __level & 0x80000000;
+  unsigned int __ext = __leaf & 0x80000000;
 
-  if (__get_cpuid_max (__ext, 0) < __level)
+  if (__get_cpuid_max (__ext, 0) < __leaf)
     return 0;
 
-  if (__ext)
-    __cpuid (__level, *__eax, *__ebx, *__ecx, *__edx);
-  else
-    {
-      if (__level >= 13)
-	__cpuid_count (__level, 1, *__eax, *__ebx, *__ecx, *__edx);
-      else if (__level >= 7)
-	__cpuid_count (__level, 0, *__eax, *__ebx, *__ecx, *__edx);
-      else
-	__cpuid (__level, *__eax, *__ebx, *__ecx, *__edx);
-    }
+  __cpuid (__leaf, *__eax, *__ebx, *__ecx, *__edx);
   return 1;
 }
+
+/* Same as above, but sub-leaf can be specified.  */
+
+static __inline int
+__get_cpuid_count (unsigned int __leaf, unsigned int __subleaf,
+		   unsigned int *__eax, unsigned int *__ebx,
+		   unsigned int *__ecx, unsigned int *__edx)
+{
+  unsigned int __ext = __leaf & 0x80000000;
+
+  if (__get_cpuid_max (__ext, 0) < __leaf)
+    return 0;
+
+  __cpuid_count (__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
+  return 1;
+}
Index: testsuite/gcc.target/i386/pr77756.c
===================================================================
--- testsuite/gcc.target/i386/pr77756.c	(revision 240626)
+++ testsuite/gcc.target/i386/pr77756.c	(working copy)
@@ -11,7 +11,7 @@
     {
       unsigned int eax, ebx, ecx, edx;
 
-      if (!__get_cpuid (7, &eax, &ebx, &ecx, &edx))
+      if (!__get_cpuid_count (7, 0, &eax, &ebx, &ecx, &edx))
 	__builtin_abort ();
 
       if (!(ebx & bit_AVX2))


More information about the Gcc-patches mailing list