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: }
Defined functions
Defined macros
ADD
defined in line
82; used 11 times