948 lines
32 KiB
ArmAsm
948 lines
32 KiB
ArmAsm
// TITLE("Large Integer Arithmetic")
|
||
//++
|
||
//
|
||
// Copyright (c) 1990 Microsoft Corporation
|
||
//
|
||
// Module Name:
|
||
//
|
||
// largeint.s
|
||
//
|
||
// Abstract:
|
||
//
|
||
// This module implements routines for performing extended integer
|
||
// arithmtic.
|
||
//
|
||
// Author:
|
||
//
|
||
// David N. Cutler (davec) 18-Apr-1990
|
||
//
|
||
// Environment:
|
||
//
|
||
// Any mode.
|
||
//
|
||
// Revision History:
|
||
//
|
||
//--
|
||
|
||
#include "ksmips.h"
|
||
|
||
SBTTL("Large Integer Add")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlLargeIntegerAdd (
|
||
// IN LARGE_INTEGER Addend1,
|
||
// IN LARGE_INTEGER Addend2
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function adds a signed large integer to a signed large integer and
|
||
// returns the signed large integer result.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Addend1 (a2, a3) - Supplies the first addend value.
|
||
//
|
||
// Addend2 (4 * 4(sp), 4 * 5(sp)) - Supplies the second addend value.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlLargeIntegerAdd)
|
||
|
||
lw t0,4 * 4(sp) // get low part of addend2 value
|
||
lw t1,4 * 5(sp) // get high part of addend2 value
|
||
addu t0,t0,a2 // add low parts of large integer
|
||
addu t1,t1,a3 // add high parts of large integer
|
||
sltu t2,t0,a2 // generate carry from low part
|
||
addu t1,t1,t2 // add carry to high part
|
||
sw t0,0(a0) // store low part of result
|
||
sw t1,4(a0) // store high part of result
|
||
move v0,a0 // set function return register
|
||
j ra // return
|
||
|
||
.end RtlLargeIntegerAdd
|
||
|
||
SBTTL("Convert Long to Large Integer")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlConvertLongToLargeInteger (
|
||
// IN LONG SignedInteger
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function converts the a signed integer to a signed large integer
|
||
// and returns the result.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// SignedInteger (a1) - Supplies the value to convert.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlConvertLongToLargeInteger)
|
||
|
||
sra a2,a1,31 // compute high part of result
|
||
sw a1,0(a0) // store low part of result
|
||
sw a2,4(a0) // store high part of result
|
||
move v0,a0 // set function return register
|
||
j ra // return
|
||
|
||
.end RtlConvertLongToLargeInteger
|
||
|
||
SBTTL("Convert Ulong to Large Integer")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlConvertUlongToLargeInteger (
|
||
// IN LONG UnsignedInteger
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function converts the an unsigned integer to a signed large
|
||
// integer and returns the result.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// UnsignedInteger (a1) - Supplies the value to convert.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlConvertUlongToLargeInteger)
|
||
|
||
sw a1,0(a0) // store low part of result
|
||
sw zero,4(a0) // store high part of result
|
||
move v0,a0 // set function return register
|
||
j ra // return
|
||
|
||
.end RtlConvertUlongToLargeInteger
|
||
|
||
SBTTL("Enlarged Signed Integer Multiply")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlEnlargedIntegerMultiply (
|
||
// IN LONG Multiplicand,
|
||
// IN LONG Multiplier
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function multiplies a signed integer by an signed integer and
|
||
// returns a signed large integer result.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Multiplicand (a1) - Supplies the multiplicand value.
|
||
//
|
||
// Multiplier (a2) - Supplies the multiplier value.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlEnlargedIntegerMultiply)
|
||
|
||
mult a1,a2 // multiply longword value
|
||
mflo t0 // get low 32-bits of result
|
||
mfhi t1 // get high 32-bits of result
|
||
sw t0,0(a0) // set low part of result
|
||
sw t1,4(a0) // set high part of result
|
||
move v0,a0 // set function return register
|
||
j ra // return
|
||
|
||
.end RtlEnlargedIntegerMultiply)
|
||
|
||
SBTTL("Enlarged Unsigned Integer Multiply")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlEnlargedUnsignedMultiply (
|
||
// IN ULONG Multiplicand,
|
||
// IN ULONG Multiplier
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function multiplies an unsigned integer by an unsigned integer
|
||
// and returns a signed large integer result.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Multiplicand (a1) - Supplies the multiplicand value.
|
||
//
|
||
// Multiplier (a2) - Supplies the multiplier value.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlEnlargedUnsignedMultiply)
|
||
|
||
multu a1,a2 // multiply longword value
|
||
mflo t0 // get low 32-bits of result
|
||
mfhi t1 // get high 32-bits of result
|
||
sw t0,0(a0) // set low part of result
|
||
sw t1,4(a0) // set high part of result
|
||
move v0,a0 // set function return register
|
||
j ra // return
|
||
|
||
.end RtlEnlargedUnsignedMultiply)
|
||
|
||
SBTTL("Enlarged Unsigned Divide")
|
||
//++
|
||
//
|
||
// ULONG
|
||
// RtlEnlargedUnsignedDivide (
|
||
// IN ULARGE_INTEGER Dividend,
|
||
// IN ULONG Divisor,
|
||
// IN PULONG Remainder.
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function divides an unsigned large integer by an unsigned long
|
||
// and returns the resultant quotient and optionally the remainder.
|
||
//
|
||
// N.B. It is assumed that no overflow will occur.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Dividend (a0, a1) - Supplies the dividend value.
|
||
//
|
||
// Divisor (a2) - Supplies the divisor value.
|
||
//
|
||
// Remainder (a3) - Supplies an optional pointer to a variable that
|
||
// receives the remainder.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The unsigned long integer quotient is returned as the function value.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlEnlargedUnsignedDivide)
|
||
|
||
sltu v1,a1,a2 // check if overflow will occur
|
||
beq zero,a2,20f // if eq, attempted division by zero
|
||
dsll a1,a1,32 // left justify hihg part of dividend
|
||
beq zero,v1,30f // if eq, overflow will occur
|
||
dsll a0,a0,32 // zero extend low part of dividend
|
||
dsrl a0,a0,32 //
|
||
or a0,a0,a1 // merge high and low part of dividend
|
||
ddivu a0,a2 // compute quotient value
|
||
mflo v0 // set quotient value
|
||
beq zero,a3,10f // if eq, remainder not requested
|
||
mfhi a0 // load remainder
|
||
sw a0,0(a3) // store longword remainder
|
||
10: j ra // return
|
||
|
||
|
||
20: break DIVIDE_BY_ZERO_BREAKPOINT // attempted division by zero
|
||
j ra //
|
||
|
||
30: break DIVIDE_OVERFLOW_BREAKPOINT // division value overflows result
|
||
j ra //
|
||
|
||
.end RtlEnlargedUnsignedDivide
|
||
|
||
SBTTL("Extended Large Integer Divide")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlExtendedLargeIntegerDivide (
|
||
// IN LARGE_INTEGER Dividend,
|
||
// IN ULONG Divisor,
|
||
// IN PULONG Remainder.
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function divides an unsigned large integer by an unsigned long
|
||
// and returns the resultant quotient and optionally the remainder.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Dividend (a2, a3) - Supplies the dividend value.
|
||
//
|
||
// Divisor (4 * 4(sp)) - Supplies the divisor value.
|
||
//
|
||
// Remainder (4 * 5(sp)- Supplies an optional pointer to a variable
|
||
// that receives the remainder.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlExtendedLargeIntegerDivide)
|
||
|
||
.set noreorder
|
||
.set noat
|
||
move v0,a0 // set function return register
|
||
lw a1,4 * 4(sp) // get divisor value
|
||
lw t0,4 * 5(sp) // get address to store remainder
|
||
beq zero,a1,30f // if eq, attempted division by zero
|
||
li t1,63 // set loop count
|
||
move t2,zero // clear partial remainder
|
||
10: sra t3,t2,31 // replicate partial remainder high bit
|
||
sll t2,t2,1 // shift next dividend bit
|
||
srl t4,a3,31 // into the partial remainder
|
||
or t2,t2,t4 //
|
||
sll a3,a3,1 // double left shift dividend
|
||
srl t4,a2,31 //
|
||
or a3,a3,t4 //
|
||
sltu t4,t2,a1 // check if partial remainder less
|
||
subu t4,t4,1 // convert to 0 or -1
|
||
or t4,t4,t3 // merge with partial remainder high bit
|
||
and t5,t4,a1 // select divisor or 0
|
||
sll a2,a2,1 //
|
||
subu a2,a2,t4 // merge quotient bit
|
||
subu t2,t2,t5 // subtract out divisor
|
||
bne zero,t1,10b // if ne, more iterations to go
|
||
subu t1,t1,1 // decrement iteration count
|
||
beq zero,t0,20f // if eq, remainder not requested
|
||
sw a2,0(a0) // store low part of quotient
|
||
sw t2,0(t0) // store longword remainder
|
||
20: j ra // return
|
||
sw a3,4(a0) // store high part of quotient
|
||
.set at
|
||
.set reorder
|
||
|
||
30: break DIVIDE_BY_ZERO_BREAKPOINT // attempted division by zero
|
||
j ra //
|
||
|
||
.end RtlExtendedLargeIntegerDivide
|
||
|
||
SBTTL("Extended Magic Divide")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlExtendedMagicDivide (
|
||
// IN LARGE_INTEGER Dividend,
|
||
// IN LARGE_INTEGER MagicDivisor,
|
||
// IN CCHAR ShiftCount
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function divides a signed large integer by an unsigned large integer
|
||
// and returns the signed large integer result. The division is performed
|
||
// using reciprocal multiplication of a signed large integer value by an
|
||
// unsigned large integer fraction which represents the most significant
|
||
// 64-bits of the reciprocal divisor rounded up in its least significant bit
|
||
// and normalized with respect to bit 63. A shift count is also provided
|
||
// which is used to truncate the fractional bits from the result value.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Dividend (a2, a3) - Supplies the dividend value.
|
||
//
|
||
// MagicDivisor (4 * 4(sp), 4 * 5(sp)) - Supplies the magic divisor value
|
||
// which is a 64-bit multiplicative reciprocal.
|
||
//
|
||
// Shiftcount (4 * 6(sp)) - Supplies the right shift adjustment value.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlExtendedMagicDivide)
|
||
|
||
move t0,a2 // assume dividend is positive
|
||
move t1,a3 //
|
||
bgez a3,10f // if gez, positive dividend
|
||
subu t0,zero,t0 // negate low part of dividend
|
||
subu t1,zero,t1 // negate high part of dividend
|
||
sltu t2,zero,t0 // set borrow from high part
|
||
subu t1,t1,t2 // subtract out out borrow
|
||
10: lw a1,4 * 4(sp) // get low part of magic dividor
|
||
lw t2,4 * 5(sp) // get high part of magic divisor
|
||
lbu v0,4 * 6(sp) // get shift count
|
||
|
||
//
|
||
// Compute low 32-bits of dividend times low 32-bits of divisor.
|
||
//
|
||
|
||
multu t0,a1 //
|
||
mfhi t3 // save high 32-bits of product
|
||
|
||
//
|
||
// Compute low 32-bits of dividend time high 32-bits of divisor.
|
||
//
|
||
|
||
multu t0,t2 //
|
||
mflo t4 // save low 32-bits of product
|
||
mfhi t5 // save high 32-bits of product
|
||
|
||
//
|
||
// Compute high 32-bits of dividend times low 32-bits of divisor.
|
||
//
|
||
|
||
multu t1,a1 //
|
||
mflo t6 // save loow 32-bits of product
|
||
mfhi t7 // save high 32-bits of product
|
||
|
||
//
|
||
// Compute high 32-bits of dividend times high 32-bits of divisor.
|
||
//
|
||
|
||
multu t1,t2 //
|
||
mflo t8 // save low 32-bits of product
|
||
mfhi t9 // save high 32-bits of product
|
||
|
||
//
|
||
// Add partial results to form high 64-bits of result.
|
||
//
|
||
|
||
addu t0,t3,t4 //
|
||
sltu t1,t0,t4 // generate carry
|
||
addu t0,t0,t6 //
|
||
sltu t2,t0,t6 // generate carry
|
||
addu t2,t1,t2 // combine carries
|
||
addu t1,t2,t5 //
|
||
sltu t2,t1,t5 // generate carry
|
||
addu t1,t1,t7 //
|
||
sltu t3,t1,t7 // generate carry
|
||
addu t2,t2,t3 // combine carries
|
||
addu t1,t1,t8 //
|
||
sltu t3,t1,t8 // generate carry
|
||
addu t2,t2,t3 // combine carries
|
||
addu t2,t2,t9 //
|
||
|
||
//
|
||
// Right shift the result by the specified shift count and negate result
|
||
// if necessary.
|
||
//
|
||
|
||
li v1,32 // compute left shift count
|
||
subu v1,v1,v0 //
|
||
bgtz v1,20f // if gtz, shift less that 32-bits
|
||
|
||
//
|
||
// Shift count is greater than or equal 32 bits - high half of result is zero,
|
||
// low half is the high half shifted right by remaining count.
|
||
//
|
||
|
||
move t1,zero // set high half of result
|
||
srl t0,t2,v0 // set low half of result
|
||
b 30f //
|
||
|
||
//
|
||
// Shift count is less than 32-bits - high half of result is the high half
|
||
// of product shifted right by count, low half of result is the shifted out
|
||
// bits of the high half combined with the rigth shifted low half of the
|
||
// product.
|
||
//
|
||
|
||
20: srl t0,t1,v0 // shift low half right count bits
|
||
srl t1,t2,v0 // shift high half right count bits
|
||
beq zero,v0,30f // if eq, no more shifts necessary
|
||
sll t2,t2,v1 // isolate shifted out bits of high half
|
||
or t0,t0,t2 // combine bits for low half of result
|
||
|
||
//
|
||
// Negate result if neccessary.
|
||
//
|
||
|
||
30: bgez a3,40f // if gez, positive result
|
||
subu t0,zero,t0 // negate low half of result
|
||
subu t1,zero,t1 // negate high half of result
|
||
beq zero,t0,40f // if eq, negation complete
|
||
subu t1,t1,1 // convert high part to ones complement
|
||
40: sw t0,0(a0) // store low half of result
|
||
sw t1,4(a0) // store high half of result
|
||
move v0,a0 // set function return register
|
||
j ra // return
|
||
|
||
.end RtlExtendedMagicDivide
|
||
|
||
SBTTL("Large Integer Divide")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlLargeIntegerDivide (
|
||
// IN LARGE_INTEGER Dividend,
|
||
// IN LARGE_INTEGER Divisor,
|
||
// IN PLARGE_INTEGER Remainder.
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function divides an unsigned large integer by an unsigned
|
||
// large and returns the resultant quotient and optionally the remainder.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Dividend (a2, a3) - Supplies the dividend value.
|
||
//
|
||
// Divisor (4 * 4(sp), 4 * 5(sp)) - Supplies the divisor value.
|
||
//
|
||
// Remainder (4 * 6(sp)- Supplies an optional pointer to a variable
|
||
// that receives the remainder.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlLargeIntegerDivide)
|
||
|
||
.set noreorder
|
||
.set noat
|
||
move v0,a0 // set function return register
|
||
lw a1,4 * 4(sp) // get low part of divisor
|
||
lw t0,4 * 5(sp) // get high part of divisor
|
||
lw t1,4 * 6(sp) // get address to store remainder
|
||
or v1,t0,a1 // combine low and high parts
|
||
beq zero,v1,60f // if eq, attempted division by zero
|
||
li t2,63 // set loop count
|
||
move t3,zero // clear partial remainder
|
||
move t4,zero //
|
||
10: sll t4,t4,1 // shift next dividend bit
|
||
srl t5,t3,31 // into the partial remainder
|
||
or t4,t4,t5 //
|
||
sll t3,t3,1 //
|
||
srl t5,a3,31 //
|
||
or t3,t3,t5 //
|
||
sll a3,a3,1 // double left shift dividend
|
||
srl t5,a2,31 //
|
||
or a3,a3,t5 //
|
||
sltu t5,t4,t0 // check if partial remainder less
|
||
beq zero,t5,20f // if eq, partial remainder not less
|
||
sll a2,a2,1 //
|
||
bne zero,t2,10b // if ne, more iterations to go
|
||
subu t2,t2,1 // decrement iteration count
|
||
beq zero,t1,50f // if eq, remainder not requested
|
||
sw a2,0(a0) // store low part of quotient
|
||
sw t3,0(t1) // store large integer remainder
|
||
sw t4,4(t1) //
|
||
j ra // return
|
||
sw a3,4(a0) // store high part of quotient
|
||
|
||
20: bne t0,t4,30f // if ne, partial remainder greater
|
||
sltu t5,t3,a1 // check is partial remainder less
|
||
bne zero,t5,40f // if ne, partial remainder less
|
||
nop //
|
||
30: or a2,a2,1 // merge quotient bit
|
||
subu t4,t4,t0 // subtract out divisor high part
|
||
sltu t5,t3,a1 // set borrow from high part
|
||
subu t4,t4,t5 // subtract borrow from high part
|
||
subu t3,t3,a1 // subtract out divisor low
|
||
40: bne zero,t2,10b // if ne, more iterations to go
|
||
subu t2,t2,1 // decrement iteration count
|
||
beq zero,t1,50f // if eq, remainder not requested
|
||
sw a2,0(a0) // store low part of quotient
|
||
sw t3,0(t1) // store large integer remainder
|
||
sw t4,4(t1) //
|
||
50: j ra // return
|
||
sw a3,4(a0) // store high part of quotient
|
||
.set at
|
||
.set reorder
|
||
|
||
60: break DIVIDE_BY_ZERO_BREAKPOINT // attempted division by zero
|
||
j ra //
|
||
|
||
.end RtlLargeIntegerDivide
|
||
|
||
SBTTL("Extended Integer Multiply")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlExtendedIntegerMultiply (
|
||
// IN LARGE_INTEGER Multiplicand,
|
||
// IN LONG Multiplier
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function multiplies a signed large integer by a signed integer and
|
||
// returns the signed large integer result.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Multiplicand (a2, a3) - Supplies the multiplicand value.
|
||
//
|
||
// Multiplier (4 * 4(sp)) - Supplies the multiplier value.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlExtendedIntegerMultiply)
|
||
|
||
lw a1,4 * 4(sp) // get multiplier value
|
||
xor t9,a1,a3 // compute sign of result
|
||
move t0,a1 // assume multiplier positive
|
||
bgez a1,10f // if gez, positive multiplier
|
||
subu t0,zero,t0 // negate multiplier
|
||
10: move t1,a2 // assume multiplicand positive
|
||
move t2,a3 //
|
||
bgez a3,20f // if gez, positive multiplicand
|
||
subu t1,zero,t1 // negate multiplicand
|
||
subu t2,zero,t2 //
|
||
sltu t3,zero,t1 // compute borrow from high part
|
||
subu t2,t2,t3 // subtract out borrow
|
||
|
||
//
|
||
// Compute low 32-bits of multiplier times the low 32-bit of multiplicand.
|
||
//
|
||
|
||
20: multu t0,t1 //
|
||
mflo t4 // save low 32-bits of product
|
||
mfhi t5 // save high 32-bits of product
|
||
|
||
//
|
||
// Compute low 32-bits of multiplier times the high 32-bits of multiplicand.
|
||
//
|
||
|
||
multu t0,t2 //
|
||
mflo t6 // save low 32-bits of product
|
||
mfhi t7 // save high 32-bits of product
|
||
|
||
//
|
||
// Add partial results to form high 64-bits of result.
|
||
//
|
||
|
||
addu t5,t5,t6 //
|
||
sltu t3,t5,t6 // generate carry
|
||
addu t6,t3,t7 //
|
||
|
||
//
|
||
// Negate result if neccessary.
|
||
//
|
||
|
||
bgez t9,40f // if gez, positive result
|
||
subu t4,zero,t4 // negate low half of result
|
||
subu t5,zero,t5 // negate high half of result
|
||
subu t6,zero,t6 // negate extended part of result
|
||
beq zero,t4,30f // if eq, negation complete
|
||
subu t5,t5,1 // convert high part to ones complement
|
||
subu t6,t6,1 // convert extended part to ones complement
|
||
b 40f //
|
||
|
||
30: beq zero,t5,40f // if eq, negation complete
|
||
subu t6,t6,1 // convert extended part to ones complement
|
||
|
||
//
|
||
// Store final result.
|
||
//
|
||
|
||
40: sw t4,0(a0) // store low half of result
|
||
sw t5,4(a0) // store high half of result
|
||
move v0,a0 // set function return register
|
||
j ra // return
|
||
|
||
.end RtlExtendedIntegerMultiply
|
||
|
||
SBTTL("Large Integer Negate")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlLargeIntegerNegate (
|
||
// IN LARGE_INTEGER Subtrahend
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function negates a signed large integer and returns the signed
|
||
// large integer result.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Subtrahend (a2, a3) - Supplies the subtrahend value.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlLargeIntegerNegate)
|
||
|
||
subu a2,zero,a2 // negate low part of subtrahend
|
||
subu a3,zero,a3 // negate high part of subtrahend
|
||
sltu t0,zero,a2 // compute borrow from high part
|
||
subu a3,a3,t0 // subtract borrow from high part
|
||
sw a2,0(a0) // store low part of result
|
||
sw a3,4(a0) // store high part of result
|
||
move v0,a0 // set function return register
|
||
j ra // return
|
||
|
||
.end RtlLargeIntegerNegate
|
||
|
||
SBTTL("Large Integer Subtract")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlLargeIntegerSubtract (
|
||
// IN LARGE_INTEGER Minuend,
|
||
// IN LARGE_INTEGER Subtrahend
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function subtracts a signed large integer from a signed large
|
||
// integer and returns the signed large integer result.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Minuend (a2, a3) - Supplies the minuend value.
|
||
//
|
||
// Subtrahend (4 * 4(sp), 4 * 5(sp)) - Supplies the subtrahend value.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlLargeIntegerSubtract)
|
||
|
||
lw a1,4 * 4(sp) // get low part of subtrahend
|
||
lw t2,4 * 5(sp) // get high part of subtrahend
|
||
subu t0,a2,a1 // subtract low parts
|
||
subu t1,a3,t2 // subtract high parts
|
||
sltu t3,a2,a1 // generate borrow from high part
|
||
subu t1,t1,t3 // subtract borrow
|
||
sw t0,0(a0) // store low part of result
|
||
sw t1,4(a0) // store high part of result
|
||
move v0,a0 // set function return register
|
||
j ra // return
|
||
|
||
.end RtlLargeIntegerSubtract
|
||
|
||
SBTTL("Large Integer Shift Left")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlLargeIntegerShiftLeft (
|
||
// IN LARGE_INTEGER LargeInteger,
|
||
// IN CCHAR ShiftCount
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function shifts a signed large integer left by an unsigned
|
||
// integer modulo 64 and returns the shifted signed large integer
|
||
// result.
|
||
//
|
||
// N.B. No test is made for significant bits shifted out of the result.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// LargeInteger (a2, a3) - Supplies the large integer to be shifted.
|
||
//
|
||
// ShiftCount (4 * 4(sp)) - Supplies the left shift count.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlLargeIntegerShiftLeft)
|
||
|
||
lbu a1,4 * 4(sp) // get shift count
|
||
move v0,a0 // set function return register
|
||
and a1,a1,0x3f // truncate shift count mod 64
|
||
|
||
//
|
||
// Left shift the operand by the specified shift count.
|
||
//
|
||
|
||
li v1,32 // compute right shift count
|
||
subu v1,v1,a1 //
|
||
bgtz v1,10f // if gtz, shift less that 32-bits
|
||
|
||
//
|
||
// Shift count is greater than or equal 32 bits - low half of result is zero,
|
||
// high half is the low half shifted left by remaining count.
|
||
//
|
||
|
||
sll a3,a2,a1 // set high half of result
|
||
sw zero,0(a0) // store low part of reuslt
|
||
sw a3,4(a0) // store high part of result
|
||
j ra // return
|
||
|
||
//
|
||
// Shift count is less than 32-bits - high half of result is the high half
|
||
// of operand shifted left by count combined with the low half of the operand
|
||
// shifted right, low half of result is the low half shifted left.
|
||
//
|
||
|
||
10: sll a3,a3,a1 // shift high half left count bits
|
||
beq zero,a1,20f // if eq, no more shifts necessary
|
||
srl t0,a2,v1 // isolate shifted out bits of low half
|
||
sll a2,a2,a1 // shift low half left count bits
|
||
or a3,a3,t0 // combine bits for high half of result
|
||
20: sw a2,0(a0) // store low part of reuslt
|
||
sw a3,4(a0) // store high part of result
|
||
j ra // return
|
||
|
||
.end RtlLargeIntegerShiftLeft
|
||
|
||
SBTTL("Large Integer Logical Shift Right")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlLargeIntegerShiftRight (
|
||
// IN LARGE_INTEGER LargeInteger,
|
||
// IN CCHAR ShiftCount
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function shifts an unsigned large integer right by an unsigned
|
||
// integer modulo 64 and returns the shifted unsigned large integer
|
||
// result.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// LargeInteger (a2, a3) - Supplies the large integer to be shifted.
|
||
//
|
||
// ShiftCount (4 * 4(sp)) - Supplies the right shift count.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlLargeIntegerShiftRight)
|
||
|
||
lbu a1,4 * 4(sp) // get shift count
|
||
move v0,a0 // set function return register
|
||
and a1,a1,0x3f // truncate shift count mod 64
|
||
|
||
//
|
||
// Right shift the operand by the specified shift count.
|
||
//
|
||
|
||
li v1,32 // compute left shift count
|
||
subu v1,v1,a1 //
|
||
bgtz v1,10f // if gtz, shift less that 32-bits
|
||
|
||
//
|
||
// Shift count is greater than or equal 32 bits - high half of result is
|
||
// zero, low half is the high half shifted right by remaining count.
|
||
//
|
||
|
||
srl a2,a3,a1 // set low half of result
|
||
sw a2,0(a0) // store low part of reuslt
|
||
sw zero,4(a0) // store high part of result
|
||
j ra // return
|
||
|
||
//
|
||
// Shift count is less than 32-bits - high half of result is the high half
|
||
// of operand shifted right by count, low half of result is the shifted out
|
||
// bits of the high half combined with the right shifted low half of the
|
||
// operand.
|
||
//
|
||
|
||
10: srl a2,a2,a1 // shift low half right count bits
|
||
beq zero,a1,20f // if eq, no more shifts necessary
|
||
sll t0,a3,v1 // isolate shifted out bits of high half
|
||
srl a3,a3,a1 // shift high half right count bits
|
||
or a2,a2,t0 // combine bits for low half of result
|
||
20: sw a2,0(a0) // store low part of reuslt
|
||
sw a3,4(a0) // store high part of result
|
||
j ra // return
|
||
|
||
.end RtlLargeIntegerShiftRight
|
||
|
||
SBTTL("Large Integer Arithmetic Shift Right")
|
||
//++
|
||
//
|
||
// LARGE_INTEGER
|
||
// RtlLargeIntegerArithmeticShift (
|
||
// IN LARGE_INTEGER LargeInteger,
|
||
// IN CCHAR ShiftCount
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function shifts a signed large integer right by an unsigned
|
||
// integer modulo 64 and returns the shifted signed large integer
|
||
// result.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// LargeInteger (a1, a2) - Supplies the large integer to be shifted.
|
||
//
|
||
// ShiftCount (a3) - Supplies the right shift count.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// The large integer result is stored at the address supplied by a0.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(RtlLargeIntegerArithmeticShift)
|
||
|
||
lbu a1,4 * 4(sp) // get shift count
|
||
move v0,a0 // set function return register
|
||
and a1,a1,0x3f // truncate shift count mod 64
|
||
|
||
//
|
||
// Right shift the operand by the specified shift count.
|
||
//
|
||
|
||
li v1,32 // compute left shift count
|
||
subu v1,v1,a1 //
|
||
bgtz v1,10f // if gtz, shift less that 32-bits
|
||
|
||
//
|
||
// Shift count is greater than or equal 32 bits - high half of result is
|
||
// zero, low half is the high half shifted right by remaining count.
|
||
//
|
||
|
||
sra a2,a3,a1 // set low half of result
|
||
sra a3,a3,31 // set high half of result
|
||
sw a2,0(a0) // store low part of reuslt
|
||
sw a3,4(a0) // store high part of result
|
||
j ra // return
|
||
|
||
//
|
||
// Shift count is less than 32-bits - high half of result is the high half
|
||
// of operand shifted right by count, low half of result is the shifted out
|
||
// bits of the high half combined with the right shifted low half of the
|
||
// operand.
|
||
//
|
||
|
||
10: srl a2,a2,a1 // shift low half right count bits
|
||
beq zero,a1,20f // if eq, no more shifts necessary
|
||
sll t0,a3,v1 // isolate shifted out bits of high half
|
||
sra a3,a3,a1 // shift high half right count bits
|
||
or a2,a2,t0 // combine bits for low half of result
|
||
20: sw a2,0(a0) // store low part of reuslt
|
||
sw a3,4(a0) // store high part of result
|
||
j ra // return
|
||
|
||
.end RtlLargeIntegerArithmeticShift
|