1#define M_OFF 4 2#define M_LEN 8 3#define IPHLEN 20 /* sizeof(struct ip) */ 4#define LGP 2 /* log2(adds in unrolled loop) */ 5#define ADDLEN 24 6 7 # r0 checksum result result 8 # r1 current longword to add curlong 9 # r2 pointer to data p 10 # r3 byte count in current mbuf count 11 # r4 "odd" byte count bytenum 12 # r5 pointer to mbuf chain m 13 14.text 15.align 1 16.globl _rdp_cksum 17 18_rdp_cksum: 19.set MASK, 0x00c0 20 .word MASK # use r6,r7 (in addition to r0-r5) 21 22 movl 4(ap), r5 # m = arg to function 23 clrl r0 # result = 0 24 25 # Assume IP header and RDP header always with in first mbuf. 26 # Assume mbuf chain is at least 1 long 27 28 addl3 M_OFF (r5), r5, r2 # p = mtod(m, cast) 29 addl2 $IPHLEN, r2 # p += sizeof(struct ip) 30 subw3 $IPHLEN, M_LEN (r5), r3 # count = m->m_len - sizeof(struct ip) 31 cvtwl r3, r3 32 33Ldombuf: 34 # Determine the number of longwords in this mbuf. Note that we 35 # are depending on the VAX Architecture that allows access to 36 # non-aligned data. (When we cross MBUF boundries an an earlier 37 # one was not filled with an 'even' number of bytes for longwords). 38 39 ashl $-2, r3, r6 # n_longs = n_bytes >> 2 40 extzv $0, $2, r3, r4 # bytenum = n_bytes & 3 41 42 # Now, can add together as many longwords as possible. We have 43 # unrolled the loop for efficiency, so let's calculate the number 44 # of times through the loop and the partial pass. 45 46 extzv $0, $LGP, r6, r7 # r7 = # adds in partial pass 47 ashl $-LGP, r6, r6 # r6 = # whole passes 48 49 mull2 $ADDLEN, r7 # convert adds to bytes of instruc 50 subl3 r7, $Lhere, r7 51 jmp (r7) # and jump into the loop 52 53 # 54 # There is VAX order, adding order, and network order to consider 55 # 56 # VAX order: 80 1 2 3 is the VAX integer 03020180 since the low 57 # bytes come first when treated as an unsigned character array 58 # on the vax. 59 # 60 # adding order: add so that carries propogate in the same manner that 61 # they would if the machine had its bytes in network order 62 # 80 01 02 03 + 80 01 02 03 = 00020406, since 80 is msb 63 # 00 80 00 00 + 00 80 00 00 = 01000000 64 # This is just essentially getting the bytes into the host's 65 # integer format. adding order should work for the rotate too. 66 # We MUST add the bytes in adding order so that different 67 # machine architectures get the same result. We cannot add 68 # in native mode and f(result) because the propogation of 69 # carries in native cannot be made equivalent to the propogation 70 # of carries in adding order 71 # 72 # network order: The resulting checksum should be transferred in 73 # network order. The VAX result 01020304 would be converted 74 # to 04030201 for communication with remote host. 75 # 76 77Ltop: 78#define SUML \ 79 ;movl (r2)+, r7 /* fetch longword */ \ 80 ;rotl $-8, r7, r1 /* put it in adding order */ \ 81 ;insv r1, $16, $8, r1 \ 82 ;movb -1(r2), r1 \ 83 ;addl2 r1, r0 /* result += ... */ \ 84 ;rotl $1, r0, r0 /* and rotate it per spec */ 85 86 SUML 87 SUML 88 SUML 89 SUML 90Lhere: 91 sobgeq r6, Ltop 92 93 # Now, add in remaining bytes, if any 94 95 tstl r4 96 bneq Leftovers 97 movl (r5), r5 # m = m->m_next 98 bneq Lnextmbuf 99Ldone: 100 # Convert result from adding order to network order 101 102 pushl r0 103 rotl $-8,(sp),r0 104 insv r0,$16,$8,r0 105 movb 3(sp),r0 106 addl2 $4, sp 107 108 ret 109 110Lnextmbuf: 111 addl3 M_OFF (r5), r5, r2 # p = mtod(m, cast) 112 cvtwl M_LEN (r5), r3 # count = m->m_len 113 brw Ldombuf # assume zero length mbufs unusual 114 115 # In adding in the remainder of this mbuf and part of the next one, 116 # we're trying to build up a single 32 bit quantity for adding into 117 # the checksum. 118 # 119 # use fact that: 120 # result += curlong = (a<<24) | (b<<16) | (c<<8) | d 121 # is the same as 122 # result += a<<24; result += b<<16; result += c<<8; result += d 123 124Leftovers: 125 movl $3, r6 126L1: 127 movzbl (r2)+, r1 # r1 = this byte (unsigned char) 128 ashl $3, r6, r7 # r7 = r6 * 8 129 ashl r7, r1, r1 # r1 <<= r7 130 addl2 r1, r0 # result += this byte 131 decl r6 132 sobgtr r4, L1 # get next byte in this mbuf 133 134 # Now, grab bytes from next mbuf 135L2: 136 movl (r5), r5 137 bneq L3 138 rotl $1, r0, r0 # last mbuf had odd byte count 139 brw Ldone 140L3: 141 cvtwl M_LEN (r5), r3 # count = m->m_len 142 beql L2 # if (count == 0) do next mbuf 143 addl3 M_OFF (r5), r5, r2 # p = mtod(m, cast) 144L4: 145 movzbl (r2)+, r1 # r1 = this byte (unsigned char) 146 ashl $3, r6, r7 # r7 = r6 * 8 147 ashl r7, r1, r1 # r1 <<= r7 148 addl2 r1, r0 # result += this byte 149 decl r6 150 bgeq L5 # got last byte in long? 151 rotl $1, r0, r0 152 decl r3 153 brw Ldombuf # and continue checksumming 154L5: 155 sobgtr r3, L4 # grab next byte from this mbuf 156 brb L2 # but go to next if have too 157