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