i386 -fPIC requires `%ebx`
authorMichael Lee <mzlee@fb.com>
Wed, 2 Mar 2016 01:32:43 +0000 (17:32 -0800)
committerFacebook Github Bot 3 <facebook-github-bot-3-bot@fb.com>
Wed, 2 Mar 2016 01:35:26 +0000 (17:35 -0800)
Summary:On i368 (until, I'm lead to believe i686) `%ebx` is used for the PIC register. Thus, when we use cpuid, we clobber that register and gcc loudly complains:

  folly/CpuId.h: In member function 'virtual void CpuId_Simple_Test::TestBody()':
  folly/CpuId.h:67:61: error: PIC register clobbered by 'ebx' in 'asm'
       __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "edx", "ecx");

Reviewed By: yfeldblum

Differential Revision: D2991229

fb-gh-sync-id: ee8795e36a4c173147d61e26c9590ec5da1d02b5
shipit-source-id: ee8795e36a4c173147d61e26c9590ec5da1d02b5

folly/CpuId.h

index e2abf39d93f772d199fd260bd3b1ce85e44fd4d6..096fc8d12080832bb8a2d708599d10dbdeac6e94 100644 (file)
@@ -44,6 +44,38 @@ class CpuId {
       f7b_ = reg[1];
       f7c_ = reg[2];
     }
+#elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && \
+    defined(__GNUC__)
+    // The following block like the normal cpuid branch below, but gcc
+    // reserves ebx for use of it's pic register so we must specially
+    // handle the save and restore to avoid clobbering the register
+    uint32_t n;
+    __asm__(
+        "pushl %%ebx\n\t"
+        "cpuid\n\t"
+        "popl %%ebx\n\t"
+        : "=a"(n)
+        : "a"(0)
+        : "edx", "ecx");
+    if (n >= 1) {
+      __asm__(
+          "pushl %%ebx\n\t"
+          "cpuid\n\t"
+          "popl %%ebx\n\t"
+          : "=c"(f1c_), "=d"(f1d_)
+          : "a"(1)
+          :);
+    }
+    if (n >= 7) {
+      __asm__(
+          "pushl %%ebx\n\t"
+          "cpuid\n\t"
+          "movl %%ebx, %%eax\n\r"
+          "popl %%ebx"
+          : "=a"(f7b_), "=c"(f7c_)
+          : "a"(7), "c"(0)
+          : "edx");
+    }
 #elif FOLLY_X64 || defined(__i386__)
     uint32_t n;
     __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "edx", "ecx");