|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.