Ticket #1443: in_cksum_powerpc.h

File in_cksum_powerpc.h, 5.9 KB (added by dufault, on 02/19/10 at 10:57:27)

Header file derived from netbsd.

Line 
1/*      $NetBSD: in_cksum.c,v 1.10 2005/12/24 23:24:01 perry Exp $      */
2
3/*
4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Simon Burge and Eduardo Horvath for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed for the NetBSD Project by
20 *      Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 *    or promote products derived from this software without specific prior
23 *    written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38/*
39 * Checksum routine for Internet Protocol family headers.
40 *
41 * This routine is very heavily used in the network
42 * code and should be modified for each CPU to be as fast as possible.
43 *
44 * This implementation is the PowerPC version.
45 *
46 *  $Id: in_cksum_powerpc.h,v 1.3 2008/08/18 21:16:42 joel Exp $
47 */
48
49#define REDUCE1         sum = (sum & 0xffff) + (sum >> 16)
50/* Two REDUCE1s is faster than REDUCE1; if (sum > 65535) sum -= 65536; */
51#define REDUCE          { REDUCE1; REDUCE1; }
52
53int
54in_cksum(struct mbuf *m, int len)
55{
56        uint8_t *w;
57        int mlen = 0;
58        int byte_swapped = 0;
59        int n;
60    u_int sum = 0;
61
62        union {
63                uint8_t  c[2];
64                uint16_t s;
65        } s_util;
66
67        for (;m && len; m = m->m_next) {
68                if (m->m_len == 0)
69                        continue;
70                w = mtod(m, uint8_t *);
71
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] = *w++;
82                        sum += s_util.s;
83                        mlen = m->m_len - 1;
84                        len--;
85                } else {
86                        mlen = m->m_len;
87                }
88                if (len < mlen)
89                        mlen = len;
90                len -= mlen;
91
92                /*
93                 * Force to a word boundary.
94                 */
95                if ((3 & (long) w) && (mlen > 0)) {
96                        if ((1 & (long) w)) {
97                                REDUCE;
98                                sum <<= 8;
99                                s_util.c[0] = *w++;
100                                mlen--;
101                                byte_swapped = 1;
102                        }
103                        if ((2 & (long) w) && (mlen > 1)) {
104                                /*
105                                 * Since the `sum' may contain full 32 bit
106                                 * value, we can't simply add any value.
107                                 */
108                                __asm volatile(
109                                    "lhz 7,0(%1);"      /* load current data
110                                                           half word */
111                                    "addc %0,%0,7;"     /* add to sum */
112                                    "addze %0,%0;"      /* add carry bit */
113                                    : "+r"(sum)
114                                    : "b"(w)
115                                    : "7", "xer");              /* clobber r7, xer */
116                                w += 2;
117                                mlen -= 2;
118                        }
119                }
120
121                if (mlen >= 64) {
122                        n = mlen >> 6;
123                        __asm volatile(
124                            "addic 0,0,0;"              /* clear carry */
125                            "mtctr %1;"                 /* load loop count */
126                            "1:"
127                            "lwz 7,4(%2);"              /* load current data
128                                                           word */
129                            "lwz 8,8(%2);"
130                            "lwz 9,12(%2);"
131                            "lwz 10,16(%2);"
132                            "adde %0,%0,7;"             /* add to sum */
133                            "adde %0,%0,8;"
134                            "adde %0,%0,9;"
135                            "adde %0,%0,10;"
136                            "lwz 7,20(%2);"
137                            "lwz 8,24(%2);"
138                            "lwz 9,28(%2);"
139                            "lwz 10,32(%2);"
140                            "adde %0,%0,7;"
141                            "adde %0,%0,8;"
142                            "adde %0,%0,9;"
143                            "adde %0,%0,10;"
144                            "lwz 7,36(%2);"
145                            "lwz 8,40(%2);"
146                            "lwz 9,44(%2);"
147                            "lwz 10,48(%2);"
148                            "adde %0,%0,7;"
149                            "adde %0,%0,8;"
150                            "adde %0,%0,9;"
151                            "adde %0,%0,10;"
152                            "lwz 7,52(%2);"
153                            "lwz 8,56(%2);"
154                            "lwz 9,60(%2);"
155                            "lwzu 10,64(%2);"
156                            "adde %0,%0,7;"
157                            "adde %0,%0,8;"
158                            "adde %0,%0,9;"
159                            "adde %0,%0,10;"
160                            "bdnz 1b;"                  /* loop */
161                            "addze %0,%0;"              /* add carry bit */
162                            : "+r"(sum)
163                            : "r"(n), "b"(w - 4)
164                            : "7", "8", "9", "10", "xer");      /* clobber r7, r8, r9,
165                                                           r10, xer  */
166                        w += n * 64;
167                        mlen -= n * 64;
168                }
169
170                if (mlen >= 8) {
171                        n = mlen >> 3;
172                        __asm volatile(
173                            "addic 0,0,0;"              /* clear carry */
174                            "mtctr %1;"                 /* load loop count */
175                            "1:"
176                            "lwz 7,4(%2);"              /* load current data
177                                                           word */
178                            "lwzu 8,8(%2);"
179                            "adde %0,%0,7;"             /* add to sum */
180                            "adde %0,%0,8;"
181                            "bdnz 1b;"                  /* loop */
182                            "addze %0,%0;"              /* add carry bit */
183                            : "+r"(sum)
184                            : "r"(n), "b"(w - 4)
185                            : "7", "8", "xer");         /* clobber r7, r8, xer */
186                        w += n * 8;
187                        mlen -= n * 8;
188                }
189
190                if (mlen == 0 && byte_swapped == 0)
191                        continue;
192                REDUCE;
193
194                while ((mlen -= 2) >= 0) {
195                        sum += *(uint16_t *)w;
196                        w += 2;
197                }
198
199                if (byte_swapped) {
200                        REDUCE;
201                        sum <<= 8;
202                        byte_swapped = 0;
203                        if (mlen == -1) {
204                                s_util.c[1] = *w;
205                                sum += s_util.s;
206                                mlen = 0;
207                        } else
208                                mlen = -1;
209                } else if (mlen == -1)
210                        s_util.c[0] = *w;
211        }
212        if (len)
213                printf("cksum: out of data\n");
214        if (mlen == -1) {
215                /* The last mbuf has odd # of bytes. Follow the
216                   standard (the odd byte may be shifted left by 8 bits
217                   or not as determined by endian-ness of the machine) */
218                s_util.c[1] = 0;
219                sum += s_util.s;
220        }
221        REDUCE;
222        return (~sum & 0xffff);
223}