localize header files
[unix-history] / usr / src / sys / vax / vax / in_cksum.c
CommitLineData
fcfe450e 1/* in_cksum.c 1.13 82/10/09 */
51041fae
BJ
2
3#include <sys/types.h>
dad64fdf 4#include "../h/mbuf.h"
fcfe450e
BJ
5#include "../netinet/in.h"
6#include "../netinet/in_systm.h"
51041fae
BJ
7
8/*
2b4b57cd
BJ
9 * Checksum routine for Internet Protocol family headers.
10 * This routine is very heavily used in the network
11 * code and should be rewritten for each CPU to be as fast as possible.
51041fae 12 */
51041fae 13
2b4b57cd 14#if vax
8a13b737 15in_cksum(m, len)
51041fae
BJ
16 register struct mbuf *m;
17 register int len;
18{
2b4b57cd 19 register u_short *w; /* known to be r9 */
51041fae
BJ
20 register int sum = 0; /* known to be r8 */
21 register int mlen = 0;
51041fae
BJ
22
23 for (;;) {
2b4b57cd
BJ
24 /*
25 * Each trip around loop adds in
26 * word from one mbuf segment.
27 */
28 w = mtod(m, u_short *);
51041fae 29 if (mlen == -1) {
2b4b57cd
BJ
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 */
51041fae 36 sum += *(u_char *)w << 8;
e6dd2097 37 w = (u_short *)((char *)w + 1);
51041fae
BJ
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;
2b4b57cd
BJ
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 */
51041fae 71 while ((mlen -= 32) >= 0) {
4d0a6cbd
BJ
72 asm("clrl r0"); /* clears carry */
73#undef ADD
74#define ADD asm("adwc (r9)+,r8;");
51041fae 75 ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
4d0a6cbd 76 asm("adwc $0,r8");
51041fae
BJ
77 }
78 mlen += 32;
79 while ((mlen -= 8) >= 0) {
4d0a6cbd
BJ
80 asm("clrl r0");
81 ADD; ADD;
82 asm("adwc $0,r8");
51041fae
BJ
83 }
84 mlen += 8;
2b4b57cd
BJ
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"); }
51041fae 93 while ((mlen -= 2) >= 0) {
2b4b57cd 94 asm("movzwl (r9)+,r0; addl2 r0,r8");
51041fae
BJ
95 }
96 if (mlen == -1)
97 sum += *(u_char *)w;
98 if (len == 0)
99 break;
2b4b57cd
BJ
100 /*
101 * Locate the next block with some data.
102 * If there is a word split across a boundary we
103 * will wrap to the top with mlen == -1 and
104 * then add it in shifted appropriately.
105 */
51041fae 106 for (;;) {
f248b7ed 107 if (m == 0) {
e6dd2097 108 printf("cksum: out of data\n");
f248b7ed
BJ
109 goto done;
110 }
51041fae
BJ
111 if (m->m_len)
112 break;
113 m = m->m_next;
114 }
115 }
f248b7ed 116done:
2b4b57cd
BJ
117 /*
118 * Add together high and low parts of sum
119 * and carry to get cksum.
120 * Have to be careful to not drop the last
121 * carry here.
122 */
e6dd2097
BJ
123 { asm("ashl $-16,r8,r0; addw2 r0,r8; adwc $0,r8");
124 asm("mcoml r8,r8; movzwl r8,r8"); }
125 return (sum);
51041fae 126}
2b4b57cd 127#endif