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