| /*++ |
| |
| Copyright (c) 1998 Intel Corporation |
| |
| Module Name: |
| |
| math.c |
| |
| Abstract: |
| |
| |
| |
| |
| Revision History |
| |
| --*/ |
| |
| #include "lib.h" |
| |
| |
| // |
| // Declare runtime functions |
| // |
| |
| #ifdef RUNTIME_CODE |
| #ifndef __GNUC__ |
| #pragma RUNTIME_CODE(LShiftU64) |
| #pragma RUNTIME_CODE(RShiftU64) |
| #pragma RUNTIME_CODE(MultU64x32) |
| #pragma RUNTIME_CODE(DivU64x32) |
| #endif |
| #endif |
| |
| // |
| // |
| // |
| |
| UINT64 |
| LShiftU64 ( |
| IN UINT64 Operand, |
| IN UINTN Count |
| ) |
| // Left shift 64bit by 32bit and get a 64bit result |
| { |
| #ifdef __GNUC__ |
| return Operand << Count; |
| #else |
| 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; |
| #endif |
| } |
| |
| UINT64 |
| RShiftU64 ( |
| IN UINT64 Operand, |
| IN UINTN Count |
| ) |
| // Right shift 64bit by 32bit and get a 64bit result |
| { |
| #ifdef __GNUC__ |
| return Operand >> Count; |
| #else |
| 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; |
| #endif |
| } |
| |
| |
| UINT64 |
| MultU64x32 ( |
| IN UINT64 Multiplicand, |
| IN UINTN Multiplier |
| ) |
| // Multiple 64bit by 32bit and get a 64bit result |
| { |
| #ifdef __GNUC__ |
| return Multiplicand * Multiplier; |
| #else |
| 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; |
| #endif |
| } |
| |
| 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!! |
| { |
| #ifdef __GNUC__ |
| if (Remainder) |
| *Remainder = Dividend % Divisor; |
| return Dividend / Divisor; |
| #else |
| 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; |
| #endif |
| } |