source: rtems/c/src/exec/libnetworking/netinet/in_cksum_m68k.c @ b3956369

4.104.114.84.95
Last change on this file since b3956369 was b3956369, checked in by Joel Sherrill <joel.sherrill@…>, on 09/11/98 at 13:12:04

Patch from "David J. Fiddes" <D.J@…>:

I've fixed a few minor probs with the optimised version that Eric put
together for me the other day and sent the fixes back to him. Provided he
doesn't have a problem with it we've got a pretty solid in_cksum for the
ColdFire? as well as straight m68k. I've enclosed my updated in_cksum_m68k.c

At the moment my own bottlenecks are elsewhere...as my driver is pulling
16bit data chunks through a libchip-esq access routine from the chip which
for a polled I/O device is never going to be quick.

  • Property mode set to 100644
File size: 7.4 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 (__mcf5200__))
41# define IS_COLDFIRE 1
42#else
43# define IS_COLDFIRE 0
44#endif
45
46#define REDUCE { sum = (sum & 0xFFFF) + (sum >> 16); if (sum > 0xFFFF) sum -= 0xFFFF; }
47
48/*
49 * Motorola 68k version of Internet Protocol Checksum routine
50 * W. Eric Norum
51 * Saskatchewan Accelerator Laboratory
52 * August, 1998
53 */
54int
55in_cksum(m, len)
56        struct mbuf *m;
57        int len;
58{
59        unsigned short *w;
60        unsigned long sum = 0;
61        int mlen = 0;
62        int byte_swapped = 0;
63        union {
64                char    c[2];
65                u_short s;
66        } s_util;
67
68        for ( ; m && len ; m = m->m_next) {
69                if (m->m_len == 0)
70                        continue;
71                w = mtod(m, u_short *);
72                if (mlen == -1) {
73                        /*
74                         * The first byte of this mbuf is the continuation
75                         * of a word spanning between this mbuf and the
76                         * last mbuf.
77                         *
78                         * s_util.c[0] is already saved when scanning previous
79                         * mbuf.
80                         */
81                        s_util.c[1] = *(char *)w;
82                        sum += s_util.s;
83                        w = (u_short *)((char *)w + 1);
84                        mlen = m->m_len - 1;
85                        len--;
86                } else
87                        mlen = m->m_len;
88                if (len < mlen)
89                        mlen = len;
90                len -= mlen;
91
92                /*
93                 * Force to longword boundary.
94                 */
95                if (3 & (int)w) {
96                        REDUCE;
97                        if ((1 & (int) w) && (mlen > 0)) {
98                                sum <<= 8;
99                                s_util.c[0] = *(u_char *)w;
100                                w = (u_short *)((char *)w + 1);
101                                mlen--;
102                                byte_swapped = 1;
103                        }
104                        if ((2 & (int) w) && (mlen >= 2)) {
105                                sum += *w++;
106                                mlen -= 2;
107                        }
108                }
109
110                /*
111                 * Sum all the longwords in the buffer.
112                 * See RFC 1071 -- Computing the Internet Checksum.
113                 * It should work for all 68k family members.
114                 */
115                {
116                unsigned long tcnt = mlen, t1, t2;
117                __asm__ volatile (
118                "movel   %2,%3\n\t"
119                "lsrl    #6,%2       | count/64 = # loop traversals\n\t"
120                "andl    #0x3c,%3    | Then find fractions of a chunk\n\t"
121                "negl    %3\n\t      | Each long uses 4 instruction bytes\n\t"
122#if IS_COLDFIRE
123                "move    %%cc,%4     | Move the CC into a temp reg\n\t"
124                "andil   #0xf,%4     | Clear X (extended carry flag)\n\t"
125                "move    %4,%%cc     | Move the modified value back to the cc\n\t"
126#else
127                "andi    #0xf,%%cc   | Clear X (extended carry flag)\n\t"
128#endif
129                "jmp     %%pc@(lcsum2_lbl-.-2:b,%3)  | Jump into loop\n"
130                "lcsum1_lbl:         | Begin inner loop...\n\t"
131                "movel   %1@+,%3     |  0: Fetch 32-bit word\n\t"
132                "addxl   %3,%0       |    Add word + previous carry\n\t"
133                "movel   %1@+,%3     |  1: Fetch 32-bit word\n\t"
134                "addxl   %3,%0       |    Add word + previous carry\n\t"
135                "movel   %1@+,%3     |  2: Fetch 32-bit word\n\t"
136                "addxl   %3,%0       |    Add word + previous carry\n\t"
137                "movel   %1@+,%3     |  3: Fetch 32-bit word\n\t"
138                "addxl   %3,%0       |    Add word + previous carry\n\t"
139                "movel   %1@+,%3     |  4: Fetch 32-bit word\n\t"
140                "addxl   %3,%0       |    Add word + previous carry\n\t"
141                "movel   %1@+,%3     |  5: Fetch 32-bit word\n\t"
142                "addxl   %3,%0       |    Add word + previous carry\n\t"
143                "movel   %1@+,%3     |  6: Fetch 32-bit word\n\t"
144                "addxl   %3,%0       |    Add word + previous carry\n\t"
145                "movel   %1@+,%3     |  7: Fetch 32-bit word\n\t"
146                "addxl   %3,%0       |    Add word + previous carry\n\t"
147                "movel   %1@+,%3     |  8: Fetch 32-bit word\n\t"
148                "addxl   %3,%0       |    Add word + previous carry\n\t"
149                "movel   %1@+,%3     |  9: Fetch 32-bit word\n\t"
150                "addxl   %3,%0       |    Add word + previous carry\n\t"
151                "movel   %1@+,%3     |  A: Fetch 32-bit word\n\t"
152                "addxl   %3,%0       |    Add word + previous carry\n\t"
153                "movel   %1@+,%3     |  B: Fetch 32-bit word\n\t"
154                "addxl   %3,%0       |    Add word + previous carry\n\t"
155                "movel   %1@+,%3     |  C: Fetch 32-bit word\n\t"
156                "addxl   %3,%0       |    Add word + previous carry\n\t"
157                "movel   %1@+,%3     |  D: Fetch 32-bit word\n\t"
158                "addxl   %3,%0       |    Add word + previous carry\n\t"
159                "movel   %1@+,%3     |  E: Fetch 32-bit word\n\t"
160                "addxl   %3,%0       |    Add word + previous carry\n\t"
161                "movel   %1@+,%3     |  F: Fetch 32-bit word\n\t"
162                "addxl   %3,%0       |    Add word + previous carry\n"
163                "lcsum2_lbl:         |  End of unrolled loop\n\t"
164#if IS_COLDFIRE
165                "moveq   #0,%3       | Add in last carry\n\t"
166                "addxl   %3,%0       |\n\t"
167                "subql   #1,%2       | Update loop count\n\t"
168                "bplb    lcsum1_lbl  | Loop (with X clear) if not done\n\t"
169                "movel   #0xffff,%2  | Get word mask\n\t"
170                "movel   %0,%3       | Fold 32 bit sum to 16 bits\n\t"
171                "swap    %3          |\n\t"
172                "andl    %2,%0       |\n\t"
173                "andl    %2,%3       |\n\t"
174                "addl    %3,%0       |\n\t"
175                "movel   %0,%3       | Add in last carry\n\t"
176                "swap    %3          |\n\t"
177                "addl    %3,%0       |\n\t"
178#else
179                "dbf     %2,lcsum1_lbl | (NB- dbf doesn't affect X)\n\t"
180                "movel   %0,%3       | Fold 32 bit sum to 16 bits\n\t"
181                "swap    %3          | (NB- swap doesn't affect X)\n\t"
182                "addxw   %3,%0       |\n\t"
183                "moveq   #0,%3       | Add in last carry\n\t"
184                "addxw   %3,%0       |\n\t"
185#endif
186                "andl    #0xffff,%0     | Mask to 16-bit sum\n" :
187                        "=d" (sum), "=a" (w), "=d" (tcnt) , "=d" (t1), "=d" (t2) :
188                        "0" (sum), "1" (w), "2" (tcnt) :
189                        "cc", "memory");
190                }
191                mlen &= 3;
192
193                /*
194                 * Soak up the last 1, 2 or 3 bytes
195                 */
196                while ((mlen -= 2) >= 0)
197                        sum += *w++;
198                if (byte_swapped) {
199                        REDUCE;
200                        sum <<= 8;
201                        byte_swapped = 0;
202                        if (mlen == -1) {
203                                s_util.c[1] = *(char *)w;
204                                sum += s_util.s;
205                                mlen = 0;
206                        } else
207                                mlen = -1;
208                } else if (mlen == -1)
209                        s_util.c[0] = *(char *)w;
210        }
211        if (len)
212                sum = 0xDEAD;
213        if (mlen == -1) {
214                /* The last mbuf has odd # of bytes. Follow the
215                   standard (the odd byte may be shifted left by 8 bits
216                   or not as determined by endian-ness of the machine) */
217                s_util.c[1] = 0;
218                sum += s_util.s;
219        }
220        REDUCE;
221        return (~sum & 0xffff);
222}
Note: See TracBrowser for help on using the repository browser.