1 /*++ 2 3 Copyright (c) 1998 Intel Corporation 4 5 Module Name: 6 7 math.c 8 9 Abstract: 10 11 12 13 14 Revision History 15 16 --*/ 17 18 #include "lib.h" 19 20 21 // 22 // Declare runtime functions 23 // 24 25 #ifdef RUNTIME_CODE 26 #ifndef __GNUC__ 27 #pragma RUNTIME_CODE(LShiftU64) 28 #pragma RUNTIME_CODE(RShiftU64) 29 #pragma RUNTIME_CODE(MultU64x32) 30 #pragma RUNTIME_CODE(DivU64x32) 31 #endif 32 #endif 33 34 // 35 // 36 // 37 38 UINT64 39 LShiftU64 ( 40 IN UINT64 Operand, 41 IN UINTN Count 42 ) 43 // Left shift 64bit by 32bit and get a 64bit result 44 { 45 #if defined(__GNUC__) || defined(_MSC_EXTENSIONS) 46 return Operand << Count; 47 #else 48 UINT64 Result; 49 _asm { 50 mov eax, dword ptr Operand[0] 51 mov edx, dword ptr Operand[4] 52 mov ecx, Count 53 and ecx, 63 54 55 shld edx, eax, cl 56 shl eax, cl 57 58 cmp ecx, 32 59 jc short ls10 60 61 mov edx, eax 62 xor eax, eax 63 64 ls10: 65 mov dword ptr Result[0], eax 66 mov dword ptr Result[4], edx 67 } 68 69 return Result; 70 #endif 71 } 72 73 UINT64 74 RShiftU64 ( 75 IN UINT64 Operand, 76 IN UINTN Count 77 ) 78 // Right shift 64bit by 32bit and get a 64bit result 79 { 80 #if defined(__GNUC__) || defined(_MSC_EXTENSIONS) 81 return Operand >> Count; 82 #else 83 UINT64 Result; 84 _asm { 85 mov eax, dword ptr Operand[0] 86 mov edx, dword ptr Operand[4] 87 mov ecx, Count 88 and ecx, 63 89 90 shrd eax, edx, cl 91 shr edx, cl 92 93 cmp ecx, 32 94 jc short rs10 95 96 mov eax, edx 97 xor edx, edx 98 99 rs10: 100 mov dword ptr Result[0], eax 101 mov dword ptr Result[4], edx 102 } 103 104 return Result; 105 #endif 106 } 107 108 109 UINT64 110 MultU64x32 ( 111 IN UINT64 Multiplicand, 112 IN UINTN Multiplier 113 ) 114 // Multiple 64bit by 32bit and get a 64bit result 115 { 116 #if defined(__GNUC__) || defined(_MSC_EXTENSIONS) 117 return Multiplicand * Multiplier; 118 #else 119 UINT64 Result; 120 _asm { 121 mov eax, dword ptr Multiplicand[0] 122 mul Multiplier 123 mov dword ptr Result[0], eax 124 mov dword ptr Result[4], edx 125 mov eax, dword ptr Multiplicand[4] 126 mul Multiplier 127 add dword ptr Result[4], eax 128 } 129 130 return Result; 131 #endif 132 } 133 134 UINT64 135 DivU64x32 ( 136 IN UINT64 Dividend, 137 IN UINTN Divisor, 138 OUT UINTN *Remainder OPTIONAL 139 ) 140 // divide 64bit by 32bit and get a 64bit result 141 // N.B. only works for 31bit divisors!! 142 { 143 #if defined(__GNUC__) || defined(_MSC_EXTENSIONS) 144 if (Remainder) 145 *Remainder = Dividend % Divisor; 146 return Dividend / Divisor; 147 #else 148 UINT32 Rem; 149 UINT32 bit; 150 151 ASSERT (Divisor != 0); 152 ASSERT ((Divisor >> 31) == 0); 153 154 // 155 // For each bit in the dividend 156 // 157 158 Rem = 0; 159 for (bit=0; bit < 64; bit++) { 160 _asm { 161 shl dword ptr Dividend[0], 1 ; shift rem:dividend left one 162 rcl dword ptr Dividend[4], 1 163 rcl dword ptr Rem, 1 164 165 mov eax, Rem 166 cmp eax, Divisor ; Is Rem >= Divisor? 167 cmc ; No - do nothing 168 sbb eax, eax ; Else, 169 sub dword ptr Dividend[0], eax ; set low bit in dividen 170 and eax, Divisor ; and 171 sub Rem, eax ; subtract divisor 172 } 173 } 174 175 if (Remainder) { 176 *Remainder = Rem; 177 } 178 179 return Dividend; 180 #endif 181 } 182