#define IPHLEN 20 /* sizeof(struct ip) */
#define LGP 2 /* log2(adds in unrolled loop) */
# r0 checksum result result
# r1 current longword to add curlong
# r3 byte count in current mbuf count
# r4 "odd" byte count bytenum
# r5 pointer to mbuf chain m
.word MASK # use r6,r7 (in addition to r0-r5)
movl 4(ap), r5 # m = arg to function
# Assume IP header and RDP header always with in first mbuf.
# Assume mbuf chain is at least 1 long
addl3 M_OFF (r5), r5, r2 # p = mtod(m, cast)
addl2 $IPHLEN, r2 # p += sizeof(struct ip)
subw3 $IPHLEN, M_LEN (r5), r3 # count = m->m_len - sizeof(struct ip)
# Determine the number of longwords in this mbuf. Note that we
# are depending on the VAX Architecture that allows access to
# non-aligned data. (When we cross MBUF boundries an an earlier
# one was not filled with an 'even' number of bytes for longwords).
ashl $-2, r3, r6 # n_longs = n_bytes >> 2
extzv $0, $2, r3, r4 # bytenum = n_bytes & 3
# Now, can add together as many longwords as possible. We have
# unrolled the loop for efficiency, so let's calculate the number
# of times through the loop and the partial pass.
extzv $0, $LGP, r6, r7 # r7 = # adds in partial pass
ashl $-LGP, r6, r6 # r6 = # whole passes
mull2 $ADDLEN, r7 # convert adds to bytes of instruc
jmp (r7) # and jump into the loop
# There is VAX order, adding order, and network order to consider
# VAX order: 80 1 2 3 is the VAX integer 03020180 since the low
# bytes come first when treated as an unsigned character array
# adding order: add so that carries propogate in the same manner that
# they would if the machine had its bytes in network order
# 80 01 02 03 + 80 01 02 03 = 00020406, since 80 is msb
# 00 80 00 00 + 00 80 00 00 = 01000000
# This is just essentially getting the bytes into the host's
# integer format. adding order should work for the rotate too.
# We MUST add the bytes in adding order so that different
# machine architectures get the same result. We cannot add
# in native mode and f(result) because the propogation of
# carries in native cannot be made equivalent to the propogation
# of carries in adding order
# network order: The resulting checksum should be transferred in
# network order. The VAX result 01020304 would be converted
# to 04030201 for communication with remote host.
;movl (r2)+, r7 /* fetch longword */ \
;rotl $-8, r7, r1 /* put it in adding order */ \
;addl2 r1, r0 /* result += ... */ \
;rotl $1, r0, r0 /* and rotate it per spec */
# Now, add in remaining bytes, if any
movl (r5), r5 # m = m->m_next
# Convert result from adding order to network order
addl3 M_OFF (r5), r5, r2 # p = mtod(m, cast)
cvtwl M_LEN (r5), r3 # count = m->m_len
brw Ldombuf # assume zero length mbufs unusual
# In adding in the remainder of this mbuf and part of the next one,
# we're trying to build up a single 32 bit quantity for adding into
# result += curlong = (a<<24) | (b<<16) | (c<<8) | d
# result += a<<24; result += b<<16; result += c<<8; result += d
movzbl (r2)+, r1 # r1 = this byte (unsigned char)
ashl $3, r6, r7 # r7 = r6 * 8
ashl r7, r1, r1 # r1 <<= r7
addl2 r1, r0 # result += this byte
sobgtr r4, L1 # get next byte in this mbuf
# Now, grab bytes from next mbuf
rotl $1, r0, r0 # last mbuf had odd byte count
cvtwl M_LEN (r5), r3 # count = m->m_len
beql L2 # if (count == 0) do next mbuf
addl3 M_OFF (r5), r5, r2 # p = mtod(m, cast)
movzbl (r2)+, r1 # r1 = this byte (unsigned char)
ashl $3, r6, r7 # r7 = r6 * 8
ashl r7, r1, r1 # r1 <<= r7
addl2 r1, r0 # result += this byte
bgeq L5 # got last byte in long?
brw Ldombuf # and continue checksumming
sobgtr r3, L4 # grab next byte from this mbuf
brb L2 # but go to next if have too