You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
3.5KB

  1. /* Cpu detection code, extracted from mmx.h ((c)1997-99 by H. Dietz
  2. and R. Fisher). Converted to C and improved by Gerard Lantau */
  3. #include <stdlib.h>
  4. #include "../dsputil.h"
  5. /* ebx saving is necessary for PIC. gcc seems unable to see it alone */
  6. #define cpuid(index,eax,ebx,ecx,edx)\
  7. __asm __volatile\
  8. ("movl %%ebx, %%esi\n\t"\
  9. "cpuid\n\t"\
  10. "xchgl %%ebx, %%esi"\
  11. : "=a" (eax), "=S" (ebx),\
  12. "=c" (ecx), "=d" (edx)\
  13. : "0" (index));
  14. /* Function to test if multimedia instructions are supported... */
  15. int mm_support(void)
  16. {
  17. int rval;
  18. int eax, ebx, ecx, edx;
  19. __asm__ __volatile__ (
  20. /* See if CPUID instruction is supported ... */
  21. /* ... Get copies of EFLAGS into eax and ecx */
  22. "pushf\n\t"
  23. "popl %0\n\t"
  24. "movl %0, %1\n\t"
  25. /* ... Toggle the ID bit in one copy and store */
  26. /* to the EFLAGS reg */
  27. "xorl $0x200000, %0\n\t"
  28. "push %0\n\t"
  29. "popf\n\t"
  30. /* ... Get the (hopefully modified) EFLAGS */
  31. "pushf\n\t"
  32. "popl %0\n\t"
  33. : "=a" (eax), "=c" (ecx)
  34. :
  35. : "cc"
  36. );
  37. if (eax == ecx)
  38. return 0; /* CPUID not supported */
  39. cpuid(0, eax, ebx, ecx, edx);
  40. if (ebx == 0x756e6547 &&
  41. edx == 0x49656e69 &&
  42. ecx == 0x6c65746e) {
  43. /* intel */
  44. inteltest:
  45. cpuid(1, eax, ebx, ecx, edx);
  46. if ((edx & 0x00800000) == 0)
  47. return 0;
  48. rval = MM_MMX;
  49. if (edx & 0x02000000)
  50. rval |= MM_MMXEXT | MM_SSE;
  51. if (edx & 0x04000000)
  52. rval |= MM_SSE2;
  53. return rval;
  54. } else if (ebx == 0x68747541 &&
  55. edx == 0x69746e65 &&
  56. ecx == 0x444d4163) {
  57. /* AMD */
  58. cpuid(0x80000000, eax, ebx, ecx, edx);
  59. if ((unsigned)eax < 0x80000001)
  60. goto inteltest;
  61. cpuid(0x80000001, eax, ebx, ecx, edx);
  62. if ((edx & 0x00800000) == 0)
  63. return 0;
  64. rval = MM_MMX;
  65. if (edx & 0x80000000)
  66. rval |= MM_3DNOW;
  67. if (edx & 0x00400000)
  68. rval |= MM_MMXEXT;
  69. return rval;
  70. } else if (ebx == 0x69727943 &&
  71. edx == 0x736e4978 &&
  72. ecx == 0x64616574) {
  73. /* Cyrix Section */
  74. /* See if extended CPUID level 80000001 is supported */
  75. /* The value of CPUID/80000001 for the 6x86MX is undefined
  76. according to the Cyrix CPU Detection Guide (Preliminary
  77. Rev. 1.01 table 1), so we'll check the value of eax for
  78. CPUID/0 to see if standard CPUID level 2 is supported.
  79. According to the table, the only CPU which supports level
  80. 2 is also the only one which supports extended CPUID levels.
  81. */
  82. if (eax != 2)
  83. goto inteltest;
  84. cpuid(0x80000001, eax, ebx, ecx, edx);
  85. if ((eax & 0x00800000) == 0)
  86. return 0;
  87. rval = MM_MMX;
  88. if (eax & 0x01000000)
  89. rval |= MM_MMXEXT;
  90. return rval;
  91. } else {
  92. return 0;
  93. }
  94. }
  95. #ifdef __TEST__
  96. int main ( void )
  97. {
  98. int mm_flags;
  99. mm_flags = mm_support();
  100. printf("mm_support = 0x%08u\n",mm_flags);
  101. return 0;
  102. }
  103. #endif