This is a rather cryptic error message:
error: can't find a register in class 'BREG' while reloading 'asm' error: 'asm' operand has impossible constraints
occurs because one of the restrictions is not allowed. In this case, it is EBX . When compiling 32-bit code with the -fPIC option (position-independent code), the EBX register is used to move. It cannot be used as output or displayed as a private register.
Although most people suggest compiling using special compiler flags, the function can be rewritten to support x86-64 / IA32 and PIC / non-PIC by changing the assembler code to save the EBX register itself and restore it after. This can be done using code like:
#include <inttypes.h> static inline void do_cpuid(uint32_t selector, uint32_t *data) { __asm__ __volatile__ ( "xchg %%ebx, %k[tempreg]\n\t" "cpuid\n\t" "xchg %%ebx, %k[tempreg]\n" : "=a" (data[0]), [tempreg]"=&r" (data[1]), "=c" (data[2]), "=d" (data[3]) : "a"(selector), "c"(0)); }
A significant change is that the value of data[1] will be returned to the accessible register selected by the compiler. The constraint =&r tells the compiler that no matter which register it chooses, it cannot be any of the other input registers (we xchg register early with the code xchg ). In the code, we exchange EBX with an accessible register selected by the compiler. Then we exchange it back afterwards. At the end, EBX will contain the original value, and the selected free register will contain what the CPUID was returned. Then the assembler pattern will move the contents of this free register to data[1] .
In fact, we circumvented the problem by letting the compiler select a free register. The compiler is smart enough not to use EBX if it is bundled because it can be used for roaming code. In 64-bit code, EBX not used for moving, as is the case with 32-bit code, so it can be available for use.
An astute observer could notice xor %%ecx,%%ecx . I made this change regardless of the EBX problem. It is now considered good practice to clean ECX because some processors made by AMD may return obsolete values if ECX not zero. If you are developing for non-PPC Mac platforms only, this change is not necessary because Apple uses Intel processors that do not exhibit this behavior.
EBX is usually special in 32-bit roaming / PIC code, so the compiler initially complained about its cryptic message.