[cairo] cairo-1.0.0 build issue

Richard Henderson rth at twiddle.net
Mon Aug 29 13:29:26 PDT 2005


On Sun, Aug 28, 2005 at 11:12:07AM -0400, Owen Taylor wrote:
> That being said, can you try the attached patch? The use of local labels
> should be more robust in any case. Hopefully it isn't some recent GCC
> addition that is going to cause portability problems..

Alternately, do as little as possible in inline assembly, as in the
following.  Also updated to notice SSE3 and 3dNow, just in case you
ever wind up using them.


r~



Index: fbmmx.c
===================================================================
RCS file: /cvs/cairo/cairo/pixman/src/fbmmx.c,v
retrieving revision 1.4
diff -u -p -r1.4 fbmmx.c
--- fbmmx.c	28 Aug 2005 01:36:09 -0000	1.4
+++ fbmmx.c	28 Aug 2005 17:20:10 -0000
@@ -2479,90 +2479,71 @@ enum CPUFeatures {
     MMX_Extensions = 0x2, 
     SSE = 0x6,
     SSE2 = 0x8,
-    CMOV = 0x10
+    CMOV = 0x10,
+    SSE3 = 0x20,
+    _3DNOW = 0x40,
+    _3DNOW_Extensions = 0x80
 };
 
-static unsigned int detectCPUFeatures(void) {
-    unsigned int result;
-    char vendor[13];
-    vendor[0] = 0;
-    vendor[12] = 0;
-    /* see p. 118 of amd64 instruction set manual Vol3 */
-    /* We need to be careful about the handling of %ebx and
-     * %esp here. We can't declare either one as clobbered
-     * since they are special registers (%ebx is the "PIC
-     * register" holding an offset to global data, %esp the
-     * stack pointer), so we need to make sure they have their
-     * original values when we access the output operands.
-     */
-    __asm__ ("pushf\n"
-             "pop %%eax\n"
-             "mov %%eax, %%ecx\n"
-             "xor $0x00200000, %%eax\n"
-             "push %%eax\n"
-             "popf\n"
-             "pushf\n"
-             "pop %%eax\n"
-             "mov $0x0, %%edx\n"
-             "xor %%ecx, %%eax\n"
-             "jz skip\n"
-
-             "mov $0x00000000, %%eax\n"
-	     "push %%ebx\n"
-             "cpuid\n"
-             "mov %%ebx, %%eax\n"
-	     "pop %%ebx\n"
-             "mov %%eax, %1\n"
-             "mov %%edx, %2\n"
-             "mov %%ecx, %3\n"
-             "mov $0x00000001, %%eax\n"
-	     "push %%ebx\n"
-             "cpuid\n"
-	     "pop %%ebx\n"
-             "skip:\n"
-             "mov %%edx, %0\n"
-             : "=r" (result), 
-               "=m" (vendor[0]), 
-               "=m" (vendor[4]), 
-               "=m" (vendor[8])
-             :
-             : "%eax", "%ecx", "%edx"
-        );
+#if defined(__PIC__) && !defined(__x86_64__)
+#define cpuid(eax, edx, ecx, level)					\
+    do {								\
+        unsigned int ebx;						\
+        __asm__ ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" 		\
+                 : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)	\
+                 : "0" (level));					\
+    } while (0)
+#else
+#define cpuid(eax, edx, ecx, level)			\
+    __asm__ ("cpuid"			 		\
+             : "=a" (eax), "=c" (ecx), "=d" (edx)	\
+             : "0" (level) : "ebx")
+#endif
 
+static unsigned int detectCPUFeatures(void) {
+    unsigned int a, c, d;
     unsigned int features = 0;
-    if (result) {
-        /* result now contains the standard feature bits */
-        if (result & (1 << 15))
-            features |= CMOV;
-        if (result & (1 << 23))
-            features |= MMX;
-        if (result & (1 << 25))
-            features |= SSE;
-        if (result & (1 << 26))
-            features |= SSE2;
-        if ((result & MMX) && !(result & SSE) && (strcmp(vendor, "AuthenticAMD") == 0)) {
-            /* check for AMD MMX extensions */
-
-            unsigned int result;            
-            __asm__("push %%ebx\n"
-                    "mov $0x80000000, %%eax\n"
-                    "cpuid\n"
-                    "xor %%edx, %%edx\n"
-                    "cmp $0x1, %%eax\n"
-                    "jge skip2\n"
-                    "mov $0x80000001, %%eax\n"
-                    "cpuid\n"
-                    "skip2:\n"
-                    "pop %%ebx\n"
-                    "mov %%edx, %0\n"
-                    : "=r" (result)
-                    :
-                    : "%eax", "%ecx", "%edx"
-                );
-            if (result & (1<<22))
-                features |= MMX_Extensions;
-        }
+
+#ifndef __x86_64__
+    /* See if we can use cpuid.  On AMD64 we always can.  */
+    /* see p. 118 of amd64 instruction set manual Vol3 */
+    __asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
+             "pushl %0; popfl; pushfl; popl %0; popfl"
+             : "=&r" (a), "=&r" (d)
+             : "i" (0x00200000));
+    if (((a ^ d) & 0x00200000) == 0)
+        return 0;
+
+    /* Host supports cpuid.  See if cpuid gives capabilities, try CPUID(0).  */
+    cpuid (a, d, c, 0);
+    if (a == 0)
+        return 0;
+#endif
+
+    cpuid (a, d, c, 1);
+    if (d & (1 << 15))
+        features |= CMOV;
+    if (d & (1 << 23))
+        features |= MMX;
+    if (d & (1 << 25))
+        features |= SSE;
+    if (d & (1 << 26))
+        features |= SSE2;
+    if (c & (1 << 0))
+        features |= SSE3;
+
+    /* Invoke CPUID(0x80000001), for AMD-defined CPU features.  */
+    cpuid (a, d, c, 0x80000000);
+    if ((a & 0xffff0000) == 0x80000000 && a >= 0x80000001) {
+        cpuid (a, d, c, 0x80000001);
+        if (d & (1 << 31))
+            features |= _3DNOW;
+        if (d & (1 << 30))
+            features |= _3DNOW_Extensions;
+        if (d & (1 << 22))
+            features |= MMX_Extensions;
     }
+
     return features;
 }
 


More information about the cairo mailing list