RTEMS CPU Kit with SuperCore  4.11.3
in_cksum_m68k.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 1988, 1992, 1993
3  * The Regents of the University of California. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  * must display the following acknowledgement:
15  * This product includes software developed by the University of
16  * California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  * may be used to endorse or promote products derived from this software
19  * without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
34  */
35 
36 #include <sys/param.h>
37 #include <sys/mbuf.h>
38 
39 #if defined(__mcoldfire__)
40 # define IS_COLDFIRE 1
41 #else
42 # define IS_COLDFIRE 0
43 #endif
44 
45 #define REDUCE { sum = (sum & 0xFFFF) + (sum >> 16); if (sum > 0xFFFF) sum -= 0xFFFF; }
46 
47 /*
48  * Motorola 68k version of Internet Protocol Checksum routine
49  * W. Eric Norum
50  * Saskatchewan Accelerator Laboratory
51  * August, 1998
52  */
53 int
54 in_cksum( struct mbuf *m,
55  int len )
56 {
57  unsigned short *w;
58  unsigned long sum = 0;
59  int mlen = 0;
60  int byte_swapped = 0;
61  union {
62  char c[2];
63  u_short s;
64  } s_util;
65 
66  for ( ; m && len ; m = m->m_next) {
67  if (m->m_len == 0)
68  continue;
69  w = mtod(m, u_short *);
70  if (mlen == -1) {
71  /*
72  * The first byte of this mbuf is the continuation
73  * of a word spanning between this mbuf and the
74  * last mbuf.
75  *
76  * s_util.c[0] is already saved when scanning previous
77  * mbuf.
78  */
79  s_util.c[1] = *(char *)w;
80  sum += s_util.s;
81  w = (u_short *)((char *)w + 1);
82  mlen = m->m_len - 1;
83  len--;
84  } else
85  mlen = m->m_len;
86  if (len < mlen)
87  mlen = len;
88  len -= mlen;
89 
90  /*
91  * Force to longword boundary.
92  */
93  if (3 & (int)w) {
94  REDUCE;
95  if ((1 & (int) w) && (mlen > 0)) {
96  sum <<= 8;
97  s_util.c[0] = *(u_char *)w;
98  w = (u_short *)((char *)w + 1);
99  mlen--;
100  byte_swapped = 1;
101  }
102  if ((2 & (int) w) && (mlen >= 2)) {
103  sum += *w++;
104  mlen -= 2;
105  }
106  }
107 
108  /*
109  * Sum all the longwords in the buffer.
110  * See RFC 1071 -- Computing the Internet Checksum.
111  * It should work for all 68k family members.
112  */
113  {
114  unsigned long tcnt = mlen, t1;
115  __asm__ volatile (
116  "movel %2,%3\n\t"
117  "lsrl #6,%2 | count/64 = # loop traversals\n\t"
118  "andl #0x3c,%3 | Then find fractions of a chunk\n\t"
119  "negl %3\n\t | Each long uses 4 instruction bytes\n\t"
120 #if IS_COLDFIRE
121  "addql #1,%2 | Clear X (extended carry flag)\n\t"
122  "subql #1,%2 | \n\t"
123 #else
124  "andi #0xf,%%cc | Clear X (extended carry flag)\n\t"
125 #endif
126  "jmp %%pc@(2f-.-2:b,%3) | Jump into loop\n"
127  "1: | Begin inner loop...\n\t"
128  "movel %1@+,%3 | 0: Fetch 32-bit word\n\t"
129  "addxl %3,%0 | Add word + previous carry\n\t"
130  "movel %1@+,%3 | 1: Fetch 32-bit word\n\t"
131  "addxl %3,%0 | Add word + previous carry\n\t"
132  "movel %1@+,%3 | 2: Fetch 32-bit word\n\t"
133  "addxl %3,%0 | Add word + previous carry\n\t"
134  "movel %1@+,%3 | 3: Fetch 32-bit word\n\t"
135  "addxl %3,%0 | Add word + previous carry\n\t"
136  "movel %1@+,%3 | 4: Fetch 32-bit word\n\t"
137  "addxl %3,%0 | Add word + previous carry\n\t"
138  "movel %1@+,%3 | 5: Fetch 32-bit word\n\t"
139  "addxl %3,%0 | Add word + previous carry\n\t"
140  "movel %1@+,%3 | 6: Fetch 32-bit word\n\t"
141  "addxl %3,%0 | Add word + previous carry\n\t"
142  "movel %1@+,%3 | 7: Fetch 32-bit word\n\t"
143  "addxl %3,%0 | Add word + previous carry\n\t"
144  "movel %1@+,%3 | 8: Fetch 32-bit word\n\t"
145  "addxl %3,%0 | Add word + previous carry\n\t"
146  "movel %1@+,%3 | 9: Fetch 32-bit word\n\t"
147  "addxl %3,%0 | Add word + previous carry\n\t"
148  "movel %1@+,%3 | A: Fetch 32-bit word\n\t"
149  "addxl %3,%0 | Add word + previous carry\n\t"
150  "movel %1@+,%3 | B: Fetch 32-bit word\n\t"
151  "addxl %3,%0 | Add word + previous carry\n\t"
152  "movel %1@+,%3 | C: Fetch 32-bit word\n\t"
153  "addxl %3,%0 | Add word + previous carry\n\t"
154  "movel %1@+,%3 | D: Fetch 32-bit word\n\t"
155  "addxl %3,%0 | Add word + previous carry\n\t"
156  "movel %1@+,%3 | E: Fetch 32-bit word\n\t"
157  "addxl %3,%0 | Add word + previous carry\n\t"
158  "movel %1@+,%3 | F: Fetch 32-bit word\n\t"
159  "addxl %3,%0 | Add word + previous carry\n"
160  "2: | End of unrolled loop\n\t"
161 #if IS_COLDFIRE
162  "moveq #0,%3 | Add in last carry\n\t"
163  "addxl %3,%0 |\n\t"
164  "subql #1,%2 | Update loop count\n\t"
165  "bplb 1b | Loop (with X clear) if not done\n\t"
166  "movel #0xffff,%2 | Get word mask\n\t"
167  "movel %0,%3 | Fold 32 bit sum to 16 bits\n\t"
168  "swap %3 |\n\t"
169  "andl %2,%0 | Mask to 16-bit sum\n\t"
170  "andl %2,%3 | Mask to 16-bit sum\n\t"
171  "addl %3,%0 |\n\t"
172  "movel %0,%3 | Add in last carry\n\t"
173  "swap %3 |\n\t"
174  "addl %3,%0 |\n\t"
175  "andl %2,%0 | Mask to 16-bit sum\n\t"
176 #else
177  "dbf %2,1b | (NB- dbf doesn't affect X)\n\t"
178  "movel %0,%3 | Fold 32 bit sum to 16 bits\n\t"
179  "swap %3 | (NB- swap doesn't affect X)\n\t"
180  "addxw %3,%0 |\n\t"
181  "moveq #0,%3 | Add in last carry\n\t"
182  "addxw %3,%0 |\n\t"
183  "andl #0xffff,%0 | Mask to 16-bit sum\n"
184 #endif
185  :
186  "=d" (sum), "=a" (w), "=d" (tcnt) , "=d" (t1) :
187  "0" (sum), "1" (w), "2" (tcnt) :
188  "cc", "memory");
189  }
190  mlen &= 3;
191 
192  /*
193  * Soak up the last 1, 2 or 3 bytes
194  */
195  while ((mlen -= 2) >= 0)
196  sum += *w++;
197  if (byte_swapped) {
198  REDUCE;
199  sum <<= 8;
200  byte_swapped = 0;
201  if (mlen == -1) {
202  s_util.c[1] = *(char *)w;
203  sum += s_util.s;
204  mlen = 0;
205  } else
206  mlen = -1;
207  } else if (mlen == -1)
208  s_util.c[0] = *(char *)w;
209  }
210  if (len)
211  sum = 0xDEAD;
212  if (mlen == -1) {
213  /* The last mbuf has odd # of bytes. Follow the
214  standard (the odd byte may be shifted left by 8 bits
215  or not as determined by endian-ness of the machine) */
216  s_util.c[1] = 0;
217  sum += s_util.s;
218  }
219  REDUCE;
220  return (~sum & 0xffff);
221 }
register struct Per_CPU_Control *_SPARC_Per_CPU_current __asm__("g6")
The pointer to the current per-CPU control is available via register g6.
Definition: mbuf.h:103