Team Fortress 2 Source Code as on 22/4/2020
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.

274 lines
6.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: win32 dependant ASM code for CPU capability detection
  4. //
  5. // $Workfile: $
  6. // $NoKeywords: $
  7. //=============================================================================//
  8. #if defined( _X360 ) || defined( WIN64 )
  9. bool CheckMMXTechnology(void) { return false; }
  10. bool CheckSSETechnology(void) { return false; }
  11. bool CheckSSE2Technology(void) { return false; }
  12. bool Check3DNowTechnology(void) { return false; }
  13. #elif defined( _WIN32 ) && !defined( _X360 )
  14. #pragma optimize( "", off )
  15. #pragma warning( disable: 4800 ) //'int' : forcing value to bool 'true' or 'false' (performance warning)
  16. // stuff from windows.h
  17. #ifndef EXCEPTION_EXECUTE_HANDLER
  18. #define EXCEPTION_EXECUTE_HANDLER 1
  19. #endif
  20. bool CheckMMXTechnology(void)
  21. {
  22. int retval = true;
  23. unsigned int RegEDX = 0;
  24. #ifdef CPUID
  25. _asm pushad;
  26. #endif
  27. __try
  28. {
  29. _asm
  30. {
  31. #ifdef CPUID
  32. xor edx, edx // Clue the compiler that EDX is about to be used.
  33. #endif
  34. mov eax, 1 // set up CPUID to return processor version and features
  35. // 0 = vendor string, 1 = version info, 2 = cache info
  36. CPUID // code bytes = 0fh, 0a2h
  37. mov RegEDX, edx // features returned in edx
  38. }
  39. }
  40. __except(EXCEPTION_EXECUTE_HANDLER)
  41. {
  42. retval = false;
  43. }
  44. // If CPUID not supported, then certainly no MMX extensions.
  45. if (retval)
  46. {
  47. if (RegEDX & 0x800000) // bit 23 is set for MMX technology
  48. {
  49. __try
  50. {
  51. // try executing the MMX instruction "emms"
  52. _asm EMMS
  53. }
  54. __except(EXCEPTION_EXECUTE_HANDLER)
  55. {
  56. retval = false;
  57. }
  58. }
  59. else
  60. retval = false; // processor supports CPUID but does not support MMX technology
  61. // if retval == 0 here, it means the processor has MMX technology but
  62. // floating-point emulation is on; so MMX technology is unavailable
  63. }
  64. #ifdef CPUID
  65. _asm popad;
  66. #endif
  67. return retval;
  68. }
  69. bool CheckSSETechnology(void)
  70. {
  71. int retval = true;
  72. unsigned int RegEDX = 0;
  73. #ifdef CPUID
  74. _asm pushad;
  75. #endif
  76. // Do we have support for the CPUID function?
  77. __try
  78. {
  79. _asm
  80. {
  81. #ifdef CPUID
  82. xor edx, edx // Clue the compiler that EDX is about to be used.
  83. #endif
  84. mov eax, 1 // set up CPUID to return processor version and features
  85. // 0 = vendor string, 1 = version info, 2 = cache info
  86. CPUID // code bytes = 0fh, 0a2h
  87. mov RegEDX, edx // features returned in edx
  88. }
  89. }
  90. __except(EXCEPTION_EXECUTE_HANDLER)
  91. {
  92. retval = false;
  93. }
  94. // If CPUID not supported, then certainly no SSE extensions.
  95. if (retval)
  96. {
  97. // Do we have support for SSE in this processor?
  98. if ( RegEDX & 0x2000000L ) // bit 25 is set for SSE technology
  99. {
  100. // Make sure that SSE is supported by executing an inline SSE instruction
  101. // BUGBUG, FIXME - Visual C Version 6.0 does not support SSE inline code YET (No macros from Intel either)
  102. // Fix this if VC7 supports inline SSE instructinons like "xorps" as shown below.
  103. #if 1
  104. __try
  105. {
  106. _asm
  107. {
  108. // Attempt execution of a SSE instruction to make sure OS supports SSE FPU context switches
  109. xorps xmm0, xmm0
  110. // This will work on Win2k+ (Including masking SSE FPU exception to "normalized" values)
  111. // This will work on Win98+ (But no "masking" of FPU exceptions provided)
  112. }
  113. }
  114. __except(EXCEPTION_EXECUTE_HANDLER)
  115. #endif
  116. {
  117. retval = false;
  118. }
  119. }
  120. else
  121. retval = false;
  122. }
  123. #ifdef CPUID
  124. _asm popad;
  125. #endif
  126. return retval;
  127. }
  128. bool CheckSSE2Technology(void)
  129. {
  130. int retval = true;
  131. unsigned int RegEDX = 0;
  132. #ifdef CPUID
  133. _asm pushad;
  134. #endif
  135. // Do we have support for the CPUID function?
  136. __try
  137. {
  138. _asm
  139. {
  140. #ifdef CPUID
  141. xor edx, edx // Clue the compiler that EDX is about to be used.
  142. #endif
  143. mov eax, 1 // set up CPUID to return processor version and features
  144. // 0 = vendor string, 1 = version info, 2 = cache info
  145. CPUID // code bytes = 0fh, 0a2h
  146. mov RegEDX, edx // features returned in edx
  147. }
  148. }
  149. __except(EXCEPTION_EXECUTE_HANDLER)
  150. {
  151. retval = false;
  152. }
  153. // If CPUID not supported, then certainly no SSE extensions.
  154. if (retval)
  155. {
  156. // Do we have support for SSE in this processor?
  157. if ( RegEDX & 0x04000000 ) // bit 26 is set for SSE2 technology
  158. {
  159. // Make sure that SSE is supported by executing an inline SSE instruction
  160. __try
  161. {
  162. _asm
  163. {
  164. // Attempt execution of a SSE2 instruction to make sure OS supports SSE FPU context switches
  165. xorpd xmm0, xmm0
  166. }
  167. }
  168. __except(EXCEPTION_EXECUTE_HANDLER)
  169. {
  170. retval = false;
  171. }
  172. }
  173. else
  174. retval = false;
  175. }
  176. #ifdef CPUID
  177. _asm popad;
  178. #endif
  179. return retval;
  180. }
  181. bool Check3DNowTechnology(void)
  182. {
  183. int retval = true;
  184. unsigned int RegEAX = 0;
  185. #ifdef CPUID
  186. _asm pushad;
  187. #endif
  188. // First see if we can execute CPUID at all
  189. __try
  190. {
  191. _asm
  192. {
  193. #ifdef CPUID
  194. // xor edx, edx // Clue the compiler that EDX is about to be used.
  195. #endif
  196. mov eax, 0x80000000 // setup CPUID to return whether AMD >0x80000000 function are supported.
  197. // 0x80000000 = Highest 0x80000000+ function, 0x80000001 = 3DNow support
  198. CPUID // code bytes = 0fh, 0a2h
  199. mov RegEAX, eax // result returned in eax
  200. }
  201. }
  202. __except(EXCEPTION_EXECUTE_HANDLER)
  203. {
  204. retval = false;
  205. }
  206. // If CPUID not supported, then there is definitely no 3DNow support
  207. if (retval)
  208. {
  209. // Are there any "higher" AMD CPUID functions?
  210. if (RegEAX > 0x80000000L )
  211. {
  212. __try
  213. {
  214. _asm
  215. {
  216. mov eax, 0x80000001 // setup to test for CPU features
  217. CPUID // code bytes = 0fh, 0a2h
  218. shr edx, 31 // If bit 31 is set, we have 3DNow support!
  219. mov retval, edx // Save the return value for end of function
  220. }
  221. }
  222. __except(EXCEPTION_EXECUTE_HANDLER)
  223. {
  224. retval = false;
  225. }
  226. }
  227. else
  228. {
  229. // processor supports CPUID but does not support AMD CPUID functions
  230. retval = false;
  231. }
  232. }
  233. #ifdef CPUID
  234. _asm popad;
  235. #endif
  236. return retval;
  237. }
  238. #pragma optimize( "", on )
  239. #endif // _WIN32