|
|
/*++
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; }
|