Curle
d588e232c4
This branch has been dedicated to purely the UEFI bootloader. As such, all other code has been removed. This code can be compiled with Visual Studio, gcc or llvm.
200 lines
3.8 KiB
C
200 lines
3.8 KiB
C
/*++
|
|
|
|
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!!
|
|
{
|
|
#if 0 && defined(__GNUC__) && !defined(__MINGW32__)
|
|
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++) {
|
|
#if defined(__GNUC__) || defined(__MINGW32__)
|
|
asm (
|
|
"shll $1, %0\n\t"
|
|
"rcll $1, 4%0\n\t"
|
|
"rcll $1, %2\n\t"
|
|
"mov %2, %%eax\n\t"
|
|
"cmp %1, %%eax\n\t"
|
|
"cmc\n\t"
|
|
"sbb %%eax, %%eax\n\t"
|
|
"sub %%eax, %0\n\t"
|
|
"and %1, %%eax\n\t"
|
|
"sub %%eax, %2"
|
|
: /* no outputs */
|
|
: "m"(Dividend), "m"(Divisor), "m"(Rem)
|
|
: "cc","memory","%eax"
|
|
);
|
|
#else
|
|
_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
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (Remainder) {
|
|
*Remainder = Rem;
|
|
}
|
|
|
|
return Dividend;
|
|
#endif
|
|
}
|