diff options
Diffstat (limited to 'arch/m68k/lib')
-rw-r--r-- | arch/m68k/lib/Makefile | 8 | ||||
-rw-r--r-- | arch/m68k/lib/ashldi3.c | 62 | ||||
-rw-r--r-- | arch/m68k/lib/ashrdi3.c | 63 | ||||
-rw-r--r-- | arch/m68k/lib/checksum.c | 422 | ||||
-rw-r--r-- | arch/m68k/lib/lshrdi3.c | 62 | ||||
-rw-r--r-- | arch/m68k/lib/memcmp.c | 11 | ||||
-rw-r--r-- | arch/m68k/lib/memcpy.c | 75 | ||||
-rw-r--r-- | arch/m68k/lib/memset.c | 68 | ||||
-rw-r--r-- | arch/m68k/lib/muldi3.c | 63 | ||||
-rw-r--r-- | arch/m68k/lib/semaphore.S | 53 |
10 files changed, 887 insertions, 0 deletions
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile new file mode 100644 index 000000000000..34b6dbc29c85 --- /dev/null +++ b/arch/m68k/lib/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for m68k-specific library files.. | ||
3 | # | ||
4 | |||
5 | EXTRA_AFLAGS := -traditional | ||
6 | |||
7 | lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ | ||
8 | checksum.o memcmp.o memcpy.o memset.o semaphore.o | ||
diff --git a/arch/m68k/lib/ashldi3.c b/arch/m68k/lib/ashldi3.c new file mode 100644 index 000000000000..7729f33878d1 --- /dev/null +++ b/arch/m68k/lib/ashldi3.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* ashrdi3.c extracted from gcc-2.95.2/libgcc2.c which is: */ | ||
2 | /* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc. | ||
3 | |||
4 | This file is part of GNU CC. | ||
5 | |||
6 | GNU CC is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2, or (at your option) | ||
9 | any later version. | ||
10 | |||
11 | GNU CC is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with GNU CC; see the file COPYING. If not, write to | ||
18 | the Free Software Foundation, 59 Temple Place - Suite 330, | ||
19 | Boston, MA 02111-1307, USA. */ | ||
20 | |||
21 | #define BITS_PER_UNIT 8 | ||
22 | |||
23 | typedef int SItype __attribute__ ((mode (SI))); | ||
24 | typedef unsigned int USItype __attribute__ ((mode (SI))); | ||
25 | typedef int DItype __attribute__ ((mode (DI))); | ||
26 | typedef int word_type __attribute__ ((mode (__word__))); | ||
27 | |||
28 | struct DIstruct {SItype high, low;}; | ||
29 | |||
30 | typedef union | ||
31 | { | ||
32 | struct DIstruct s; | ||
33 | DItype ll; | ||
34 | } DIunion; | ||
35 | |||
36 | DItype | ||
37 | __ashldi3 (DItype u, word_type b) | ||
38 | { | ||
39 | DIunion w; | ||
40 | word_type bm; | ||
41 | DIunion uu; | ||
42 | |||
43 | if (b == 0) | ||
44 | return u; | ||
45 | |||
46 | uu.ll = u; | ||
47 | |||
48 | bm = (sizeof (SItype) * BITS_PER_UNIT) - b; | ||
49 | if (bm <= 0) | ||
50 | { | ||
51 | w.s.low = 0; | ||
52 | w.s.high = (USItype)uu.s.low << -bm; | ||
53 | } | ||
54 | else | ||
55 | { | ||
56 | USItype carries = (USItype)uu.s.low >> bm; | ||
57 | w.s.low = (USItype)uu.s.low << b; | ||
58 | w.s.high = ((USItype)uu.s.high << b) | carries; | ||
59 | } | ||
60 | |||
61 | return w.ll; | ||
62 | } | ||
diff --git a/arch/m68k/lib/ashrdi3.c b/arch/m68k/lib/ashrdi3.c new file mode 100644 index 000000000000..18ea5f7ed921 --- /dev/null +++ b/arch/m68k/lib/ashrdi3.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ | ||
2 | /* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. | ||
3 | |||
4 | This file is part of GNU CC. | ||
5 | |||
6 | GNU CC is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2, or (at your option) | ||
9 | any later version. | ||
10 | |||
11 | GNU CC is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with GNU CC; see the file COPYING. If not, write to | ||
18 | the Free Software Foundation, 59 Temple Place - Suite 330, | ||
19 | Boston, MA 02111-1307, USA. */ | ||
20 | |||
21 | #define BITS_PER_UNIT 8 | ||
22 | |||
23 | typedef int SItype __attribute__ ((mode (SI))); | ||
24 | typedef unsigned int USItype __attribute__ ((mode (SI))); | ||
25 | typedef int DItype __attribute__ ((mode (DI))); | ||
26 | typedef int word_type __attribute__ ((mode (__word__))); | ||
27 | |||
28 | struct DIstruct {SItype high, low;}; | ||
29 | |||
30 | typedef union | ||
31 | { | ||
32 | struct DIstruct s; | ||
33 | DItype ll; | ||
34 | } DIunion; | ||
35 | |||
36 | DItype | ||
37 | __ashrdi3 (DItype u, word_type b) | ||
38 | { | ||
39 | DIunion w; | ||
40 | word_type bm; | ||
41 | DIunion uu; | ||
42 | |||
43 | if (b == 0) | ||
44 | return u; | ||
45 | |||
46 | uu.ll = u; | ||
47 | |||
48 | bm = (sizeof (SItype) * BITS_PER_UNIT) - b; | ||
49 | if (bm <= 0) | ||
50 | { | ||
51 | /* w.s.high = 1..1 or 0..0 */ | ||
52 | w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1); | ||
53 | w.s.low = uu.s.high >> -bm; | ||
54 | } | ||
55 | else | ||
56 | { | ||
57 | USItype carries = (USItype)uu.s.high << bm; | ||
58 | w.s.high = uu.s.high >> b; | ||
59 | w.s.low = ((USItype)uu.s.low >> b) | carries; | ||
60 | } | ||
61 | |||
62 | return w.ll; | ||
63 | } | ||
diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c new file mode 100644 index 000000000000..4a5c5445c610 --- /dev/null +++ b/arch/m68k/lib/checksum.c | |||
@@ -0,0 +1,422 @@ | |||
1 | /* | ||
2 | * INET An implementation of the TCP/IP protocol suite for the LINUX | ||
3 | * operating system. INET is implemented using the BSD Socket | ||
4 | * interface as the means of communication with the user level. | ||
5 | * | ||
6 | * IP/TCP/UDP checksumming routines | ||
7 | * | ||
8 | * Authors: Jorge Cwik, <jorge@laser.satlink.net> | ||
9 | * Arnt Gulbrandsen, <agulbra@nvg.unit.no> | ||
10 | * Tom May, <ftom@netcom.com> | ||
11 | * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de> | ||
12 | * Lots of code moved from tcp.c and ip.c; see those files | ||
13 | * for more names. | ||
14 | * | ||
15 | * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek: | ||
16 | * Fixed some nasty bugs, causing some horrible crashes. | ||
17 | * A: At some points, the sum (%0) was used as | ||
18 | * length-counter instead of the length counter | ||
19 | * (%1). Thanks to Roman Hodek for pointing this out. | ||
20 | * B: GCC seems to mess up if one uses too many | ||
21 | * data-registers to hold input values and one tries to | ||
22 | * specify d0 and d1 as scratch registers. Letting gcc | ||
23 | * choose these registers itself solves the problem. | ||
24 | * | ||
25 | * This program is free software; you can redistribute it and/or | ||
26 | * modify it under the terms of the GNU General Public License | ||
27 | * as published by the Free Software Foundation; either version | ||
28 | * 2 of the License, or (at your option) any later version. | ||
29 | * | ||
30 | * 1998/8/31 Andreas Schwab: | ||
31 | * Zero out rest of buffer on exception in | ||
32 | * csum_partial_copy_from_user. | ||
33 | */ | ||
34 | |||
35 | #include <linux/module.h> | ||
36 | #include <net/checksum.h> | ||
37 | |||
38 | /* | ||
39 | * computes a partial checksum, e.g. for TCP/UDP fragments | ||
40 | */ | ||
41 | |||
42 | unsigned int | ||
43 | csum_partial (const unsigned char *buff, int len, unsigned int sum) | ||
44 | { | ||
45 | unsigned long tmp1, tmp2; | ||
46 | /* | ||
47 | * Experiments with ethernet and slip connections show that buff | ||
48 | * is aligned on either a 2-byte or 4-byte boundary. | ||
49 | */ | ||
50 | __asm__("movel %2,%3\n\t" | ||
51 | "btst #1,%3\n\t" /* Check alignment */ | ||
52 | "jeq 2f\n\t" | ||
53 | "subql #2,%1\n\t" /* buff%4==2: treat first word */ | ||
54 | "jgt 1f\n\t" | ||
55 | "addql #2,%1\n\t" /* len was == 2, treat only rest */ | ||
56 | "jra 4f\n" | ||
57 | "1:\t" | ||
58 | "addw %2@+,%0\n\t" /* add first word to sum */ | ||
59 | "clrl %3\n\t" | ||
60 | "addxl %3,%0\n" /* add X bit */ | ||
61 | "2:\t" | ||
62 | /* unrolled loop for the main part: do 8 longs at once */ | ||
63 | "movel %1,%3\n\t" /* save len in tmp1 */ | ||
64 | "lsrl #5,%1\n\t" /* len/32 */ | ||
65 | "jeq 2f\n\t" /* not enough... */ | ||
66 | "subql #1,%1\n" | ||
67 | "1:\t" | ||
68 | "movel %2@+,%4\n\t" | ||
69 | "addxl %4,%0\n\t" | ||
70 | "movel %2@+,%4\n\t" | ||
71 | "addxl %4,%0\n\t" | ||
72 | "movel %2@+,%4\n\t" | ||
73 | "addxl %4,%0\n\t" | ||
74 | "movel %2@+,%4\n\t" | ||
75 | "addxl %4,%0\n\t" | ||
76 | "movel %2@+,%4\n\t" | ||
77 | "addxl %4,%0\n\t" | ||
78 | "movel %2@+,%4\n\t" | ||
79 | "addxl %4,%0\n\t" | ||
80 | "movel %2@+,%4\n\t" | ||
81 | "addxl %4,%0\n\t" | ||
82 | "movel %2@+,%4\n\t" | ||
83 | "addxl %4,%0\n\t" | ||
84 | "dbra %1,1b\n\t" | ||
85 | "clrl %4\n\t" | ||
86 | "addxl %4,%0\n\t" /* add X bit */ | ||
87 | "clrw %1\n\t" | ||
88 | "subql #1,%1\n\t" | ||
89 | "jcc 1b\n" | ||
90 | "2:\t" | ||
91 | "movel %3,%1\n\t" /* restore len from tmp1 */ | ||
92 | "andw #0x1c,%3\n\t" /* number of rest longs */ | ||
93 | "jeq 4f\n\t" | ||
94 | "lsrw #2,%3\n\t" | ||
95 | "subqw #1,%3\n" | ||
96 | "3:\t" | ||
97 | /* loop for rest longs */ | ||
98 | "movel %2@+,%4\n\t" | ||
99 | "addxl %4,%0\n\t" | ||
100 | "dbra %3,3b\n\t" | ||
101 | "clrl %4\n\t" | ||
102 | "addxl %4,%0\n" /* add X bit */ | ||
103 | "4:\t" | ||
104 | /* now check for rest bytes that do not fit into longs */ | ||
105 | "andw #3,%1\n\t" | ||
106 | "jeq 7f\n\t" | ||
107 | "clrl %4\n\t" /* clear tmp2 for rest bytes */ | ||
108 | "subqw #2,%1\n\t" | ||
109 | "jlt 5f\n\t" | ||
110 | "movew %2@+,%4\n\t" /* have rest >= 2: get word */ | ||
111 | "swap %4\n\t" /* into bits 16..31 */ | ||
112 | "tstw %1\n\t" /* another byte? */ | ||
113 | "jeq 6f\n" | ||
114 | "5:\t" | ||
115 | "moveb %2@,%4\n\t" /* have odd rest: get byte */ | ||
116 | "lslw #8,%4\n\t" /* into bits 8..15; 16..31 untouched */ | ||
117 | "6:\t" | ||
118 | "addl %4,%0\n\t" /* now add rest long to sum */ | ||
119 | "clrl %4\n\t" | ||
120 | "addxl %4,%0\n" /* add X bit */ | ||
121 | "7:\t" | ||
122 | : "=d" (sum), "=d" (len), "=a" (buff), | ||
123 | "=&d" (tmp1), "=&d" (tmp2) | ||
124 | : "0" (sum), "1" (len), "2" (buff) | ||
125 | ); | ||
126 | return(sum); | ||
127 | } | ||
128 | |||
129 | EXPORT_SYMBOL(csum_partial); | ||
130 | |||
131 | |||
132 | /* | ||
133 | * copy from user space while checksumming, with exception handling. | ||
134 | */ | ||
135 | |||
136 | unsigned int | ||
137 | csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, | ||
138 | int len, int sum, int *csum_err) | ||
139 | { | ||
140 | /* | ||
141 | * GCC doesn't like more than 10 operands for the asm | ||
142 | * statements so we have to use tmp2 for the error | ||
143 | * code. | ||
144 | */ | ||
145 | unsigned long tmp1, tmp2; | ||
146 | |||
147 | __asm__("movel %2,%4\n\t" | ||
148 | "btst #1,%4\n\t" /* Check alignment */ | ||
149 | "jeq 2f\n\t" | ||
150 | "subql #2,%1\n\t" /* buff%4==2: treat first word */ | ||
151 | "jgt 1f\n\t" | ||
152 | "addql #2,%1\n\t" /* len was == 2, treat only rest */ | ||
153 | "jra 4f\n" | ||
154 | "1:\n" | ||
155 | "10:\t" | ||
156 | "movesw %2@+,%4\n\t" /* add first word to sum */ | ||
157 | "addw %4,%0\n\t" | ||
158 | "movew %4,%3@+\n\t" | ||
159 | "clrl %4\n\t" | ||
160 | "addxl %4,%0\n" /* add X bit */ | ||
161 | "2:\t" | ||
162 | /* unrolled loop for the main part: do 8 longs at once */ | ||
163 | "movel %1,%4\n\t" /* save len in tmp1 */ | ||
164 | "lsrl #5,%1\n\t" /* len/32 */ | ||
165 | "jeq 2f\n\t" /* not enough... */ | ||
166 | "subql #1,%1\n" | ||
167 | "1:\n" | ||
168 | "11:\t" | ||
169 | "movesl %2@+,%5\n\t" | ||
170 | "addxl %5,%0\n\t" | ||
171 | "movel %5,%3@+\n\t" | ||
172 | "12:\t" | ||
173 | "movesl %2@+,%5\n\t" | ||
174 | "addxl %5,%0\n\t" | ||
175 | "movel %5,%3@+\n\t" | ||
176 | "13:\t" | ||
177 | "movesl %2@+,%5\n\t" | ||
178 | "addxl %5,%0\n\t" | ||
179 | "movel %5,%3@+\n\t" | ||
180 | "14:\t" | ||
181 | "movesl %2@+,%5\n\t" | ||
182 | "addxl %5,%0\n\t" | ||
183 | "movel %5,%3@+\n\t" | ||
184 | "15:\t" | ||
185 | "movesl %2@+,%5\n\t" | ||
186 | "addxl %5,%0\n\t" | ||
187 | "movel %5,%3@+\n\t" | ||
188 | "16:\t" | ||
189 | "movesl %2@+,%5\n\t" | ||
190 | "addxl %5,%0\n\t" | ||
191 | "movel %5,%3@+\n\t" | ||
192 | "17:\t" | ||
193 | "movesl %2@+,%5\n\t" | ||
194 | "addxl %5,%0\n\t" | ||
195 | "movel %5,%3@+\n\t" | ||
196 | "18:\t" | ||
197 | "movesl %2@+,%5\n\t" | ||
198 | "addxl %5,%0\n\t" | ||
199 | "movel %5,%3@+\n\t" | ||
200 | "dbra %1,1b\n\t" | ||
201 | "clrl %5\n\t" | ||
202 | "addxl %5,%0\n\t" /* add X bit */ | ||
203 | "clrw %1\n\t" | ||
204 | "subql #1,%1\n\t" | ||
205 | "jcc 1b\n" | ||
206 | "2:\t" | ||
207 | "movel %4,%1\n\t" /* restore len from tmp1 */ | ||
208 | "andw #0x1c,%4\n\t" /* number of rest longs */ | ||
209 | "jeq 4f\n\t" | ||
210 | "lsrw #2,%4\n\t" | ||
211 | "subqw #1,%4\n" | ||
212 | "3:\n" | ||
213 | /* loop for rest longs */ | ||
214 | "19:\t" | ||
215 | "movesl %2@+,%5\n\t" | ||
216 | "addxl %5,%0\n\t" | ||
217 | "movel %5,%3@+\n\t" | ||
218 | "dbra %4,3b\n\t" | ||
219 | "clrl %5\n\t" | ||
220 | "addxl %5,%0\n" /* add X bit */ | ||
221 | "4:\t" | ||
222 | /* now check for rest bytes that do not fit into longs */ | ||
223 | "andw #3,%1\n\t" | ||
224 | "jeq 7f\n\t" | ||
225 | "clrl %5\n\t" /* clear tmp2 for rest bytes */ | ||
226 | "subqw #2,%1\n\t" | ||
227 | "jlt 5f\n\t" | ||
228 | "20:\t" | ||
229 | "movesw %2@+,%5\n\t" /* have rest >= 2: get word */ | ||
230 | "movew %5,%3@+\n\t" | ||
231 | "swap %5\n\t" /* into bits 16..31 */ | ||
232 | "tstw %1\n\t" /* another byte? */ | ||
233 | "jeq 6f\n" | ||
234 | "5:\n" | ||
235 | "21:\t" | ||
236 | "movesb %2@,%5\n\t" /* have odd rest: get byte */ | ||
237 | "moveb %5,%3@+\n\t" | ||
238 | "lslw #8,%5\n\t" /* into bits 8..15; 16..31 untouched */ | ||
239 | "6:\t" | ||
240 | "addl %5,%0\n\t" /* now add rest long to sum */ | ||
241 | "clrl %5\n\t" | ||
242 | "addxl %5,%0\n\t" /* add X bit */ | ||
243 | "7:\t" | ||
244 | "clrl %5\n" /* no error - clear return value */ | ||
245 | "8:\n" | ||
246 | ".section .fixup,\"ax\"\n" | ||
247 | ".even\n" | ||
248 | /* If any exception occurs zero out the rest. | ||
249 | Similarities with the code above are intentional :-) */ | ||
250 | "90:\t" | ||
251 | "clrw %3@+\n\t" | ||
252 | "movel %1,%4\n\t" | ||
253 | "lsrl #5,%1\n\t" | ||
254 | "jeq 1f\n\t" | ||
255 | "subql #1,%1\n" | ||
256 | "91:\t" | ||
257 | "clrl %3@+\n" | ||
258 | "92:\t" | ||
259 | "clrl %3@+\n" | ||
260 | "93:\t" | ||
261 | "clrl %3@+\n" | ||
262 | "94:\t" | ||
263 | "clrl %3@+\n" | ||
264 | "95:\t" | ||
265 | "clrl %3@+\n" | ||
266 | "96:\t" | ||
267 | "clrl %3@+\n" | ||
268 | "97:\t" | ||
269 | "clrl %3@+\n" | ||
270 | "98:\t" | ||
271 | "clrl %3@+\n\t" | ||
272 | "dbra %1,91b\n\t" | ||
273 | "clrw %1\n\t" | ||
274 | "subql #1,%1\n\t" | ||
275 | "jcc 91b\n" | ||
276 | "1:\t" | ||
277 | "movel %4,%1\n\t" | ||
278 | "andw #0x1c,%4\n\t" | ||
279 | "jeq 1f\n\t" | ||
280 | "lsrw #2,%4\n\t" | ||
281 | "subqw #1,%4\n" | ||
282 | "99:\t" | ||
283 | "clrl %3@+\n\t" | ||
284 | "dbra %4,99b\n\t" | ||
285 | "1:\t" | ||
286 | "andw #3,%1\n\t" | ||
287 | "jeq 9f\n" | ||
288 | "100:\t" | ||
289 | "clrw %3@+\n\t" | ||
290 | "tstw %1\n\t" | ||
291 | "jeq 9f\n" | ||
292 | "101:\t" | ||
293 | "clrb %3@+\n" | ||
294 | "9:\t" | ||
295 | #define STR(X) STR1(X) | ||
296 | #define STR1(X) #X | ||
297 | "moveq #-" STR(EFAULT) ",%5\n\t" | ||
298 | "jra 8b\n" | ||
299 | ".previous\n" | ||
300 | ".section __ex_table,\"a\"\n" | ||
301 | ".long 10b,90b\n" | ||
302 | ".long 11b,91b\n" | ||
303 | ".long 12b,92b\n" | ||
304 | ".long 13b,93b\n" | ||
305 | ".long 14b,94b\n" | ||
306 | ".long 15b,95b\n" | ||
307 | ".long 16b,96b\n" | ||
308 | ".long 17b,97b\n" | ||
309 | ".long 18b,98b\n" | ||
310 | ".long 19b,99b\n" | ||
311 | ".long 20b,100b\n" | ||
312 | ".long 21b,101b\n" | ||
313 | ".previous" | ||
314 | : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst), | ||
315 | "=&d" (tmp1), "=d" (tmp2) | ||
316 | : "0" (sum), "1" (len), "2" (src), "3" (dst) | ||
317 | ); | ||
318 | |||
319 | *csum_err = tmp2; | ||
320 | |||
321 | return(sum); | ||
322 | } | ||
323 | |||
324 | /* | ||
325 | * copy from kernel space while checksumming, otherwise like csum_partial | ||
326 | */ | ||
327 | |||
328 | unsigned int | ||
329 | csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst, int len, int sum) | ||
330 | { | ||
331 | unsigned long tmp1, tmp2; | ||
332 | __asm__("movel %2,%4\n\t" | ||
333 | "btst #1,%4\n\t" /* Check alignment */ | ||
334 | "jeq 2f\n\t" | ||
335 | "subql #2,%1\n\t" /* buff%4==2: treat first word */ | ||
336 | "jgt 1f\n\t" | ||
337 | "addql #2,%1\n\t" /* len was == 2, treat only rest */ | ||
338 | "jra 4f\n" | ||
339 | "1:\t" | ||
340 | "movew %2@+,%4\n\t" /* add first word to sum */ | ||
341 | "addw %4,%0\n\t" | ||
342 | "movew %4,%3@+\n\t" | ||
343 | "clrl %4\n\t" | ||
344 | "addxl %4,%0\n" /* add X bit */ | ||
345 | "2:\t" | ||
346 | /* unrolled loop for the main part: do 8 longs at once */ | ||
347 | "movel %1,%4\n\t" /* save len in tmp1 */ | ||
348 | "lsrl #5,%1\n\t" /* len/32 */ | ||
349 | "jeq 2f\n\t" /* not enough... */ | ||
350 | "subql #1,%1\n" | ||
351 | "1:\t" | ||
352 | "movel %2@+,%5\n\t" | ||
353 | "addxl %5,%0\n\t" | ||
354 | "movel %5,%3@+\n\t" | ||
355 | "movel %2@+,%5\n\t" | ||
356 | "addxl %5,%0\n\t" | ||
357 | "movel %5,%3@+\n\t" | ||
358 | "movel %2@+,%5\n\t" | ||
359 | "addxl %5,%0\n\t" | ||
360 | "movel %5,%3@+\n\t" | ||
361 | "movel %2@+,%5\n\t" | ||
362 | "addxl %5,%0\n\t" | ||
363 | "movel %5,%3@+\n\t" | ||
364 | "movel %2@+,%5\n\t" | ||
365 | "addxl %5,%0\n\t" | ||
366 | "movel %5,%3@+\n\t" | ||
367 | "movel %2@+,%5\n\t" | ||
368 | "addxl %5,%0\n\t" | ||
369 | "movel %5,%3@+\n\t" | ||
370 | "movel %2@+,%5\n\t" | ||
371 | "addxl %5,%0\n\t" | ||
372 | "movel %5,%3@+\n\t" | ||
373 | "movel %2@+,%5\n\t" | ||
374 | "addxl %5,%0\n\t" | ||
375 | "movel %5,%3@+\n\t" | ||
376 | "dbra %1,1b\n\t" | ||
377 | "clrl %5\n\t" | ||
378 | "addxl %5,%0\n\t" /* add X bit */ | ||
379 | "clrw %1\n\t" | ||
380 | "subql #1,%1\n\t" | ||
381 | "jcc 1b\n" | ||
382 | "2:\t" | ||
383 | "movel %4,%1\n\t" /* restore len from tmp1 */ | ||
384 | "andw #0x1c,%4\n\t" /* number of rest longs */ | ||
385 | "jeq 4f\n\t" | ||
386 | "lsrw #2,%4\n\t" | ||
387 | "subqw #1,%4\n" | ||
388 | "3:\t" | ||
389 | /* loop for rest longs */ | ||
390 | "movel %2@+,%5\n\t" | ||
391 | "addxl %5,%0\n\t" | ||
392 | "movel %5,%3@+\n\t" | ||
393 | "dbra %4,3b\n\t" | ||
394 | "clrl %5\n\t" | ||
395 | "addxl %5,%0\n" /* add X bit */ | ||
396 | "4:\t" | ||
397 | /* now check for rest bytes that do not fit into longs */ | ||
398 | "andw #3,%1\n\t" | ||
399 | "jeq 7f\n\t" | ||
400 | "clrl %5\n\t" /* clear tmp2 for rest bytes */ | ||
401 | "subqw #2,%1\n\t" | ||
402 | "jlt 5f\n\t" | ||
403 | "movew %2@+,%5\n\t" /* have rest >= 2: get word */ | ||
404 | "movew %5,%3@+\n\t" | ||
405 | "swap %5\n\t" /* into bits 16..31 */ | ||
406 | "tstw %1\n\t" /* another byte? */ | ||
407 | "jeq 6f\n" | ||
408 | "5:\t" | ||
409 | "moveb %2@,%5\n\t" /* have odd rest: get byte */ | ||
410 | "moveb %5,%3@+\n\t" | ||
411 | "lslw #8,%5\n" /* into bits 8..15; 16..31 untouched */ | ||
412 | "6:\t" | ||
413 | "addl %5,%0\n\t" /* now add rest long to sum */ | ||
414 | "clrl %5\n\t" | ||
415 | "addxl %5,%0\n" /* add X bit */ | ||
416 | "7:\t" | ||
417 | : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst), | ||
418 | "=&d" (tmp1), "=&d" (tmp2) | ||
419 | : "0" (sum), "1" (len), "2" (src), "3" (dst) | ||
420 | ); | ||
421 | return(sum); | ||
422 | } | ||
diff --git a/arch/m68k/lib/lshrdi3.c b/arch/m68k/lib/lshrdi3.c new file mode 100644 index 000000000000..d06442d3a328 --- /dev/null +++ b/arch/m68k/lib/lshrdi3.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ | ||
2 | /* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. | ||
3 | |||
4 | This file is part of GNU CC. | ||
5 | |||
6 | GNU CC is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published by | ||
8 | the Free Software Foundation; either version 2, or (at your option) | ||
9 | any later version. | ||
10 | |||
11 | GNU CC is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with GNU CC; see the file COPYING. If not, write to | ||
18 | the Free Software Foundation, 59 Temple Place - Suite 330, | ||
19 | Boston, MA 02111-1307, USA. */ | ||
20 | |||
21 | #define BITS_PER_UNIT 8 | ||
22 | |||
23 | typedef int SItype __attribute__ ((mode (SI))); | ||
24 | typedef unsigned int USItype __attribute__ ((mode (SI))); | ||
25 | typedef int DItype __attribute__ ((mode (DI))); | ||
26 | typedef int word_type __attribute__ ((mode (__word__))); | ||
27 | |||
28 | struct DIstruct {SItype high, low;}; | ||
29 | |||
30 | typedef union | ||
31 | { | ||
32 | struct DIstruct s; | ||
33 | DItype ll; | ||
34 | } DIunion; | ||
35 | |||
36 | DItype | ||
37 | __lshrdi3 (DItype u, word_type b) | ||
38 | { | ||
39 | DIunion w; | ||
40 | word_type bm; | ||
41 | DIunion uu; | ||
42 | |||
43 | if (b == 0) | ||
44 | return u; | ||
45 | |||
46 | uu.ll = u; | ||
47 | |||
48 | bm = (sizeof (SItype) * BITS_PER_UNIT) - b; | ||
49 | if (bm <= 0) | ||
50 | { | ||
51 | w.s.high = 0; | ||
52 | w.s.low = (USItype)uu.s.high >> -bm; | ||
53 | } | ||
54 | else | ||
55 | { | ||
56 | USItype carries = (USItype)uu.s.high << bm; | ||
57 | w.s.high = (USItype)uu.s.high >> b; | ||
58 | w.s.low = ((USItype)uu.s.low >> b) | carries; | ||
59 | } | ||
60 | |||
61 | return w.ll; | ||
62 | } | ||
diff --git a/arch/m68k/lib/memcmp.c b/arch/m68k/lib/memcmp.c new file mode 100644 index 000000000000..f4796febb773 --- /dev/null +++ b/arch/m68k/lib/memcmp.c | |||
@@ -0,0 +1,11 @@ | |||
1 | #include <linux/types.h> | ||
2 | |||
3 | int memcmp(const void * cs,const void * ct,size_t count) | ||
4 | { | ||
5 | const unsigned char *su1, *su2; | ||
6 | |||
7 | for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) | ||
8 | if (*su1 != *su2) | ||
9 | return((*su1 < *su2) ? -1 : +1); | ||
10 | return(0); | ||
11 | } | ||
diff --git a/arch/m68k/lib/memcpy.c b/arch/m68k/lib/memcpy.c new file mode 100644 index 000000000000..73e181823d9b --- /dev/null +++ b/arch/m68k/lib/memcpy.c | |||
@@ -0,0 +1,75 @@ | |||
1 | #include <linux/types.h> | ||
2 | |||
3 | void * memcpy(void * to, const void * from, size_t n) | ||
4 | { | ||
5 | void *xto = to; | ||
6 | size_t temp, temp1; | ||
7 | |||
8 | if (!n) | ||
9 | return xto; | ||
10 | if ((long) to & 1) | ||
11 | { | ||
12 | char *cto = to; | ||
13 | const char *cfrom = from; | ||
14 | *cto++ = *cfrom++; | ||
15 | to = cto; | ||
16 | from = cfrom; | ||
17 | n--; | ||
18 | } | ||
19 | if (n > 2 && (long) to & 2) | ||
20 | { | ||
21 | short *sto = to; | ||
22 | const short *sfrom = from; | ||
23 | *sto++ = *sfrom++; | ||
24 | to = sto; | ||
25 | from = sfrom; | ||
26 | n -= 2; | ||
27 | } | ||
28 | temp = n >> 2; | ||
29 | if (temp) | ||
30 | { | ||
31 | long *lto = to; | ||
32 | const long *lfrom = from; | ||
33 | |||
34 | __asm__ __volatile__("movel %2,%3\n\t" | ||
35 | "andw #7,%3\n\t" | ||
36 | "lsrl #3,%2\n\t" | ||
37 | "negw %3\n\t" | ||
38 | "jmp %%pc@(1f,%3:w:2)\n\t" | ||
39 | "4:\t" | ||
40 | "movel %0@+,%1@+\n\t" | ||
41 | "movel %0@+,%1@+\n\t" | ||
42 | "movel %0@+,%1@+\n\t" | ||
43 | "movel %0@+,%1@+\n\t" | ||
44 | "movel %0@+,%1@+\n\t" | ||
45 | "movel %0@+,%1@+\n\t" | ||
46 | "movel %0@+,%1@+\n\t" | ||
47 | "movel %0@+,%1@+\n\t" | ||
48 | "1:\t" | ||
49 | "dbra %2,4b\n\t" | ||
50 | "clrw %2\n\t" | ||
51 | "subql #1,%2\n\t" | ||
52 | "jpl 4b\n\t" | ||
53 | : "=a" (lfrom), "=a" (lto), "=d" (temp), | ||
54 | "=&d" (temp1) | ||
55 | : "0" (lfrom), "1" (lto), "2" (temp) | ||
56 | ); | ||
57 | to = lto; | ||
58 | from = lfrom; | ||
59 | } | ||
60 | if (n & 2) | ||
61 | { | ||
62 | short *sto = to; | ||
63 | const short *sfrom = from; | ||
64 | *sto++ = *sfrom++; | ||
65 | to = sto; | ||
66 | from = sfrom; | ||
67 | } | ||
68 | if (n & 1) | ||
69 | { | ||
70 | char *cto = to; | ||
71 | const char *cfrom = from; | ||
72 | *cto = *cfrom; | ||
73 | } | ||
74 | return xto; | ||
75 | } | ||
diff --git a/arch/m68k/lib/memset.c b/arch/m68k/lib/memset.c new file mode 100644 index 000000000000..d55fdb2ee9d3 --- /dev/null +++ b/arch/m68k/lib/memset.c | |||
@@ -0,0 +1,68 @@ | |||
1 | #include <linux/types.h> | ||
2 | |||
3 | void * memset(void * s, int c, size_t count) | ||
4 | { | ||
5 | void *xs = s; | ||
6 | size_t temp, temp1; | ||
7 | |||
8 | if (!count) | ||
9 | return xs; | ||
10 | c &= 0xff; | ||
11 | c |= c << 8; | ||
12 | c |= c << 16; | ||
13 | if ((long) s & 1) | ||
14 | { | ||
15 | char *cs = s; | ||
16 | *cs++ = c; | ||
17 | s = cs; | ||
18 | count--; | ||
19 | } | ||
20 | if (count > 2 && (long) s & 2) | ||
21 | { | ||
22 | short *ss = s; | ||
23 | *ss++ = c; | ||
24 | s = ss; | ||
25 | count -= 2; | ||
26 | } | ||
27 | temp = count >> 2; | ||
28 | if (temp) | ||
29 | { | ||
30 | long *ls = s; | ||
31 | |||
32 | __asm__ __volatile__("movel %1,%2\n\t" | ||
33 | "andw #7,%2\n\t" | ||
34 | "lsrl #3,%1\n\t" | ||
35 | "negw %2\n\t" | ||
36 | "jmp %%pc@(2f,%2:w:2)\n\t" | ||
37 | "1:\t" | ||
38 | "movel %3,%0@+\n\t" | ||
39 | "movel %3,%0@+\n\t" | ||
40 | "movel %3,%0@+\n\t" | ||
41 | "movel %3,%0@+\n\t" | ||
42 | "movel %3,%0@+\n\t" | ||
43 | "movel %3,%0@+\n\t" | ||
44 | "movel %3,%0@+\n\t" | ||
45 | "movel %3,%0@+\n\t" | ||
46 | "2:\t" | ||
47 | "dbra %1,1b\n\t" | ||
48 | "clrw %1\n\t" | ||
49 | "subql #1,%1\n\t" | ||
50 | "jpl 1b\n\t" | ||
51 | : "=a" (ls), "=d" (temp), "=&d" (temp1) | ||
52 | : "d" (c), "0" (ls), "1" (temp) | ||
53 | ); | ||
54 | s = ls; | ||
55 | } | ||
56 | if (count & 2) | ||
57 | { | ||
58 | short *ss = s; | ||
59 | *ss++ = c; | ||
60 | s = ss; | ||
61 | } | ||
62 | if (count & 1) | ||
63 | { | ||
64 | char *cs = s; | ||
65 | *cs = c; | ||
66 | } | ||
67 | return xs; | ||
68 | } | ||
diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c new file mode 100644 index 000000000000..be4f275649e3 --- /dev/null +++ b/arch/m68k/lib/muldi3.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and | ||
2 | gcc-2.7.2.3/longlong.h which is: */ | ||
3 | /* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. | ||
4 | |||
5 | This file is part of GNU CC. | ||
6 | |||
7 | GNU CC is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2, or (at your option) | ||
10 | any later version. | ||
11 | |||
12 | GNU CC is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with GNU CC; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, 59 Temple Place - Suite 330, | ||
20 | Boston, MA 02111-1307, USA. */ | ||
21 | |||
22 | #define BITS_PER_UNIT 8 | ||
23 | |||
24 | #define umul_ppmm(w1, w0, u, v) \ | ||
25 | __asm__ ("mulu%.l %3,%1:%0" \ | ||
26 | : "=d" ((USItype)(w0)), \ | ||
27 | "=d" ((USItype)(w1)) \ | ||
28 | : "%0" ((USItype)(u)), \ | ||
29 | "dmi" ((USItype)(v))) | ||
30 | |||
31 | #define __umulsidi3(u, v) \ | ||
32 | ({DIunion __w; \ | ||
33 | umul_ppmm (__w.s.high, __w.s.low, u, v); \ | ||
34 | __w.ll; }) | ||
35 | |||
36 | typedef int SItype __attribute__ ((mode (SI))); | ||
37 | typedef unsigned int USItype __attribute__ ((mode (SI))); | ||
38 | typedef int DItype __attribute__ ((mode (DI))); | ||
39 | typedef int word_type __attribute__ ((mode (__word__))); | ||
40 | |||
41 | struct DIstruct {SItype high, low;}; | ||
42 | |||
43 | typedef union | ||
44 | { | ||
45 | struct DIstruct s; | ||
46 | DItype ll; | ||
47 | } DIunion; | ||
48 | |||
49 | DItype | ||
50 | __muldi3 (DItype u, DItype v) | ||
51 | { | ||
52 | DIunion w; | ||
53 | DIunion uu, vv; | ||
54 | |||
55 | uu.ll = u, | ||
56 | vv.ll = v; | ||
57 | |||
58 | w.ll = __umulsidi3 (uu.s.low, vv.s.low); | ||
59 | w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high | ||
60 | + (USItype) uu.s.high * (USItype) vv.s.low); | ||
61 | |||
62 | return w.ll; | ||
63 | } | ||
diff --git a/arch/m68k/lib/semaphore.S b/arch/m68k/lib/semaphore.S new file mode 100644 index 000000000000..0215624c1602 --- /dev/null +++ b/arch/m68k/lib/semaphore.S | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * linux/arch/m68k/lib/semaphore.S | ||
3 | * | ||
4 | * Copyright (C) 1996 Linus Torvalds | ||
5 | * | ||
6 | * m68k version by Andreas Schwab | ||
7 | */ | ||
8 | |||
9 | #include <linux/linkage.h> | ||
10 | #include <asm/semaphore.h> | ||
11 | |||
12 | /* | ||
13 | * The semaphore operations have a special calling sequence that | ||
14 | * allow us to do a simpler in-line version of them. These routines | ||
15 | * need to convert that sequence back into the C sequence when | ||
16 | * there is contention on the semaphore. | ||
17 | */ | ||
18 | ENTRY(__down_failed) | ||
19 | moveml %a0/%d0/%d1,-(%sp) | ||
20 | movel %a1,-(%sp) | ||
21 | jbsr __down | ||
22 | movel (%sp)+,%a1 | ||
23 | moveml (%sp)+,%a0/%d0/%d1 | ||
24 | rts | ||
25 | |||
26 | ENTRY(__down_failed_interruptible) | ||
27 | movel %a0,-(%sp) | ||
28 | movel %d1,-(%sp) | ||
29 | movel %a1,-(%sp) | ||
30 | jbsr __down_interruptible | ||
31 | movel (%sp)+,%a1 | ||
32 | movel (%sp)+,%d1 | ||
33 | movel (%sp)+,%a0 | ||
34 | rts | ||
35 | |||
36 | ENTRY(__down_failed_trylock) | ||
37 | movel %a0,-(%sp) | ||
38 | movel %d1,-(%sp) | ||
39 | movel %a1,-(%sp) | ||
40 | jbsr __down_trylock | ||
41 | movel (%sp)+,%a1 | ||
42 | movel (%sp)+,%d1 | ||
43 | movel (%sp)+,%a0 | ||
44 | rts | ||
45 | |||
46 | ENTRY(__up_wakeup) | ||
47 | moveml %a0/%d0/%d1,-(%sp) | ||
48 | movel %a1,-(%sp) | ||
49 | jbsr __up | ||
50 | movel (%sp)+,%a1 | ||
51 | moveml (%sp)+,%a0/%d0/%d1 | ||
52 | rts | ||
53 | |||