1: /*
   2:  * Copyright (c) 1982, 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)in_cksum.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "types.h"
  10: #include "mbuf.h"
  11: #include "../netinet/in.h"
  12: #include "../netinet/in_systm.h"
  13: 
  14: /*
  15:  * Checksum routine for Internet Protocol family headers (VAX Version).
  16:  *
  17:  * This routine is very heavily used in the network
  18:  * code and should be modified for each CPU to be as fast as possible.
  19:  */
  20: 
  21: in_cksum(m, len)
  22:     register struct mbuf *m;
  23:     register int len;
  24: {
  25:     register u_short *w;        /* on vax, known to be r9 */
  26:     register int sum = 0;       /* on vax, known to be r8 */
  27:     register int mlen = 0;
  28: 
  29:     for (;;) {
  30:         /*
  31: 		 * Each trip around loop adds in
  32: 		 * word from one mbuf segment.
  33: 		 */
  34:         w = mtod(m, u_short *);
  35:         if (mlen == -1) {
  36:             /*
  37: 			 * There is a byte left from the last segment;
  38: 			 * add it into the checksum.  Don't have to worry
  39: 			 * about a carry-out here because we make sure
  40: 			 * that high part of (32 bit) sum is small below.
  41: 			 */
  42:             sum += *(u_char *)w << 8;
  43:             w = (u_short *)((char *)w + 1);
  44:             mlen = m->m_len - 1;
  45:             len--;
  46:         } else
  47:             mlen = m->m_len;
  48:         m = m->m_next;
  49:         if (len < mlen)
  50:             mlen = len;
  51:         len -= mlen;
  52:         /*
  53: 		 * Force to long boundary so we do longword aligned
  54: 		 * memory operations.  It is too hard to do byte
  55: 		 * adjustment, do only word adjustment.
  56: 		 */
  57:         if (((int)w&0x2) && mlen >= 2) {
  58:             sum += *w++;
  59:             mlen -= 2;
  60:         }
  61:         /*
  62: 		 * Do as much of the checksum as possible 32 bits at at time.
  63: 		 * In fact, this loop is unrolled to make overhead from
  64: 		 * branches &c small.
  65: 		 *
  66: 		 * We can do a 16 bit ones complement sum 32 bits at a time
  67: 		 * because the 32 bit register is acting as two 16 bit
  68: 		 * registers for adding, with carries from the low added
  69: 		 * into the high (by normal carry-chaining) and carries
  70: 		 * from the high carried into the low on the next word
  71: 		 * by use of the adwc instruction.  This lets us run
  72: 		 * this loop at almost memory speed.
  73: 		 *
  74: 		 * Here there is the danger of high order carry out, and
  75: 		 * we carefully use adwc.
  76: 		 */
  77:         while ((mlen -= 32) >= 0) {
  78: #undef ADD
  79: #ifdef unneeded      /* The loop construct clears carry for us... */
  80:             asm("bicpsr $1");       /* clears carry */
  81: #endif
  82: #define ADD     asm("adwc (r9)+,r8;");
  83:             ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
  84:             asm("adwc $0,r8");
  85:         }
  86:         mlen += 32;
  87:         while ((mlen -= 8) >= 0) {
  88: #ifdef unneeded      /* The loop construct clears carry for us... */
  89:             asm("bicpsr $1");       /* clears carry */
  90: #endif
  91:             ADD; ADD;
  92:             asm("adwc $0,r8");
  93:         }
  94:         mlen += 8;
  95:         /*
  96: 		 * Now eliminate the possibility of carry-out's by
  97: 		 * folding back to a 16 bit number (adding high and
  98: 		 * low parts together.)  Then mop up trailing words
  99: 		 * and maybe an odd byte.
 100: 		 */
 101:         { asm("ashl $-16,r8,r0; addw2 r0,r8");
 102:           asm("adwc $0,r8; movzwl r8,r8"); }
 103:         while ((mlen -= 2) >= 0) {
 104:             asm("movzwl (r9)+,r0; addl2 r0,r8");
 105:         }
 106:         if (mlen == -1) {
 107:             sum += *(u_char *)w;
 108:         }
 109:         if (len == 0)
 110:             break;
 111:         /*
 112: 		 * Locate the next block with some data.
 113: 		 * If there is a word split across a boundary we
 114: 		 * will wrap to the top with mlen == -1 and
 115: 		 * then add it in shifted appropriately.
 116: 		 */
 117:         for (;;) {
 118:             if (m == 0) {
 119:                 printf("cksum: out of data\n");
 120:                 goto done;
 121:             }
 122:             if (m->m_len)
 123:                 break;
 124:             m = m->m_next;
 125:         }
 126:     }
 127: done:
 128:     /*
 129: 	 * Add together high and low parts of sum
 130: 	 * and carry to get cksum.
 131: 	 * Have to be careful to not drop the last
 132: 	 * carry here.
 133: 	 */
 134:     { asm("ashl $-16,r8,r0; addw2 r0,r8; adwc $0,r8");
 135:       asm("mcoml r8,r8; movzwl r8,r8"); }
 136:     return (sum);
 137: }

Defined functions

Defined macros

ADD defined in line 82; used 11 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 832
Valid CSS Valid XHTML 1.0 Strict