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

Subversion Repositories openrisc

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

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 the PowerPC version.
8
 *
9
 *  $Id: in_cksum_powerpc.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
 
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
 
40
int
41
in_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
}

powered by: WebSVN 2.1.0

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