source: rtems/c/src/libnetworking/netinet/in_cksum_powerpc.c @ d3c1060

4.104.114.84.95
Last change on this file since d3c1060 was 1564ca8, checked in by Joel Sherrill <joel.sherrill@…>, on 02/04/99 at 14:56:09

Added PowerPC specific header checksum code.

  • Property mode set to 100644
File size: 3.5 KB
Line 
1/*
2 * Checksum routine for Internet Protocol family headers.
3 *
4 * This routine is very heavily used in the network
5 * code and should be modified for each CPU to be as fast as possible.
6 *
7 * This implementation is the PowerPC version.
8 *
9 *  $Id$
10 */
11
12#include <stdio.h>                /* for puts */
13
14#undef  ADDCARRY
15#define ADDCARRY(x)     if ((x) > 0xffff) (x) -= 0xffff
16#define REDUCE          {sum = (sum & 0xffff) + (sum >> 16); ADDCARRY(sum);}
17
18/*
19 * Thanks to gcc we don't have to guess
20 * which registers contain sum & w.
21 */
22
23#define LDTMP(n) tmp = *((u_int *)((u_char *)w + n))
24
25#define ADD(n)  \
26  LDTMP(n);  \
27  __asm__ volatile("addc %0,%0,%2" : "=r" (sum) : "0" (sum), "r" (tmp))
28
29#define ADDC(n) \
30  LDTMP(n);  \
31  __asm__ volatile("adde  %0,%0,%2" : "=r" (sum) : "0" (sum), "r" (tmp))
32
33#define MOP \
34  tmp = 0; \
35  __asm__ volatile("adde  %0,%0,%2" : "=r" (sum) : "0" (sum), "r" (tmp))
36
37#define LOAD(n) junk = (u_char) *((volatile u_char *) w + n)
38
39
40int
41in_cksum(m, len)
42        register struct mbuf *m;
43        register int len;
44{
45        u_char junk;
46        register u_short *w;
47        register unsigned sum = 0;
48        register unsigned tmp;
49        register int mlen = 0;
50        int byte_swapped = 0;
51        union { char    c[2]; u_short   s; } su;
52
53        for (;m && len; m = m->m_next) {
54                if (m->m_len == 0)
55                        continue;
56                w = mtod(m, u_short *);
57                if (mlen == -1) {
58                        /*
59                         * The first byte of this mbuf is the continuation
60                         * of a word spanning between this mbuf and the
61                         * last mbuf.
62                         */
63
64                        /* su.c[0] is already saved when scanning previous
65                         * mbuf.  sum was REDUCEd when we found mlen == -1
66                         */
67                        su.c[1] = *(u_char *)w;
68                        sum += su.s;
69                        w = (u_short *)((char *)w + 1);
70                        mlen = m->m_len - 1;
71                        len--;
72                } else
73                        mlen = m->m_len;
74                if (len < mlen)
75                        mlen = len;
76                len -= mlen;
77                /*
78                 * Force to long boundary so we do longword aligned
79                 * memory operations
80                 */
81                if (3 & (int) w) {
82                        REDUCE;
83                        if ((1 & (int) w) && (mlen > 0)) {
84                                sum <<= 8;
85                                su.c[0] = *(char *)w;
86                                w = (u_short *)((char *)w + 1);
87                                mlen--;
88                                byte_swapped = 1;
89                        }
90                        if ((2 & (int) w) && (mlen >= 2)) {
91                                sum += *w++;
92                                mlen -= 2;
93                        }
94                }
95
96                /*
97                 * Do as much of the checksum as possible 32 bits at at time.
98                 * In fact, this loop is unrolled to keep overhead from
99                 * branches small.
100                 */
101                while (mlen >= 32) {
102                        /*
103                         * Add with carry 16 words and fold in the last
104                         * carry by adding a 0 with carry.
105                         *
106                         * The early ADD(16) and the LOAD(32) are intended
107                         * to help  get the data into the cache.
108                         */
109                        ADD(16);
110                        ADDC(0);
111                        ADDC(4);
112                        ADDC(8);
113                        ADDC(12);
114                        LOAD(32);
115                        ADDC(20);
116                        ADDC(24);
117                        ADDC(28);
118                        MOP;
119                        w += 16;
120                        mlen -= 32;
121                }
122                if (mlen >= 16) {
123                        ADD(0);
124                        ADDC(4);
125                        ADDC(8);
126                        ADDC(12);
127                        MOP;
128                        w += 8;
129                        mlen -= 16;
130                }
131                if (mlen >= 8) {
132                        ADD(0);
133                        ADDC(4);
134                        MOP;
135                        w += 4;
136                        mlen -= 8;
137                }
138                if (mlen == 0 && byte_swapped == 0)
139                        continue;       /* worth 1% maybe ?? */
140                REDUCE;
141                while ((mlen -= 2) >= 0) {
142                        sum += *w++;
143                }
144                if (byte_swapped) {
145                        sum <<= 8;
146                        byte_swapped = 0;
147                        if (mlen == -1) {
148                                su.c[1] = *(char *)w;
149                                sum += su.s;
150                                mlen = 0;
151                        } else
152                                mlen = -1;
153                } else if (mlen == -1)
154                        /*
155                         * This mbuf has odd number of bytes.
156                         * There could be a word split betwen
157                         * this mbuf and the next mbuf.
158                         * Save the last byte (to prepend to next mbuf).
159                         */
160                        su.c[0] = *(char *)w;
161        }
162
163        if (len)
164                puts("cksum: out of data");
165        if (mlen == -1) {
166                /* The last mbuf has odd # of bytes. Follow the
167                   standard (the odd byte is shifted left by 8 bits) */
168                su.c[1] = 0;
169                sum += su.s;
170        }
171        REDUCE;
172        return (~sum & 0xffff);
173}
Note: See TracBrowser for help on using the repository browser.