Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

174 lines
5.5 KiB

// TITLE("Large Integer Arithmetic")
//++
//
// Copyright (c) 1990 Microsoft Corporation
// Copyright (c) 1993 Digital Equipment Corporation
//
// Module Name:
//
// muldiv.s
//
// Abstract:
//
// This module implements routines for performing extended integer
// arithmetic.
//
// Author:
//
// David N. Cutler (davec) 18-Apr-1990
//
// Environment:
//
// Any mode.
//
// Revision History:
//
// Thomas Van Baak (tvb) 9-May-1992
// Eric Rehm/Joe Notarangelo 19-Jul-1993
// Pulled over a subset for windows. Note we killed the exception
// checking in the divide routine.
//
//
//--
#include "ksalpha.h"
SBTTL("Enlarged Signed Integer Multiply")
//++
//
// LARGE_INTEGER
// RtlEnlargedIntegerMultiply (
// IN LONG Multiplicand,
// IN LONG Multiplier
// )
//
// Routine Description:
//
// This function multiplies a signed integer by a signed integer and
// returns a signed large integer result.
//
// N.B. An overflow is not possible.
//
// Arguments:
//
// Multiplicand (a0) - Supplies the multiplicand value.
//
// Multiplier (a1) - Supplies the multiplier value.
//
// Return Value:
//
// The large integer result is returned as the function value in v0.
//
//--
LEAF_ENTRY(RtlEnlargedIntegerMultiply)
addl a0, 0, a0 // ensure canonical (signed long) form
addl a1, 0, a1 // ensure canonical (signed long) form
mulq a0, a1, v0 // multiply signed both quadwords
ret zero, (ra) // return
.end RtlEnlargedIntegerMultiply
SBTTL("Enlarged Unsigned Divide")
//++
//
// ULONG
// RtlEnlargedUnsignedDivide (
// IN ULARGE_INTEGER Dividend,
// IN ULONG Divisor,
// IN OUT PULONG Remainder OPTIONAL
// )
//
// Routine Description:
//
// This function divides an unsigned large integer by an unsigned long
// and returns the resultant quotient and optionally the remainder.
//
// N.B. An overflow or divide by zero exception is possible.
//
// Arguments:
//
// Dividend (a0) - Supplies the unsigned 64-bit dividend value.
//
// Divisor (a1) - Supplies the unsigned 32-bit divisor value.
//
// Remainder (a2) - Supplies an optional pointer to a variable that
// receives the unsigned 32-bit remainder.
//
// Return Value:
//
// The unsigned long integer quotient is returned as the function value.
//
//--
LEAF_ENTRY(RtlEnlargedUnsignedDivide)
//
// Perform the shift/subtract loop 8 times and 4 bits per loop.
//
// t0 - Temp used for 0/1 results of compares.
// t1 - High 64-bits of 128-bit (t1, a0) dividend.
// t2 - Loop counter.
//
ldiq t2, 32/4 // set iteration count
srl a0, 32, t1 // get top 32 bits of carry-out
sll a0, 32, a0 // preshift first 32 bits left
10: cmplt a0, 0, t0 // predict low-dividend shift carry-out
addq a0, a0, a0 // shift low-dividend left
addq t1, t1, t1 // shift high-dividend left
bis t1, t0, t1 // merge in carry-out of low-dividend
cmpule a1, t1, t0 // if dividend >= divisor,
addq a0, t0, a0 // then set quotient bit
subq t1, a1, t0 // subtract divisor from dividend,
cmovlbs a0, t0, t1 // if dividend >= divisor
cmplt a0, 0, t0 // predict low-dividend shift carry-out
addq a0, a0, a0 // shift low-dividend left
addq t1, t1, t1 // shift high-dividend left
bis t1, t0, t1 // merge in carry-out of low-dividend
cmpule a1, t1, t0 // if dividend >= divisor,
addq a0, t0, a0 // then set quotient bit
subq t1, a1, t0 // subtract divisor from dividend,
cmovlbs a0, t0, t1 // if dividend >= divisor
cmplt a0, 0, t0 // predict low-dividend shift carry-out
addq a0, a0, a0 // shift low-dividend left
addq t1, t1, t1 // shift high-dividend left
bis t1, t0, t1 // merge in carry-out of low-dividend
cmpule a1, t1, t0 // if dividend >= divisor,
addq a0, t0, a0 // then set quotient bit
subq t1, a1, t0 // subtract divisor from dividend,
cmovlbs a0, t0, t1 // if dividend >= divisor
cmplt a0, 0, t0 // predict low-dividend shift carry-out
addq a0, a0, a0 // shift low-dividend left
addq t1, t1, t1 // shift high-dividend left
bis t1, t0, t1 // merge in carry-out of low-dividend
cmpule a1, t1, t0 // if dividend >= divisor,
addq a0, t0, a0 // then set quotient bit
subq t1, a1, t0 // subtract divisor from dividend,
cmovlbs a0, t0, t1 // if dividend >= divisor
subq t2, 1, t2 // any more iterations?
bne t2, 10b //
//
// Finished with remainder value in t1 and quotient value in a0.
//
addl a0, 0, v0 // set longword quotient return value
beq a2, 20f // skip optional remainder store
stl t1, 0(a2) // store longword remainder
20: ret zero, (ra) // return
.end RtlEnlargedUnsignedDivide