cannam@95: /* cannam@95: * Copyright (c) 2003, 2007-11 Matteo Frigo cannam@95: * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology cannam@95: * cannam@95: * This program is free software; you can redistribute it and/or modify cannam@95: * it under the terms of the GNU General Public License as published by cannam@95: * the Free Software Foundation; either version 2 of the License, or cannam@95: * (at your option) any later version. cannam@95: * cannam@95: * This program is distributed in the hope that it will be useful, cannam@95: * but WITHOUT ANY WARRANTY; without even the implied warranty of cannam@95: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the cannam@95: * GNU General Public License for more details. cannam@95: * cannam@95: * You should have received a copy of the GNU General Public License cannam@95: * along with this program; if not, write to the Free Software cannam@95: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA cannam@95: * cannam@95: */ cannam@95: cannam@95: cannam@95: /* this code was kindly donated by Eric J. Korpela */ cannam@95: cannam@95: #ifdef _MSC_VER cannam@95: #ifndef inline cannam@95: #define inline __inline cannam@95: #endif cannam@95: #endif cannam@95: cannam@95: static inline int is_386() cannam@95: { cannam@95: #ifdef _MSC_VER cannam@95: unsigned int result,tst; cannam@95: _asm { cannam@95: pushfd cannam@95: pop eax cannam@95: mov edx,eax cannam@95: xor eax,40000h cannam@95: push eax cannam@95: popfd cannam@95: pushfd cannam@95: pop eax cannam@95: push edx cannam@95: popfd cannam@95: mov tst,edx cannam@95: mov result,eax cannam@95: } cannam@95: #else cannam@95: register unsigned int result,tst; cannam@95: __asm__ ( cannam@95: "pushfl\n\t" cannam@95: "popl %0\n\t" cannam@95: "movl %0,%1\n\t" cannam@95: "xorl $0x40000,%0\n\t" cannam@95: "pushl %0\n\t" cannam@95: "popfl\n\t" cannam@95: "pushfl\n\t" cannam@95: "popl %0\n\t" cannam@95: "pushl %1\n\t" cannam@95: "popfl" cannam@95: : "=r" (result), "=r" (tst) /* output */ cannam@95: : /* no inputs */ cannam@95: ); cannam@95: #endif cannam@95: return (result == tst); cannam@95: } cannam@95: cannam@95: static inline int has_cpuid() cannam@95: { cannam@95: #ifdef _MSC_VER cannam@95: unsigned int result,tst; cannam@95: _asm { cannam@95: pushfd cannam@95: pop eax cannam@95: mov edx,eax cannam@95: xor eax,200000h cannam@95: push eax cannam@95: popfd cannam@95: pushfd cannam@95: pop eax cannam@95: push edx cannam@95: popfd cannam@95: mov tst,edx cannam@95: mov result,eax cannam@95: } cannam@95: #else cannam@95: register unsigned int result,tst; cannam@95: __asm__ ( cannam@95: "pushfl\n\t" cannam@95: "pop %0\n\t" cannam@95: "movl %0,%1\n\t" cannam@95: "xorl $0x200000,%0\n\t" cannam@95: "pushl %0\n\t" cannam@95: "popfl\n\t" cannam@95: "pushfl\n\t" cannam@95: "popl %0\n\t" cannam@95: "pushl %1\n\t" cannam@95: "popfl" cannam@95: : "=r" (result), "=r" (tst) /* output */ cannam@95: : /* no inputs */ cannam@95: ); cannam@95: #endif cannam@95: return (result != tst); cannam@95: } cannam@95: cannam@95: static inline int cpuid_edx(int op) cannam@95: { cannam@95: # ifdef _MSC_VER cannam@95: int result; cannam@95: _asm { cannam@95: push ebx cannam@95: mov eax,op cannam@95: cpuid cannam@95: mov result,edx cannam@95: pop ebx cannam@95: } cannam@95: return result; cannam@95: # else cannam@95: int eax, ecx, edx; cannam@95: cannam@95: __asm__("push %%ebx\n\tcpuid\n\tpop %%ebx" cannam@95: : "=a" (eax), "=c" (ecx), "=d" (edx) cannam@95: : "a" (op)); cannam@95: return edx; cannam@95: # endif cannam@95: } cannam@95: cannam@95: static inline int cpuid_ecx(int op) cannam@95: { cannam@95: # ifdef _MSC_VER cannam@95: int result; cannam@95: _asm { cannam@95: push ebx cannam@95: mov eax,op cannam@95: cpuid cannam@95: mov result,ecx cannam@95: pop ebx cannam@95: } cannam@95: return result; cannam@95: # else cannam@95: int eax, ecx, edx; cannam@95: cannam@95: __asm__("push %%ebx\n\tcpuid\n\tpop %%ebx" cannam@95: : "=a" (eax), "=c" (ecx), "=d" (edx) cannam@95: : "a" (op)); cannam@95: return ecx; cannam@95: # endif cannam@95: } cannam@95: cannam@95: static inline int xgetbv_eax(int op) cannam@95: { cannam@95: # ifdef _MSC_VER cannam@95: int veax, vedx; cannam@95: _asm { cannam@95: mov ecx,op cannam@95: # if defined(__INTEL_COMPILER) || (_MSC_VER >= 1600) cannam@95: xgetbv cannam@95: # else cannam@95: __emit 15 cannam@95: __emit 1 cannam@95: __emit 208 cannam@95: # endif cannam@95: mov veax,eax cannam@95: mov vedx,edx cannam@95: } cannam@95: return veax; cannam@95: # else cannam@95: int eax, edx; cannam@95: __asm__ (".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c" (op)); cannam@95: return eax; cannam@95: #endif cannam@95: }