update copyrights, rm unnecessary inet includes
[unix-history] / usr / src / sys / vax / vax / in_cksum.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
5f7901a4 3 * All rights reserved.
da7c5cc6 4 *
5f7901a4
MK
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of California at Berkeley. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
11 *
12 * @(#)in_cksum.c 7.2 (Berkeley) %G%
da7c5cc6 13 */
51041fae 14
1884f3f6
JB
15#include "types.h"
16#include "mbuf.h"
51041fae
BJ
17
18/*
e1cdb8f4
SL
19 * Checksum routine for Internet Protocol family headers (VAX Version).
20 *
2b4b57cd 21 * This routine is very heavily used in the network
9a480eec 22 * code and should be modified for each CPU to be as fast as possible.
51041fae 23 */
51041fae 24
8a13b737 25in_cksum(m, len)
51041fae
BJ
26 register struct mbuf *m;
27 register int len;
28{
9a480eec
BJ
29 register u_short *w; /* on vax, known to be r9 */
30 register int sum = 0; /* on vax, known to be r8 */
51041fae 31 register int mlen = 0;
51041fae
BJ
32
33 for (;;) {
2b4b57cd
BJ
34 /*
35 * Each trip around loop adds in
36 * word from one mbuf segment.
37 */
38 w = mtod(m, u_short *);
51041fae 39 if (mlen == -1) {
2b4b57cd
BJ
40 /*
41 * There is a byte left from the last segment;
42 * add it into the checksum. Don't have to worry
43 * about a carry-out here because we make sure
44 * that high part of (32 bit) sum is small below.
45 */
51041fae 46 sum += *(u_char *)w << 8;
e6dd2097 47 w = (u_short *)((char *)w + 1);
51041fae
BJ
48 mlen = m->m_len - 1;
49 len--;
50 } else
51 mlen = m->m_len;
52 m = m->m_next;
53 if (len < mlen)
54 mlen = len;
55 len -= mlen;
2b4b57cd
BJ
56 /*
57 * Force to long boundary so we do longword aligned
58 * memory operations. It is too hard to do byte
59 * adjustment, do only word adjustment.
60 */
61 if (((int)w&0x2) && mlen >= 2) {
62 sum += *w++;
63 mlen -= 2;
64 }
65 /*
66 * Do as much of the checksum as possible 32 bits at at time.
67 * In fact, this loop is unrolled to make overhead from
68 * branches &c small.
69 *
70 * We can do a 16 bit ones complement sum 32 bits at a time
71 * because the 32 bit register is acting as two 16 bit
72 * registers for adding, with carries from the low added
73 * into the high (by normal carry-chaining) and carries
74 * from the high carried into the low on the next word
75 * by use of the adwc instruction. This lets us run
76 * this loop at almost memory speed.
77 *
78 * Here there is the danger of high order carry out, and
79 * we carefully use adwc.
80 */
51041fae 81 while ((mlen -= 32) >= 0) {
4d0a6cbd 82#undef ADD
1fd3f510
MK
83#ifdef unneeded /* The loop construct clears carry for us... */
84 asm("bicpsr $1"); /* clears carry */
85#endif
4d0a6cbd 86#define ADD asm("adwc (r9)+,r8;");
51041fae 87 ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
4d0a6cbd 88 asm("adwc $0,r8");
51041fae
BJ
89 }
90 mlen += 32;
91 while ((mlen -= 8) >= 0) {
1fd3f510
MK
92#ifdef unneeded /* The loop construct clears carry for us... */
93 asm("bicpsr $1"); /* clears carry */
94#endif
4d0a6cbd
BJ
95 ADD; ADD;
96 asm("adwc $0,r8");
51041fae
BJ
97 }
98 mlen += 8;
2b4b57cd
BJ
99 /*
100 * Now eliminate the possibility of carry-out's by
101 * folding back to a 16 bit number (adding high and
102 * low parts together.) Then mop up trailing words
103 * and maybe an odd byte.
104 */
105 { asm("ashl $-16,r8,r0; addw2 r0,r8");
106 asm("adwc $0,r8; movzwl r8,r8"); }
51041fae 107 while ((mlen -= 2) >= 0) {
2b4b57cd 108 asm("movzwl (r9)+,r0; addl2 r0,r8");
51041fae 109 }
9a480eec 110 if (mlen == -1) {
51041fae 111 sum += *(u_char *)w;
9a480eec 112 }
51041fae
BJ
113 if (len == 0)
114 break;
2b4b57cd
BJ
115 /*
116 * Locate the next block with some data.
117 * If there is a word split across a boundary we
118 * will wrap to the top with mlen == -1 and
119 * then add it in shifted appropriately.
120 */
51041fae 121 for (;;) {
f248b7ed 122 if (m == 0) {
e6dd2097 123 printf("cksum: out of data\n");
f248b7ed
BJ
124 goto done;
125 }
51041fae
BJ
126 if (m->m_len)
127 break;
128 m = m->m_next;
129 }
130 }
f248b7ed 131done:
2b4b57cd
BJ
132 /*
133 * Add together high and low parts of sum
134 * and carry to get cksum.
135 * Have to be careful to not drop the last
136 * carry here.
137 */
e6dd2097
BJ
138 { asm("ashl $-16,r8,r0; addw2 r0,r8; adwc $0,r8");
139 asm("mcoml r8,r8; movzwl r8,r8"); }
140 return (sum);
51041fae 141}