1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
|
// TITLE("Compute Checksum")
//++
//
// Copyright (c) 1992 Microsoft Corporation
//
// Module Name:
//
// chksum.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")
//++
//
// USHORT
// ChkSum (
// IN ULONG Checksum,
// IN PUSHORT 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 buffer that is checksumed.
//
// Length (a2) - Supplies the length of the buffer in words.
//
// Return Value:
//
// The computed checksum is returned as the function value.
//
//--
LEAF_ENTRY(ChkSum)
sll a2,a2,1 // convert length to bytes
//
// Compute the checksum in 8-byte blocks.
//
.set noreorder
.set at
10: and t0,a2,8 - 1 // isolate residual bytes
subu t9,a2,t0 // subtract out residual bytes
beq zero,t9,60f // if eq, no 8-byte 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,20f // if eq, no 8-byte block
and v0,t9,1 << 4 // check for initial 16-byte block
lhu t0,0(a1) // load 8-byte block
lhu t1,2(a1) //
lhu t2,4(a1) //
lhu t3,6(a1) //
addu a1,a1,8 // advance source address
addu a0,a0,t0 // compute 8-byte checksum
addu a0,a0,t1 //
addu a0,a0,t2 //
beq t8,a1,60f // if eq, end of block
addu a0,a0,t3 //
20: beq zero,v0,30f // if eq, no 16-byte block
and v0,t9,1 << 5 // check for initial 32-byte block
lhu t0,0(a1) // load 16-byte data block
lhu t1,2(a1) //
lhu t2,4(a1) //
lhu t3,6(a1) //
lhu t4,8(a1) //
lhu t5,10(a1) //
lhu t6,12(a1) //
lhu t7,14(a1) //
addu a1,a1,16 // advance source address
addu a0,a0,t0 // compute 16-byte block checksum
addu a0,a0,t1 //
addu a0,a0,t2 //
addu a0,a0,t3 //
addu a0,a0,t4 //
addu a0,a0,t5 //
addu a0,a0,t6 //
beq t8,a1,60f // if eq, end of block
addu a0,a0,t7 //
30: beq zero,v0,50f // if eq, no 32-byte block
lhu t0,0(a1) // load 16-byte data block
lhu t1,2(a1) //
lhu t2,4(a1) //
lhu t3,6(a1) //
lhu t4,8(a1) //
lhu t5,10(a1) //
lhu t6,12(a1) //
lhu t7,14(a1) //
addu a0,a0,t0 // compute 16-byte block checksum
addu a0,a0,t1 //
addu a0,a0,t2 //
addu a0,a0,t3 //
addu a0,a0,t4 //
addu a0,a0,t5 //
addu a0,a0,t6 //
addu a0,a0,t7 //
lhu t0,16(a1) // load 16-byte data block
lhu t1,18(a1) //
lhu t2,20(a1) //
lhu t3,22(a1) //
lhu t4,24(a1) //
lhu t5,26(a1) //
lhu t6,28(a1) //
lhu t7,30(a1) //
addu a0,a0,t0 // compute 16-byte block checksum
addu a0,a0,t1 //
addu a0,a0,t2 //
addu a0,a0,t3 //
addu a0,a0,t4 //
addu a0,a0,t5 //
addu a0,a0,t6 //
addu a1,a1,32 // advance source address
beq t8,a1,60f // if eq, end of block
addu a0,a0,t7 //
40: lhu t0,0(a1) // load 16-byte data block
50: lhu t1,2(a1) //
lhu t2,4(a1) //
lhu t3,6(a1) //
lhu t4,8(a1) //
lhu t5,10(a1) //
lhu t6,12(a1) //
lhu t7,14(a1) //
addu a0,a0,t0 // compute 16-byte block checksum
addu a0,a0,t1 //
addu a0,a0,t2 //
addu a0,a0,t3 //
addu a0,a0,t4 //
addu a0,a0,t5 //
addu a0,a0,t6 //
addu a0,a0,t7 //
lhu t0,16(a1) // load 16-byte data block
lhu t1,18(a1) //
lhu t2,20(a1) //
lhu t3,22(a1) //
lhu t4,24(a1) //
lhu t5,26(a1) //
lhu t6,28(a1) //
lhu t7,30(a1) //
addu a0,a0,t0 // compute 16-byte block checksum
addu a0,a0,t1 //
addu a0,a0,t2 //
addu a0,a0,t3 //
addu a0,a0,t4 //
addu a0,a0,t5 //
addu a0,a0,t6 //
addu a0,a0,t7 //
lhu t0,32(a1) // load 16-byte data block
lhu t1,34(a1) //
lhu t2,36(a1) //
lhu t3,38(a1) //
lhu t4,40(a1) //
lhu t5,42(a1) //
lhu t6,44(a1) //
lhu t7,46(a1) //
addu a0,a0,t0 // compute 16-byte block checksum
addu a0,a0,t1 //
addu a0,a0,t2 //
addu a0,a0,t3 //
addu a0,a0,t4 //
addu a0,a0,t5 //
addu a0,a0,t6 //
addu a0,a0,t7 //
lhu t0,48(a1) // load 16-byte data block
lhu t1,50(a1) //
lhu t2,52(a1) //
lhu t3,54(a1) //
lhu t4,56(a1) //
lhu t5,58(a1) //
lhu t6,60(a1) //
lhu t7,62(a1) //
addu a0,a0,t0 // compute 16-byte block checksum
addu a0,a0,t1 //
addu a0,a0,t2 //
addu a0,a0,t3 //
addu a0,a0,t4 //
addu a0,a0,t5 //
addu a0,a0,t6 //
addu a0,a0,t7 //
srl t0,a0,16 // isolate carry bits
and t1,a0,0xffff // isolate sum bits
addu a1,a1,64 // advance source address
bne t8,a1,40b // if ne, not end of block
addu a0,t0,t1 // add sum bits to carry bits
.set at
.set reorder
//
// Compute the checksum of in 2-byte blocks.
//
60: addu t8,a1,a2 // compute ending block address
beq zero,a2,80f // if eq, no bytes to zero
.set noreorder
.set noat
70: lhu t0,0(a1) // compute checksum of 2-byte block
addu a1,a1,2 // advance source address
bne t8,a1,70b // if ne, more 2-byte blocks
addu a0,a0,t0 //
.set at
.set reorder
//
// Fold checksum into 16-bits.
//
80: srl v0,a0,16 // isolate carry bits
and a0,a0,0xffff // isolate sum bits
addu v0,v0,a0 // add sum bits to carry bits
srl a0,v0,16 // isolate possible carry bit
add v0,v0,a0 // add carry bit
and v0,v0,0xffff // isolate sum bits
j ra // return
.end ChkSum
|