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