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.

131 lines
4.0KB

  1. /* Cpu detection code, extracted from mmx.h ((c)1997-99 by H. Dietz
  2. and R. Fisher). Converted to C and improved by Fabrice Bellard */
  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 == 0x746e6543 &&
  71. edx == 0x48727561 &&
  72. ecx == 0x736c7561) { /* "CentaurHauls" */
  73. /* VIA C3 */
  74. cpuid(0x80000000, eax, ebx, ecx, edx);
  75. if ((unsigned)eax < 0x80000001)
  76. goto inteltest;
  77. cpuid(0x80000001, eax, ebx, ecx, edx);
  78. rval = 0;
  79. if( edx & ( 1 << 31) )
  80. rval |= MM_3DNOW;
  81. if( edx & ( 1 << 23) )
  82. rval |= MM_MMX;
  83. if( edx & ( 1 << 24) )
  84. rval |= MM_MMXEXT;
  85. return rval;
  86. } else if (ebx == 0x69727943 &&
  87. edx == 0x736e4978 &&
  88. ecx == 0x64616574) {
  89. /* Cyrix Section */
  90. /* See if extended CPUID level 80000001 is supported */
  91. /* The value of CPUID/80000001 for the 6x86MX is undefined
  92. according to the Cyrix CPU Detection Guide (Preliminary
  93. Rev. 1.01 table 1), so we'll check the value of eax for
  94. CPUID/0 to see if standard CPUID level 2 is supported.
  95. According to the table, the only CPU which supports level
  96. 2 is also the only one which supports extended CPUID levels.
  97. */
  98. if (eax != 2)
  99. goto inteltest;
  100. cpuid(0x80000001, eax, ebx, ecx, edx);
  101. if ((eax & 0x00800000) == 0)
  102. return 0;
  103. rval = MM_MMX;
  104. if (eax & 0x01000000)
  105. rval |= MM_MMXEXT;
  106. return rval;
  107. } else {
  108. return 0;
  109. }
  110. }
  111. #ifdef __TEST__
  112. int main ( void )
  113. {
  114. int mm_flags;
  115. mm_flags = mm_support();
  116. printf("mm_support = 0x%08u\n",mm_flags);
  117. return 0;
  118. }
  119. #endif