1 /* 2 * Copyright (c) 1985, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)ns_cksum.c 7.3 (Berkeley) 06/27/91 8 */ 9 10 #include "param.h" 11 #include "mbuf.h" 12 13 14 /* 15 * Checksum routine for Network Systems Protocol Packets (SUN 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 u_short 22 ns_cksum(m, len) 23 register struct mbuf *m; 24 register int len; 25 { 26 register u_short *w; /* on sun, known to be a4 */ 27 register int sum = 0; /* on sun, known to be d6 */ 28 register int low = 0; /* on sun, known to be d5 */ 29 register int mlen = low; /* want 0, shuts lint up about low */ 30 register int zero = mlen; /* handy for fold */ 31 register int sumH = mlen; /* handy for fold2 */ 32 #undef ADD 33 #define ADD asm("addw a4@+,d6; addxw d3,d6; rolw #1,d6") 34 #define FOLD asm("movw d6,d5; swap d6; addw d6,d5; addxw d3,d5; movl d5,d6"); 35 #define ADDH asm("movb a4@+,d5; addl d5,d2; addl d2,d2") 36 #define ADDL asm("movb a4@+,d5; addl d5,d6; addl d6,d6") 37 #define FOLDH asm("movw d2,d5; swap d2; addw d2,d5; addxw d3,d5; movl d5,d2"); 38 39 for (;;) { 40 /* 41 * Each trip around loop adds in 42 * word from one mbuf segment. 43 */ 44 w = mtod(m, u_short *); 45 if (mlen == -1) { 46 /* 47 * There is a byte left from the last segment; 48 * ones-complement add it into the checksum. 49 */ 50 low = *(u_char *)w; 51 asm("addw d5,d6; addxw d3,d6; rolw #1,d6"); 52 w = (u_short *)((char *)w + 1); 53 mlen = m->m_len - 1; 54 len--; 55 } else 56 mlen = m->m_len; 57 m = m->m_next; 58 if (len < mlen) 59 mlen = len; 60 len -= mlen; 61 /* 62 * 63 * We can do a 16 bit ones complement sum using 64 * 32 bit arithmetic registers for adding, 65 * with carries from the low added 66 * into the high (by normal carry-chaining) 67 * so long as we fold back before 16 carries have occured. 68 * 69 */ 70 #ifndef OKTOODDWORD 71 if (((int) w & 1)==0) goto easycase; 72 while ((mlen -= 32) >= 0) { 73 ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; 74 ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; 75 FOLD; 76 FOLDH; 77 ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; 78 ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; 79 FOLD; 80 FOLDH; 81 } 82 mlen += 32; 83 while ((mlen -= 8) >= 0) { 84 ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; 85 FOLD; 86 FOLDH; 87 } 88 mlen += 8; 89 while ((mlen -= 2) >= 0) { 90 ADDH; ADDL; 91 } 92 FOLDH; 93 sum = (sumH << 8) + sum; 94 FOLD; 95 sumH = 0; 96 goto commoncase; 97 easycase: 98 #endif 99 /* In this sequence there will be no carries out of 100 * the lower 16 bits. 101 */ 102 while ((mlen -= 32) >= 0) { 103 ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD; 104 ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD; 105 } 106 mlen += 32; 107 while ((mlen -= 8) >= 0) { 108 ADD; ADD; ADD; ADD; 109 } 110 mlen += 8; 111 while ((mlen -= 2) >= 0) { 112 ADD; 113 } 114 commoncase: 115 if (mlen == -1) { 116 /*sum += *(u_char *)w << 8; FOLD*/ 117 low = *(u_char *)w << 8; 118 asm("addw d5,d6; addxw d3,d6"); 119 } 120 if (len == 0) 121 break; 122 /* 123 * Locate the next block with some data. 124 * If there is a word split across a boundary we 125 * will wrap to the top with mlen == -1 and 126 * then add it in shifted appropriately. 127 */ 128 for (;;) { 129 if (m == 0) { 130 printf("idpcksum: out of data\n"); 131 goto done; 132 } 133 if (m->m_len) 134 break; 135 m = m->m_next; 136 } 137 } 138 done: 139 /* 140 * sum has already been kept to low sixteen bits. 141 * just examine result and exit. 142 */ 143 144 if(sum==0xffff) sum = 0; 145 return (sum); 146 } 147