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