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