|
|
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.