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.

132 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. #ifdef ARCH_X86_64
  6. # define REG_b "rbx"
  7. # define REG_S "rsi"
  8. #else
  9. # define REG_b "ebx"
  10. # define REG_S "esi"
  11. #endif
  12. /* ebx saving is necessary for PIC. gcc seems unable to see it alone */
  13. #define cpuid(index,eax,ebx,ecx,edx)\
  14. __asm __volatile\
  15. ("mov %%"REG_b", %%"REG_S"\n\t"\
  16. "cpuid\n\t"\
  17. "xchg %%"REG_b", %%"REG_S\
  18. : "=a" (eax), "=S" (ebx),\
  19. "=c" (ecx), "=d" (edx)\
  20. : "0" (index));
  21. /* Function to test if multimedia instructions are supported... */
  22. int mm_support(void)
  23. {
  24. int rval = 0;
  25. int eax, ebx, ecx, edx;
  26. int max_std_level, max_ext_level, std_caps=0, ext_caps=0;
  27. long a, c;
  28. __asm__ __volatile__ (
  29. /* See if CPUID instruction is supported ... */
  30. /* ... Get copies of EFLAGS into eax and ecx */
  31. "pushf\n\t"
  32. "pop %0\n\t"
  33. "mov %0, %1\n\t"
  34. /* ... Toggle the ID bit in one copy and store */
  35. /* to the EFLAGS reg */
  36. "xor $0x200000, %0\n\t"
  37. "push %0\n\t"
  38. "popf\n\t"
  39. /* ... Get the (hopefully modified) EFLAGS */
  40. "pushf\n\t"
  41. "pop %0\n\t"
  42. : "=a" (a), "=c" (c)
  43. :
  44. : "cc"
  45. );
  46. if (a == c)
  47. return 0; /* CPUID not supported */
  48. cpuid(0, max_std_level, ebx, ecx, edx);
  49. if(max_std_level >= 1){
  50. cpuid(1, eax, ebx, ecx, std_caps);
  51. if (std_caps & (1<<23))
  52. rval |= MM_MMX;
  53. if (std_caps & (1<<25))
  54. rval |= MM_MMXEXT | MM_SSE;
  55. if (std_caps & (1<<26))
  56. rval |= MM_SSE2;
  57. }
  58. cpuid(0x80000000, max_ext_level, ebx, ecx, edx);
  59. if(max_ext_level >= 0x80000001){
  60. cpuid(0x80000001, eax, ebx, ecx, ext_caps);
  61. if (ext_caps & (1<<31))
  62. rval |= MM_3DNOW;
  63. if (ext_caps & (1<<30))
  64. rval |= MM_3DNOWEXT;
  65. if (ext_caps & (1<<23))
  66. rval |= MM_MMX;
  67. }
  68. cpuid(0, eax, ebx, ecx, edx);
  69. if ( ebx == 0x68747541 &&
  70. edx == 0x69746e65 &&
  71. ecx == 0x444d4163) {
  72. /* AMD */
  73. if(ext_caps & (1<<22))
  74. rval |= MM_MMXEXT;
  75. } else if (ebx == 0x746e6543 &&
  76. edx == 0x48727561 &&
  77. ecx == 0x736c7561) { /* "CentaurHauls" */
  78. /* VIA C3 */
  79. if(ext_caps & (1<<24))
  80. rval |= MM_MMXEXT;
  81. } else if (ebx == 0x69727943 &&
  82. edx == 0x736e4978 &&
  83. ecx == 0x64616574) {
  84. /* Cyrix Section */
  85. /* See if extended CPUID level 80000001 is supported */
  86. /* The value of CPUID/80000001 for the 6x86MX is undefined
  87. according to the Cyrix CPU Detection Guide (Preliminary
  88. Rev. 1.01 table 1), so we'll check the value of eax for
  89. CPUID/0 to see if standard CPUID level 2 is supported.
  90. According to the table, the only CPU which supports level
  91. 2 is also the only one which supports extended CPUID levels.
  92. */
  93. if (eax < 2)
  94. return rval;
  95. if (ext_caps & (1<<24))
  96. rval |= MM_MMXEXT;
  97. }
  98. #if 0
  99. av_log(NULL, AV_LOG_DEBUG, "%s%s%s%s%s%s\n",
  100. (rval&MM_MMX) ? "MMX ":"",
  101. (rval&MM_MMXEXT) ? "MMX2 ":"",
  102. (rval&MM_SSE) ? "SSE ":"",
  103. (rval&MM_SSE2) ? "SSE2 ":"",
  104. (rval&MM_3DNOW) ? "3DNow ":"",
  105. (rval&MM_3DNOWEXT) ? "3DNowExt ":"");
  106. #endif
  107. return rval;
  108. }
  109. #ifdef __TEST__
  110. int main ( void )
  111. {
  112. int mm_flags;
  113. mm_flags = mm_support();
  114. printf("mm_support = 0x%08X\n",mm_flags);
  115. return 0;
  116. }
  117. #endif