Difference between revisions of "Kernel/RtlExtendedLargeIntegerDivide"

From xboxdevwiki
Jump to: navigation, search
(Add binary division algorithm)
 
 
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;
    carry = (quotient.QuadPart >> 63) & 0x1;
+
        remainder_carry = (local_remainder >> 31) & 0x1;
    remainder_carry = (local_remainder >> 31) & 0x1;
+
        quotient.QuadPart <<= 1;
    quotient.QuadPart <<= 1;
+
        local_remainder = (local_remainder << 1) | carry;
    local_remainder = (local_remainder << 1) | carry;
+
        if (remainder_carry || (local_remainder >= Divisor)) {
    if (remainder_carry || (local_remainder >= Divisor)) {
+
            quotient.u.LowPart += 1;
        quotient.u.LowPart += 1;
+
            local_remainder -= Divisor;
        local_remainder -= Divisor;
+
        }
 +
    }
 +
    if (Remainder) {
 +
        *Remainder = local_remainder;
 
     }
 
     }
}
 
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;
   }