mirror of https://github.com/lianthony/NT4.0
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
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
|