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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [netinet/] [in_cksum_i386.c] - Blame information for rev 227

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

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

powered by: WebSVN 2.1.0

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