1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
/*++
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
}
|