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 #ifdef __GNUC__ 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 #ifdef __GNUC__ 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 #ifdef __GNUC__ 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 0 && defined(__GNUC__) && !defined(__MINGW32__) 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 #if defined(__GNUC__) || defined(__MINGW32__) 161 asm ( 162 "shll $1, %0\n\t" 163 "rcll $1, 4%0\n\t" 164 "rcll $1, %2\n\t" 165 "mov %2, %%eax\n\t" 166 "cmp %1, %%eax\n\t" 167 "cmc\n\t" 168 "sbb %%eax, %%eax\n\t" 169 "sub %%eax, %0\n\t" 170 "and %1, %%eax\n\t" 171 "sub %%eax, %2" 172 : /* no outputs */ 173 : "m"(Dividend), "m"(Divisor), "m"(Rem) 174 : "cc","memory","%eax" 175 ); 176 #else 177 _asm { 178 shl dword ptr Dividend[0], 1 ; shift rem:dividend left one 179 rcl dword ptr Dividend[4], 1 180 rcl dword ptr Rem, 1 181 182 mov eax, Rem 183 cmp eax, Divisor ; Is Rem >= Divisor? 184 cmc ; No - do nothing 185 sbb eax, eax ; Else, 186 sub dword ptr Dividend[0], eax ; set low bit in dividen 187 and eax, Divisor ; and 188 sub Rem, eax ; subtract divisor 189 } 190 #endif 191 } 192 193 if (Remainder) { 194 *Remainder = Rem; 195 } 196 197 return Dividend; 198 #endif 199 } 200