|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)in_cksum.c 7.5 (Berkeley) 6/28/90
21: */
22:
23: #include "param.h"
24: #include "mbuf.h"
25:
26: /*
27: * Checksum routine for Internet Protocol family headers (VAX Version).
28: *
29: * This routine is very heavily used in the network
30: * code and should be modified for each CPU to be as fast as possible.
31: */
32:
33: in_cksum(m, len)
34: register struct mbuf *m;
35: register int len;
36: {
37: register u_short *w; /* on vax, known to be r9 */
38: register int sum = 0; /* on vax, known to be r8 */
39: register int mlen = 0;
40:
41: for (;;) {
42: /*
43: * Each trip around loop adds in
44: * word from one mbuf segment.
45: */
46: w = mtod(m, u_short *);
47: if (mlen == -1) {
48: /*
49: * There is a byte left from the last segment;
50: * add it into the checksum. Don't have to worry
51: * about a carry-out here because we make sure
52: * that high part of (32 bit) sum is small below.
53: */
54: sum += *(u_char *)w << 8;
55: w = (u_short *)((char *)w + 1);
56: mlen = m->m_len - 1;
57: len--;
58: } else
59: mlen = m->m_len;
60: m = m->m_next;
61: if (len < mlen)
62: mlen = len;
63: len -= mlen;
64: /*
65: * Force to long boundary so we do longword aligned
66: * memory operations. It is too hard to do byte
67: * adjustment, do only word adjustment.
68: */
69: if (((int)w&0x2) && mlen >= 2) {
70: sum += *w++;
71: mlen -= 2;
72: }
73: /*
74: * Do as much of the checksum as possible 32 bits at at time.
75: * In fact, this loop is unrolled to make overhead from
76: * branches &c small.
77: *
78: * We can do a 16 bit ones complement sum 32 bits at a time
79: * because the 32 bit register is acting as two 16 bit
80: * registers for adding, with carries from the low added
81: * into the high (by normal carry-chaining) and carries
82: * from the high carried into the low on the next word
83: * by use of the adwc instruction. This lets us run
84: * this loop at almost memory speed.
85: *
86: * Here there is the danger of high order carry out, and
87: * we carefully use adwc.
88: */
89: while ((mlen -= 32) >= 0) {
90: #undef ADD
91: #ifdef unneeded /* The loop construct clears carry for us... */
92: asm("bicpsr $1"); /* clears carry */
93: #endif
94: #define ADD asm("adwc (r9)+,r8;");
95: ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
96: asm("adwc $0,r8");
97: }
98: mlen += 32;
99: while ((mlen -= 8) >= 0) {
100: #ifdef unneeded /* The loop construct clears carry for us... */
101: asm("bicpsr $1"); /* clears carry */
102: #endif
103: ADD; ADD;
104: asm("adwc $0,r8");
105: }
106: mlen += 8;
107: /*
108: * Now eliminate the possibility of carry-out's by
109: * folding back to a 16 bit number (adding high and
110: * low parts together.) Then mop up trailing words
111: * and maybe an odd byte.
112: */
113: { asm("ashl $-16,r8,r0; addw2 r0,r8");
114: asm("adwc $0,r8; movzwl r8,r8"); }
115: while ((mlen -= 2) >= 0) {
116: asm("movzwl (r9)+,r0; addl2 r0,r8");
117: }
118: if (mlen == -1) {
119: sum += *(u_char *)w;
120: }
121: if (len == 0)
122: break;
123: /*
124: * Locate the next block with some data.
125: * If there is a word split across a boundary we
126: * will wrap to the top with mlen == -1 and
127: * then add it in shifted appropriately.
128: */
129: for (;;) {
130: if (m == 0) {
131: printf("cksum: out of data\n");
132: goto done;
133: }
134: if (m->m_len)
135: break;
136: m = m->m_next;
137: }
138: }
139: done:
140: /*
141: * Add together high and low parts of sum
142: * and carry to get cksum.
143: * Have to be careful to not drop the last
144: * carry here.
145: */
146: { asm("ashl $-16,r8,r0; addw2 r0,r8; adwc $0,r8");
147: asm("mcoml r8,r8; movzwl r8,r8"); }
148: return (sum);
149: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.