|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985, 1986 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution is only permitted until one year after the first shipment ! 6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 7: * binary forms are permitted provided that: (1) source distributions retain ! 8: * this entire copyright notice and comment, and (2) distributions including ! 9: * binaries display the following acknowledgement: This product includes ! 10: * software developed by the University of California, Berkeley and its ! 11: * contributors'' in the documentation or other materials provided with the ! 12: * distribution and in all advertising materials mentioning features or use ! 13: * of this software. Neither the name of the University nor the names of ! 14: * its contributors may be used to endorse or promote products derived from ! 15: * this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)ns_cksum.c 7.1 (Berkeley) 5/8/90 ! 21: */ ! 22: ! 23: #include "types.h" ! 24: #include "mbuf.h" ! 25: ! 26: ! 27: /* ! 28: * Checksum routine for Network Systems Protocol Packets (SUN Version). ! 29: * ! 30: * This routine is very heavily used in the network ! 31: * code and should be modified for each CPU to be as fast as possible. ! 32: */ ! 33: ! 34: u_short ! 35: ns_cksum(m, len) ! 36: register struct mbuf *m; ! 37: register int len; ! 38: { ! 39: register u_short *w; /* on sun, known to be a4 */ ! 40: register int sum = 0; /* on sun, known to be d6 */ ! 41: register int low = 0; /* on sun, known to be d5 */ ! 42: register int mlen = low; /* want 0, shuts lint up about low */ ! 43: register int zero = mlen; /* handy for fold */ ! 44: register int sumH = mlen; /* handy for fold2 */ ! 45: #undef ADD ! 46: #define ADD asm("addw a4@+,d6; addxw d3,d6; rolw #1,d6") ! 47: #define FOLD asm("movw d6,d5; swap d6; addw d6,d5; addxw d3,d5; movl d5,d6"); ! 48: #define ADDH asm("movb a4@+,d5; addl d5,d2; addl d2,d2") ! 49: #define ADDL asm("movb a4@+,d5; addl d5,d6; addl d6,d6") ! 50: #define FOLDH asm("movw d2,d5; swap d2; addw d2,d5; addxw d3,d5; movl d5,d2"); ! 51: ! 52: for (;;) { ! 53: /* ! 54: * Each trip around loop adds in ! 55: * word from one mbuf segment. ! 56: */ ! 57: w = mtod(m, u_short *); ! 58: if (mlen == -1) { ! 59: /* ! 60: * There is a byte left from the last segment; ! 61: * ones-complement add it into the checksum. ! 62: */ ! 63: low = *(u_char *)w; ! 64: asm("addw d5,d6; addxw d3,d6; rolw #1,d6"); ! 65: w = (u_short *)((char *)w + 1); ! 66: mlen = m->m_len - 1; ! 67: len--; ! 68: } else ! 69: mlen = m->m_len; ! 70: m = m->m_next; ! 71: if (len < mlen) ! 72: mlen = len; ! 73: len -= mlen; ! 74: /* ! 75: * ! 76: * We can do a 16 bit ones complement sum using ! 77: * 32 bit arithmetic registers for adding, ! 78: * with carries from the low added ! 79: * into the high (by normal carry-chaining) ! 80: * so long as we fold back before 16 carries have occured. ! 81: * ! 82: */ ! 83: #ifndef OKTOODDWORD ! 84: if (((int) w & 1)==0) goto easycase; ! 85: while ((mlen -= 32) >= 0) { ! 86: ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ! 87: ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ! 88: FOLD; ! 89: FOLDH; ! 90: ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ! 91: ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ! 92: FOLD; ! 93: FOLDH; ! 94: } ! 95: mlen += 32; ! 96: while ((mlen -= 8) >= 0) { ! 97: ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ! 98: FOLD; ! 99: FOLDH; ! 100: } ! 101: mlen += 8; ! 102: while ((mlen -= 2) >= 0) { ! 103: ADDH; ADDL; ! 104: } ! 105: FOLDH; ! 106: sum = (sumH << 8) + sum; ! 107: FOLD; ! 108: sumH = 0; ! 109: goto commoncase; ! 110: easycase: ! 111: #endif ! 112: /* In this sequence there will be no carries out of ! 113: * the lower 16 bits. ! 114: */ ! 115: while ((mlen -= 32) >= 0) { ! 116: ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD; ! 117: ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD; ! 118: } ! 119: mlen += 32; ! 120: while ((mlen -= 8) >= 0) { ! 121: ADD; ADD; ADD; ADD; ! 122: } ! 123: mlen += 8; ! 124: while ((mlen -= 2) >= 0) { ! 125: ADD; ! 126: } ! 127: commoncase: ! 128: if (mlen == -1) { ! 129: /*sum += *(u_char *)w << 8; FOLD*/ ! 130: low = *(u_char *)w << 8; ! 131: asm("addw d5,d6; addxw d3,d6"); ! 132: } ! 133: if (len == 0) ! 134: break; ! 135: /* ! 136: * Locate the next block with some data. ! 137: * If there is a word split across a boundary we ! 138: * will wrap to the top with mlen == -1 and ! 139: * then add it in shifted appropriately. ! 140: */ ! 141: for (;;) { ! 142: if (m == 0) { ! 143: printf("idpcksum: out of data\n"); ! 144: goto done; ! 145: } ! 146: if (m->m_len) ! 147: break; ! 148: m = m->m_next; ! 149: } ! 150: } ! 151: done: ! 152: /* ! 153: * sum has already been kept to low sixteen bits. ! 154: * just examine result and exit. ! 155: */ ! 156: ! 157: if(sum==0xffff) sum = 0; ! 158: return (sum); ! 159: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.