Rework 64-bit division routines to support i686 architecture
This commit is contained in:
parent
a852993842
commit
cca2e65376
@ -183,10 +183,17 @@ RtlDivide64(IN LONGLONG Dividend,
|
|||||||
IN LONGLONG Divisor,
|
IN LONGLONG Divisor,
|
||||||
OUT PLONGLONG Remainder)
|
OUT PLONGLONG Remainder)
|
||||||
{
|
{
|
||||||
LONGLONG Quotient;
|
LONGLONG DividendSign, DivisorSign, Quotient, UDividend, UDivisor;
|
||||||
|
|
||||||
|
/* Remove the sign bit from dividend and divisor if present */
|
||||||
|
DividendSign = Dividend >> ((sizeof(LONGLONG) * BITS_PER_BYTE) - 1);
|
||||||
|
DivisorSign = Divisor >> ((sizeof(LONGLONG) * BITS_PER_BYTE) - 1);
|
||||||
|
UDividend = (Dividend ^ DividendSign) - DividendSign;
|
||||||
|
UDivisor = (Divisor ^ DivisorSign) - DivisorSign;
|
||||||
|
|
||||||
/* Calculate the quotient */
|
/* Calculate the quotient */
|
||||||
Quotient = Dividend / Divisor;
|
DividendSign ^= DivisorSign;
|
||||||
|
Quotient = (RtlDivideUnsigned64(UDividend, UDivisor, NULL) ^ DividendSign) - DividendSign;
|
||||||
|
|
||||||
/* Make sure a pointer to remainder provided */
|
/* Make sure a pointer to remainder provided */
|
||||||
if(Remainder)
|
if(Remainder)
|
||||||
@ -254,15 +261,210 @@ RtlDivideUnsigned64(IN ULONGLONG Dividend,
|
|||||||
IN ULONGLONG Divisor,
|
IN ULONGLONG Divisor,
|
||||||
OUT PULONGLONG Remainder)
|
OUT PULONGLONG Remainder)
|
||||||
{
|
{
|
||||||
/* Make sure a pointer to remainder provided */
|
ULARGE_INTEGER DividendParts, DivisorParts, QuotientParts, RemainderParts;
|
||||||
if(Remainder)
|
LONGLONG Difference;
|
||||||
|
ULONGLONG Shift;
|
||||||
|
ULONG Carry;
|
||||||
|
|
||||||
|
/* Make sure divisor is not 0 */
|
||||||
|
if(Divisor == 0)
|
||||||
{
|
{
|
||||||
/* Calculate remainder */
|
/* Cannot divide by 0 */
|
||||||
*Remainder = Dividend % Divisor;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assign dividend and divisor to large integer representations */
|
||||||
|
DividendParts.QuadPart = Dividend;
|
||||||
|
DivisorParts.QuadPart = Divisor;
|
||||||
|
|
||||||
|
/* Check if dividend is 32-bit value */
|
||||||
|
if(DividendParts.u.HighPart == 0)
|
||||||
|
{
|
||||||
|
/* Check if devisor is 32-bit value */
|
||||||
|
if(DivisorParts.u.HighPart == 0)
|
||||||
|
{
|
||||||
|
/* 32-bit divide operation, check if remainder provided */
|
||||||
|
if(Remainder != NULL)
|
||||||
|
{
|
||||||
|
/* Calculate remainder */
|
||||||
|
*Remainder = DividendParts.u.LowPart % DivisorParts.u.LowPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the quotient */
|
||||||
|
return DividendParts.u.LowPart / DivisorParts.u.LowPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 32-bit value divided by a 64-bit value, check if remainder provided */
|
||||||
|
if(Remainder != NULL)
|
||||||
|
{
|
||||||
|
/* Calculate remainder */
|
||||||
|
*Remainder = DividendParts.u.LowPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return zero as quotient */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dividend is a 64-bit value, check if divisor has a low part */
|
||||||
|
if(DivisorParts.u.LowPart != 0)
|
||||||
|
{
|
||||||
|
/* Divisor has a non-zero low part, check if divisor has a high part */
|
||||||
|
if(DivisorParts.u.HighPart != 0)
|
||||||
|
{
|
||||||
|
/* Divisor is 64-bit value, calculate the shift count */
|
||||||
|
Shift = RtlCountLeadingZeroes32(DivisorParts.u.HighPart) - RtlCountLeadingZeroes32(DividendParts.u.HighPart);
|
||||||
|
|
||||||
|
/* Check if shift count exceeds 32-bits */
|
||||||
|
if(Shift > ((sizeof(ULONG) * BITS_PER_BYTE) - 1))
|
||||||
|
{
|
||||||
|
/* Check if remainder provided */
|
||||||
|
if(Remainder != NULL)
|
||||||
|
{
|
||||||
|
/* Calculate remainder */
|
||||||
|
*Remainder = DividendParts.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increase shift and clear quotient low part */
|
||||||
|
Shift++;
|
||||||
|
QuotientParts.u.LowPart = 0;
|
||||||
|
|
||||||
|
/* Check if shift is 32-bits */
|
||||||
|
if(Shift == (sizeof(ULONG) * BITS_PER_BYTE)) {
|
||||||
|
/* Get the quotient high part and remainder */
|
||||||
|
QuotientParts.u.HighPart = DividendParts.u.LowPart;
|
||||||
|
RemainderParts.u.LowPart = DividendParts.u.HighPart;
|
||||||
|
RemainderParts.u.HighPart = 0;
|
||||||
|
} else {
|
||||||
|
/* Get the quotient high part and remainder */
|
||||||
|
QuotientParts.u.HighPart = DividendParts.u.LowPart << ((sizeof(ULONG) * BITS_PER_BYTE) - Shift);
|
||||||
|
RemainderParts.u.LowPart = (DividendParts.u.HighPart << ((sizeof(ULONG) * BITS_PER_BYTE) - Shift)) |
|
||||||
|
(DividendParts.u.LowPart >> Shift);
|
||||||
|
RemainderParts.u.HighPart = DividendParts.u.HighPart >> Shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Divisor is 32-bit value, calculate the shift count */
|
||||||
|
Shift = (sizeof(ULONG) * BITS_PER_BYTE) + 1 +
|
||||||
|
RtlCountLeadingZeroes32(DivisorParts.u.LowPart) -
|
||||||
|
RtlCountLeadingZeroes32(DividendParts.u.HighPart);
|
||||||
|
|
||||||
|
/* Check if shift is 32-bit */
|
||||||
|
if(Shift == (sizeof(ULONG) * BITS_PER_BYTE))
|
||||||
|
{
|
||||||
|
/* Get the quotient and remainder */
|
||||||
|
QuotientParts.u.LowPart = 0;
|
||||||
|
QuotientParts.u.HighPart = DividendParts.u.LowPart;
|
||||||
|
RemainderParts.u.LowPart = DividendParts.u.HighPart;
|
||||||
|
RemainderParts.u.HighPart = 0;
|
||||||
|
}
|
||||||
|
else if(Shift < (sizeof(ULONG) * BITS_PER_BYTE))
|
||||||
|
{
|
||||||
|
/* Shift is smaller, get the quotient and remainder */
|
||||||
|
QuotientParts.u.LowPart = 0;
|
||||||
|
QuotientParts.u.HighPart = DividendParts.u.LowPart << ((sizeof(ULONG) * BITS_PER_BYTE) - Shift);
|
||||||
|
RemainderParts.u.LowPart = (DividendParts.u.HighPart <<
|
||||||
|
((sizeof(ULONG) * BITS_PER_BYTE) - Shift)) |
|
||||||
|
(DividendParts.u.LowPart >> Shift);
|
||||||
|
RemainderParts.u.HighPart = DividendParts.u.HighPart >> Shift;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Shift is larger, get the quotient and remainder */
|
||||||
|
QuotientParts.u.LowPart = DividendParts.u.LowPart << ((sizeof(ULONGLONG) * BITS_PER_BYTE) - Shift);
|
||||||
|
QuotientParts.u.HighPart = (DividendParts.u.HighPart << ((sizeof(ULONGLONG) * BITS_PER_BYTE) - Shift)) |
|
||||||
|
(DividendParts.u.LowPart >> (Shift - (sizeof(ULONG) * BITS_PER_BYTE)));
|
||||||
|
RemainderParts.u.LowPart = DividendParts.u.HighPart >> (Shift - (sizeof(ULONG) * BITS_PER_BYTE));
|
||||||
|
RemainderParts.u.HighPart = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Divisor is 64-bit value, check if dividend has low part set */
|
||||||
|
if(DividendParts.u.LowPart == 0)
|
||||||
|
{
|
||||||
|
/* Check if remainder provided */
|
||||||
|
if(Remainder != NULL)
|
||||||
|
{
|
||||||
|
/* Calculate the remainder */
|
||||||
|
RemainderParts.u.HighPart = DividendParts.u.HighPart % DivisorParts.u.HighPart;
|
||||||
|
RemainderParts.u.LowPart = 0;
|
||||||
|
*Remainder = RemainderParts.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the quotient */
|
||||||
|
return DividendParts.u.HighPart / DivisorParts.u.HighPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the shift count */
|
||||||
|
Shift = RtlCountLeadingZeroes32(DivisorParts.u.HighPart) - RtlCountLeadingZeroes32(DividendParts.u.HighPart);
|
||||||
|
|
||||||
|
/* Check if shift exceeds 32-bits */
|
||||||
|
if(Shift > ((sizeof(ULONG) * BITS_PER_BYTE) - 2))
|
||||||
|
{
|
||||||
|
/* Check if remainder provided */
|
||||||
|
if(Remainder != NULL)
|
||||||
|
{
|
||||||
|
/* Calculate the remainder */
|
||||||
|
*Remainder = DividendParts.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return 0 */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increase shift and clear quotient low part */
|
||||||
|
Shift++;
|
||||||
|
QuotientParts.u.LowPart = 0;
|
||||||
|
|
||||||
|
/* Get the quotient high part and remainder */
|
||||||
|
QuotientParts.u.HighPart = DividendParts.u.LowPart << ((sizeof(ULONG) * BITS_PER_BYTE) - Shift);
|
||||||
|
RemainderParts.u.HighPart = DividendParts.u.HighPart >> Shift;
|
||||||
|
RemainderParts.u.LowPart = (DividendParts.u.HighPart <<
|
||||||
|
((sizeof(ULONG) * BITS_PER_BYTE) - Shift)) |
|
||||||
|
(DividendParts.u.LowPart >> Shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform the division until shift is zero */
|
||||||
|
Carry = 0;
|
||||||
|
while(Shift > 0)
|
||||||
|
{
|
||||||
|
/* Shift the remainder and the quotient */
|
||||||
|
RemainderParts.u.HighPart = (RemainderParts.u.HighPart << 1) |
|
||||||
|
(RemainderParts.u.LowPart >>
|
||||||
|
((sizeof(ULONG) * BITS_PER_BYTE) - 1));
|
||||||
|
RemainderParts.u.LowPart = (RemainderParts.u.LowPart << 1) |
|
||||||
|
(QuotientParts.u.HighPart >>
|
||||||
|
((sizeof(ULONG) * BITS_PER_BYTE) - 1));
|
||||||
|
QuotientParts.u.HighPart = (QuotientParts.u.HighPart << 1) |
|
||||||
|
(QuotientParts.u.LowPart >>
|
||||||
|
((sizeof(ULONG) * BITS_PER_BYTE) - 1));
|
||||||
|
QuotientParts.u.LowPart = (QuotientParts.u.LowPart << 1) | Carry;
|
||||||
|
|
||||||
|
/* Set the carry and subtract the divisor */
|
||||||
|
Difference = (LONGLONG)(DivisorParts.QuadPart - RemainderParts.QuadPart - 1) >>
|
||||||
|
((sizeof(ULONGLONG) * BITS_PER_BYTE) - 1);
|
||||||
|
Carry = Difference & 0x1;
|
||||||
|
RemainderParts.QuadPart -= DivisorParts.QuadPart & Difference;
|
||||||
|
Shift -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the carry to the quotient */
|
||||||
|
QuotientParts.QuadPart = (QuotientParts.QuadPart << 1) | Carry;
|
||||||
|
|
||||||
|
/* Check if remainder provided */
|
||||||
|
if(Remainder != NULL)
|
||||||
|
{
|
||||||
|
/* Calculate the remainder */
|
||||||
|
*Remainder = RemainderParts.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the quotient */
|
/* Return the quotient */
|
||||||
return Dividend / Divisor;
|
return QuotientParts.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -287,17 +489,24 @@ RtlDivideLargeInteger(IN LARGE_INTEGER Dividend,
|
|||||||
IN ULONG Divisor,
|
IN ULONG Divisor,
|
||||||
OUT PULONG Remainder)
|
OUT PULONG Remainder)
|
||||||
{
|
{
|
||||||
|
LONGLONG DividendSign, UDividend;
|
||||||
LARGE_INTEGER LargeInt;
|
LARGE_INTEGER LargeInt;
|
||||||
|
|
||||||
|
/* Remove the sign bit from dividend if present */
|
||||||
|
DividendSign = Dividend.QuadPart >> ((sizeof(LONGLONG) * BITS_PER_BYTE) - 1);
|
||||||
|
UDividend = (Dividend.QuadPart ^ DividendSign) - DividendSign;
|
||||||
|
|
||||||
|
/* Calculate the quotient */
|
||||||
|
LargeInt.QuadPart = (RtlDivideUnsigned64(UDividend, Divisor, NULL) ^ DividendSign) - DividendSign;
|
||||||
|
|
||||||
/* Make sure a pointer to remainder provided */
|
/* Make sure a pointer to remainder provided */
|
||||||
if(Remainder)
|
if(Remainder)
|
||||||
{
|
{
|
||||||
/* Calculate remainder */
|
/* Calculate remainder */
|
||||||
*Remainder = Dividend.QuadPart % Divisor;
|
*Remainder = Dividend.QuadPart - (LargeInt.QuadPart * Divisor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the quotient */
|
/* Return the quotient */
|
||||||
LargeInt.QuadPart = Dividend.QuadPart / Divisor;
|
|
||||||
return LargeInt;
|
return LargeInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user