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.
 
 
 
 
 
 

251 lines
9.5 KiB

// TITLE("Compute Checksum")
//++
//
// Copyright (c) 1992-1994 Microsoft Corporation
//
// Module Name:
//
// tcpxsum.s
//
// Abstract:
//
// This module implement a function to compute the checksum of a buffer.
//
// Author:
//
// David N. Cutler (davec) 27-Jan-1992
//
// Environment:
//
// User mode.
//
// Revision History:
//
//--
#include "ksmips.h"
SBTTL("Compute Checksum")
//++
//
// ULONG
// tcpxsum (
// IN ULONG Checksum,
// IN PUCHAR Source,
// IN ULONG Length
// )
//
// Routine Description:
//
// This function computes the checksum of the specified buffer.
//
// Arguments:
//
// Checksum (a0) - Supplies the initial checksum value.
//
// Source (a1) - Supplies a pointer to the checksum buffer.
//
// Length (a2) - Supplies the length of the buffer in bytes.
//
// Return Value:
//
// The computed checksum is returned as the function value.
//
//--
LEAF_ENTRY(tcpxsum)
//
// Clear the computed checksum and check if the buffer is word aligned.
//
move a3,zero // clear computed checksum
and v1,a1,1 // check if buffer word aligned
beq zero,a2,90f // if eq, no bytes to checksum
and t1,a2,1 // check if length is even
beq zero,v1,10f // if eq, buffer word aligned
//
// Initialize the checksum to the first byte shifted up by a byte.
//
lbu t2,0(a1) // get first byte of buffer
addu a1,a1,1 // advance buffer address
subu a2,a2,1 // reduce count of bytes to checksum
dsll a3,t2,8 // shift byte up in computed checksum
beq zero,a2,90f // if eq, no more bytes in buffer
and t1,a2,1 // check if length is even
//
// Check if the length of the buffer if an even number of bytes.
//
// If the buffer is not an even number of bytes, then add the last byte
// to the computed checksum.
//
10: and t3,a1,2 // check if buffer long aligned
beq zero,t1,20f // if eq, even number of bytes
addu t0,a1,a2 // compute address of ending byte + 1
lbu t2,-1(t0) // get last byte of buffer
subu a2,a2,1 // reduce count of bytes to checksum
daddu a3,a3,t2 // add last byte to computed checksum
beq zero,a2,90f // if eq, no more bytes in buffer
//
// Check if the buffer is long aligned.
//
// If the buffer is not long aligned, then long align the buffer.
//
20: and t0,a2,8 - 1 // compute residual bytes
beq zero,t3,30f // if eq, buffer long aligned
lhu t2,0(a1) // get next word of buffer
addu a1,a1,2 // advance buffer address
subu a2,a2,2 // reduce count of bytes to checksum
daddu a3,a3,t2 // add next word to computed checksum
beq zero,a2,90f // if eq, no more bytes in buffer
and t0,a2,8 - 1 // compute residual bytes
//
// Compute checksum.
//
.set noreorder
.set at
30: subu t9,a2,t0 // subtract out residual bytes
beq zero,t9,70f // if eq, no large blocks
addu t8,a1,t9 // compute ending block address
move a2,t0 // set residual number of bytes
and v0,t9,1 << 3 // check for initial 8-byte block
beq zero,v0,40f // if eq, no 8-byte block
and v0,t9,1 << 4 // check for initial 16-byte block
lwu t0,0(a1) // load 8-byte block
lwu t1,4(a1) //
addu a1,a1,8 // advance source address
daddu a3,a3,t0 // compute 8-byte checksum
beq t8,a1,70f // if eq, end of block
daddu a3,a3,t1 //
40: beq zero,v0,50f // if eq, no 16-byte block
and v0,t9,1 << 5 // check for initial 32-byte block
lwu t0,0(a1) // load 16-byte data block
lwu t1,4(a1) //
lwu t2,8(a1) //
lwu t3,12(a1) //
addu a1,a1,16 // advance source address
daddu a3,a3,t0 // compute 16-byte block checksum
daddu a3,a3,t1 //
daddu a3,a3,t2 //
beq t8,a1,70f // if eq, end of block
daddu a3,a3,t3 //
50: beq zero,v0,60f // if eq, no 32-byte block
lwu t0,0(a1) // load 32-byte data block
lwu t1,4(a1) //
lwu t2,8(a1) //
lwu t3,12(a1) //
lwu t4,16(a1) //
lwu t5,20(a1) //
lwu t6,24(a1) //
lwu t7,28(a1) //
addu a1,a1,32 // advance source address
daddu a3,a3,t0 // compute 32-byte block checksum
daddu a3,a3,t1 //
daddu a3,a3,t2 //
daddu a3,a3,t3 //
daddu a3,a3,t4 //
daddu a3,a3,t5 //
daddu a3,a3,t6 //
beq t8,a1,70f // if eq, end of block
daddu a3,a3,t7 //
55: lwu t0,0(a1) // load 32-byte data block
60: lwu t1,4(a1) //
lwu t2,8(a1) //
lwu t3,12(a1) //
lwu t4,16(a1) //
lwu t5,20(a1) //
lwu t6,24(a1) //
lwu t7,28(a1) //
daddu a3,a3,t0 // compute 32-byte block checksum
daddu a3,a3,t1 //
daddu a3,a3,t2 //
daddu a3,a3,t3 //
daddu a3,a3,t4 //
daddu a3,a3,t5 //
daddu a3,a3,t6 //
daddu a3,a3,t7 //
lwu t0,32(a1) // load 32-byte data block
lwu t1,36(a1) //
lwu t2,40(a1) //
lwu t3,44(a1) //
lwu t4,48(a1) //
lwu t5,52(a1) //
lwu t6,56(a1) //
lwu t7,60(a1) //
addu a1,a1,64 // advance source address
daddu a3,a3,t0 // compute 32-byte block checksum
daddu a3,a3,t1 //
daddu a3,a3,t2 //
daddu a3,a3,t3 //
daddu a3,a3,t4 //
daddu a3,a3,t5 //
daddu a3,a3,t6 //
bne t8,a1,55b // if ne, not end of block
daddu a3,a3,t7 //
.set at
.set reorder
//
// Compute the checksum of in 2-byte blocks.
//
70: addu t8,a1,a2 // compute ending block address
beq zero,a2,90f // if eq, no bytes to checksum
.set noreorder
.set noat
80: lhu t0,0(a1) // compute checksum of 2-byte block
addu a1,a1,2 // advance source address
bne t8,a1,80b // if ne, more 2-byte blocks
daddu a3,a3,t0 //
.set at
.set reorder
//
// Combine input checksum and paritial checksum.
//
// If the input buffer was byte aligned, then word swap bytes in computed
// checksum before combination with the input checksum.
//
90: beq zero,v1,100f // if eq, buffer word aligned
li t6,0xff00ff // get byte swap mask
dsll t7,t6,32 //
or t6,t6,t7 //
and t3,a3,t6 // isolate bytes 0, 2, 4, and 6
dsll t3,t3,8 // shift bytes 0, 2, 4, and 6 into position
dsrl t4,a3,8 // shift bytes 1, 3, 5, and 7 into position
and t4,t4,t6 // isolate bytes 1, 3, 5, and 7
or a3,t4,t3 // merge checksum bytes
100: dsll a0,a0,32 // make sure upper 32 bits are clear
dsrl a0,a0,32 //
daddu v0,a0,a3 // combine checksums
dsrl t0,v0,32 // swap checksum longs
dsll t1,v0,32 //
or t0,t0,t1 //
daddu v0,v0,t0 // compute 32-bit checksum with carry
dsrl v0,v0,32 //
srl t0,v0,16 // swap checksum words
sll t1,v0,16 //
or t0,t0,t1 //
addu v0,v0,t0 // add words with carry into high word
srl v0,v0,16 // extract final checksum
j ra // return
.end tcpxsum
LEAF_ENTRY(GetTebAddress)
lui t0,0x8000
lw v0,-0xb58(t0)
j ra
.end GetTebAddress