source: rtems-libbsd/freebsd/sparc64/sparc64/in_cksum.c @ 6434b4b

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 6434b4b was 6434b4b, checked in by Joel Sherrill <joel.sherrill@…>, on 03/09/12 at 15:38:23

Add other architecture specific in_cksum routines

+ arm, i386, mips, and sparc64
+ freebsd-to-rtems.py: Updated
+ Makefile: Regenerated.

  • Property mode set to 100644
File size: 7.7 KB
Line 
1#include <freebsd/machine/rtems-bsd-config.h>
2
3/*-
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 4. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31/*-
32 * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>.
33 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 *    notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 *    notice, this list of conditions and the following disclaimer in the
42 *    documentation and/or other materials provided with the distribution.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
45 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
48 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
49 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
50 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
51 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
52 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
53 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 *
55 *      from tahoe:     in_cksum.c      1.2     86/01/05
56 *      from:           @(#)in_cksum.c  1.3 (Berkeley) 1/19/91
57 *      from: FreeBSD: src/sys/i386/i386/in_cksum.c,v 1.22 2000/11/25
58 */
59
60#include <freebsd/sys/cdefs.h>
61__FBSDID("$FreeBSD$");
62
63#include <freebsd/sys/param.h>
64#include <freebsd/sys/systm.h>
65#include <freebsd/sys/mbuf.h>
66
67#include <freebsd/netinet/in.h>
68#include <freebsd/netinet/in_systm.h>
69#include <freebsd/netinet/ip.h>
70
71#include <freebsd/machine/in_cksum.h>
72
73/*
74 * Checksum routine for Internet Protocol family headers.
75 *
76 * This routine is very heavily used in the network
77 * code and should be modified for each CPU to be as fast as possible.
78 *
79 * This implementation is a sparc64 version.  Most code was taken over
80 * and adapted from the i386.  Some optimizations were changed to achieve
81 * (hopefully) better performance.
82 * This uses 64-bit loads, but 32-bit additions due to the lack of a 64-bit
83 * add-with-carry operation.
84 */
85
86/*
87 * REDUCE() is actually not used that frequently... maybe a C implementation
88 * would suffice.
89 */
90#define REDUCE(sum, tmp) __asm(                                         \
91        "sll %2, 16, %1\n"                                              \
92        "addcc %2, %1, %0\n"                                            \
93        "srl %0, 16, %0\n"                                              \
94        "addc %0, 0, %0" : "=r" (sum), "=&r" (tmp) : "0" (sum) : "cc")
95
96/*
97 * Note that some of these macros depend on the flags being preserved
98 * between calls, thus they have to be used within a single __asm().
99 */
100#define LD64_ADD32(n, mod)                                              \
101        "ldx [%3 + " #n "], %1\n"                                       \
102        "add" #mod " %2, %1, %0\n"                                      \
103        "srlx %1, 32, %1\n"                                             \
104        "addccc %0, %1, %0\n"
105
106#define LD32_ADD32(n, mod)                                              \
107        "lduw [%3 + " #n "], %1\n"                                      \
108        "add" #mod " %2, %1, %0\n"
109
110#define MOP(sum, tmp, addr)                                             \
111        "addc %2, 0, %0"                                                \
112        : "=r" (sum), "=&r" (tmp) : "0" (sum), "r" (addr) : "cc"
113
114u_short
115in_cksum_skip(struct mbuf *m, int len, int skip)
116{
117        u_short *w;
118        unsigned long tmp, sum = 0;
119        int mlen = 0;
120        int byte_swapped = 0;
121        u_short su = 0;
122
123        len -= skip;
124        for (; skip > 0 && m != NULL; m = m->m_next) {
125                if (m->m_len > skip) {
126                        mlen = m->m_len - skip;
127                        w = (u_short *)(mtod(m, u_char *) + skip);
128                        goto skip_start;
129                } else
130                        skip -= m->m_len;
131        }
132
133        for (; m != NULL && len > 0; m = m->m_next) {
134                if (m->m_len == 0)
135                        continue;
136                w = mtod(m, u_short *);
137                if (mlen == -1) {
138                        /*
139                         * The first byte of this mbuf is the continuation
140                         * of a word spanning between this mbuf and the
141                         * last mbuf.
142                         *
143                         * The high order byte of su is already saved when
144                         * scanning previous mbuf.  sum was REDUCEd when we
145                         * found mlen == -1
146                         */
147                        sum += su | *(u_char *)w;
148                        w = (u_short *)((u_char *)w + 1);
149                        mlen = m->m_len - 1;
150                        len--;
151                } else
152                        mlen = m->m_len;
153skip_start:
154                if (len < mlen)
155                        mlen = len;
156                len -= mlen;
157                /*
158                 * Force to a 8-byte boundary first so that we can use
159                 * LD64_ADD32.
160                 */
161                if (((u_long)w & 7) != 0) {
162                        REDUCE(sum, tmp);
163                        if (((u_long)w & 1) != 0 && mlen >= 1) {
164                                sum <<= 8;
165                                su = *(u_char *)w << 8;
166                                w = (u_short *)((u_char *)w + 1);
167                                mlen--;
168                                byte_swapped = 1;
169                        }
170                        if (((u_long)w & 2) != 0 && mlen >= 2) {
171                                sum += *w++;
172                                mlen -= 2;
173                        }
174                        if (((u_long)w & 4) != 0 && mlen >= 4) {
175                                __asm(
176                                    LD32_ADD32(0, cc)
177                                    MOP(sum, tmp, w)
178                                );
179                                w += 2;
180                                mlen -= 4;
181                        }
182                }
183                /*
184                 * Do as much of the checksum as possible 64 bits at at time.
185                 * In fact, this loop is unrolled to make overhead from
186                 * branches &c small.
187                 */
188                for (; mlen >= 64; mlen -= 64) {
189                        __asm(
190                            LD64_ADD32(0, cc)
191                            LD64_ADD32(8, ccc)
192                            LD64_ADD32(16, ccc)
193                            LD64_ADD32(24, ccc)
194                            LD64_ADD32(32, ccc)
195                            LD64_ADD32(40, ccc)
196                            LD64_ADD32(48, ccc)
197                            LD64_ADD32(56, ccc)
198                            MOP(sum, tmp, w)
199                        );
200                        w += 32;
201                }
202                if (mlen >= 32) {
203                        __asm(
204                            LD64_ADD32(0, cc)
205                            LD64_ADD32(8, ccc)
206                            LD64_ADD32(16, ccc)
207                            LD64_ADD32(24, ccc)
208                            MOP(sum, tmp, w)
209                        );
210                        w += 16;
211                        mlen -= 32;
212                }
213                if (mlen >= 16) {
214                        __asm(
215                            LD64_ADD32(0, cc)
216                            LD64_ADD32(8, ccc)
217                            MOP(sum, tmp, w)
218                        );
219                        w += 8;
220                        mlen -= 16;
221                }
222                if (mlen >= 8) {
223                        __asm(
224                            LD64_ADD32(0, cc)
225                            MOP(sum, tmp, w)
226                        );
227                        w += 4;
228                        mlen -= 8;
229                }
230                REDUCE(sum, tmp);
231                while ((mlen -= 2) >= 0)
232                        sum += *w++;
233                if (byte_swapped) {
234                        sum <<= 8;
235                        byte_swapped = 0;
236                        if (mlen == -1) {
237                                su |= *(u_char *)w;
238                                sum += su;
239                                mlen = 0;
240                        } else
241                                mlen = -1;
242                } else if (mlen == -1) {
243                        /*
244                         * This mbuf has odd number of bytes.
245                         * There could be a word split between
246                         * this mbuf and the next mbuf.
247                         * Save the last byte (to prepend to next mbuf).
248                         */
249                        su = *(u_char *)w << 8;
250                }
251        }
252
253        if (len)
254                printf("%s: out of data by %d\n", __func__, len);
255        if (mlen == -1) {
256                /*
257                 * The last mbuf has odd # of bytes.  Follow the
258                 * standard (the odd byte is shifted left by 8 bits).
259                 */
260                sum += su & 0xff00;
261        }
262        REDUCE(sum, tmp);
263        return (~sum & 0xffff);
264}
Note: See TracBrowser for help on using the repository browser.