|
|
1.1 root 1: /*
2: * Copyright (c) 1985, 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: * @(#)ns_cksum.c 7.1 (Berkeley) 5/8/90
21: */
22:
23: #include "types.h"
24: #include "mbuf.h"
25:
26:
27: /*
28: * Checksum routine for Network Systems Protocol Packets (SUN Version).
29: *
30: * This routine is very heavily used in the network
31: * code and should be modified for each CPU to be as fast as possible.
32: */
33:
34: u_short
35: ns_cksum(m, len)
36: register struct mbuf *m;
37: register int len;
38: {
39: register u_short *w; /* on sun, known to be a4 */
40: register int sum = 0; /* on sun, known to be d6 */
41: register int low = 0; /* on sun, known to be d5 */
42: register int mlen = low; /* want 0, shuts lint up about low */
43: register int zero = mlen; /* handy for fold */
44: register int sumH = mlen; /* handy for fold2 */
45: #undef ADD
46: #define ADD asm("addw a4@+,d6; addxw d3,d6; rolw #1,d6")
47: #define FOLD asm("movw d6,d5; swap d6; addw d6,d5; addxw d3,d5; movl d5,d6");
48: #define ADDH asm("movb a4@+,d5; addl d5,d2; addl d2,d2")
49: #define ADDL asm("movb a4@+,d5; addl d5,d6; addl d6,d6")
50: #define FOLDH asm("movw d2,d5; swap d2; addw d2,d5; addxw d3,d5; movl d5,d2");
51:
52: for (;;) {
53: /*
54: * Each trip around loop adds in
55: * word from one mbuf segment.
56: */
57: w = mtod(m, u_short *);
58: if (mlen == -1) {
59: /*
60: * There is a byte left from the last segment;
61: * ones-complement add it into the checksum.
62: */
63: low = *(u_char *)w;
64: asm("addw d5,d6; addxw d3,d6; rolw #1,d6");
65: w = (u_short *)((char *)w + 1);
66: mlen = m->m_len - 1;
67: len--;
68: } else
69: mlen = m->m_len;
70: m = m->m_next;
71: if (len < mlen)
72: mlen = len;
73: len -= mlen;
74: /*
75: *
76: * We can do a 16 bit ones complement sum using
77: * 32 bit arithmetic registers for adding,
78: * with carries from the low added
79: * into the high (by normal carry-chaining)
80: * so long as we fold back before 16 carries have occured.
81: *
82: */
83: #ifndef OKTOODDWORD
84: if (((int) w & 1)==0) goto easycase;
85: while ((mlen -= 32) >= 0) {
86: ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
87: ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
88: FOLD;
89: FOLDH;
90: ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
91: ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
92: FOLD;
93: FOLDH;
94: }
95: mlen += 32;
96: while ((mlen -= 8) >= 0) {
97: ADDH; ADDL; ADDH; ADDL; ADDH; ADDL; ADDH; ADDL;
98: FOLD;
99: FOLDH;
100: }
101: mlen += 8;
102: while ((mlen -= 2) >= 0) {
103: ADDH; ADDL;
104: }
105: FOLDH;
106: sum = (sumH << 8) + sum;
107: FOLD;
108: sumH = 0;
109: goto commoncase;
110: easycase:
111: #endif
112: /* In this sequence there will be no carries out of
113: * the lower 16 bits.
114: */
115: while ((mlen -= 32) >= 0) {
116: ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
117: ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
118: }
119: mlen += 32;
120: while ((mlen -= 8) >= 0) {
121: ADD; ADD; ADD; ADD;
122: }
123: mlen += 8;
124: while ((mlen -= 2) >= 0) {
125: ADD;
126: }
127: commoncase:
128: if (mlen == -1) {
129: /*sum += *(u_char *)w << 8; FOLD*/
130: low = *(u_char *)w << 8;
131: asm("addw d5,d6; addxw d3,d6");
132: }
133: if (len == 0)
134: break;
135: /*
136: * Locate the next block with some data.
137: * If there is a word split across a boundary we
138: * will wrap to the top with mlen == -1 and
139: * then add it in shifted appropriately.
140: */
141: for (;;) {
142: if (m == 0) {
143: printf("idpcksum: out of data\n");
144: goto done;
145: }
146: if (m->m_len)
147: break;
148: m = m->m_next;
149: }
150: }
151: done:
152: /*
153: * sum has already been kept to low sixteen bits.
154: * just examine result and exit.
155: */
156:
157: if(sum==0xffff) sum = 0;
158: return (sum);
159: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.