Leaked source code of windows server 2003
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.

316 lines
8.3 KiB

  1. #include <limits.h>
  2. #include "lsidefs.h"
  3. #include "zqfromza.h"
  4. #ifdef _X86_
  5. /* =========================================================== */
  6. /* */
  7. /* Functions implemented on Intel X86 Assember */
  8. /* */
  9. /* =========================================================== */
  10. #define HIWORD(x) DWORD PTR [x+4]
  11. #define LOWORD(x) DWORD PTR [x]
  12. long ZqFromZa_Asm (long dzqInch, long za)
  13. {
  14. long result;
  15. __asm
  16. {
  17. mov eax, za;
  18. cmp eax, 0
  19. jge POSITIVE
  20. neg eax
  21. mul dzqInch;
  22. add eax, czaUnitInch / 2
  23. mov ecx, czaUnitInch
  24. adc edx, 0
  25. div ecx;
  26. neg eax
  27. jmp RETURN
  28. POSITIVE:
  29. mul dzqInch;
  30. add eax, czaUnitInch / 2
  31. mov ecx, czaUnitInch
  32. adc edx, 0
  33. div ecx;
  34. RETURN:
  35. mov result, eax
  36. };
  37. /*
  38. Assert (result == ZqFromZa_C (dzqInch, za));
  39. */
  40. return result;
  41. }
  42. /* D I V 6 4 _ A S M */
  43. /*----------------------------------------------------------------------------
  44. %%Function: Div64_Asm
  45. %%Contact: antons
  46. Intel assembler implementation of 64-bit division. The
  47. orignal code was taken from lldiv.asm (VC++ 6.0).
  48. ----------------------------------------------------------------------------*/
  49. __int64 Div64_Asm (__int64 DVND, __int64 DVSR)
  50. {
  51. __int64 result;
  52. __asm {
  53. xor edi,edi // result sign assumed positive
  54. mov eax,HIWORD(DVND) // hi word of a
  55. or eax,eax // test to see if signed
  56. jge L1 // skip rest if a is already positive
  57. inc edi // complement result sign flag
  58. mov edx,LOWORD(DVND) // lo word of a
  59. neg eax // make a positive
  60. neg edx
  61. sbb eax,0
  62. mov HIWORD(DVND),eax // save positive value
  63. mov LOWORD(DVND),edx
  64. L1:
  65. mov eax,HIWORD(DVSR) // hi word of b
  66. or eax,eax // test to see if signed
  67. jge L2 // skip rest if b is already positive
  68. inc edi // complement the result sign flag
  69. mov edx,LOWORD(DVSR) // lo word of a
  70. neg eax // make b positive
  71. neg edx
  72. sbb eax,0
  73. mov HIWORD(DVSR),eax // save positive value
  74. mov LOWORD(DVSR),edx
  75. L2:
  76. // Now do the divide. First look to see if the divisor is less than 4194304K.
  77. // If so, then we can use a simple algorithm with word divides, otherwise
  78. // things get a little more complex.
  79. //
  80. // NOTE - eax currently contains the high order word of DVSR
  81. or eax,eax // check to see if divisor < 4194304K
  82. jnz L3 // nope, gotta do this the hard way
  83. mov ecx,LOWORD(DVSR) // load divisor
  84. mov eax,HIWORD(DVND) // load high word of dividend
  85. xor edx,edx
  86. div ecx // eax <- high order bits of quotient
  87. mov ebx,eax // save high bits of quotient
  88. mov eax,LOWORD(DVND) // edx:eax <- remainder:lo word of dividend
  89. div ecx // eax <- low order bits of quotient
  90. mov edx,ebx // edx:eax <- quotient
  91. jmp L4 // set sign, restore stack and return
  92. //
  93. // Here we do it the hard way. Remember, eax contains the high word of DVSR
  94. //
  95. L3:
  96. mov ebx,eax // ebx:ecx <- divisor
  97. mov ecx,LOWORD(DVSR)
  98. mov edx,HIWORD(DVND) // edx:eax <- dividend
  99. mov eax,LOWORD(DVND)
  100. L5:
  101. shr ebx,1 // shift divisor right one bit
  102. rcr ecx,1
  103. shr edx,1 // shift dividend right one bit
  104. rcr eax,1
  105. or ebx,ebx
  106. jnz L5 // loop until divisor < 4194304K
  107. div ecx // now divide, ignore remainder
  108. mov esi,eax // save quotient
  109. /*
  110. // We may be off by one, so to check, we will multiply the quotient
  111. // by the divisor and check the result against the orignal dividend
  112. // Note that we must also check for overflow, which can occur if the
  113. // dividend is close to 2**64 and the quotient is off by 1.
  114. */
  115. mul HIWORD(DVSR) // QUOT * HIWORD(DVSR)
  116. mov ecx,eax
  117. mov eax,LOWORD(DVSR)
  118. mul esi // QUOT * LOWORD(DVSR)
  119. add edx,ecx // EDX:EAX = QUOT * DVSR
  120. jc L6 // carry means Quotient is off by 1
  121. //
  122. // do long compare here between original dividend and the result of the
  123. // multiply in edx:eax. If original is larger or equal, we are ok, otherwise
  124. // subtract one (1) from the quotient.
  125. //
  126. cmp edx,HIWORD(DVND) // compare hi words of result and original
  127. ja L6 // if result > original, do subtract
  128. jb L7 // if result < original, we are ok
  129. cmp eax,LOWORD(DVND) // hi words are equal, compare lo words
  130. jbe L7 // if less or equal we are ok, else subtract
  131. L6:
  132. dec esi // subtract 1 from quotient
  133. L7:
  134. xor edx,edx // edx:eax <- quotient
  135. mov eax,esi
  136. //
  137. // Just the cleanup left to do. edx:eax contains the quotient. Set the sign
  138. // according to the save value, cleanup the stack, and return.
  139. //
  140. L4:
  141. dec edi // check to see if result is negative
  142. jnz L8 // if EDI == 0, result should be negative
  143. neg edx // otherwise, negate the result
  144. neg eax
  145. sbb edx,0
  146. //
  147. // Restore the saved registers and return.
  148. //
  149. L8:
  150. mov HIWORD(result),edx
  151. mov LOWORD(result),eax
  152. }; /* ASM */
  153. return result;
  154. }
  155. /* M U L 6 4 _ A S M */
  156. /*----------------------------------------------------------------------------
  157. %%Function: Mul64_Asm
  158. %%Contact: antons
  159. Intel assembler implementation of 64-bit multiplication. The
  160. orignal code was taken from llmul.asm (VC++ 6.0).
  161. ----------------------------------------------------------------------------*/
  162. __int64 Mul64_Asm (__int64 A, __int64 B)
  163. {
  164. __int64 result;
  165. __asm {
  166. mov eax,HIWORD(A)
  167. mov ecx,LOWORD(B)
  168. mul ecx // eax has AHI, ecx has BLO, so AHI * BLO
  169. mov esi,eax // save result
  170. mov eax,LOWORD(A)
  171. mul HIWORD(B) // ALO * BHI
  172. add esi,eax // ebx = ((ALO * BHI) + (AHI * BLO))
  173. mov eax,LOWORD(A) // ecx = BLO
  174. mul ecx // so edx:eax = ALO*BLO
  175. add edx,esi // now edx has all the LO*HI stuff
  176. mov HIWORD(result),edx
  177. mov LOWORD(result),eax
  178. }; /* ASM */
  179. return result;
  180. }
  181. /* =========================================================== */
  182. /* */
  183. /* End of Assembler functions */
  184. /* */
  185. /* =========================================================== */
  186. #endif /* _X86_ */
  187. long ZqFromZa_C (long dzqInch, long za)
  188. {
  189. long cInches;
  190. long zaExtra;
  191. if (za < 0)
  192. {
  193. Assert (((long) -za) > 0); /* Check for overflow */
  194. return -ZqFromZa_C (dzqInch, -za);
  195. };
  196. Assert(0 <= za);
  197. Assert(0 < dzqInch && dzqInch < zqLim);
  198. Assert(0 < czaUnitInch);
  199. cInches = za / czaUnitInch;
  200. zaExtra = za % czaUnitInch;
  201. return (cInches * dzqInch) +
  202. ((zaExtra * dzqInch) + (czaUnitInch/2)) / czaUnitInch;
  203. }
  204. long ZaFromZq(long dzqInch, long zq)
  205. {
  206. long cInches;
  207. long zqExtra;
  208. if (zq < 0)
  209. return -ZaFromZq(dzqInch, -zq);
  210. Assert(0 <= zq);
  211. Assert(0 < dzqInch && dzqInch < zqLim);
  212. Assert(0 < czaUnitInch);
  213. cInches = zq / dzqInch;
  214. zqExtra = zq % dzqInch;
  215. return (cInches * czaUnitInch) +
  216. ((zqExtra * czaUnitInch) + ((unsigned long) dzqInch/2)) / dzqInch;
  217. }
  218. long LsLwMultDivR(long l, long lNumer, long lDenom)
  219. {
  220. __int64 llT;
  221. Assert(lDenom != 0);
  222. if (lDenom == 0) /* this is really sloppy! Don't depend on this! */
  223. return LONG_MAX;
  224. if (l == 0)
  225. return 0;
  226. if (lNumer == lDenom)
  227. return l;
  228. llT = Mul64 (l, lNumer);
  229. if ( (l ^ lNumer ^ lDenom) < 0) /* xor sign bits to give result sign */
  230. llT -= lDenom / 2;
  231. else
  232. llT += lDenom / 2;
  233. if ((__int64)(long)llT == llT) /* Did the multiply fit in 32-bits */
  234. return ( ((long)llT) / lDenom); /* If so, do a 32-bit divide. */
  235. llT = Div64 (llT, lDenom);
  236. if (llT > LONG_MAX)
  237. return LONG_MAX;
  238. else if (llT < LONG_MIN)
  239. return LONG_MIN;
  240. else
  241. return (long) llT;
  242. }