Difference between revisions of "Kernel/RtlExtendedLargeIntegerDivide"
From xboxdevwiki
Fisherman166 (talk | contribs) (Add binary division algorithm) |
Fisherman166 (talk | contribs) |
||
| Line 1: | Line 1: | ||
RtlExtendedLargeIntegerDivide will call RtlRaiseStatus(STATUS_INTEGER_DIVIDE_BY_ZERO) if Divisor = 0. Otherwise, a custom binary division algorithm is used to perform the divide operation. The algorithm below was reverse engineered from original hardware. | RtlExtendedLargeIntegerDivide will call RtlRaiseStatus(STATUS_INTEGER_DIVIDE_BY_ZERO) if Divisor = 0. Otherwise, a custom binary division algorithm is used to perform the divide operation. The algorithm below was reverse engineered from original hardware. | ||
| − | LARGE_INTEGER quotient = Dividend; | + | LARGE_INTEGER quotient = Dividend; |
| − | ULONG local_remainder = 0; | + | ULONG local_remainder = 0; |
| − | BOOLEAN carry, remainder_carry; | + | BOOLEAN carry, remainder_carry; |
| − | + | for (uint8_t i = 64; i > 0; i--) { | |
| − | for (uint8_t i = 64; i > 0; i--) { | + | carry = (quotient.QuadPart >> 63) & 0x1; |
| − | + | remainder_carry = (local_remainder >> 31) & 0x1; | |
| − | + | quotient.QuadPart <<= 1; | |
| − | + | local_remainder = (local_remainder << 1) | carry; | |
| − | + | if (remainder_carry || (local_remainder >= Divisor)) { | |
| − | + | quotient.u.LowPart += 1; | |
| − | + | local_remainder -= Divisor; | |
| − | + | } | |
| + | } | ||
| + | if (Remainder) { | ||
| + | *Remainder = local_remainder; | ||
} | } | ||
| − | |||
| − | |||
| − | |||
| − | |||
Latest revision as of 05:51, 17 January 2019
RtlExtendedLargeIntegerDivide will call RtlRaiseStatus(STATUS_INTEGER_DIVIDE_BY_ZERO) if Divisor = 0. Otherwise, a custom binary division algorithm is used to perform the divide operation. The algorithm below was reverse engineered from original hardware.
LARGE_INTEGER quotient = Dividend;
ULONG local_remainder = 0;
BOOLEAN carry, remainder_carry;
for (uint8_t i = 64; i > 0; i--) {
carry = (quotient.QuadPart >> 63) & 0x1;
remainder_carry = (local_remainder >> 31) & 0x1;
quotient.QuadPart <<= 1;
local_remainder = (local_remainder << 1) | carry;
if (remainder_carry || (local_remainder >= Divisor)) {
quotient.u.LowPart += 1;
local_remainder -= Divisor;
}
}
if (Remainder) {
*Remainder = local_remainder;
}