Source code of Windows XP (NT5)
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.

219 lines
7.2 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1992 - 1994 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. // muldiv32.h
  13. //
  14. // Description:
  15. // math routines for 32 bit signed and unsiged numbers.
  16. //
  17. // MulDiv32(a,b,c) = (a * b) / c (round down, signed)
  18. //
  19. // MulDivRD(a,b,c) = (a * b) / c (round down, unsigned)
  20. // MulDivRN(a,b,c) = (a * b + c/2) / c (round nearest, unsigned)
  21. // MulDivRU(a,b,c) = (a * b + c-1) / c (round up, unsigned)
  22. //
  23. //==========================================================================;
  24. #ifndef _INC_MULDIV32
  25. #define _INC_MULDIV32
  26. #ifndef INLINE
  27. #define INLINE __inline
  28. #endif
  29. #if ( defined(WIN32) || defined(_WIN32) ) && !defined(WIN4)
  30. //
  31. // Compile for Daytona - use __int64 support on C9.
  32. //
  33. INLINE LONG MulDiv32( LONG a, LONG b, LONG c )
  34. {
  35. return (LONG)( ((LONGLONG)a*b) / c );
  36. }
  37. INLINE DWORD MulDivRD( DWORD a, DWORD b, DWORD c )
  38. {
  39. return (DWORD)( ((DWORDLONG)a*b) / c );
  40. }
  41. INLINE DWORD MulDivRN( DWORD a, DWORD b, DWORD c )
  42. {
  43. return (DWORD)( (((DWORDLONG)a*b)+c/2) / c );
  44. }
  45. INLINE DWORD MulDivRU( DWORD a, DWORD b, DWORD c )
  46. {
  47. return (DWORD)( (((DWORDLONG)a*b)+c-1) / c );
  48. }
  49. #else
  50. //
  51. // Compile for Win16 or Chicago - either way, we can use X86 assembly.
  52. //
  53. #pragma warning(disable:4035 4704)
  54. #ifdef WIN32
  55. //
  56. // Compile for 32-bit Chicago - we can use i386 assembly.
  57. //
  58. INLINE LONG MulDiv32(LONG a,LONG b,LONG c)
  59. {
  60. _asm mov eax,dword ptr a // mov eax, a
  61. _asm mov ebx,dword ptr b // mov ebx, b
  62. _asm mov ecx,dword ptr c // mov ecx, c
  63. _asm imul ebx // imul ebx
  64. _asm idiv ecx // idiv ecx
  65. _asm shld edx, eax, 16 // shld edx, eax, 16
  66. } // MulDiv32()
  67. INLINE DWORD MulDivRN(DWORD a,DWORD b,DWORD c)
  68. {
  69. _asm mov eax,dword ptr a // mov eax, a
  70. _asm mov ebx,dword ptr b // mov ebx, b
  71. _asm mov ecx,dword ptr c // mov ecx, c
  72. _asm mul ebx // mul ebx
  73. _asm mov ebx,ecx // mov ebx,ecx
  74. _asm shr ebx,1 // sar ebx,1
  75. _asm add eax,ebx // add eax,ebx
  76. _asm adc edx,0 // adc edx,0
  77. _asm div ecx // div ecx
  78. _asm shld edx, eax, 16 // shld edx, eax, 16
  79. } // MulDiv32()
  80. INLINE DWORD MulDivRU(DWORD a,DWORD b,DWORD c)
  81. {
  82. _asm mov eax,dword ptr a // mov eax, a
  83. _asm mov ebx,dword ptr b // mov ebx, b
  84. _asm mov ecx,dword ptr c // mov ecx, c
  85. _asm mul ebx // mul ebx
  86. _asm mov ebx,ecx // mov ebx,ecx
  87. _asm dec ebx // dec ebx
  88. _asm add eax,ebx // add eax,ebx
  89. _asm adc edx,0 // adc edx,0
  90. _asm div ecx // div ecx
  91. _asm shld edx, eax, 16 // shld edx, eax, 16
  92. } // MulDivRU32()
  93. INLINE DWORD MulDivRD(DWORD a,DWORD b,DWORD c)
  94. {
  95. _asm mov eax,dword ptr a // mov eax, a
  96. _asm mov ebx,dword ptr b // mov ebx, b
  97. _asm mov ecx,dword ptr c // mov ecx, c
  98. _asm mul ebx // mul ebx
  99. _asm div ecx // div ecx
  100. _asm shld edx, eax, 16 // shld edx, eax, 16
  101. } // MulDivRD32()
  102. #else
  103. //
  104. // Compile for 16-bit - we can use x86 with proper opcode prefixes
  105. // to get 32-bit instructions.
  106. //
  107. INLINE LONG MulDiv32(LONG a,LONG b,LONG c)
  108. {
  109. _asm _emit 0x66 _asm mov ax,word ptr a // mov eax, a
  110. _asm _emit 0x66 _asm mov bx,word ptr b // mov ebx, b
  111. _asm _emit 0x66 _asm mov cx,word ptr c // mov ecx, c
  112. _asm _emit 0x66 _asm imul bx // imul ebx
  113. _asm _emit 0x66 _asm idiv cx // idiv ecx
  114. _asm _emit 0x66 // shld edx, eax, 16
  115. _asm _emit 0x0F
  116. _asm _emit 0xA4
  117. _asm _emit 0xC2
  118. _asm _emit 0x10
  119. } // MulDiv32()
  120. INLINE DWORD MulDivRN(DWORD a,DWORD b,DWORD c)
  121. {
  122. _asm _emit 0x66 _asm mov ax,word ptr a // mov eax, a
  123. _asm _emit 0x66 _asm mov bx,word ptr b // mov ebx, b
  124. _asm _emit 0x66 _asm mov cx,word ptr c // mov ecx, c
  125. _asm _emit 0x66 _asm mul bx // mul ebx
  126. _asm _emit 0x66 _asm mov bx,cx // mov ebx,ecx
  127. _asm _emit 0x66 _asm shr bx,1 // sar ebx,1
  128. _asm _emit 0x66 _asm add ax,bx // add eax,ebx
  129. _asm _emit 0x66 _asm adc dx,0 // adc edx,0
  130. _asm _emit 0x66 _asm div cx // div ecx
  131. _asm _emit 0x66 // shld edx, eax, 16
  132. _asm _emit 0x0F
  133. _asm _emit 0xA4
  134. _asm _emit 0xC2
  135. _asm _emit 0x10
  136. } // MulDiv32()
  137. INLINE DWORD MulDivRU(DWORD a,DWORD b,DWORD c)
  138. {
  139. _asm _emit 0x66 _asm mov ax,word ptr a // mov eax, a
  140. _asm _emit 0x66 _asm mov bx,word ptr b // mov ebx, b
  141. _asm _emit 0x66 _asm mov cx,word ptr c // mov ecx, c
  142. _asm _emit 0x66 _asm mul bx // mul ebx
  143. _asm _emit 0x66 _asm mov bx,cx // mov ebx,ecx
  144. _asm _emit 0x66 _asm dec bx // dec ebx
  145. _asm _emit 0x66 _asm add ax,bx // add eax,ebx
  146. _asm _emit 0x66 _asm adc dx,0 // adc edx,0
  147. _asm _emit 0x66 _asm div cx // div ecx
  148. _asm _emit 0x66 // shld edx, eax, 16
  149. _asm _emit 0x0F
  150. _asm _emit 0xA4
  151. _asm _emit 0xC2
  152. _asm _emit 0x10
  153. } // MulDivRU32()
  154. INLINE DWORD MulDivRD(DWORD a,DWORD b,DWORD c)
  155. {
  156. _asm _emit 0x66 _asm mov ax,word ptr a // mov eax, a
  157. _asm _emit 0x66 _asm mov bx,word ptr b // mov ebx, b
  158. _asm _emit 0x66 _asm mov cx,word ptr c // mov ecx, c
  159. _asm _emit 0x66 _asm mul bx // mul ebx
  160. _asm _emit 0x66 _asm div cx // div ecx
  161. _asm _emit 0x66 // shld edx, eax, 16
  162. _asm _emit 0x0F
  163. _asm _emit 0xA4
  164. _asm _emit 0xC2
  165. _asm _emit 0x10
  166. } // MulDivRD32()
  167. #endif
  168. #pragma warning(default:4035 4704)
  169. #endif
  170. //
  171. // some code references these by other names.
  172. //
  173. #define muldiv32 MulDivRN
  174. #define muldivrd32 MulDivRD
  175. #define muldivru32 MulDivRU
  176. #endif // _INC_MULDIV32