math.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. #ifndef __GNUC__
  14. #pragma RUNTIME_CODE(LShiftU64)
  15. #pragma RUNTIME_CODE(RShiftU64)
  16. #pragma RUNTIME_CODE(MultU64x32)
  17. #pragma RUNTIME_CODE(DivU64x32)
  18. #endif
  19. #endif
  20. //
  21. //
  22. //
  23. UINT64
  24. LShiftU64 (
  25. IN UINT64 Operand,
  26. IN UINTN Count
  27. )
  28. // Left shift 64bit by 32bit and get a 64bit result
  29. {
  30. #if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
  31. return Operand << Count;
  32. #else
  33. UINT64 Result;
  34. _asm {
  35. mov eax, dword ptr Operand[0]
  36. mov edx, dword ptr Operand[4]
  37. mov ecx, Count
  38. and ecx, 63
  39. shld edx, eax, cl
  40. shl eax, cl
  41. cmp ecx, 32
  42. jc short ls10
  43. mov edx, eax
  44. xor eax, eax
  45. ls10:
  46. mov dword ptr Result[0], eax
  47. mov dword ptr Result[4], edx
  48. }
  49. return Result;
  50. #endif
  51. }
  52. UINT64
  53. RShiftU64 (
  54. IN UINT64 Operand,
  55. IN UINTN Count
  56. )
  57. // Right shift 64bit by 32bit and get a 64bit result
  58. {
  59. #if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
  60. return Operand >> Count;
  61. #else
  62. UINT64 Result;
  63. _asm {
  64. mov eax, dword ptr Operand[0]
  65. mov edx, dword ptr Operand[4]
  66. mov ecx, Count
  67. and ecx, 63
  68. shrd eax, edx, cl
  69. shr edx, cl
  70. cmp ecx, 32
  71. jc short rs10
  72. mov eax, edx
  73. xor edx, edx
  74. rs10:
  75. mov dword ptr Result[0], eax
  76. mov dword ptr Result[4], edx
  77. }
  78. return Result;
  79. #endif
  80. }
  81. UINT64
  82. MultU64x32 (
  83. IN UINT64 Multiplicand,
  84. IN UINTN Multiplier
  85. )
  86. // Multiple 64bit by 32bit and get a 64bit result
  87. {
  88. #if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
  89. return Multiplicand * Multiplier;
  90. #else
  91. UINT64 Result;
  92. _asm {
  93. mov eax, dword ptr Multiplicand[0]
  94. mul Multiplier
  95. mov dword ptr Result[0], eax
  96. mov dword ptr Result[4], edx
  97. mov eax, dword ptr Multiplicand[4]
  98. mul Multiplier
  99. add dword ptr Result[4], eax
  100. }
  101. return Result;
  102. #endif
  103. }
  104. UINT64
  105. DivU64x32 (
  106. IN UINT64 Dividend,
  107. IN UINTN Divisor,
  108. OUT UINTN *Remainder OPTIONAL
  109. )
  110. // divide 64bit by 32bit and get a 64bit result
  111. // N.B. only works for 31bit divisors!!
  112. {
  113. #if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
  114. if (Remainder)
  115. *Remainder = Dividend % Divisor;
  116. return Dividend / Divisor;
  117. #else
  118. UINT32 Rem;
  119. UINT32 bit;
  120. ASSERT (Divisor != 0);
  121. ASSERT ((Divisor >> 31) == 0);
  122. //
  123. // For each bit in the dividend
  124. //
  125. Rem = 0;
  126. for (bit=0; bit < 64; bit++) {
  127. _asm {
  128. shl dword ptr Dividend[0], 1 ; shift rem:dividend left one
  129. rcl dword ptr Dividend[4], 1
  130. rcl dword ptr Rem, 1
  131. mov eax, Rem
  132. cmp eax, Divisor ; Is Rem >= Divisor?
  133. cmc ; No - do nothing
  134. sbb eax, eax ; Else,
  135. sub dword ptr Dividend[0], eax ; set low bit in dividen
  136. and eax, Divisor ; and
  137. sub Rem, eax ; subtract divisor
  138. }
  139. }
  140. if (Remainder) {
  141. *Remainder = Rem;
  142. }
  143. return Dividend;
  144. #endif
  145. }