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.

152 lines
4.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 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;
  25. int eax, ebx, ecx, edx;
  26. __asm__ __volatile__ (
  27. /* See if CPUID instruction is supported ... */
  28. /* ... Get copies of EFLAGS into eax and ecx */
  29. "pushf\n\t"
  30. "pop %0\n\t"
  31. "movl %0, %1\n\t"
  32. /* ... Toggle the ID bit in one copy and store */
  33. /* to the EFLAGS reg */
  34. "xorl $0x200000, %0\n\t"
  35. "push %0\n\t"
  36. "popf\n\t"
  37. /* ... Get the (hopefully modified) EFLAGS */
  38. "pushf\n\t"
  39. "pop %0\n\t"
  40. : "=a" (eax), "=c" (ecx)
  41. :
  42. : "cc"
  43. );
  44. if (eax == ecx)
  45. return 0; /* CPUID not supported */
  46. cpuid(0, eax, ebx, ecx, edx);
  47. if (ebx == 0x756e6547 &&
  48. edx == 0x49656e69 &&
  49. ecx == 0x6c65746e) {
  50. /* intel */
  51. inteltest:
  52. cpuid(1, eax, ebx, ecx, edx);
  53. if ((edx & 0x00800000) == 0)
  54. return 0;
  55. rval = MM_MMX;
  56. if (edx & 0x02000000)
  57. rval |= MM_MMXEXT | MM_SSE;
  58. if (edx & 0x04000000)
  59. rval |= MM_SSE2;
  60. return rval;
  61. } else if (ebx == 0x68747541 &&
  62. edx == 0x69746e65 &&
  63. ecx == 0x444d4163) {
  64. /* AMD */
  65. cpuid(0x80000000, eax, ebx, ecx, edx);
  66. if ((unsigned)eax < 0x80000001)
  67. goto inteltest;
  68. cpuid(0x80000001, eax, ebx, ecx, edx);
  69. if ((edx & 0x00800000) == 0)
  70. return 0;
  71. rval = MM_MMX;
  72. if (edx & 0x80000000)
  73. rval |= MM_3DNOW;
  74. if (edx & 0x00400000)
  75. rval |= MM_MMXEXT;
  76. return rval;
  77. } else if (ebx == 0x746e6543 &&
  78. edx == 0x48727561 &&
  79. ecx == 0x736c7561) { /* "CentaurHauls" */
  80. /* VIA C3 */
  81. cpuid(0x80000000, eax, ebx, ecx, edx);
  82. if ((unsigned)eax < 0x80000001)
  83. goto inteltest;
  84. cpuid(0x80000001, eax, ebx, ecx, edx);
  85. rval = 0;
  86. if( edx & ( 1 << 31) )
  87. rval |= MM_3DNOW;
  88. if( edx & ( 1 << 23) )
  89. rval |= MM_MMX;
  90. if( edx & ( 1 << 24) )
  91. rval |= MM_MMXEXT;
  92. if(rval==0)
  93. goto inteltest;
  94. return rval;
  95. } else if (ebx == 0x69727943 &&
  96. edx == 0x736e4978 &&
  97. ecx == 0x64616574) {
  98. /* Cyrix Section */
  99. /* See if extended CPUID level 80000001 is supported */
  100. /* The value of CPUID/80000001 for the 6x86MX is undefined
  101. according to the Cyrix CPU Detection Guide (Preliminary
  102. Rev. 1.01 table 1), so we'll check the value of eax for
  103. CPUID/0 to see if standard CPUID level 2 is supported.
  104. According to the table, the only CPU which supports level
  105. 2 is also the only one which supports extended CPUID levels.
  106. */
  107. if (eax != 2)
  108. goto inteltest;
  109. cpuid(0x80000001, eax, ebx, ecx, edx);
  110. if ((eax & 0x00800000) == 0)
  111. return 0;
  112. rval = MM_MMX;
  113. if (eax & 0x01000000)
  114. rval |= MM_MMXEXT;
  115. return rval;
  116. } else if (ebx == 0x756e6547 &&
  117. edx == 0x54656e69 &&
  118. ecx == 0x3638784d) {
  119. /* Tranmeta Crusoe */
  120. cpuid(0x80000000, eax, ebx, ecx, edx);
  121. if ((unsigned)eax < 0x80000001)
  122. return 0;
  123. cpuid(0x80000001, eax, ebx, ecx, edx);
  124. if ((edx & 0x00800000) == 0)
  125. return 0;
  126. return MM_MMX;
  127. } else {
  128. return 0;
  129. }
  130. }
  131. #ifdef __TEST__
  132. int main ( void )
  133. {
  134. int mm_flags;
  135. mm_flags = mm_support();
  136. printf("mm_support = 0x%08X\n",mm_flags);
  137. return 0;
  138. }
  139. #endif