/*++ Copyright (c) 1998 Intel Corporation Module Name: math.c Abstract: Revision History --*/ #include "lib.h" /* * Declare runtime functions */ #ifdef RUNTIME_CODE #pragma RUNTIME_CODE(LShiftU64) #pragma RUNTIME_CODE(RShiftU64) #pragma RUNTIME_CODE(MultU64x32) #pragma RUNTIME_CODE(DivU64x32) #endif /* * */ UINT64 LShiftU64 ( IN UINT64 Operand, IN UINTN Count ) /* Left shift 64bit by 32bit and get a 64bit result */ { UINT64 Result; _asm { mov eax, dword ptr Operand[0] mov edx, dword ptr Operand[4] mov ecx, Count and ecx, 63 shld edx, eax, cl shl eax, cl cmp ecx, 32 jc short ls10 mov edx, eax xor eax, eax ls10: mov dword ptr Result[0], eax mov dword ptr Result[4], edx } return Result; } UINT64 RShiftU64 ( IN UINT64 Operand, IN UINTN Count ) /* Right shift 64bit by 32bit and get a 64bit result */ { UINT64 Result; _asm { mov eax, dword ptr Operand[0] mov edx, dword ptr Operand[4] mov ecx, Count and ecx, 63 shrd eax, edx, cl shr edx, cl cmp ecx, 32 jc short rs10 mov eax, edx xor edx, edx rs10: mov dword ptr Result[0], eax mov dword ptr Result[4], edx } return Result; } UINT64 MultU64x32 ( IN UINT64 Multiplicand, IN UINTN Multiplier ) /* Multiple 64bit by 32bit and get a 64bit result */ { UINT64 Result; _asm { mov eax, dword ptr Multiplicand[0] mul Multiplier mov dword ptr Result[0], eax mov dword ptr Result[4], edx mov eax, dword ptr Multiplicand[4] mul Multiplier add dword ptr Result[4], eax } return Result; } UINT64 DivU64x32 ( IN UINT64 Dividend, IN UINTN Divisor, OUT UINTN *Remainder OPTIONAL ) /* divide 64bit by 32bit and get a 64bit result * N.B. only works for 31bit divisors!! */ { UINT32 Rem; UINT32 bit; ASSERT (Divisor != 0); ASSERT ((Divisor >> 31) == 0); /* * For each bit in the dividend */ Rem = 0; for (bit=0; bit < 64; bit++) { _asm { shl dword ptr Dividend[0], 1 ; shift rem:dividend left one rcl dword ptr Dividend[4], 1 rcl dword ptr Rem, 1 mov eax, Rem cmp eax, Divisor ; Is Rem >= Divisor? cmc ; No - do nothing sbb eax, eax ; Else, sub dword ptr Dividend[0], eax ; set low bit in dividen and eax, Divisor ; and sub Rem, eax ; subtract divisor } } if (Remainder) { *Remainder = Rem; } return Dividend; }