OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [libnetworking/] [netinet/] [in_cksum_i386.c] - Blame information for rev 1778

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
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 386 version.
8
 *
9
 *  in_cksum_i386.c,v 1.3 2002/04/26 21:34:58 joel Exp
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
#define ADD(n)  __asm__ volatile \
23
    ("addl " #n "(%2), %0" : "=r" (sum) : "0" (sum), "r" (w))
24
#define ADDC(n) __asm__ volatile \
25
    ("adcl " #n "(%2), %0" : "=r" (sum) : "0" (sum), "r" (w))
26
#define LOAD(n) __asm__ volatile \
27
     ("movb " #n "(%1), %0" : "=r" (junk) : "r" (w))
28
#define MOP     __asm__ volatile \
29
    ("adcl         $0, %0" : "=r" (sum) : "0" (sum))
30
 
31
int
32
in_cksum(m, len)
33
        register struct mbuf *m;
34
        register int len;
35
{
36
        register u_short *w;
37
        register unsigned sum = 0;
38
        register int mlen = 0;
39
        int byte_swapped = 0;
40
        union { char    c[2]; u_short   s; } su;
41
 
42
        for (;m && len; m = m->m_next) {
43
                if (m->m_len == 0)
44
                        continue;
45
                w = mtod(m, u_short *);
46
                if (mlen == -1) {
47
                        /*
48
                         * The first byte of this mbuf is the continuation
49
                         * of a word spanning between this mbuf and the
50
                         * last mbuf.
51
                         */
52
 
53
                        /* su.c[0] is already saved when scanning previous
54
                         * mbuf.  sum was REDUCEd when we found mlen == -1
55
                         */
56
                        su.c[1] = *(u_char *)w;
57
                        sum += su.s;
58
                        w = (u_short *)((char *)w + 1);
59
                        mlen = m->m_len - 1;
60
                        len--;
61
                } else
62
                        mlen = m->m_len;
63
                if (len < mlen)
64
                        mlen = len;
65
                len -= mlen;
66
                /*
67
                 * Force to long boundary so we do longword aligned
68
                 * memory operations
69
                 */
70
                if (3 & (int) w) {
71
                        REDUCE;
72
                        if ((1 & (int) w) && (mlen > 0)) {
73
                                sum <<= 8;
74
                                su.c[0] = *(char *)w;
75
                                w = (u_short *)((char *)w + 1);
76
                                mlen--;
77
                                byte_swapped = 1;
78
                        }
79
                        if ((2 & (int) w) && (mlen >= 2)) {
80
                                sum += *w++;
81
                                mlen -= 2;
82
                        }
83
                }
84
                /*
85
                 * Advance to a 486 cache line boundary.
86
                 */
87
                if (4 & (int) w && mlen >= 4) {
88
                        ADD(0);
89
                        MOP;
90
                        w += 2;
91
                        mlen -= 4;
92
                }
93
                if (8 & (int) w && mlen >= 8) {
94
                        ADD(0);
95
                        ADDC(4);
96
                        MOP;
97
                        w += 4;
98
                        mlen -= 8;
99
                }
100
                /*
101
                 * Do as much of the checksum as possible 32 bits at at time.
102
                 * In fact, this loop is unrolled to make overhead from
103
                 * branches &c small.
104
                 */
105
                mlen -= 1;
106
                while ((mlen -= 32) >= 0) {
107
                        u_char junk;
108
                        /*
109
                         * Add with carry 16 words and fold in the last
110
                         * carry by adding a 0 with carry.
111
                         *
112
                         * The early ADD(16) and the LOAD(32) are to load
113
                         * the next 2 cache lines in advance on 486's.  The
114
                         * 486 has a penalty of 2 clock cycles for loading
115
                         * a cache line, plus whatever time the external
116
                         * memory takes to load the first word(s) addressed.
117
                         * These penalties are unavoidable.  Subsequent
118
                         * accesses to a cache line being loaded (and to
119
                         * other external memory?) are delayed until the
120
                         * whole load finishes.  These penalties are mostly
121
                         * avoided by not accessing external memory for
122
                         * 8 cycles after the ADD(16) and 12 cycles after
123
                         * the LOAD(32).  The loop terminates when mlen
124
                         * is initially 33 (not 32) to guaranteed that
125
                         * the LOAD(32) is within bounds.
126
                         */
127
                        ADD(16);
128
                        ADDC(0);
129
                        ADDC(4);
130
                        ADDC(8);
131
                        ADDC(12);
132
                        LOAD(32);
133
                        ADDC(20);
134
                        ADDC(24);
135
                        ADDC(28);
136
                        MOP;
137
                        w += 16;
138
                }
139
                mlen += 32 + 1;
140
                if (mlen >= 32) {
141
                        ADD(16);
142
                        ADDC(0);
143
                        ADDC(4);
144
                        ADDC(8);
145
                        ADDC(12);
146
                        ADDC(20);
147
                        ADDC(24);
148
                        ADDC(28);
149
                        MOP;
150
                        w += 16;
151
                        mlen -= 32;
152
                }
153
                if (mlen >= 16) {
154
                        ADD(0);
155
                        ADDC(4);
156
                        ADDC(8);
157
                        ADDC(12);
158
                        MOP;
159
                        w += 8;
160
                        mlen -= 16;
161
                }
162
                if (mlen >= 8) {
163
                        ADD(0);
164
                        ADDC(4);
165
                        MOP;
166
                        w += 4;
167
                        mlen -= 8;
168
                }
169
                if (mlen == 0 && byte_swapped == 0)
170
                        continue;       /* worth 1% maybe ?? */
171
                REDUCE;
172
                while ((mlen -= 2) >= 0) {
173
                        sum += *w++;
174
                }
175
                if (byte_swapped) {
176
                        sum <<= 8;
177
                        byte_swapped = 0;
178
                        if (mlen == -1) {
179
                                su.c[1] = *(char *)w;
180
                                sum += su.s;
181
                                mlen = 0;
182
                        } else
183
                                mlen = -1;
184
                } else if (mlen == -1)
185
                        /*
186
                         * This mbuf has odd number of bytes.
187
                         * There could be a word split betwen
188
                         * this mbuf and the next mbuf.
189
                         * Save the last byte (to prepend to next mbuf).
190
                         */
191
                        su.c[0] = *(char *)w;
192
        }
193
 
194
        if (len)
195
                puts("cksum: out of data");
196
        if (mlen == -1) {
197
                /* The last mbuf has odd # of bytes. Follow the
198
                   standard (the odd byte is shifted left by 8 bits) */
199
                su.c[1] = 0;
200
                sum += su.s;
201
        }
202
        REDUCE;
203
        return (~sum & 0xffff);
204
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.