From 3d90e8634da590a171151aadd2191e6fea8111e3 Mon Sep 17 00:00:00 2001 From: Michael Lee Date: Tue, 1 Mar 2016 17:32:43 -0800 Subject: [PATCH] i386 -fPIC requires `%ebx` 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 | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/folly/CpuId.h b/folly/CpuId.h index e2abf39d..096fc8d1 100644 --- a/folly/CpuId.h +++ b/folly/CpuId.h @@ -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"); -- 2.34.1