Counter Strike : Global Offensive Source Code
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.

160 lines
4.1 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: 3DNow Math primitives.
  4. //
  5. //=====================================================================================//
  6. #include <math.h>
  7. #include <float.h> // needed for flt_epsilon
  8. #include "basetypes.h"
  9. //#include <memory.h>
  10. #include "tier0/dbg.h"
  11. #include "mathlib/mathlib.h"
  12. //#include "mathlib/amd3dx.h"
  13. #include "mathlib/vector.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. #ifdef COMPILER_MSVC
  17. #pragma warning(disable:4244) // "conversion from 'const int' to 'float', possible loss of data"
  18. #pragma warning(disable:4730) // "mixing _m64 and floating point expressions may result in incorrect code"
  19. #endif
  20. //-----------------------------------------------------------------------------
  21. // 3D Now Implementations of optimized routines:
  22. //-----------------------------------------------------------------------------
  23. float _3DNow_Sqrt(float x)
  24. {
  25. Assert( s_bMathlibInitialized );
  26. float root = 0.f;
  27. #ifdef _WIN32
  28. _asm
  29. {
  30. femms
  31. movd mm0, x
  32. PFRSQRT (mm1,mm0)
  33. punpckldq mm0, mm0
  34. PFMUL (mm0, mm1)
  35. movd root, mm0
  36. femms
  37. }
  38. #elif POSIX
  39. __asm __volatile__( "femms" );
  40. __asm __volatile__ ( "pfrsqrt %y0, %y1 \n\t" "punpckldq %y1, %y1 \n\t" "pfmul %y1, %y0 \n\t" : "=y" (root), "=y" (x) :"0" (x));
  41. __asm __volatile__( "femms" );
  42. #else
  43. #error
  44. #endif
  45. return root;
  46. }
  47. // NJS FIXME: Need to test Recripricol squareroot performance and accuraccy
  48. // on AMD's before using the specialized instruction.
  49. float _3DNow_RSqrt(float x)
  50. {
  51. Assert( s_bMathlibInitialized );
  52. return 1.f / _3DNow_Sqrt(x);
  53. }
  54. float FASTCALL _3DNow_VectorNormalize (Vector& vec)
  55. {
  56. Assert( s_bMathlibInitialized );
  57. float *v = &vec[0];
  58. float radius = 0.f;
  59. if ( v[0] || v[1] || v[2] )
  60. {
  61. #ifdef _WIN32
  62. _asm
  63. {
  64. mov eax, v
  65. femms
  66. movq mm0, QWORD PTR [eax]
  67. movd mm1, DWORD PTR [eax+8]
  68. movq mm2, mm0
  69. movq mm3, mm1
  70. PFMUL (mm0, mm0)
  71. PFMUL (mm1, mm1)
  72. PFACC (mm0, mm0)
  73. PFADD (mm1, mm0)
  74. PFRSQRT (mm0, mm1)
  75. punpckldq mm1, mm1
  76. PFMUL (mm1, mm0)
  77. PFMUL (mm2, mm0)
  78. PFMUL (mm3, mm0)
  79. movq QWORD PTR [eax], mm2
  80. movd DWORD PTR [eax+8], mm3
  81. movd radius, mm1
  82. femms
  83. }
  84. #elif POSIX
  85. long long a,c;
  86. int b,d;
  87. memcpy(&a,&vec[0],sizeof(a));
  88. memcpy(&b,&vec[2],sizeof(b));
  89. memcpy(&c,&vec[0],sizeof(c));
  90. memcpy(&d,&vec[2],sizeof(d));
  91. __asm __volatile__( "femms" );
  92. __asm __volatile__ ( "pfmul %y3, %y3\n\t" "pfmul %y0, %y0 \n\t" "pfacc %y3, %y3 \n\t" "pfadd %y3, %y0 \n\t" "pfrsqrt %y0, %y3 \n\t" "punpckldq %y0, %y0 \n\t" "pfmul %y3, %y0 \n\t" "pfmul %y3, %y2 \n\t" "pfmul %y3, %y1 \n\t" : "=y" (radius), "=y" (c), "=y" (d) : "y" (a), "0" (b), "1" (c), "2" (d));
  93. memcpy(&vec[0],&c,sizeof(c));
  94. memcpy(&vec[2],&d,sizeof(d));
  95. __asm __volatile__( "femms" );
  96. #else
  97. #error
  98. #endif
  99. }
  100. return radius;
  101. }
  102. void FASTCALL _3DNow_VectorNormalizeFast (Vector& vec)
  103. {
  104. _3DNow_VectorNormalize( vec );
  105. }
  106. // JAY: This complains with the latest processor pack
  107. #pragma warning(disable: 4730)
  108. float _3DNow_InvRSquared(const float* v)
  109. {
  110. Assert( s_bMathlibInitialized );
  111. float r2 = 1.f;
  112. #ifdef _WIN32
  113. _asm { // AMD 3DNow only routine
  114. mov eax, v
  115. femms
  116. movq mm0, QWORD PTR [eax]
  117. movd mm1, DWORD PTR [eax+8]
  118. movd mm2, [r2]
  119. PFMUL (mm0, mm0)
  120. PFMUL (mm1, mm1)
  121. PFACC (mm0, mm0)
  122. PFADD (mm1, mm0)
  123. PFMAX (mm1, mm2)
  124. PFRCP (mm0, mm1)
  125. movd [r2], mm0
  126. femms
  127. }
  128. #elif POSIX
  129. long long a,c;
  130. int b;
  131. memcpy(&a,&v[0],sizeof(a));
  132. memcpy(&b,&v[2],sizeof(b));
  133. memcpy(&c,&v[0],sizeof(c));
  134. __asm __volatile__( "femms" );
  135. __asm __volatile__ ( "PFMUL %y2, %y2 \n\t" "PFMUL %y3, %y3 \n\t" "PFACC %y2, %y2 \n\t" "PFADD %y2, %y3 \n\t" "PFMAX %y3, %y4 \n\t" "PFRCP %y3, %y2 \n\t" "movq %y2, %y0 \n\t" : "=y" (r2) : "0" (r2), "y" (a), "y" (b), "y" (c));
  136. __asm __volatile__( "femms" );
  137. #else
  138. #error
  139. #endif
  140. return r2;
  141. }