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.

164 lines
3.0 KiB

  1. /*++
  2. Copyright (c) 1998 Intel Corporation
  3. Module Name:
  4. math.c
  5. Abstract:
  6. Revision History
  7. --*/
  8. #include "lib.h"
  9. /*
  10. * Declare runtime functions
  11. */
  12. #ifdef RUNTIME_CODE
  13. #pragma RUNTIME_CODE(LShiftU64)
  14. #pragma RUNTIME_CODE(RShiftU64)
  15. #pragma RUNTIME_CODE(MultU64x32)
  16. #pragma RUNTIME_CODE(DivU64x32)
  17. #endif
  18. /*
  19. *
  20. */
  21. UINT64
  22. LShiftU64 (
  23. IN UINT64 Operand,
  24. IN UINTN Count
  25. )
  26. /* Left shift 64bit by 32bit and get a 64bit result */
  27. {
  28. UINT64 Result;
  29. _asm {
  30. mov eax, dword ptr Operand[0]
  31. mov edx, dword ptr Operand[4]
  32. mov ecx, Count
  33. and ecx, 63
  34. shld edx, eax, cl
  35. shl eax, cl
  36. cmp ecx, 32
  37. jc short ls10
  38. mov edx, eax
  39. xor eax, eax
  40. ls10:
  41. mov dword ptr Result[0], eax
  42. mov dword ptr Result[4], edx
  43. }
  44. return Result;
  45. }
  46. UINT64
  47. RShiftU64 (
  48. IN UINT64 Operand,
  49. IN UINTN Count
  50. )
  51. /* Right shift 64bit by 32bit and get a 64bit result */
  52. {
  53. UINT64 Result;
  54. _asm {
  55. mov eax, dword ptr Operand[0]
  56. mov edx, dword ptr Operand[4]
  57. mov ecx, Count
  58. and ecx, 63
  59. shrd eax, edx, cl
  60. shr edx, cl
  61. cmp ecx, 32
  62. jc short rs10
  63. mov eax, edx
  64. xor edx, edx
  65. rs10:
  66. mov dword ptr Result[0], eax
  67. mov dword ptr Result[4], edx
  68. }
  69. return Result;
  70. }
  71. UINT64
  72. MultU64x32 (
  73. IN UINT64 Multiplicand,
  74. IN UINTN Multiplier
  75. )
  76. /* Multiple 64bit by 32bit and get a 64bit result */
  77. {
  78. UINT64 Result;
  79. _asm {
  80. mov eax, dword ptr Multiplicand[0]
  81. mul Multiplier
  82. mov dword ptr Result[0], eax
  83. mov dword ptr Result[4], edx
  84. mov eax, dword ptr Multiplicand[4]
  85. mul Multiplier
  86. add dword ptr Result[4], eax
  87. }
  88. return Result;
  89. }
  90. UINT64
  91. DivU64x32 (
  92. IN UINT64 Dividend,
  93. IN UINTN Divisor,
  94. OUT UINTN *Remainder OPTIONAL
  95. )
  96. /* divide 64bit by 32bit and get a 64bit result
  97. * N.B. only works for 31bit divisors!! */
  98. {
  99. UINT32 Rem;
  100. UINT32 bit;
  101. ASSERT (Divisor != 0);
  102. ASSERT ((Divisor >> 31) == 0);
  103. /*
  104. * For each bit in the dividend
  105. */
  106. Rem = 0;
  107. for (bit=0; bit < 64; bit++) {
  108. _asm {
  109. shl dword ptr Dividend[0], 1 ; shift rem:dividend left one
  110. rcl dword ptr Dividend[4], 1
  111. rcl dword ptr Rem, 1
  112. mov eax, Rem
  113. cmp eax, Divisor ; Is Rem >= Divisor?
  114. cmc ; No - do nothing
  115. sbb eax, eax ; Else,
  116. sub dword ptr Dividend[0], eax ; set low bit in dividen
  117. and eax, Divisor ; and
  118. sub Rem, eax ; subtract divisor
  119. }
  120. }
  121. if (Remainder) {
  122. *Remainder = Rem;
  123. }
  124. return Dividend;
  125. }