source: rtems/c/src/libnetworking/netinet/in_cksum_m68k.c @ 23cdd84c

4.104.114.84.95
Last change on this file since 23cdd84c was 23cdd84c, checked in by Joel Sherrill <joel.sherrill@…>, on 09/10/98 at 12:43:00

Patch from David Fiddes <D.J.Fiddes@…> to make this compile
for the ColdFire?.

  • Property mode set to 100644
File size: 9.0 KB
Line 
1/*
2 * Copyright (c) 1988, 1992, 1993
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the University of
16 *      California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 *      @(#)in_cksum.c  8.1 (Berkeley) 6/10/93
34 * $Id$
35 */
36
37#include <sys/param.h>
38#include <sys/mbuf.h>
39
40#if (defined(__GNUC__) && (defined(__mc68000__) || defined(__m68k__)) && (!__mcf5200__))
41
42#define REDUCE { sum = (sum & 0xFFFF) + (sum >> 16); if (sum > 0xFFFF) sum -= 0xFFFF; }
43
44/*
45 * Motorola 68k version of Internet Protocol Checksum routine
46 * W. Eric Norum
47 * Saskatchewan Accelerator Laboratory
48 * August, 1998
49 */
50int
51in_cksum(m, len)
52        struct mbuf *m;
53        int len;
54{
55        unsigned short *w;
56        unsigned long sum = 0;
57        int mlen = 0;
58        int byte_swapped = 0;
59        union {
60                char    c[2];
61                u_short s;
62        } s_util;
63
64        for ( ; m && len ; m = m->m_next) {
65                if (m->m_len == 0)
66                        continue;
67                w = mtod(m, u_short *);
68                if (mlen == -1) {
69                        /*
70                         * The first byte of this mbuf is the continuation
71                         * of a word spanning between this mbuf and the
72                         * last mbuf.
73                         *
74                         * s_util.c[0] is already saved when scanning previous
75                         * mbuf.
76                         */
77                        s_util.c[1] = *(char *)w;
78                        sum += s_util.s;
79                        w = (u_short *)((char *)w + 1);
80                        mlen = m->m_len - 1;
81                        len--;
82                } else
83                        mlen = m->m_len;
84                if (len < mlen)
85                        mlen = len;
86                len -= mlen;
87
88                /*
89                 * Force to longword boundary.
90                 */
91                if (3 & (int)w) {
92                        REDUCE;
93                        if ((1 & (int) w) && (mlen > 0)) {
94                                sum <<= 8;
95                                s_util.c[0] = *(u_char *)w;
96                                w = (u_short *)((char *)w + 1);
97                                mlen--;
98                                byte_swapped = 1;
99                        }
100                        if ((2 & (int) w) && (mlen >= 2)) {
101                                sum += *w++;
102                                mlen -= 2;
103                        }
104                }
105
106                /*
107                 * Sum all the longwords in the buffer.
108                 * See RFC 1071 -- Computing the Internet Checksum.
109                 * It should work for all 68k family members.
110                 */
111                {
112                unsigned long tcnt = mlen, t1;
113                __asm__ volatile (
114                "movel   %2,%3\n\t"
115                "lsrl    #6,%2       | count/64 = # loop traversals\n\t"
116                "andl    #0x3c,%3    | Then find fractions of a chunk\n\t"
117                "negl    %3\n\t      | Each long uses 4 instruction bytes\n\t"
118                "andi    #0xf,%%cc   | Clear X (extended carry flag)\n\t"
119                "jmp     %%pc@(lcsum2_lbl-.-2:b,%3)  | Jump into loop\n"
120                "lcsum1_lbl:     | Begin inner loop...\n\t"
121                "movel   %1@+,%3     |  0: Fetch 32-bit word\n\t"
122                "addxl   %3,%0       |    Add word + previous carry\n\t"
123                "movel   %1@+,%3     |  1: Fetch 32-bit word\n\t"
124                "addxl   %3,%0       |    Add word + previous carry\n\t"
125                "movel   %1@+,%3     |  2: Fetch 32-bit word\n\t"
126                "addxl   %3,%0       |    Add word + previous carry\n\t"
127                "movel   %1@+,%3     |  3: Fetch 32-bit word\n\t"
128                "addxl   %3,%0       |    Add word + previous carry\n\t"
129                "movel   %1@+,%3     |  4: Fetch 32-bit word\n\t"
130                "addxl   %3,%0       |    Add word + previous carry\n\t"
131                "movel   %1@+,%3     |  5: Fetch 32-bit word\n\t"
132                "addxl   %3,%0       |    Add word + previous carry\n\t"
133                "movel   %1@+,%3     |  6: Fetch 32-bit word\n\t"
134                "addxl   %3,%0       |    Add word + previous carry\n\t"
135                "movel   %1@+,%3     |  7: Fetch 32-bit word\n\t"
136                "addxl   %3,%0       |    Add word + previous carry\n\t"
137                "movel   %1@+,%3     |  8: Fetch 32-bit word\n\t"
138                "addxl   %3,%0       |    Add word + previous carry\n\t"
139                "movel   %1@+,%3     |  9: Fetch 32-bit word\n\t"
140                "addxl   %3,%0       |    Add word + previous carry\n\t"
141                "movel   %1@+,%3     |  A: Fetch 32-bit word\n\t"
142                "addxl   %3,%0       |    Add word + previous carry\n\t"
143                "movel   %1@+,%3     |  B: Fetch 32-bit word\n\t"
144                "addxl   %3,%0       |    Add word + previous carry\n\t"
145                "movel   %1@+,%3     |  C: Fetch 32-bit word\n\t"
146                "addxl   %3,%0       |    Add word + previous carry\n\t"
147                "movel   %1@+,%3     |  D: Fetch 32-bit word\n\t"
148                "addxl   %3,%0       |    Add word + previous carry\n\t"
149                "movel   %1@+,%3     |  E: Fetch 32-bit word\n\t"
150                "addxl   %3,%0       |    Add word + previous carry\n\t"
151                "movel   %1@+,%3     |  F: Fetch 32-bit word\n\t"
152                "addxl   %3,%0       |    Add word + previous carry\n"
153                "lcsum2_lbl:\n\tdbf    %2,lcsum1_lbl   | (NB- dbra doesn't affect X)\n\t"
154                "movel    %0,%3         | Fold 32 bit sum to 16 bits\n\t"
155                "swap    %3             | (NB- swap doesn't affect X)\n\t"
156                "addxw   %3,%0          |\n\t"
157                "moveq   #0,%3          | Add in last carry\n\t"
158                "addxw   %3,%0          |\n\t"
159                "andl    #0xffff,%0     | Mask to 16-bit sum\n" :
160                        "=d" (sum), "=a" (w), "=d" (tcnt) , "=d" (t1) :
161                        "0" (sum), "1" (w), "2" (tcnt) :
162                        "cc", "memory");
163                }
164                mlen &= 3;
165
166                /*
167                 * Soak up the last 1, 2 or 3 bytes
168                 */
169                while ((mlen -= 2) >= 0)
170                        sum += *w++;
171                if (byte_swapped) {
172                        REDUCE;
173                        sum <<= 8;
174                        byte_swapped = 0;
175                        if (mlen == -1) {
176                                s_util.c[1] = *(char *)w;
177                                sum += s_util.s;
178                                mlen = 0;
179                        } else
180                                mlen = -1;
181                } else if (mlen == -1)
182                        s_util.c[0] = *(char *)w;
183        }
184        if (len)
185                sum = 0xDEAD;
186        if (mlen == -1) {
187                /* The last mbuf has odd # of bytes. Follow the
188                   standard (the odd byte may be shifted left by 8 bits
189                   or not as determined by endian-ness of the machine) */
190                s_util.c[1] = 0;
191                sum += s_util.s;
192        }
193        REDUCE;
194        return (~sum & 0xffff);
195}
196
197
198#else
199/*
200 * Checksum routine for Internet Protocol family headers (Portable Version).
201 *
202 * This routine is very heavily used in the network
203 * code and should be modified for each CPU to be as fast as possible.
204 */
205
206#define ADDCARRY(x)  (x > 65535 ? x -= 65535 : x)
207#define REDUCE \
208  {l_util.l = sum; sum = l_util.s[0] + l_util.s[1];  ADDCARRY(sum);}
209
210int
211in_cksum(m, len)
212        register struct mbuf *m;
213        register int len;
214{
215        register u_short *w;
216        register int sum = 0;
217        register int mlen = 0;
218        int byte_swapped = 0;
219
220        union {
221                char    c[2];
222                u_short s;
223        } s_util;
224        union {
225                u_short s[2];
226                long    l;
227        } l_util;
228
229        for (;m && len; m = m->m_next) {
230                if (m->m_len == 0)
231                        continue;
232                w = mtod(m, u_short *);
233                if (mlen == -1) {
234                        /*
235                         * The first byte of this mbuf is the continuation
236                         * of a word spanning between this mbuf and the
237                         * last mbuf.
238                         *
239                         * s_util.c[0] is already saved when scanning previous
240                         * mbuf.
241                         */
242                        s_util.c[1] = *(char *)w;
243                        sum += s_util.s;
244                        w = (u_short *)((char *)w + 1);
245                        mlen = m->m_len - 1;
246                        len--;
247                } else
248                        mlen = m->m_len;
249                if (len < mlen)
250                        mlen = len;
251                len -= mlen;
252                /*
253                 * Force to even boundary.
254                 */
255                if ((1 & (int) w) && (mlen > 0)) {
256                        REDUCE;
257                        sum <<= 8;
258                        s_util.c[0] = *(u_char *)w;
259                        w = (u_short *)((char *)w + 1);
260                        mlen--;
261                        byte_swapped = 1;
262                }
263                /*
264                 * Unroll the loop to make overhead from
265                 * branches &c small.
266                 */
267                while ((mlen -= 32) >= 0) {
268                        sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
269                        sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
270                        sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
271                        sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
272                        w += 16;
273                }
274                mlen += 32;
275                while ((mlen -= 8) >= 0) {
276                        sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
277                        w += 4;
278                }
279                mlen += 8;
280                if (mlen == 0 && byte_swapped == 0)
281                        continue;
282                REDUCE;
283                while ((mlen -= 2) >= 0) {
284                        sum += *w++;
285                }
286                if (byte_swapped) {
287                        REDUCE;
288                        sum <<= 8;
289                        byte_swapped = 0;
290                        if (mlen == -1) {
291                                s_util.c[1] = *(char *)w;
292                                sum += s_util.s;
293                                mlen = 0;
294                        } else
295                                mlen = -1;
296                } else if (mlen == -1)
297                        s_util.c[0] = *(char *)w;
298        }
299        if (len)
300                printf("cksum: out of data\n");
301        if (mlen == -1) {
302                /* The last mbuf has odd # of bytes. Follow the
303                   standard (the odd byte may be shifted left by 8 bits
304                   or not as determined by endian-ness of the machine) */
305                s_util.c[1] = 0;
306                sum += s_util.s;
307        }
308        REDUCE;
309        return (~sum & 0xffff);
310}
311#endif
Note: See TracBrowser for help on using the repository browser.