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.

233 lines
7.8 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
  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. #ifdef WIN32
  30. //----------------------------------------------------------------------;
  31. //
  32. // Win 32
  33. //
  34. //----------------------------------------------------------------------;
  35. #ifdef _X86_
  36. //
  37. // Use 32-bit x86 assembly.
  38. //
  39. #pragma warning(disable:4035 4704)
  40. INLINE LONG MulDiv32(LONG a,LONG b,LONG c)
  41. {
  42. _asm mov eax,dword ptr a // mov eax, a
  43. _asm mov ebx,dword ptr b // mov ebx, b
  44. _asm mov ecx,dword ptr c // mov ecx, c
  45. _asm imul ebx // imul ebx
  46. _asm idiv ecx // idiv ecx
  47. _asm shld edx, eax, 16 // shld edx, eax, 16
  48. } // MulDiv32()
  49. INLINE DWORD MulDivRN(DWORD a,DWORD b,DWORD c)
  50. {
  51. _asm mov eax,dword ptr a // mov eax, a
  52. _asm mov ebx,dword ptr b // mov ebx, b
  53. _asm mov ecx,dword ptr c // mov ecx, c
  54. _asm mul ebx // mul ebx
  55. _asm mov ebx,ecx // mov ebx,ecx
  56. _asm shr ebx,1 // sar ebx,1
  57. _asm add eax,ebx // add eax,ebx
  58. _asm adc edx,0 // adc edx,0
  59. _asm div ecx // div ecx
  60. _asm shld edx, eax, 16 // shld edx, eax, 16
  61. } // MulDiv32()
  62. INLINE DWORD MulDivRU(DWORD a,DWORD b,DWORD c)
  63. {
  64. _asm mov eax,dword ptr a // mov eax, a
  65. _asm mov ebx,dword ptr b // mov ebx, b
  66. _asm mov ecx,dword ptr c // mov ecx, c
  67. _asm mul ebx // mul ebx
  68. _asm mov ebx,ecx // mov ebx,ecx
  69. _asm dec ebx // dec ebx
  70. _asm add eax,ebx // add eax,ebx
  71. _asm adc edx,0 // adc edx,0
  72. _asm div ecx // div ecx
  73. _asm shld edx, eax, 16 // shld edx, eax, 16
  74. } // MulDivRU32()
  75. INLINE DWORD MulDivRD(DWORD a,DWORD b,DWORD c)
  76. {
  77. _asm mov eax,dword ptr a // mov eax, a
  78. _asm mov ebx,dword ptr b // mov ebx, b
  79. _asm mov ecx,dword ptr c // mov ecx, c
  80. _asm mul ebx // mul ebx
  81. _asm div ecx // div ecx
  82. _asm shld edx, eax, 16 // shld edx, eax, 16
  83. } // MulDivRD32()
  84. #pragma warning(default:4035 4704)
  85. #else
  86. //
  87. // Use C9 __int64 support for Daytona RISC platforms.
  88. //
  89. INLINE LONG MulDiv32( LONG a, LONG b, LONG c )
  90. {
  91. return (LONG)( Int32x32To64(a,b) / c );
  92. }
  93. INLINE DWORD MulDivRD( DWORD a, DWORD b, DWORD c )
  94. {
  95. return (DWORD)( UInt32x32To64(a,b) / c );
  96. }
  97. INLINE DWORD MulDivRN( DWORD a, DWORD b, DWORD c )
  98. {
  99. return (DWORD)( (UInt32x32To64(a,b)+c/2) / c );
  100. }
  101. INLINE DWORD MulDivRU( DWORD a, DWORD b, DWORD c )
  102. {
  103. return (DWORD)( (UInt32x32To64(a,b)+c-1) / c );
  104. }
  105. #endif
  106. #else
  107. //----------------------------------------------------------------------;
  108. //
  109. // Win 16
  110. //
  111. //----------------------------------------------------------------------;
  112. #pragma warning(disable:4035 4704)
  113. //
  114. // Compile for 16-bit - we can use x86 with proper opcode prefixes
  115. // to get 32-bit instructions.
  116. //
  117. INLINE LONG MulDiv32(LONG a,LONG b,LONG c)
  118. {
  119. _asm _emit 0x66 _asm mov ax,word ptr a // mov eax, a
  120. _asm _emit 0x66 _asm mov bx,word ptr b // mov ebx, b
  121. _asm _emit 0x66 _asm mov cx,word ptr c // mov ecx, c
  122. _asm _emit 0x66 _asm imul bx // imul ebx
  123. _asm _emit 0x66 _asm idiv cx // idiv ecx
  124. _asm _emit 0x66 // shld edx, eax, 16
  125. _asm _emit 0x0F
  126. _asm _emit 0xA4
  127. _asm _emit 0xC2
  128. _asm _emit 0x10
  129. } // MulDiv32()
  130. INLINE DWORD MulDivRN(DWORD a,DWORD b,DWORD c)
  131. {
  132. _asm _emit 0x66 _asm mov ax,word ptr a // mov eax, a
  133. _asm _emit 0x66 _asm mov bx,word ptr b // mov ebx, b
  134. _asm _emit 0x66 _asm mov cx,word ptr c // mov ecx, c
  135. _asm _emit 0x66 _asm mul bx // mul ebx
  136. _asm _emit 0x66 _asm mov bx,cx // mov ebx,ecx
  137. _asm _emit 0x66 _asm shr bx,1 // sar ebx,1
  138. _asm _emit 0x66 _asm add ax,bx // add eax,ebx
  139. _asm _emit 0x66 _asm adc dx,0 // adc edx,0
  140. _asm _emit 0x66 _asm div cx // div ecx
  141. _asm _emit 0x66 // shld edx, eax, 16
  142. _asm _emit 0x0F
  143. _asm _emit 0xA4
  144. _asm _emit 0xC2
  145. _asm _emit 0x10
  146. } // MulDiv32()
  147. INLINE DWORD MulDivRU(DWORD a,DWORD b,DWORD c)
  148. {
  149. _asm _emit 0x66 _asm mov ax,word ptr a // mov eax, a
  150. _asm _emit 0x66 _asm mov bx,word ptr b // mov ebx, b
  151. _asm _emit 0x66 _asm mov cx,word ptr c // mov ecx, c
  152. _asm _emit 0x66 _asm mul bx // mul ebx
  153. _asm _emit 0x66 _asm mov bx,cx // mov ebx,ecx
  154. _asm _emit 0x66 _asm dec bx // dec ebx
  155. _asm _emit 0x66 _asm add ax,bx // add eax,ebx
  156. _asm _emit 0x66 _asm adc dx,0 // adc edx,0
  157. _asm _emit 0x66 _asm div cx // div ecx
  158. _asm _emit 0x66 // shld edx, eax, 16
  159. _asm _emit 0x0F
  160. _asm _emit 0xA4
  161. _asm _emit 0xC2
  162. _asm _emit 0x10
  163. } // MulDivRU32()
  164. INLINE DWORD MulDivRD(DWORD a,DWORD b,DWORD c)
  165. {
  166. _asm _emit 0x66 _asm mov ax,word ptr a // mov eax, a
  167. _asm _emit 0x66 _asm mov bx,word ptr b // mov ebx, b
  168. _asm _emit 0x66 _asm mov cx,word ptr c // mov ecx, c
  169. _asm _emit 0x66 _asm mul bx // mul ebx
  170. _asm _emit 0x66 _asm div cx // div ecx
  171. _asm _emit 0x66 // shld edx, eax, 16
  172. _asm _emit 0x0F
  173. _asm _emit 0xA4
  174. _asm _emit 0xC2
  175. _asm _emit 0x10
  176. } // MulDivRD32()
  177. #pragma warning(default:4035 4704)
  178. #endif
  179. //
  180. // some code references these by other names.
  181. //
  182. #define muldiv32 MulDivRN
  183. #define muldivrd32 MulDivRD
  184. #define muldivru32 MulDivRU
  185. #endif // _INC_MULDIV32