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