xref: /original-bsd/sys/hp300/hp300/ns_cksum.c (revision d11ff5ba)
1 /*
2  * Copyright (c) 1985, 1986 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)ns_cksum.c	7.2 (Berkeley) 12/16/90
8  */
9 
10 #include "sys/types.h"
11 #include "sys/mbuf.h"
12 
13 
14 /*
15  * Checksum routine for Network Systems Protocol Packets (SUN 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 u_short
22 ns_cksum(m, len)
23 	register struct mbuf *m;
24 	register int len;
25 {
26 	register u_short *w;		/* on sun, known to be a4 */
27 	register int sum = 0;		/* on sun, known to be d6 */
28 	register int low = 0;		/* on sun, known to be d5 */
29 	register int mlen = low;	/* want 0, shuts lint up about low */
30 	register int zero = mlen;	/* handy for fold */
31 	register int sumH = mlen;	/* handy for fold2 */
32 #undef ADD
33 #define ADD asm("addw a4@+,d6; addxw d3,d6; rolw #1,d6")
34 #define FOLD asm("movw d6,d5; swap d6; addw d6,d5; addxw d3,d5;  movl d5,d6");
35 #define ADDH asm("movb a4@+,d5; addl d5,d2; addl d2,d2")
36 #define ADDL asm("movb a4@+,d5; addl d5,d6; addl d6,d6")
37 #define FOLDH asm("movw d2,d5; swap d2; addw d2,d5; addxw d3,d5; movl d5,d2");
38 
39 	for (;;) {
40 		/*
41 		 * Each trip around loop adds in
42 		 * word from one mbuf segment.
43 		 */
44 		w = mtod(m, u_short *);
45 		if (mlen == -1) {
46 			/*
47 			 * There is a byte left from the last segment;
48 			 * ones-complement add it into the checksum.
49 			 */
50 			low = *(u_char *)w;
51 			asm("addw d5,d6; addxw d3,d6; rolw #1,d6");
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 		 *
63 		 * We can do a 16 bit ones complement sum using
64 		 * 32 bit arithmetic registers for adding,
65 		 * with carries from the low added
66 		 * into the high (by normal carry-chaining)
67 		 * so long as we fold back before 16 carries have occured.
68 		 *
69 		 */
70 #ifndef OKTOODDWORD
71 		if (((int) w & 1)==0) goto easycase;
72 		while ((mlen -= 32) >= 0) {
73 			ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
74 			ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
75 			FOLD;
76 			FOLDH;
77 			ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
78 			ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
79 			FOLD;
80 			FOLDH;
81 		}
82 		mlen += 32;
83 		while ((mlen -= 8) >= 0) {
84 			ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
85 			FOLD;
86 			FOLDH;
87 		}
88 		mlen += 8;
89 		while ((mlen -= 2) >= 0) {
90 			ADDH; ADDL;
91 		}
92 		FOLDH;
93 		sum = (sumH << 8) + sum;
94 		FOLD;
95 		sumH = 0;
96 		goto commoncase;
97 easycase:
98 #endif
99 		/* In this sequence there will be no carries out of
100 		 * the lower 16 bits.
101 		 */
102 		while ((mlen -= 32) >= 0) {
103 			ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
104 			ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
105 		}
106 		mlen += 32;
107 		while ((mlen -= 8) >= 0) {
108 			ADD; ADD; ADD; ADD;
109 		}
110 		mlen += 8;
111 		while ((mlen -= 2) >= 0) {
112 			ADD;
113 		}
114 commoncase:
115 		if (mlen == -1) {
116 			/*sum += *(u_char *)w << 8; FOLD*/
117 			low = *(u_char *)w << 8;
118 			asm("addw d5,d6; addxw d3,d6");
119 		}
120 		if (len == 0)
121 			break;
122 		/*
123 		 * Locate the next block with some data.
124 		 * If there is a word split across a boundary we
125 		 * will wrap to the top with mlen == -1 and
126 		 * then add it in shifted appropriately.
127 		 */
128 		for (;;) {
129 			if (m == 0) {
130 				printf("idpcksum: out of data\n");
131 				goto done;
132 			}
133 			if (m->m_len)
134 				break;
135 			m = m->m_next;
136 		}
137 	}
138 done:
139 	/*
140 	 * sum has already been kept to low sixteen bits.
141 	 * just examine result and exit.
142 	 */
143 
144 	if(sum==0xffff) sum = 0;
145 	return (sum);
146 }
147