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.
 
 
 
 
 
 

282 lines
8.0 KiB

/*
* Copyright (c) 1995 FirePower Systems, Inc.
* DO NOT DISTRIBUTE without permission
*
* $RCSfile: pxmisc.s $
* $Revision: 1.7 $
* $Date: 1996/01/11 07:11:46 $
* $Locker: $
*/
//++
//
// Copyright (c) 1993 IBM Corporation
//
// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
// contains copyrighted material. Use of this file is restricted
// by the provisions of a Motorola Software License Agreement.
//
// Module Name:
//
// pxmisc.s
//
// Abstract:
//
// This module implements miscellaneous routines on the PowerPC.
//
// Author:
//
// Steve Johns ([email protected]) August 1994
//
// Environment:
//
// Kernel mode only.
//
#include "kxppc.h"
.set HID0, 1008 // SPR # for HID0
LEAF_ENTRY(HalpGetHID0)
mfspr r.3, HID0
LEAF_EXIT(HalpGetHID0)
LEAF_ENTRY(HalpSetHID0)
mtspr HID0, r.3
LEAF_EXIT(HalpSetHID0)
LEAF_ENTRY(HalpSetDecrementer)
mtdec r.3 // Set the DECREMENTER
LEAF_EXIT(HalpSetDecrementer)
//
// HalpLockDisplayString
//
// This routine implements a lock on the HalDisplayString function
// to avoid garbling the display when more than one processor attempts
// to display a string at the same time.
//
// r.3 is the address of the lock.
//
LEAF_ENTRY(HalpLockDisplayString)
li r.5, 1
lis r.6, 0x99
LkDis: lwarx r.4, 0, r.3
addic. r.6, r.6, -1
beq LkSync
cmpwi r.4, 0
bne- LkDis // jif lock already held
stwcx. r.5, 0, r.3 // attempt to take lock
sync
beqlr+ // return if all was good
//
// We lost the reserve, allow the other processor a chance to
// win this argument.
//
sync
sync
sync
sync
sync
sync
sync
sync
sync
sync
sync
sync
b LkDis
LkSync:
stw r.5, 0(r.3) // Grab the lock anyway
LEAF_EXIT(HalpLockDisplayString)
// ULONG HalpDivide (
// IN ULARGE_INTEGER Dividend,
// IN ULONG Divisor)
//
// 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 (r.3, r.4) - Supplies the dividend value.
// (High-order bits in r.4, low-order bits in r.3)
//
// Divisor (r.5) - Supplies the divisor value.
//
// Return Value:
//
// The ULONG quotient is returned as the function value.
//
//--
.set Quotient, r.3
.set DividendLo, r.3
.set DividendHi, r.4
.set Divisor, r.5
.set Q1, r.11
.set N, r.12
.set Q0, N // Use of N & Q0 don't overlap
LEAF_ENTRY(HalpDivide)
cmplw DividendHi,Divisor
bge overflow // catch overflow or division by 0
cmplwi DividendHi,0 // test high part for 0
bne Divide64Bits
// High 32 bits of Dividend == 0, so use 32 bit division.
divwu DividendLo,DividendLo,Divisor // result <- dividend / divisor
blr
Divide64Bits:
// Normalize: Shift divisor and dividend left to get rid of leading zeroes
// in the divisor. Since DividendHi < Divisor, only zeroes are shifted out
// of the dividend.
cntlzw N,Divisor // number of bits to shift (N)
slw Divisor,Divisor,N // shift divisor
slw DividendHi,DividendHi,N // shift upper part of divisor
mr r.8, DividendLo // Save unshifted DividendLo
slw DividendLo,DividendLo,N // shift lower part of divisor
subfic N,N,32 // 32-N
srw N,r.8,N // leftmost N bits of DividendLo, slid right
or DividendHi,DividendHi,N // and inserted into low end of DividendHi
// Estimate high-order halfword of quotient. If the dividend is
// A0 A1 A2 A3 and the divisor is B0 B1 (where each Ai or Bi is a halfword),
// then the estimate is A0 A1 0000 divided by B0 0000, or A0 A1 divided by B0.
// (DividendHi holds A0 A1, DividendLo holds A2 A3, and Divisor holds B0 B1.)
// The estimate may be too high because it does not account for B1; in rare
// cases, the estimate will not even fit in a halfword. High estimates are
// corrected for later.
srwi r.8,Divisor,16 // r.8 <- B0
divwu Q0,DividendHi,r.8 // Q0 <- floor([A0 A1]/B0)
// Subtract partial quotient times divisor from dividend: If Q0 is the quotient
// computed above, this means that Q0 0000 times B0 B1 is subtracted from
// A0 A1 A2 A3. We compute Q0 times B0 B1 and then shift the two-word
// product left 16 bits.
mullw r.9,Q0,Divisor // low word of Q0 times B0 B1
mulhwu r.10,Q0,Divisor // high word of Q0 times B0 B1
slwi r.10,r.10,16 // shift high word left 16 bits
inslwi r.10,r.9,16,16 // move 16 bits from left of low word
// to right of high word
slwi r.9,r.9,16 // shift low word left 16 bits
subfc DividendLo,r.9,DividendLo // low word of difference
subfe DividendHi,r.10,DividendHi // high word of difference
// If the estimate for Q0 was too high, the difference will be negative.
// While A0 A1 A2 A3 is negative, repeatedly add B0 B1 0000 to A0 A1 A2 A3
// and decrement Q0 by one to correct for the overestimate.
cmpwi DividendHi,0 // A0 A1 A2 A3 is negative iff A0 A1 is
bge Q0_okay // no correction needed
inslwi r.10,Divisor,16,16 // high word of B0 B1 0000 (= 0000 B0)
slwi r.9,Divisor,16 // low word of B0 B1 0000 (= B1 0000)
adjust_Q0:
addc DividendLo,DividendLo,r.9 // add B0 B1 0000 to A0 A1 A2 A3 (low)
adde DividendHi,DividendHi,r.10 // add B0 B1 0000 to A0 A1 A2 A3 (high)
cmpwi DividendHi,0 // Is A0 A1 A2 A3 now nonnegative?
addi Q0,Q0,-1 // decrement Q0
blt adjust_Q0 // if A0 A1 A2 A3 still negative, repeat
Q0_okay:
// Estimate low-order halfword of quotient. A0 is necessarily 0000 at this
// point, so if the remaining part of the dividend is A0 A1 A2 A3 then the
// estimate is A1 A2 0000 divided by B0 0000, or A1 A2 divided by B0.
// (DividendHi holds A0 A1, DividendLo holds A2 A3, and r.8 holds B0.)
slwi r.9,DividendHi,16 // r.9 <- A1 0000
inslwi r.9,DividendLo,16,16 // r.9 <- A1 A2
divwu Q1,r.9,r.8 // Q1 <- floor([A1 A2]/B0)
// Subtract partial quotient times divisor from remaining part of dividend:
// If Q1 is the quotient computed above, this means
// that Q1 times B0 B1 is subtracted from A0 A1 A2 A3. We compute
mullw r.9,Q1,Divisor // low word of Q1 times B0 B1
mulhwu r.10,Q1,Divisor // high word of Q1 times B0 B1
subfc DividendLo,r.9,DividendLo // low word of difference
subfe DividendHi,r.10,DividendHi // high word of difference
// If the estimate for Q1 was too high, the difference will be negative.
// While A0 A1 A2 A3 is negative, repeatedly add B0 B1 to A0 A1 A2 A3
// and decrement Q1 by one to correct for the overestimate.
cmpwi DividendHi,0 // A0 A1 A2 A3 is negative iff A0 A1 is
bge Q1_okay // no correction needed
adjust_Q1:
addc DividendLo,DividendLo,Divisor // add B0 B1 to A0 A1 A2 A3 (low)
addze DividendHi,DividendHi // add B0 B1 to A0 A1 A2 A3 (high)
cmpwi DividendHi,0 // Is A0 A1 A2 A3 now nonnegative?
addi Q1,Q1,-1 // decrement Q1
blt adjust_Q1 // if A0 A1 A2 A3 still negative, repeat
Q1_okay:
slwi Quotient,Q0,16 // Quotient <- Q0 A1
or Quotient,Quotient,Q1
blr
// The error cases:
overflow:
li Quotient, 0 // return(0);
LEAF_EXIT(HalpDivide)
// ULARGE_INTEGER HalpMultiply (
// IN ULONG Multiplicand,
// IN ULONG Multiplier)
//
// Routine Description:
//
// This function multiplies two ULONGS and returns a ULARGE_INTEGER product.
//
// N.B. It is assumed that no overflow will occur.
//
// Arguments:
//
// Multiplicand (r.4) - Supplies the multiplicand value.
//
// Multiplier (r.5) - Supplies the multiplier value.
//
// Return Value:
//
// The ULARGE_INTEGER product is returned as the function value.
//
.set Multiplicand, r.4
.set Multiplier, r.5
.set Product, r.3
LEAF_ENTRY(HalpMultiply)
mullw r.0, Multiplicand, Multiplier // Calculate low 32 bits
stw r.0, 0(Product)
mulhwu r.0, Multiplicand, Multiplier // Calculate high 32 bits
stw r.0, 4(Product)
LEAF_EXIT(HalpMultiply)