|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: * ! 17: * @(#)in_cksum.c 7.3 (Berkeley) 6/29/88 ! 18: */ ! 19: ! 20: #include "types.h" ! 21: #include "mbuf.h" ! 22: ! 23: /* ! 24: * Checksum routine for Internet Protocol family headers (VAX Version). ! 25: * ! 26: * This routine is very heavily used in the network ! 27: * code and should be modified for each CPU to be as fast as possible. ! 28: */ ! 29: ! 30: in_cksum(m, len) ! 31: register struct mbuf *m; ! 32: register int len; ! 33: { ! 34: register u_short *w; /* on vax, known to be r9 */ ! 35: register int sum = 0; /* on vax, known to be r8 */ ! 36: register int mlen = 0; ! 37: ! 38: for (;;) { ! 39: /* ! 40: * Each trip around loop adds in ! 41: * word from one mbuf segment. ! 42: */ ! 43: w = mtod(m, u_short *); ! 44: if (mlen == -1) { ! 45: /* ! 46: * There is a byte left from the last segment; ! 47: * add it into the checksum. Don't have to worry ! 48: * about a carry-out here because we make sure ! 49: * that high part of (32 bit) sum is small below. ! 50: */ ! 51: sum += *(u_char *)w << 8; ! 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: * Force to long boundary so we do longword aligned ! 63: * memory operations. It is too hard to do byte ! 64: * adjustment, do only word adjustment. ! 65: */ ! 66: if (((int)w&0x2) && mlen >= 2) { ! 67: sum += *w++; ! 68: mlen -= 2; ! 69: } ! 70: /* ! 71: * Do as much of the checksum as possible 32 bits at at time. ! 72: * In fact, this loop is unrolled to make overhead from ! 73: * branches &c small. ! 74: * ! 75: * We can do a 16 bit ones complement sum 32 bits at a time ! 76: * because the 32 bit register is acting as two 16 bit ! 77: * registers for adding, with carries from the low added ! 78: * into the high (by normal carry-chaining) and carries ! 79: * from the high carried into the low on the next word ! 80: * by use of the adwc instruction. This lets us run ! 81: * this loop at almost memory speed. ! 82: * ! 83: * Here there is the danger of high order carry out, and ! 84: * we carefully use adwc. ! 85: */ ! 86: while ((mlen -= 32) >= 0) { ! 87: #undef ADD ! 88: #ifdef unneeded /* The loop construct clears carry for us... */ ! 89: asm("bicpsr $1"); /* clears carry */ ! 90: #endif ! 91: #define ADD asm("adwc (r9)+,r8;"); ! 92: ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD; ! 93: asm("adwc $0,r8"); ! 94: } ! 95: mlen += 32; ! 96: while ((mlen -= 8) >= 0) { ! 97: #ifdef unneeded /* The loop construct clears carry for us... */ ! 98: asm("bicpsr $1"); /* clears carry */ ! 99: #endif ! 100: ADD; ADD; ! 101: asm("adwc $0,r8"); ! 102: } ! 103: mlen += 8; ! 104: /* ! 105: * Now eliminate the possibility of carry-out's by ! 106: * folding back to a 16 bit number (adding high and ! 107: * low parts together.) Then mop up trailing words ! 108: * and maybe an odd byte. ! 109: */ ! 110: { asm("ashl $-16,r8,r0; addw2 r0,r8"); ! 111: asm("adwc $0,r8; movzwl r8,r8"); } ! 112: while ((mlen -= 2) >= 0) { ! 113: asm("movzwl (r9)+,r0; addl2 r0,r8"); ! 114: } ! 115: if (mlen == -1) { ! 116: sum += *(u_char *)w; ! 117: } ! 118: if (len == 0) ! 119: break; ! 120: /* ! 121: * Locate the next block with some data. ! 122: * If there is a word split across a boundary we ! 123: * will wrap to the top with mlen == -1 and ! 124: * then add it in shifted appropriately. ! 125: */ ! 126: for (;;) { ! 127: if (m == 0) { ! 128: printf("cksum: out of data\n"); ! 129: goto done; ! 130: } ! 131: if (m->m_len) ! 132: break; ! 133: m = m->m_next; ! 134: } ! 135: } ! 136: done: ! 137: /* ! 138: * Add together high and low parts of sum ! 139: * and carry to get cksum. ! 140: * Have to be careful to not drop the last ! 141: * carry here. ! 142: */ ! 143: { asm("ashl $-16,r8,r0; addw2 r0,r8; adwc $0,r8"); ! 144: asm("mcoml r8,r8; movzwl r8,r8"); } ! 145: return (sum); ! 146: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.