diff options
author | Greg Ungerer <gerg@uclinux.org> | 2011-03-21 23:39:27 -0400 |
---|---|---|
committer | Greg Ungerer <gerg@uclinux.org> | 2011-03-25 00:05:13 -0400 |
commit | 66d857b08b8c3ed5c72c361f863cce77d2a978d7 (patch) | |
tree | 47222d86f4d78dc0da31baf64188bd2e4b38ac1e /arch/m68k/lib | |
parent | d39dd11c3e6a7af5c20bfac40594db36cf270f42 (diff) |
m68k: merge m68k and m68knommu arch directories
There is a lot of common code that could be shared between the m68k
and m68knommu arch branches. It makes sense to merge the two branches
into a single directory structure so that we can more easily share
that common code.
This is a brute force merge, based on a script from Stephen King
<sfking@fdwdc.com>, which was originally written by Arnd Bergmann
<arnd@arndb.de>.
> The script was inspired by the script Sam Ravnborg used to merge the
> includes from m68knommu. For those files common to both arches but
> differing in content, the m68k version of the file is renamed to
> <file>_mm.<ext> and the m68knommu version of the file is moved into the
> corresponding m68k directory and renamed <file>_no.<ext> and a small
> wrapper file <file>.<ext> is used to select between the two version. Files
> that are common to both but don't differ are removed from the m68knommu
> tree and files and directories that are unique to the m68knommu tree are
> moved to the m68k tree. Finally, the arch/m68knommu tree is removed.
>
> To select between the the versions of the files, the wrapper uses
>
> #ifdef CONFIG_MMU
> #include <file>_mm.<ext>
> #else
> #include <file>_no.<ext>
> #endif
On top of this file merge I have done a simplistic merge of m68k and
m68knommu Kconfig, which primarily attempts to keep existing options and
menus in place. Other than a handful of options being moved it produces
identical .config outputs on m68k and m68knommu targets I tested it on.
With this in place there is now quite a bit of scope for merge cleanups
in future patches.
Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Diffstat (limited to 'arch/m68k/lib')
-rw-r--r-- | arch/m68k/lib/Makefile | 11 | ||||
-rw-r--r-- | arch/m68k/lib/Makefile_mm | 6 | ||||
-rw-r--r-- | arch/m68k/lib/Makefile_no | 7 | ||||
-rw-r--r-- | arch/m68k/lib/checksum.c | 430 | ||||
-rw-r--r-- | arch/m68k/lib/checksum_mm.c | 425 | ||||
-rw-r--r-- | arch/m68k/lib/checksum_no.c | 153 | ||||
-rw-r--r-- | arch/m68k/lib/delay.c | 21 | ||||
-rw-r--r-- | arch/m68k/lib/divsi3.S | 125 | ||||
-rw-r--r-- | arch/m68k/lib/memcpy.c | 62 | ||||
-rw-r--r-- | arch/m68k/lib/memmove.c | 105 | ||||
-rw-r--r-- | arch/m68k/lib/memset.c | 47 | ||||
-rw-r--r-- | arch/m68k/lib/modsi3.S | 113 | ||||
-rw-r--r-- | arch/m68k/lib/muldi3.c | 68 | ||||
-rw-r--r-- | arch/m68k/lib/muldi3_mm.c | 63 | ||||
-rw-r--r-- | arch/m68k/lib/muldi3_no.c | 86 | ||||
-rw-r--r-- | arch/m68k/lib/mulsi3.S | 110 | ||||
-rw-r--r-- | arch/m68k/lib/udivsi3.S | 162 | ||||
-rw-r--r-- | arch/m68k/lib/umodsi3.S | 113 |
18 files changed, 1613 insertions, 494 deletions
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile index af9abf8d9d98..1f95881d8437 100644 --- a/arch/m68k/lib/Makefile +++ b/arch/m68k/lib/Makefile | |||
@@ -1,6 +1,5 @@ | |||
1 | # | 1 | ifdef CONFIG_MMU |
2 | # Makefile for m68k-specific library files.. | 2 | include arch/m68k/lib/Makefile_mm |
3 | # | 3 | else |
4 | 4 | include arch/m68k/lib/Makefile_no | |
5 | lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ | 5 | endif |
6 | checksum.o string.o uaccess.o | ||
diff --git a/arch/m68k/lib/Makefile_mm b/arch/m68k/lib/Makefile_mm new file mode 100644 index 000000000000..af9abf8d9d98 --- /dev/null +++ b/arch/m68k/lib/Makefile_mm | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for m68k-specific library files.. | ||
3 | # | ||
4 | |||
5 | lib-y := ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ | ||
6 | checksum.o string.o uaccess.o | ||
diff --git a/arch/m68k/lib/Makefile_no b/arch/m68k/lib/Makefile_no new file mode 100644 index 000000000000..32d852e586d7 --- /dev/null +++ b/arch/m68k/lib/Makefile_no | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for m68knommu specific library files.. | ||
3 | # | ||
4 | |||
5 | lib-y := ashldi3.o ashrdi3.o lshrdi3.o \ | ||
6 | muldi3.o mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \ | ||
7 | checksum.o memcpy.o memmove.o memset.o delay.o | ||
diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c index 6216f12a756b..1297536060de 100644 --- a/arch/m68k/lib/checksum.c +++ b/arch/m68k/lib/checksum.c | |||
@@ -1,425 +1,5 @@ | |||
1 | /* | 1 | #ifdef CONFIG_MMU |
2 | * INET An implementation of the TCP/IP protocol suite for the LINUX | 2 | #include "checksum_mm.c" |
3 | * operating system. INET is implemented using the BSD Socket | 3 | #else |
4 | * interface as the means of communication with the user level. | 4 | #include "checksum_no.c" |
5 | * | 5 | #endif |
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 | __wsum csum_partial(const void *buff, int len, __wsum sum) | ||
43 | { | ||
44 | unsigned long tmp1, tmp2; | ||
45 | /* | ||
46 | * Experiments with ethernet and slip connections show that buff | ||
47 | * is aligned on either a 2-byte or 4-byte boundary. | ||
48 | */ | ||
49 | __asm__("movel %2,%3\n\t" | ||
50 | "btst #1,%3\n\t" /* Check alignment */ | ||
51 | "jeq 2f\n\t" | ||
52 | "subql #2,%1\n\t" /* buff%4==2: treat first word */ | ||
53 | "jgt 1f\n\t" | ||
54 | "addql #2,%1\n\t" /* len was == 2, treat only rest */ | ||
55 | "jra 4f\n" | ||
56 | "1:\t" | ||
57 | "addw %2@+,%0\n\t" /* add first word to sum */ | ||
58 | "clrl %3\n\t" | ||
59 | "addxl %3,%0\n" /* add X bit */ | ||
60 | "2:\t" | ||
61 | /* unrolled loop for the main part: do 8 longs at once */ | ||
62 | "movel %1,%3\n\t" /* save len in tmp1 */ | ||
63 | "lsrl #5,%1\n\t" /* len/32 */ | ||
64 | "jeq 2f\n\t" /* not enough... */ | ||
65 | "subql #1,%1\n" | ||
66 | "1:\t" | ||
67 | "movel %2@+,%4\n\t" | ||
68 | "addxl %4,%0\n\t" | ||
69 | "movel %2@+,%4\n\t" | ||
70 | "addxl %4,%0\n\t" | ||
71 | "movel %2@+,%4\n\t" | ||
72 | "addxl %4,%0\n\t" | ||
73 | "movel %2@+,%4\n\t" | ||
74 | "addxl %4,%0\n\t" | ||
75 | "movel %2@+,%4\n\t" | ||
76 | "addxl %4,%0\n\t" | ||
77 | "movel %2@+,%4\n\t" | ||
78 | "addxl %4,%0\n\t" | ||
79 | "movel %2@+,%4\n\t" | ||
80 | "addxl %4,%0\n\t" | ||
81 | "movel %2@+,%4\n\t" | ||
82 | "addxl %4,%0\n\t" | ||
83 | "dbra %1,1b\n\t" | ||
84 | "clrl %4\n\t" | ||
85 | "addxl %4,%0\n\t" /* add X bit */ | ||
86 | "clrw %1\n\t" | ||
87 | "subql #1,%1\n\t" | ||
88 | "jcc 1b\n" | ||
89 | "2:\t" | ||
90 | "movel %3,%1\n\t" /* restore len from tmp1 */ | ||
91 | "andw #0x1c,%3\n\t" /* number of rest longs */ | ||
92 | "jeq 4f\n\t" | ||
93 | "lsrw #2,%3\n\t" | ||
94 | "subqw #1,%3\n" | ||
95 | "3:\t" | ||
96 | /* loop for rest longs */ | ||
97 | "movel %2@+,%4\n\t" | ||
98 | "addxl %4,%0\n\t" | ||
99 | "dbra %3,3b\n\t" | ||
100 | "clrl %4\n\t" | ||
101 | "addxl %4,%0\n" /* add X bit */ | ||
102 | "4:\t" | ||
103 | /* now check for rest bytes that do not fit into longs */ | ||
104 | "andw #3,%1\n\t" | ||
105 | "jeq 7f\n\t" | ||
106 | "clrl %4\n\t" /* clear tmp2 for rest bytes */ | ||
107 | "subqw #2,%1\n\t" | ||
108 | "jlt 5f\n\t" | ||
109 | "movew %2@+,%4\n\t" /* have rest >= 2: get word */ | ||
110 | "swap %4\n\t" /* into bits 16..31 */ | ||
111 | "tstw %1\n\t" /* another byte? */ | ||
112 | "jeq 6f\n" | ||
113 | "5:\t" | ||
114 | "moveb %2@,%4\n\t" /* have odd rest: get byte */ | ||
115 | "lslw #8,%4\n\t" /* into bits 8..15; 16..31 untouched */ | ||
116 | "6:\t" | ||
117 | "addl %4,%0\n\t" /* now add rest long to sum */ | ||
118 | "clrl %4\n\t" | ||
119 | "addxl %4,%0\n" /* add X bit */ | ||
120 | "7:\t" | ||
121 | : "=d" (sum), "=d" (len), "=a" (buff), | ||
122 | "=&d" (tmp1), "=&d" (tmp2) | ||
123 | : "0" (sum), "1" (len), "2" (buff) | ||
124 | ); | ||
125 | return(sum); | ||
126 | } | ||
127 | |||
128 | EXPORT_SYMBOL(csum_partial); | ||
129 | |||
130 | |||
131 | /* | ||
132 | * copy from user space while checksumming, with exception handling. | ||
133 | */ | ||
134 | |||
135 | __wsum | ||
136 | csum_partial_copy_from_user(const void __user *src, void *dst, | ||
137 | int len, __wsum sum, int *csum_err) | ||
138 | { | ||
139 | /* | ||
140 | * GCC doesn't like more than 10 operands for the asm | ||
141 | * statements so we have to use tmp2 for the error | ||
142 | * code. | ||
143 | */ | ||
144 | unsigned long tmp1, tmp2; | ||
145 | |||
146 | __asm__("movel %2,%4\n\t" | ||
147 | "btst #1,%4\n\t" /* Check alignment */ | ||
148 | "jeq 2f\n\t" | ||
149 | "subql #2,%1\n\t" /* buff%4==2: treat first word */ | ||
150 | "jgt 1f\n\t" | ||
151 | "addql #2,%1\n\t" /* len was == 2, treat only rest */ | ||
152 | "jra 4f\n" | ||
153 | "1:\n" | ||
154 | "10:\t" | ||
155 | "movesw %2@+,%4\n\t" /* add first word to sum */ | ||
156 | "addw %4,%0\n\t" | ||
157 | "movew %4,%3@+\n\t" | ||
158 | "clrl %4\n\t" | ||
159 | "addxl %4,%0\n" /* add X bit */ | ||
160 | "2:\t" | ||
161 | /* unrolled loop for the main part: do 8 longs at once */ | ||
162 | "movel %1,%4\n\t" /* save len in tmp1 */ | ||
163 | "lsrl #5,%1\n\t" /* len/32 */ | ||
164 | "jeq 2f\n\t" /* not enough... */ | ||
165 | "subql #1,%1\n" | ||
166 | "1:\n" | ||
167 | "11:\t" | ||
168 | "movesl %2@+,%5\n\t" | ||
169 | "addxl %5,%0\n\t" | ||
170 | "movel %5,%3@+\n\t" | ||
171 | "12:\t" | ||
172 | "movesl %2@+,%5\n\t" | ||
173 | "addxl %5,%0\n\t" | ||
174 | "movel %5,%3@+\n\t" | ||
175 | "13:\t" | ||
176 | "movesl %2@+,%5\n\t" | ||
177 | "addxl %5,%0\n\t" | ||
178 | "movel %5,%3@+\n\t" | ||
179 | "14:\t" | ||
180 | "movesl %2@+,%5\n\t" | ||
181 | "addxl %5,%0\n\t" | ||
182 | "movel %5,%3@+\n\t" | ||
183 | "15:\t" | ||
184 | "movesl %2@+,%5\n\t" | ||
185 | "addxl %5,%0\n\t" | ||
186 | "movel %5,%3@+\n\t" | ||
187 | "16:\t" | ||
188 | "movesl %2@+,%5\n\t" | ||
189 | "addxl %5,%0\n\t" | ||
190 | "movel %5,%3@+\n\t" | ||
191 | "17:\t" | ||
192 | "movesl %2@+,%5\n\t" | ||
193 | "addxl %5,%0\n\t" | ||
194 | "movel %5,%3@+\n\t" | ||
195 | "18:\t" | ||
196 | "movesl %2@+,%5\n\t" | ||
197 | "addxl %5,%0\n\t" | ||
198 | "movel %5,%3@+\n\t" | ||
199 | "dbra %1,1b\n\t" | ||
200 | "clrl %5\n\t" | ||
201 | "addxl %5,%0\n\t" /* add X bit */ | ||
202 | "clrw %1\n\t" | ||
203 | "subql #1,%1\n\t" | ||
204 | "jcc 1b\n" | ||
205 | "2:\t" | ||
206 | "movel %4,%1\n\t" /* restore len from tmp1 */ | ||
207 | "andw #0x1c,%4\n\t" /* number of rest longs */ | ||
208 | "jeq 4f\n\t" | ||
209 | "lsrw #2,%4\n\t" | ||
210 | "subqw #1,%4\n" | ||
211 | "3:\n" | ||
212 | /* loop for rest longs */ | ||
213 | "19:\t" | ||
214 | "movesl %2@+,%5\n\t" | ||
215 | "addxl %5,%0\n\t" | ||
216 | "movel %5,%3@+\n\t" | ||
217 | "dbra %4,3b\n\t" | ||
218 | "clrl %5\n\t" | ||
219 | "addxl %5,%0\n" /* add X bit */ | ||
220 | "4:\t" | ||
221 | /* now check for rest bytes that do not fit into longs */ | ||
222 | "andw #3,%1\n\t" | ||
223 | "jeq 7f\n\t" | ||
224 | "clrl %5\n\t" /* clear tmp2 for rest bytes */ | ||
225 | "subqw #2,%1\n\t" | ||
226 | "jlt 5f\n\t" | ||
227 | "20:\t" | ||
228 | "movesw %2@+,%5\n\t" /* have rest >= 2: get word */ | ||
229 | "movew %5,%3@+\n\t" | ||
230 | "swap %5\n\t" /* into bits 16..31 */ | ||
231 | "tstw %1\n\t" /* another byte? */ | ||
232 | "jeq 6f\n" | ||
233 | "5:\n" | ||
234 | "21:\t" | ||
235 | "movesb %2@,%5\n\t" /* have odd rest: get byte */ | ||
236 | "moveb %5,%3@+\n\t" | ||
237 | "lslw #8,%5\n\t" /* into bits 8..15; 16..31 untouched */ | ||
238 | "6:\t" | ||
239 | "addl %5,%0\n\t" /* now add rest long to sum */ | ||
240 | "clrl %5\n\t" | ||
241 | "addxl %5,%0\n\t" /* add X bit */ | ||
242 | "7:\t" | ||
243 | "clrl %5\n" /* no error - clear return value */ | ||
244 | "8:\n" | ||
245 | ".section .fixup,\"ax\"\n" | ||
246 | ".even\n" | ||
247 | /* If any exception occurs zero out the rest. | ||
248 | Similarities with the code above are intentional :-) */ | ||
249 | "90:\t" | ||
250 | "clrw %3@+\n\t" | ||
251 | "movel %1,%4\n\t" | ||
252 | "lsrl #5,%1\n\t" | ||
253 | "jeq 1f\n\t" | ||
254 | "subql #1,%1\n" | ||
255 | "91:\t" | ||
256 | "clrl %3@+\n" | ||
257 | "92:\t" | ||
258 | "clrl %3@+\n" | ||
259 | "93:\t" | ||
260 | "clrl %3@+\n" | ||
261 | "94:\t" | ||
262 | "clrl %3@+\n" | ||
263 | "95:\t" | ||
264 | "clrl %3@+\n" | ||
265 | "96:\t" | ||
266 | "clrl %3@+\n" | ||
267 | "97:\t" | ||
268 | "clrl %3@+\n" | ||
269 | "98:\t" | ||
270 | "clrl %3@+\n\t" | ||
271 | "dbra %1,91b\n\t" | ||
272 | "clrw %1\n\t" | ||
273 | "subql #1,%1\n\t" | ||
274 | "jcc 91b\n" | ||
275 | "1:\t" | ||
276 | "movel %4,%1\n\t" | ||
277 | "andw #0x1c,%4\n\t" | ||
278 | "jeq 1f\n\t" | ||
279 | "lsrw #2,%4\n\t" | ||
280 | "subqw #1,%4\n" | ||
281 | "99:\t" | ||
282 | "clrl %3@+\n\t" | ||
283 | "dbra %4,99b\n\t" | ||
284 | "1:\t" | ||
285 | "andw #3,%1\n\t" | ||
286 | "jeq 9f\n" | ||
287 | "100:\t" | ||
288 | "clrw %3@+\n\t" | ||
289 | "tstw %1\n\t" | ||
290 | "jeq 9f\n" | ||
291 | "101:\t" | ||
292 | "clrb %3@+\n" | ||
293 | "9:\t" | ||
294 | #define STR(X) STR1(X) | ||
295 | #define STR1(X) #X | ||
296 | "moveq #-" STR(EFAULT) ",%5\n\t" | ||
297 | "jra 8b\n" | ||
298 | ".previous\n" | ||
299 | ".section __ex_table,\"a\"\n" | ||
300 | ".long 10b,90b\n" | ||
301 | ".long 11b,91b\n" | ||
302 | ".long 12b,92b\n" | ||
303 | ".long 13b,93b\n" | ||
304 | ".long 14b,94b\n" | ||
305 | ".long 15b,95b\n" | ||
306 | ".long 16b,96b\n" | ||
307 | ".long 17b,97b\n" | ||
308 | ".long 18b,98b\n" | ||
309 | ".long 19b,99b\n" | ||
310 | ".long 20b,100b\n" | ||
311 | ".long 21b,101b\n" | ||
312 | ".previous" | ||
313 | : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst), | ||
314 | "=&d" (tmp1), "=d" (tmp2) | ||
315 | : "0" (sum), "1" (len), "2" (src), "3" (dst) | ||
316 | ); | ||
317 | |||
318 | *csum_err = tmp2; | ||
319 | |||
320 | return(sum); | ||
321 | } | ||
322 | |||
323 | EXPORT_SYMBOL(csum_partial_copy_from_user); | ||
324 | |||
325 | |||
326 | /* | ||
327 | * copy from kernel space while checksumming, otherwise like csum_partial | ||
328 | */ | ||
329 | |||
330 | __wsum | ||
331 | csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) | ||
332 | { | ||
333 | unsigned long tmp1, tmp2; | ||
334 | __asm__("movel %2,%4\n\t" | ||
335 | "btst #1,%4\n\t" /* Check alignment */ | ||
336 | "jeq 2f\n\t" | ||
337 | "subql #2,%1\n\t" /* buff%4==2: treat first word */ | ||
338 | "jgt 1f\n\t" | ||
339 | "addql #2,%1\n\t" /* len was == 2, treat only rest */ | ||
340 | "jra 4f\n" | ||
341 | "1:\t" | ||
342 | "movew %2@+,%4\n\t" /* add first word to sum */ | ||
343 | "addw %4,%0\n\t" | ||
344 | "movew %4,%3@+\n\t" | ||
345 | "clrl %4\n\t" | ||
346 | "addxl %4,%0\n" /* add X bit */ | ||
347 | "2:\t" | ||
348 | /* unrolled loop for the main part: do 8 longs at once */ | ||
349 | "movel %1,%4\n\t" /* save len in tmp1 */ | ||
350 | "lsrl #5,%1\n\t" /* len/32 */ | ||
351 | "jeq 2f\n\t" /* not enough... */ | ||
352 | "subql #1,%1\n" | ||
353 | "1:\t" | ||
354 | "movel %2@+,%5\n\t" | ||
355 | "addxl %5,%0\n\t" | ||
356 | "movel %5,%3@+\n\t" | ||
357 | "movel %2@+,%5\n\t" | ||
358 | "addxl %5,%0\n\t" | ||
359 | "movel %5,%3@+\n\t" | ||
360 | "movel %2@+,%5\n\t" | ||
361 | "addxl %5,%0\n\t" | ||
362 | "movel %5,%3@+\n\t" | ||
363 | "movel %2@+,%5\n\t" | ||
364 | "addxl %5,%0\n\t" | ||
365 | "movel %5,%3@+\n\t" | ||
366 | "movel %2@+,%5\n\t" | ||
367 | "addxl %5,%0\n\t" | ||
368 | "movel %5,%3@+\n\t" | ||
369 | "movel %2@+,%5\n\t" | ||
370 | "addxl %5,%0\n\t" | ||
371 | "movel %5,%3@+\n\t" | ||
372 | "movel %2@+,%5\n\t" | ||
373 | "addxl %5,%0\n\t" | ||
374 | "movel %5,%3@+\n\t" | ||
375 | "movel %2@+,%5\n\t" | ||
376 | "addxl %5,%0\n\t" | ||
377 | "movel %5,%3@+\n\t" | ||
378 | "dbra %1,1b\n\t" | ||
379 | "clrl %5\n\t" | ||
380 | "addxl %5,%0\n\t" /* add X bit */ | ||
381 | "clrw %1\n\t" | ||
382 | "subql #1,%1\n\t" | ||
383 | "jcc 1b\n" | ||
384 | "2:\t" | ||
385 | "movel %4,%1\n\t" /* restore len from tmp1 */ | ||
386 | "andw #0x1c,%4\n\t" /* number of rest longs */ | ||
387 | "jeq 4f\n\t" | ||
388 | "lsrw #2,%4\n\t" | ||
389 | "subqw #1,%4\n" | ||
390 | "3:\t" | ||
391 | /* loop for rest longs */ | ||
392 | "movel %2@+,%5\n\t" | ||
393 | "addxl %5,%0\n\t" | ||
394 | "movel %5,%3@+\n\t" | ||
395 | "dbra %4,3b\n\t" | ||
396 | "clrl %5\n\t" | ||
397 | "addxl %5,%0\n" /* add X bit */ | ||
398 | "4:\t" | ||
399 | /* now check for rest bytes that do not fit into longs */ | ||
400 | "andw #3,%1\n\t" | ||
401 | "jeq 7f\n\t" | ||
402 | "clrl %5\n\t" /* clear tmp2 for rest bytes */ | ||
403 | "subqw #2,%1\n\t" | ||
404 | "jlt 5f\n\t" | ||
405 | "movew %2@+,%5\n\t" /* have rest >= 2: get word */ | ||
406 | "movew %5,%3@+\n\t" | ||
407 | "swap %5\n\t" /* into bits 16..31 */ | ||
408 | "tstw %1\n\t" /* another byte? */ | ||
409 | "jeq 6f\n" | ||
410 | "5:\t" | ||
411 | "moveb %2@,%5\n\t" /* have odd rest: get byte */ | ||
412 | "moveb %5,%3@+\n\t" | ||
413 | "lslw #8,%5\n" /* into bits 8..15; 16..31 untouched */ | ||
414 | "6:\t" | ||
415 | "addl %5,%0\n\t" /* now add rest long to sum */ | ||
416 | "clrl %5\n\t" | ||
417 | "addxl %5,%0\n" /* add X bit */ | ||
418 | "7:\t" | ||
419 | : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst), | ||
420 | "=&d" (tmp1), "=&d" (tmp2) | ||
421 | : "0" (sum), "1" (len), "2" (src), "3" (dst) | ||
422 | ); | ||
423 | return(sum); | ||
424 | } | ||
425 | EXPORT_SYMBOL(csum_partial_copy_nocheck); | ||
diff --git a/arch/m68k/lib/checksum_mm.c b/arch/m68k/lib/checksum_mm.c new file mode 100644 index 000000000000..6216f12a756b --- /dev/null +++ b/arch/m68k/lib/checksum_mm.c | |||
@@ -0,0 +1,425 @@ | |||
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 | __wsum csum_partial(const void *buff, int len, __wsum sum) | ||
43 | { | ||
44 | unsigned long tmp1, tmp2; | ||
45 | /* | ||
46 | * Experiments with ethernet and slip connections show that buff | ||
47 | * is aligned on either a 2-byte or 4-byte boundary. | ||
48 | */ | ||
49 | __asm__("movel %2,%3\n\t" | ||
50 | "btst #1,%3\n\t" /* Check alignment */ | ||
51 | "jeq 2f\n\t" | ||
52 | "subql #2,%1\n\t" /* buff%4==2: treat first word */ | ||
53 | "jgt 1f\n\t" | ||
54 | "addql #2,%1\n\t" /* len was == 2, treat only rest */ | ||
55 | "jra 4f\n" | ||
56 | "1:\t" | ||
57 | "addw %2@+,%0\n\t" /* add first word to sum */ | ||
58 | "clrl %3\n\t" | ||
59 | "addxl %3,%0\n" /* add X bit */ | ||
60 | "2:\t" | ||
61 | /* unrolled loop for the main part: do 8 longs at once */ | ||
62 | "movel %1,%3\n\t" /* save len in tmp1 */ | ||
63 | "lsrl #5,%1\n\t" /* len/32 */ | ||
64 | "jeq 2f\n\t" /* not enough... */ | ||
65 | "subql #1,%1\n" | ||
66 | "1:\t" | ||
67 | "movel %2@+,%4\n\t" | ||
68 | "addxl %4,%0\n\t" | ||
69 | "movel %2@+,%4\n\t" | ||
70 | "addxl %4,%0\n\t" | ||
71 | "movel %2@+,%4\n\t" | ||
72 | "addxl %4,%0\n\t" | ||
73 | "movel %2@+,%4\n\t" | ||
74 | "addxl %4,%0\n\t" | ||
75 | "movel %2@+,%4\n\t" | ||
76 | "addxl %4,%0\n\t" | ||
77 | "movel %2@+,%4\n\t" | ||
78 | "addxl %4,%0\n\t" | ||
79 | "movel %2@+,%4\n\t" | ||
80 | "addxl %4,%0\n\t" | ||
81 | "movel %2@+,%4\n\t" | ||
82 | "addxl %4,%0\n\t" | ||
83 | "dbra %1,1b\n\t" | ||
84 | "clrl %4\n\t" | ||
85 | "addxl %4,%0\n\t" /* add X bit */ | ||
86 | "clrw %1\n\t" | ||
87 | "subql #1,%1\n\t" | ||
88 | "jcc 1b\n" | ||
89 | "2:\t" | ||
90 | "movel %3,%1\n\t" /* restore len from tmp1 */ | ||
91 | "andw #0x1c,%3\n\t" /* number of rest longs */ | ||
92 | "jeq 4f\n\t" | ||
93 | "lsrw #2,%3\n\t" | ||
94 | "subqw #1,%3\n" | ||
95 | "3:\t" | ||
96 | /* loop for rest longs */ | ||
97 | "movel %2@+,%4\n\t" | ||
98 | "addxl %4,%0\n\t" | ||
99 | "dbra %3,3b\n\t" | ||
100 | "clrl %4\n\t" | ||
101 | "addxl %4,%0\n" /* add X bit */ | ||
102 | "4:\t" | ||
103 | /* now check for rest bytes that do not fit into longs */ | ||
104 | "andw #3,%1\n\t" | ||
105 | "jeq 7f\n\t" | ||
106 | "clrl %4\n\t" /* clear tmp2 for rest bytes */ | ||
107 | "subqw #2,%1\n\t" | ||
108 | "jlt 5f\n\t" | ||
109 | "movew %2@+,%4\n\t" /* have rest >= 2: get word */ | ||
110 | "swap %4\n\t" /* into bits 16..31 */ | ||
111 | "tstw %1\n\t" /* another byte? */ | ||
112 | "jeq 6f\n" | ||
113 | "5:\t" | ||
114 | "moveb %2@,%4\n\t" /* have odd rest: get byte */ | ||
115 | "lslw #8,%4\n\t" /* into bits 8..15; 16..31 untouched */ | ||
116 | "6:\t" | ||
117 | "addl %4,%0\n\t" /* now add rest long to sum */ | ||
118 | "clrl %4\n\t" | ||
119 | "addxl %4,%0\n" /* add X bit */ | ||
120 | "7:\t" | ||
121 | : "=d" (sum), "=d" (len), "=a" (buff), | ||
122 | "=&d" (tmp1), "=&d" (tmp2) | ||
123 | : "0" (sum), "1" (len), "2" (buff) | ||
124 | ); | ||
125 | return(sum); | ||
126 | } | ||
127 | |||
128 | EXPORT_SYMBOL(csum_partial); | ||
129 | |||
130 | |||
131 | /* | ||
132 | * copy from user space while checksumming, with exception handling. | ||
133 | */ | ||
134 | |||
135 | __wsum | ||
136 | csum_partial_copy_from_user(const void __user *src, void *dst, | ||
137 | int len, __wsum sum, int *csum_err) | ||
138 | { | ||
139 | /* | ||
140 | * GCC doesn't like more than 10 operands for the asm | ||
141 | * statements so we have to use tmp2 for the error | ||
142 | * code. | ||
143 | */ | ||
144 | unsigned long tmp1, tmp2; | ||
145 | |||
146 | __asm__("movel %2,%4\n\t" | ||
147 | "btst #1,%4\n\t" /* Check alignment */ | ||
148 | "jeq 2f\n\t" | ||
149 | "subql #2,%1\n\t" /* buff%4==2: treat first word */ | ||
150 | "jgt 1f\n\t" | ||
151 | "addql #2,%1\n\t" /* len was == 2, treat only rest */ | ||
152 | "jra 4f\n" | ||
153 | "1:\n" | ||
154 | "10:\t" | ||
155 | "movesw %2@+,%4\n\t" /* add first word to sum */ | ||
156 | "addw %4,%0\n\t" | ||
157 | "movew %4,%3@+\n\t" | ||
158 | "clrl %4\n\t" | ||
159 | "addxl %4,%0\n" /* add X bit */ | ||
160 | "2:\t" | ||
161 | /* unrolled loop for the main part: do 8 longs at once */ | ||
162 | "movel %1,%4\n\t" /* save len in tmp1 */ | ||
163 | "lsrl #5,%1\n\t" /* len/32 */ | ||
164 | "jeq 2f\n\t" /* not enough... */ | ||
165 | "subql #1,%1\n" | ||
166 | "1:\n" | ||
167 | "11:\t" | ||
168 | "movesl %2@+,%5\n\t" | ||
169 | "addxl %5,%0\n\t" | ||
170 | "movel %5,%3@+\n\t" | ||
171 | "12:\t" | ||
172 | "movesl %2@+,%5\n\t" | ||
173 | "addxl %5,%0\n\t" | ||
174 | "movel %5,%3@+\n\t" | ||
175 | "13:\t" | ||
176 | "movesl %2@+,%5\n\t" | ||
177 | "addxl %5,%0\n\t" | ||
178 | "movel %5,%3@+\n\t" | ||
179 | "14:\t" | ||
180 | "movesl %2@+,%5\n\t" | ||
181 | "addxl %5,%0\n\t" | ||
182 | "movel %5,%3@+\n\t" | ||
183 | "15:\t" | ||
184 | "movesl %2@+,%5\n\t" | ||
185 | "addxl %5,%0\n\t" | ||
186 | "movel %5,%3@+\n\t" | ||
187 | "16:\t" | ||
188 | "movesl %2@+,%5\n\t" | ||
189 | "addxl %5,%0\n\t" | ||
190 | "movel %5,%3@+\n\t" | ||
191 | "17:\t" | ||
192 | "movesl %2@+,%5\n\t" | ||
193 | "addxl %5,%0\n\t" | ||
194 | "movel %5,%3@+\n\t" | ||
195 | "18:\t" | ||
196 | "movesl %2@+,%5\n\t" | ||
197 | "addxl %5,%0\n\t" | ||
198 | "movel %5,%3@+\n\t" | ||
199 | "dbra %1,1b\n\t" | ||
200 | "clrl %5\n\t" | ||
201 | "addxl %5,%0\n\t" /* add X bit */ | ||
202 | "clrw %1\n\t" | ||
203 | "subql #1,%1\n\t" | ||
204 | "jcc 1b\n" | ||
205 | "2:\t" | ||
206 | "movel %4,%1\n\t" /* restore len from tmp1 */ | ||
207 | "andw #0x1c,%4\n\t" /* number of rest longs */ | ||
208 | "jeq 4f\n\t" | ||
209 | "lsrw #2,%4\n\t" | ||
210 | "subqw #1,%4\n" | ||
211 | "3:\n" | ||
212 | /* loop for rest longs */ | ||
213 | "19:\t" | ||
214 | "movesl %2@+,%5\n\t" | ||
215 | "addxl %5,%0\n\t" | ||
216 | "movel %5,%3@+\n\t" | ||
217 | "dbra %4,3b\n\t" | ||
218 | "clrl %5\n\t" | ||
219 | "addxl %5,%0\n" /* add X bit */ | ||
220 | "4:\t" | ||
221 | /* now check for rest bytes that do not fit into longs */ | ||
222 | "andw #3,%1\n\t" | ||
223 | "jeq 7f\n\t" | ||
224 | "clrl %5\n\t" /* clear tmp2 for rest bytes */ | ||
225 | "subqw #2,%1\n\t" | ||
226 | "jlt 5f\n\t" | ||
227 | "20:\t" | ||
228 | "movesw %2@+,%5\n\t" /* have rest >= 2: get word */ | ||
229 | "movew %5,%3@+\n\t" | ||
230 | "swap %5\n\t" /* into bits 16..31 */ | ||
231 | "tstw %1\n\t" /* another byte? */ | ||
232 | "jeq 6f\n" | ||
233 | "5:\n" | ||
234 | "21:\t" | ||
235 | "movesb %2@,%5\n\t" /* have odd rest: get byte */ | ||
236 | "moveb %5,%3@+\n\t" | ||
237 | "lslw #8,%5\n\t" /* into bits 8..15; 16..31 untouched */ | ||
238 | "6:\t" | ||
239 | "addl %5,%0\n\t" /* now add rest long to sum */ | ||
240 | "clrl %5\n\t" | ||
241 | "addxl %5,%0\n\t" /* add X bit */ | ||
242 | "7:\t" | ||
243 | "clrl %5\n" /* no error - clear return value */ | ||
244 | "8:\n" | ||
245 | ".section .fixup,\"ax\"\n" | ||
246 | ".even\n" | ||
247 | /* If any exception occurs zero out the rest. | ||
248 | Similarities with the code above are intentional :-) */ | ||
249 | "90:\t" | ||
250 | "clrw %3@+\n\t" | ||
251 | "movel %1,%4\n\t" | ||
252 | "lsrl #5,%1\n\t" | ||
253 | "jeq 1f\n\t" | ||
254 | "subql #1,%1\n" | ||
255 | "91:\t" | ||
256 | "clrl %3@+\n" | ||
257 | "92:\t" | ||
258 | "clrl %3@+\n" | ||
259 | "93:\t" | ||
260 | "clrl %3@+\n" | ||
261 | "94:\t" | ||
262 | "clrl %3@+\n" | ||
263 | "95:\t" | ||
264 | "clrl %3@+\n" | ||
265 | "96:\t" | ||
266 | "clrl %3@+\n" | ||
267 | "97:\t" | ||
268 | "clrl %3@+\n" | ||
269 | "98:\t" | ||
270 | "clrl %3@+\n\t" | ||
271 | "dbra %1,91b\n\t" | ||
272 | "clrw %1\n\t" | ||
273 | "subql #1,%1\n\t" | ||
274 | "jcc 91b\n" | ||
275 | "1:\t" | ||
276 | "movel %4,%1\n\t" | ||
277 | "andw #0x1c,%4\n\t" | ||
278 | "jeq 1f\n\t" | ||
279 | "lsrw #2,%4\n\t" | ||
280 | "subqw #1,%4\n" | ||
281 | "99:\t" | ||
282 | "clrl %3@+\n\t" | ||
283 | "dbra %4,99b\n\t" | ||
284 | "1:\t" | ||
285 | "andw #3,%1\n\t" | ||
286 | "jeq 9f\n" | ||
287 | "100:\t" | ||
288 | "clrw %3@+\n\t" | ||
289 | "tstw %1\n\t" | ||
290 | "jeq 9f\n" | ||
291 | "101:\t" | ||
292 | "clrb %3@+\n" | ||
293 | "9:\t" | ||
294 | #define STR(X) STR1(X) | ||
295 | #define STR1(X) #X | ||
296 | "moveq #-" STR(EFAULT) ",%5\n\t" | ||
297 | "jra 8b\n" | ||
298 | ".previous\n" | ||
299 | ".section __ex_table,\"a\"\n" | ||
300 | ".long 10b,90b\n" | ||
301 | ".long 11b,91b\n" | ||
302 | ".long 12b,92b\n" | ||
303 | ".long 13b,93b\n" | ||
304 | ".long 14b,94b\n" | ||
305 | ".long 15b,95b\n" | ||
306 | ".long 16b,96b\n" | ||
307 | ".long 17b,97b\n" | ||
308 | ".long 18b,98b\n" | ||
309 | ".long 19b,99b\n" | ||
310 | ".long 20b,100b\n" | ||
311 | ".long 21b,101b\n" | ||
312 | ".previous" | ||
313 | : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst), | ||
314 | "=&d" (tmp1), "=d" (tmp2) | ||
315 | : "0" (sum), "1" (len), "2" (src), "3" (dst) | ||
316 | ); | ||
317 | |||
318 | *csum_err = tmp2; | ||
319 | |||
320 | return(sum); | ||
321 | } | ||
322 | |||
323 | EXPORT_SYMBOL(csum_partial_copy_from_user); | ||
324 | |||
325 | |||
326 | /* | ||
327 | * copy from kernel space while checksumming, otherwise like csum_partial | ||
328 | */ | ||
329 | |||
330 | __wsum | ||
331 | csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) | ||
332 | { | ||
333 | unsigned long tmp1, tmp2; | ||
334 | __asm__("movel %2,%4\n\t" | ||
335 | "btst #1,%4\n\t" /* Check alignment */ | ||
336 | "jeq 2f\n\t" | ||
337 | "subql #2,%1\n\t" /* buff%4==2: treat first word */ | ||
338 | "jgt 1f\n\t" | ||
339 | "addql #2,%1\n\t" /* len was == 2, treat only rest */ | ||
340 | "jra 4f\n" | ||
341 | "1:\t" | ||
342 | "movew %2@+,%4\n\t" /* add first word to sum */ | ||
343 | "addw %4,%0\n\t" | ||
344 | "movew %4,%3@+\n\t" | ||
345 | "clrl %4\n\t" | ||
346 | "addxl %4,%0\n" /* add X bit */ | ||
347 | "2:\t" | ||
348 | /* unrolled loop for the main part: do 8 longs at once */ | ||
349 | "movel %1,%4\n\t" /* save len in tmp1 */ | ||
350 | "lsrl #5,%1\n\t" /* len/32 */ | ||
351 | "jeq 2f\n\t" /* not enough... */ | ||
352 | "subql #1,%1\n" | ||
353 | "1:\t" | ||
354 | "movel %2@+,%5\n\t" | ||
355 | "addxl %5,%0\n\t" | ||
356 | "movel %5,%3@+\n\t" | ||
357 | "movel %2@+,%5\n\t" | ||
358 | "addxl %5,%0\n\t" | ||
359 | "movel %5,%3@+\n\t" | ||
360 | "movel %2@+,%5\n\t" | ||
361 | "addxl %5,%0\n\t" | ||
362 | "movel %5,%3@+\n\t" | ||
363 | "movel %2@+,%5\n\t" | ||
364 | "addxl %5,%0\n\t" | ||
365 | "movel %5,%3@+\n\t" | ||
366 | "movel %2@+,%5\n\t" | ||
367 | "addxl %5,%0\n\t" | ||
368 | "movel %5,%3@+\n\t" | ||
369 | "movel %2@+,%5\n\t" | ||
370 | "addxl %5,%0\n\t" | ||
371 | "movel %5,%3@+\n\t" | ||
372 | "movel %2@+,%5\n\t" | ||
373 | "addxl %5,%0\n\t" | ||
374 | "movel %5,%3@+\n\t" | ||
375 | "movel %2@+,%5\n\t" | ||
376 | "addxl %5,%0\n\t" | ||
377 | "movel %5,%3@+\n\t" | ||
378 | "dbra %1,1b\n\t" | ||
379 | "clrl %5\n\t" | ||
380 | "addxl %5,%0\n\t" /* add X bit */ | ||
381 | "clrw %1\n\t" | ||
382 | "subql #1,%1\n\t" | ||
383 | "jcc 1b\n" | ||
384 | "2:\t" | ||
385 | "movel %4,%1\n\t" /* restore len from tmp1 */ | ||
386 | "andw #0x1c,%4\n\t" /* number of rest longs */ | ||
387 | "jeq 4f\n\t" | ||
388 | "lsrw #2,%4\n\t" | ||
389 | "subqw #1,%4\n" | ||
390 | "3:\t" | ||
391 | /* loop for rest longs */ | ||
392 | "movel %2@+,%5\n\t" | ||
393 | "addxl %5,%0\n\t" | ||
394 | "movel %5,%3@+\n\t" | ||
395 | "dbra %4,3b\n\t" | ||
396 | "clrl %5\n\t" | ||
397 | "addxl %5,%0\n" /* add X bit */ | ||
398 | "4:\t" | ||
399 | /* now check for rest bytes that do not fit into longs */ | ||
400 | "andw #3,%1\n\t" | ||
401 | "jeq 7f\n\t" | ||
402 | "clrl %5\n\t" /* clear tmp2 for rest bytes */ | ||
403 | "subqw #2,%1\n\t" | ||
404 | "jlt 5f\n\t" | ||
405 | "movew %2@+,%5\n\t" /* have rest >= 2: get word */ | ||
406 | "movew %5,%3@+\n\t" | ||
407 | "swap %5\n\t" /* into bits 16..31 */ | ||
408 | "tstw %1\n\t" /* another byte? */ | ||
409 | "jeq 6f\n" | ||
410 | "5:\t" | ||
411 | "moveb %2@,%5\n\t" /* have odd rest: get byte */ | ||
412 | "moveb %5,%3@+\n\t" | ||
413 | "lslw #8,%5\n" /* into bits 8..15; 16..31 untouched */ | ||
414 | "6:\t" | ||
415 | "addl %5,%0\n\t" /* now add rest long to sum */ | ||
416 | "clrl %5\n\t" | ||
417 | "addxl %5,%0\n" /* add X bit */ | ||
418 | "7:\t" | ||
419 | : "=d" (sum), "=d" (len), "=a" (src), "=a" (dst), | ||
420 | "=&d" (tmp1), "=&d" (tmp2) | ||
421 | : "0" (sum), "1" (len), "2" (src), "3" (dst) | ||
422 | ); | ||
423 | return(sum); | ||
424 | } | ||
425 | EXPORT_SYMBOL(csum_partial_copy_nocheck); | ||
diff --git a/arch/m68k/lib/checksum_no.c b/arch/m68k/lib/checksum_no.c new file mode 100644 index 000000000000..eccf25d3d73e --- /dev/null +++ b/arch/m68k/lib/checksum_no.c | |||
@@ -0,0 +1,153 @@ | |||
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 choose these | ||
23 | * 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 | |||
31 | /* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most | ||
32 | of the assembly has to go. */ | ||
33 | |||
34 | #include <linux/module.h> | ||
35 | #include <net/checksum.h> | ||
36 | |||
37 | static inline unsigned short from32to16(unsigned long x) | ||
38 | { | ||
39 | /* add up 16-bit and 16-bit for 16+c bit */ | ||
40 | x = (x & 0xffff) + (x >> 16); | ||
41 | /* add up carry.. */ | ||
42 | x = (x & 0xffff) + (x >> 16); | ||
43 | return x; | ||
44 | } | ||
45 | |||
46 | static unsigned long do_csum(const unsigned char * buff, int len) | ||
47 | { | ||
48 | int odd, count; | ||
49 | unsigned long result = 0; | ||
50 | |||
51 | if (len <= 0) | ||
52 | goto out; | ||
53 | odd = 1 & (unsigned long) buff; | ||
54 | if (odd) { | ||
55 | result = *buff; | ||
56 | len--; | ||
57 | buff++; | ||
58 | } | ||
59 | count = len >> 1; /* nr of 16-bit words.. */ | ||
60 | if (count) { | ||
61 | if (2 & (unsigned long) buff) { | ||
62 | result += *(unsigned short *) buff; | ||
63 | count--; | ||
64 | len -= 2; | ||
65 | buff += 2; | ||
66 | } | ||
67 | count >>= 1; /* nr of 32-bit words.. */ | ||
68 | if (count) { | ||
69 | unsigned long carry = 0; | ||
70 | do { | ||
71 | unsigned long w = *(unsigned long *) buff; | ||
72 | count--; | ||
73 | buff += 4; | ||
74 | result += carry; | ||
75 | result += w; | ||
76 | carry = (w > result); | ||
77 | } while (count); | ||
78 | result += carry; | ||
79 | result = (result & 0xffff) + (result >> 16); | ||
80 | } | ||
81 | if (len & 2) { | ||
82 | result += *(unsigned short *) buff; | ||
83 | buff += 2; | ||
84 | } | ||
85 | } | ||
86 | if (len & 1) | ||
87 | result += (*buff << 8); | ||
88 | result = from32to16(result); | ||
89 | if (odd) | ||
90 | result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); | ||
91 | out: | ||
92 | return result; | ||
93 | } | ||
94 | |||
95 | #ifdef CONFIG_COLDFIRE | ||
96 | /* | ||
97 | * This is a version of ip_compute_csum() optimized for IP headers, | ||
98 | * which always checksum on 4 octet boundaries. | ||
99 | */ | ||
100 | __sum16 ip_fast_csum(const void *iph, unsigned int ihl) | ||
101 | { | ||
102 | return (__force __sum16)~do_csum(iph,ihl*4); | ||
103 | } | ||
104 | #endif | ||
105 | |||
106 | /* | ||
107 | * computes the checksum of a memory block at buff, length len, | ||
108 | * and adds in "sum" (32-bit) | ||
109 | * | ||
110 | * returns a 32-bit number suitable for feeding into itself | ||
111 | * or csum_tcpudp_magic | ||
112 | * | ||
113 | * this function must be called with even lengths, except | ||
114 | * for the last fragment, which may be odd | ||
115 | * | ||
116 | * it's best to have buff aligned on a 32-bit boundary | ||
117 | */ | ||
118 | __wsum csum_partial(const void *buff, int len, __wsum sum) | ||
119 | { | ||
120 | unsigned int result = do_csum(buff, len); | ||
121 | |||
122 | /* add in old sum, and carry.. */ | ||
123 | result += (__force u32)sum; | ||
124 | if ((__force u32)sum > result) | ||
125 | result += 1; | ||
126 | return (__force __wsum)result; | ||
127 | } | ||
128 | |||
129 | EXPORT_SYMBOL(csum_partial); | ||
130 | |||
131 | /* | ||
132 | * copy from fs while checksumming, otherwise like csum_partial | ||
133 | */ | ||
134 | |||
135 | __wsum | ||
136 | csum_partial_copy_from_user(const void __user *src, void *dst, | ||
137 | int len, __wsum sum, int *csum_err) | ||
138 | { | ||
139 | if (csum_err) *csum_err = 0; | ||
140 | memcpy(dst, (__force const void *)src, len); | ||
141 | return csum_partial(dst, len, sum); | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * copy from ds while checksumming, otherwise like csum_partial | ||
146 | */ | ||
147 | |||
148 | __wsum | ||
149 | csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) | ||
150 | { | ||
151 | memcpy(dst, src, len); | ||
152 | return csum_partial(dst, len, sum); | ||
153 | } | ||
diff --git a/arch/m68k/lib/delay.c b/arch/m68k/lib/delay.c new file mode 100644 index 000000000000..5bd5472d38a0 --- /dev/null +++ b/arch/m68k/lib/delay.c | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * arch/m68knommu/lib/delay.c | ||
3 | * | ||
4 | * (C) Copyright 2004, Greg Ungerer <gerg@snapgear.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <asm/param.h> | ||
13 | #include <asm/delay.h> | ||
14 | |||
15 | EXPORT_SYMBOL(udelay); | ||
16 | |||
17 | void udelay(unsigned long usecs) | ||
18 | { | ||
19 | _udelay(usecs); | ||
20 | } | ||
21 | |||
diff --git a/arch/m68k/lib/divsi3.S b/arch/m68k/lib/divsi3.S new file mode 100644 index 000000000000..ec307b61991e --- /dev/null +++ b/arch/m68k/lib/divsi3.S | |||
@@ -0,0 +1,125 @@ | |||
1 | /* libgcc1 routines for 68000 w/o floating-point hardware. | ||
2 | Copyright (C) 1994, 1996, 1997, 1998 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 it | ||
7 | under the terms of the GNU General Public License as published by the | ||
8 | Free Software Foundation; either version 2, or (at your option) any | ||
9 | later version. | ||
10 | |||
11 | In addition to the permissions in the GNU General Public License, the | ||
12 | Free Software Foundation gives you unlimited permission to link the | ||
13 | compiled version of this file with other programs, and to distribute | ||
14 | those programs without any restriction coming from the use of this | ||
15 | file. (The General Public License restrictions do apply in other | ||
16 | respects; for example, they cover modification of the file, and | ||
17 | distribution when not linked into another program.) | ||
18 | |||
19 | This file is distributed in the hope that it will be useful, but | ||
20 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
22 | General Public License for more details. | ||
23 | |||
24 | You should have received a copy of the GNU General Public License | ||
25 | along with this program; see the file COPYING. If not, write to | ||
26 | the Free Software Foundation, 59 Temple Place - Suite 330, | ||
27 | Boston, MA 02111-1307, USA. */ | ||
28 | |||
29 | /* As a special exception, if you link this library with files | ||
30 | compiled with GCC to produce an executable, this does not cause | ||
31 | the resulting executable to be covered by the GNU General Public License. | ||
32 | This exception does not however invalidate any other reasons why | ||
33 | the executable file might be covered by the GNU General Public License. */ | ||
34 | |||
35 | /* Use this one for any 680x0; assumes no floating point hardware. | ||
36 | The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. | ||
37 | Some of this code comes from MINIX, via the folks at ericsson. | ||
38 | D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992 | ||
39 | */ | ||
40 | |||
41 | /* These are predefined by new versions of GNU cpp. */ | ||
42 | |||
43 | #ifndef __USER_LABEL_PREFIX__ | ||
44 | #define __USER_LABEL_PREFIX__ _ | ||
45 | #endif | ||
46 | |||
47 | #ifndef __REGISTER_PREFIX__ | ||
48 | #define __REGISTER_PREFIX__ | ||
49 | #endif | ||
50 | |||
51 | #ifndef __IMMEDIATE_PREFIX__ | ||
52 | #define __IMMEDIATE_PREFIX__ # | ||
53 | #endif | ||
54 | |||
55 | /* ANSI concatenation macros. */ | ||
56 | |||
57 | #define CONCAT1(a, b) CONCAT2(a, b) | ||
58 | #define CONCAT2(a, b) a ## b | ||
59 | |||
60 | /* Use the right prefix for global labels. */ | ||
61 | |||
62 | #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) | ||
63 | |||
64 | /* Use the right prefix for registers. */ | ||
65 | |||
66 | #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) | ||
67 | |||
68 | /* Use the right prefix for immediate values. */ | ||
69 | |||
70 | #define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) | ||
71 | |||
72 | #define d0 REG (d0) | ||
73 | #define d1 REG (d1) | ||
74 | #define d2 REG (d2) | ||
75 | #define d3 REG (d3) | ||
76 | #define d4 REG (d4) | ||
77 | #define d5 REG (d5) | ||
78 | #define d6 REG (d6) | ||
79 | #define d7 REG (d7) | ||
80 | #define a0 REG (a0) | ||
81 | #define a1 REG (a1) | ||
82 | #define a2 REG (a2) | ||
83 | #define a3 REG (a3) | ||
84 | #define a4 REG (a4) | ||
85 | #define a5 REG (a5) | ||
86 | #define a6 REG (a6) | ||
87 | #define fp REG (fp) | ||
88 | #define sp REG (sp) | ||
89 | |||
90 | .text | ||
91 | .proc | ||
92 | .globl SYM (__divsi3) | ||
93 | SYM (__divsi3): | ||
94 | movel d2, sp@- | ||
95 | |||
96 | moveq IMM (1), d2 /* sign of result stored in d2 (=1 or =-1) */ | ||
97 | movel sp@(12), d1 /* d1 = divisor */ | ||
98 | jpl L1 | ||
99 | negl d1 | ||
100 | #if !(defined(__mcf5200__) || defined(__mcoldfire__)) | ||
101 | negb d2 /* change sign because divisor <0 */ | ||
102 | #else | ||
103 | negl d2 /* change sign because divisor <0 */ | ||
104 | #endif | ||
105 | L1: movel sp@(8), d0 /* d0 = dividend */ | ||
106 | jpl L2 | ||
107 | negl d0 | ||
108 | #if !(defined(__mcf5200__) || defined(__mcoldfire__)) | ||
109 | negb d2 | ||
110 | #else | ||
111 | negl d2 | ||
112 | #endif | ||
113 | |||
114 | L2: movel d1, sp@- | ||
115 | movel d0, sp@- | ||
116 | jbsr SYM (__udivsi3) /* divide abs(dividend) by abs(divisor) */ | ||
117 | addql IMM (8), sp | ||
118 | |||
119 | tstb d2 | ||
120 | jpl L3 | ||
121 | negl d0 | ||
122 | |||
123 | L3: movel sp@+, d2 | ||
124 | rts | ||
125 | |||
diff --git a/arch/m68k/lib/memcpy.c b/arch/m68k/lib/memcpy.c new file mode 100644 index 000000000000..b50dbcad4746 --- /dev/null +++ b/arch/m68k/lib/memcpy.c | |||
@@ -0,0 +1,62 @@ | |||
1 | |||
2 | #include <linux/types.h> | ||
3 | |||
4 | void * memcpy(void * to, const void * from, size_t n) | ||
5 | { | ||
6 | #ifdef CONFIG_COLDFIRE | ||
7 | void *xto = to; | ||
8 | size_t temp; | ||
9 | |||
10 | if (!n) | ||
11 | return xto; | ||
12 | if ((long) to & 1) | ||
13 | { | ||
14 | char *cto = to; | ||
15 | const char *cfrom = from; | ||
16 | *cto++ = *cfrom++; | ||
17 | to = cto; | ||
18 | from = cfrom; | ||
19 | n--; | ||
20 | } | ||
21 | if (n > 2 && (long) to & 2) | ||
22 | { | ||
23 | short *sto = to; | ||
24 | const short *sfrom = from; | ||
25 | *sto++ = *sfrom++; | ||
26 | to = sto; | ||
27 | from = sfrom; | ||
28 | n -= 2; | ||
29 | } | ||
30 | temp = n >> 2; | ||
31 | if (temp) | ||
32 | { | ||
33 | long *lto = to; | ||
34 | const long *lfrom = from; | ||
35 | for (; temp; temp--) | ||
36 | *lto++ = *lfrom++; | ||
37 | to = lto; | ||
38 | from = lfrom; | ||
39 | } | ||
40 | if (n & 2) | ||
41 | { | ||
42 | short *sto = to; | ||
43 | const short *sfrom = from; | ||
44 | *sto++ = *sfrom++; | ||
45 | to = sto; | ||
46 | from = sfrom; | ||
47 | } | ||
48 | if (n & 1) | ||
49 | { | ||
50 | char *cto = to; | ||
51 | const char *cfrom = from; | ||
52 | *cto = *cfrom; | ||
53 | } | ||
54 | return xto; | ||
55 | #else | ||
56 | const char *c_from = from; | ||
57 | char *c_to = to; | ||
58 | while (n-- > 0) | ||
59 | *c_to++ = *c_from++; | ||
60 | return((void *) to); | ||
61 | #endif | ||
62 | } | ||
diff --git a/arch/m68k/lib/memmove.c b/arch/m68k/lib/memmove.c new file mode 100644 index 000000000000..b3dcfe9dab7e --- /dev/null +++ b/arch/m68k/lib/memmove.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file COPYING in the main directory of this archive | ||
4 | * for more details. | ||
5 | */ | ||
6 | |||
7 | #define __IN_STRING_C | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/string.h> | ||
11 | |||
12 | void *memmove(void *dest, const void *src, size_t n) | ||
13 | { | ||
14 | void *xdest = dest; | ||
15 | size_t temp; | ||
16 | |||
17 | if (!n) | ||
18 | return xdest; | ||
19 | |||
20 | if (dest < src) { | ||
21 | if ((long)dest & 1) { | ||
22 | char *cdest = dest; | ||
23 | const char *csrc = src; | ||
24 | *cdest++ = *csrc++; | ||
25 | dest = cdest; | ||
26 | src = csrc; | ||
27 | n--; | ||
28 | } | ||
29 | if (n > 2 && (long)dest & 2) { | ||
30 | short *sdest = dest; | ||
31 | const short *ssrc = src; | ||
32 | *sdest++ = *ssrc++; | ||
33 | dest = sdest; | ||
34 | src = ssrc; | ||
35 | n -= 2; | ||
36 | } | ||
37 | temp = n >> 2; | ||
38 | if (temp) { | ||
39 | long *ldest = dest; | ||
40 | const long *lsrc = src; | ||
41 | temp--; | ||
42 | do | ||
43 | *ldest++ = *lsrc++; | ||
44 | while (temp--); | ||
45 | dest = ldest; | ||
46 | src = lsrc; | ||
47 | } | ||
48 | if (n & 2) { | ||
49 | short *sdest = dest; | ||
50 | const short *ssrc = src; | ||
51 | *sdest++ = *ssrc++; | ||
52 | dest = sdest; | ||
53 | src = ssrc; | ||
54 | } | ||
55 | if (n & 1) { | ||
56 | char *cdest = dest; | ||
57 | const char *csrc = src; | ||
58 | *cdest = *csrc; | ||
59 | } | ||
60 | } else { | ||
61 | dest = (char *)dest + n; | ||
62 | src = (const char *)src + n; | ||
63 | if ((long)dest & 1) { | ||
64 | char *cdest = dest; | ||
65 | const char *csrc = src; | ||
66 | *--cdest = *--csrc; | ||
67 | dest = cdest; | ||
68 | src = csrc; | ||
69 | n--; | ||
70 | } | ||
71 | if (n > 2 && (long)dest & 2) { | ||
72 | short *sdest = dest; | ||
73 | const short *ssrc = src; | ||
74 | *--sdest = *--ssrc; | ||
75 | dest = sdest; | ||
76 | src = ssrc; | ||
77 | n -= 2; | ||
78 | } | ||
79 | temp = n >> 2; | ||
80 | if (temp) { | ||
81 | long *ldest = dest; | ||
82 | const long *lsrc = src; | ||
83 | temp--; | ||
84 | do | ||
85 | *--ldest = *--lsrc; | ||
86 | while (temp--); | ||
87 | dest = ldest; | ||
88 | src = lsrc; | ||
89 | } | ||
90 | if (n & 2) { | ||
91 | short *sdest = dest; | ||
92 | const short *ssrc = src; | ||
93 | *--sdest = *--ssrc; | ||
94 | dest = sdest; | ||
95 | src = ssrc; | ||
96 | } | ||
97 | if (n & 1) { | ||
98 | char *cdest = dest; | ||
99 | const char *csrc = src; | ||
100 | *--cdest = *--csrc; | ||
101 | } | ||
102 | } | ||
103 | return xdest; | ||
104 | } | ||
105 | EXPORT_SYMBOL(memmove); | ||
diff --git a/arch/m68k/lib/memset.c b/arch/m68k/lib/memset.c new file mode 100644 index 000000000000..1389bf455633 --- /dev/null +++ b/arch/m68k/lib/memset.c | |||
@@ -0,0 +1,47 @@ | |||
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; | ||
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 | for (; temp; temp--) | ||
32 | *ls++ = c; | ||
33 | s = ls; | ||
34 | } | ||
35 | if (count & 2) | ||
36 | { | ||
37 | short *ss = s; | ||
38 | *ss++ = c; | ||
39 | s = ss; | ||
40 | } | ||
41 | if (count & 1) | ||
42 | { | ||
43 | char *cs = s; | ||
44 | *cs = c; | ||
45 | } | ||
46 | return xs; | ||
47 | } | ||
diff --git a/arch/m68k/lib/modsi3.S b/arch/m68k/lib/modsi3.S new file mode 100644 index 000000000000..ef3849435768 --- /dev/null +++ b/arch/m68k/lib/modsi3.S | |||
@@ -0,0 +1,113 @@ | |||
1 | /* libgcc1 routines for 68000 w/o floating-point hardware. | ||
2 | Copyright (C) 1994, 1996, 1997, 1998 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 it | ||
7 | under the terms of the GNU General Public License as published by the | ||
8 | Free Software Foundation; either version 2, or (at your option) any | ||
9 | later version. | ||
10 | |||
11 | In addition to the permissions in the GNU General Public License, the | ||
12 | Free Software Foundation gives you unlimited permission to link the | ||
13 | compiled version of this file with other programs, and to distribute | ||
14 | those programs without any restriction coming from the use of this | ||
15 | file. (The General Public License restrictions do apply in other | ||
16 | respects; for example, they cover modification of the file, and | ||
17 | distribution when not linked into another program.) | ||
18 | |||
19 | This file is distributed in the hope that it will be useful, but | ||
20 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
22 | General Public License for more details. | ||
23 | |||
24 | You should have received a copy of the GNU General Public License | ||
25 | along with this program; see the file COPYING. If not, write to | ||
26 | the Free Software Foundation, 59 Temple Place - Suite 330, | ||
27 | Boston, MA 02111-1307, USA. */ | ||
28 | |||
29 | /* As a special exception, if you link this library with files | ||
30 | compiled with GCC to produce an executable, this does not cause | ||
31 | the resulting executable to be covered by the GNU General Public License. | ||
32 | This exception does not however invalidate any other reasons why | ||
33 | the executable file might be covered by the GNU General Public License. */ | ||
34 | |||
35 | /* Use this one for any 680x0; assumes no floating point hardware. | ||
36 | The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. | ||
37 | Some of this code comes from MINIX, via the folks at ericsson. | ||
38 | D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992 | ||
39 | */ | ||
40 | |||
41 | /* These are predefined by new versions of GNU cpp. */ | ||
42 | |||
43 | #ifndef __USER_LABEL_PREFIX__ | ||
44 | #define __USER_LABEL_PREFIX__ _ | ||
45 | #endif | ||
46 | |||
47 | #ifndef __REGISTER_PREFIX__ | ||
48 | #define __REGISTER_PREFIX__ | ||
49 | #endif | ||
50 | |||
51 | #ifndef __IMMEDIATE_PREFIX__ | ||
52 | #define __IMMEDIATE_PREFIX__ # | ||
53 | #endif | ||
54 | |||
55 | /* ANSI concatenation macros. */ | ||
56 | |||
57 | #define CONCAT1(a, b) CONCAT2(a, b) | ||
58 | #define CONCAT2(a, b) a ## b | ||
59 | |||
60 | /* Use the right prefix for global labels. */ | ||
61 | |||
62 | #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) | ||
63 | |||
64 | /* Use the right prefix for registers. */ | ||
65 | |||
66 | #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) | ||
67 | |||
68 | /* Use the right prefix for immediate values. */ | ||
69 | |||
70 | #define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) | ||
71 | |||
72 | #define d0 REG (d0) | ||
73 | #define d1 REG (d1) | ||
74 | #define d2 REG (d2) | ||
75 | #define d3 REG (d3) | ||
76 | #define d4 REG (d4) | ||
77 | #define d5 REG (d5) | ||
78 | #define d6 REG (d6) | ||
79 | #define d7 REG (d7) | ||
80 | #define a0 REG (a0) | ||
81 | #define a1 REG (a1) | ||
82 | #define a2 REG (a2) | ||
83 | #define a3 REG (a3) | ||
84 | #define a4 REG (a4) | ||
85 | #define a5 REG (a5) | ||
86 | #define a6 REG (a6) | ||
87 | #define fp REG (fp) | ||
88 | #define sp REG (sp) | ||
89 | |||
90 | .text | ||
91 | .proc | ||
92 | .globl SYM (__modsi3) | ||
93 | SYM (__modsi3): | ||
94 | movel sp@(8), d1 /* d1 = divisor */ | ||
95 | movel sp@(4), d0 /* d0 = dividend */ | ||
96 | movel d1, sp@- | ||
97 | movel d0, sp@- | ||
98 | jbsr SYM (__divsi3) | ||
99 | addql IMM (8), sp | ||
100 | movel sp@(8), d1 /* d1 = divisor */ | ||
101 | #if !(defined(__mcf5200__) || defined(__mcoldfire__)) | ||
102 | movel d1, sp@- | ||
103 | movel d0, sp@- | ||
104 | jbsr SYM (__mulsi3) /* d0 = (a/b)*b */ | ||
105 | addql IMM (8), sp | ||
106 | #else | ||
107 | mulsl d1,d0 | ||
108 | #endif | ||
109 | movel sp@(4), d1 /* d1 = dividend */ | ||
110 | subl d0, d1 /* d1 = a - (a/b)*b */ | ||
111 | movel d1, d0 | ||
112 | rts | ||
113 | |||
diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c index be4f275649e3..16e0eb338ee0 100644 --- a/arch/m68k/lib/muldi3.c +++ b/arch/m68k/lib/muldi3.c | |||
@@ -1,63 +1,5 @@ | |||
1 | /* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and | 1 | #ifdef CONFIG_MMU |
2 | gcc-2.7.2.3/longlong.h which is: */ | 2 | #include "muldi3_mm.c" |
3 | /* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. | 3 | #else |
4 | 4 | #include "muldi3_no.c" | |
5 | This file is part of GNU CC. | 5 | #endif |
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/muldi3_mm.c b/arch/m68k/lib/muldi3_mm.c new file mode 100644 index 000000000000..be4f275649e3 --- /dev/null +++ b/arch/m68k/lib/muldi3_mm.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/muldi3_no.c b/arch/m68k/lib/muldi3_no.c new file mode 100644 index 000000000000..34af72c30303 --- /dev/null +++ b/arch/m68k/lib/muldi3_no.c | |||
@@ -0,0 +1,86 @@ | |||
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 | #define SI_TYPE_SIZE 32 | ||
24 | |||
25 | #define __BITS4 (SI_TYPE_SIZE / 4) | ||
26 | #define __ll_B (1L << (SI_TYPE_SIZE / 2)) | ||
27 | #define __ll_lowpart(t) ((USItype) (t) % __ll_B) | ||
28 | #define __ll_highpart(t) ((USItype) (t) / __ll_B) | ||
29 | |||
30 | #define umul_ppmm(w1, w0, u, v) \ | ||
31 | do { \ | ||
32 | USItype __x0, __x1, __x2, __x3; \ | ||
33 | USItype __ul, __vl, __uh, __vh; \ | ||
34 | \ | ||
35 | __ul = __ll_lowpart (u); \ | ||
36 | __uh = __ll_highpart (u); \ | ||
37 | __vl = __ll_lowpart (v); \ | ||
38 | __vh = __ll_highpart (v); \ | ||
39 | \ | ||
40 | __x0 = (USItype) __ul * __vl; \ | ||
41 | __x1 = (USItype) __ul * __vh; \ | ||
42 | __x2 = (USItype) __uh * __vl; \ | ||
43 | __x3 = (USItype) __uh * __vh; \ | ||
44 | \ | ||
45 | __x1 += __ll_highpart (__x0);/* this can't give carry */ \ | ||
46 | __x1 += __x2; /* but this indeed can */ \ | ||
47 | if (__x1 < __x2) /* did we get it? */ \ | ||
48 | __x3 += __ll_B; /* yes, add it in the proper pos. */ \ | ||
49 | \ | ||
50 | (w1) = __x3 + __ll_highpart (__x1); \ | ||
51 | (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ | ||
52 | } while (0) | ||
53 | |||
54 | #define __umulsidi3(u, v) \ | ||
55 | ({DIunion __w; \ | ||
56 | umul_ppmm (__w.s.high, __w.s.low, u, v); \ | ||
57 | __w.ll; }) | ||
58 | |||
59 | typedef int SItype __attribute__ ((mode (SI))); | ||
60 | typedef unsigned int USItype __attribute__ ((mode (SI))); | ||
61 | typedef int DItype __attribute__ ((mode (DI))); | ||
62 | typedef int word_type __attribute__ ((mode (__word__))); | ||
63 | |||
64 | struct DIstruct {SItype high, low;}; | ||
65 | |||
66 | typedef union | ||
67 | { | ||
68 | struct DIstruct s; | ||
69 | DItype ll; | ||
70 | } DIunion; | ||
71 | |||
72 | DItype | ||
73 | __muldi3 (DItype u, DItype v) | ||
74 | { | ||
75 | DIunion w; | ||
76 | DIunion uu, vv; | ||
77 | |||
78 | uu.ll = u, | ||
79 | vv.ll = v; | ||
80 | |||
81 | w.ll = __umulsidi3 (uu.s.low, vv.s.low); | ||
82 | w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high | ||
83 | + (USItype) uu.s.high * (USItype) vv.s.low); | ||
84 | |||
85 | return w.ll; | ||
86 | } | ||
diff --git a/arch/m68k/lib/mulsi3.S b/arch/m68k/lib/mulsi3.S new file mode 100644 index 000000000000..ce29ea37b45f --- /dev/null +++ b/arch/m68k/lib/mulsi3.S | |||
@@ -0,0 +1,110 @@ | |||
1 | /* libgcc1 routines for 68000 w/o floating-point hardware. | ||
2 | Copyright (C) 1994, 1996, 1997, 1998 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 it | ||
7 | under the terms of the GNU General Public License as published by the | ||
8 | Free Software Foundation; either version 2, or (at your option) any | ||
9 | later version. | ||
10 | |||
11 | In addition to the permissions in the GNU General Public License, the | ||
12 | Free Software Foundation gives you unlimited permission to link the | ||
13 | compiled version of this file with other programs, and to distribute | ||
14 | those programs without any restriction coming from the use of this | ||
15 | file. (The General Public License restrictions do apply in other | ||
16 | respects; for example, they cover modification of the file, and | ||
17 | distribution when not linked into another program.) | ||
18 | |||
19 | This file is distributed in the hope that it will be useful, but | ||
20 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
22 | General Public License for more details. | ||
23 | |||
24 | You should have received a copy of the GNU General Public License | ||
25 | along with this program; see the file COPYING. If not, write to | ||
26 | the Free Software Foundation, 59 Temple Place - Suite 330, | ||
27 | Boston, MA 02111-1307, USA. */ | ||
28 | |||
29 | /* As a special exception, if you link this library with files | ||
30 | compiled with GCC to produce an executable, this does not cause | ||
31 | the resulting executable to be covered by the GNU General Public License. | ||
32 | This exception does not however invalidate any other reasons why | ||
33 | the executable file might be covered by the GNU General Public License. */ | ||
34 | |||
35 | /* Use this one for any 680x0; assumes no floating point hardware. | ||
36 | The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. | ||
37 | Some of this code comes from MINIX, via the folks at ericsson. | ||
38 | D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992 | ||
39 | */ | ||
40 | |||
41 | /* These are predefined by new versions of GNU cpp. */ | ||
42 | |||
43 | #ifndef __USER_LABEL_PREFIX__ | ||
44 | #define __USER_LABEL_PREFIX__ _ | ||
45 | #endif | ||
46 | |||
47 | #ifndef __REGISTER_PREFIX__ | ||
48 | #define __REGISTER_PREFIX__ | ||
49 | #endif | ||
50 | |||
51 | #ifndef __IMMEDIATE_PREFIX__ | ||
52 | #define __IMMEDIATE_PREFIX__ # | ||
53 | #endif | ||
54 | |||
55 | /* ANSI concatenation macros. */ | ||
56 | |||
57 | #define CONCAT1(a, b) CONCAT2(a, b) | ||
58 | #define CONCAT2(a, b) a ## b | ||
59 | |||
60 | /* Use the right prefix for global labels. */ | ||
61 | |||
62 | #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) | ||
63 | |||
64 | /* Use the right prefix for registers. */ | ||
65 | |||
66 | #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) | ||
67 | |||
68 | /* Use the right prefix for immediate values. */ | ||
69 | |||
70 | #define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) | ||
71 | |||
72 | #define d0 REG (d0) | ||
73 | #define d1 REG (d1) | ||
74 | #define d2 REG (d2) | ||
75 | #define d3 REG (d3) | ||
76 | #define d4 REG (d4) | ||
77 | #define d5 REG (d5) | ||
78 | #define d6 REG (d6) | ||
79 | #define d7 REG (d7) | ||
80 | #define a0 REG (a0) | ||
81 | #define a1 REG (a1) | ||
82 | #define a2 REG (a2) | ||
83 | #define a3 REG (a3) | ||
84 | #define a4 REG (a4) | ||
85 | #define a5 REG (a5) | ||
86 | #define a6 REG (a6) | ||
87 | #define fp REG (fp) | ||
88 | #define sp REG (sp) | ||
89 | |||
90 | .text | ||
91 | .proc | ||
92 | .globl SYM (__mulsi3) | ||
93 | SYM (__mulsi3): | ||
94 | movew sp@(4), d0 /* x0 -> d0 */ | ||
95 | muluw sp@(10), d0 /* x0*y1 */ | ||
96 | movew sp@(6), d1 /* x1 -> d1 */ | ||
97 | muluw sp@(8), d1 /* x1*y0 */ | ||
98 | #if !(defined(__mcf5200__) || defined(__mcoldfire__)) | ||
99 | addw d1, d0 | ||
100 | #else | ||
101 | addl d1, d0 | ||
102 | #endif | ||
103 | swap d0 | ||
104 | clrw d0 | ||
105 | movew sp@(6), d1 /* x1 -> d1 */ | ||
106 | muluw sp@(10), d1 /* x1*y1 */ | ||
107 | addl d1, d0 | ||
108 | |||
109 | rts | ||
110 | |||
diff --git a/arch/m68k/lib/udivsi3.S b/arch/m68k/lib/udivsi3.S new file mode 100644 index 000000000000..c424c4a1f0a3 --- /dev/null +++ b/arch/m68k/lib/udivsi3.S | |||
@@ -0,0 +1,162 @@ | |||
1 | /* libgcc1 routines for 68000 w/o floating-point hardware. | ||
2 | Copyright (C) 1994, 1996, 1997, 1998 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 it | ||
7 | under the terms of the GNU General Public License as published by the | ||
8 | Free Software Foundation; either version 2, or (at your option) any | ||
9 | later version. | ||
10 | |||
11 | In addition to the permissions in the GNU General Public License, the | ||
12 | Free Software Foundation gives you unlimited permission to link the | ||
13 | compiled version of this file with other programs, and to distribute | ||
14 | those programs without any restriction coming from the use of this | ||
15 | file. (The General Public License restrictions do apply in other | ||
16 | respects; for example, they cover modification of the file, and | ||
17 | distribution when not linked into another program.) | ||
18 | |||
19 | This file is distributed in the hope that it will be useful, but | ||
20 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
22 | General Public License for more details. | ||
23 | |||
24 | You should have received a copy of the GNU General Public License | ||
25 | along with this program; see the file COPYING. If not, write to | ||
26 | the Free Software Foundation, 59 Temple Place - Suite 330, | ||
27 | Boston, MA 02111-1307, USA. */ | ||
28 | |||
29 | /* As a special exception, if you link this library with files | ||
30 | compiled with GCC to produce an executable, this does not cause | ||
31 | the resulting executable to be covered by the GNU General Public License. | ||
32 | This exception does not however invalidate any other reasons why | ||
33 | the executable file might be covered by the GNU General Public License. */ | ||
34 | |||
35 | /* Use this one for any 680x0; assumes no floating point hardware. | ||
36 | The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. | ||
37 | Some of this code comes from MINIX, via the folks at ericsson. | ||
38 | D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992 | ||
39 | */ | ||
40 | |||
41 | /* These are predefined by new versions of GNU cpp. */ | ||
42 | |||
43 | #ifndef __USER_LABEL_PREFIX__ | ||
44 | #define __USER_LABEL_PREFIX__ _ | ||
45 | #endif | ||
46 | |||
47 | #ifndef __REGISTER_PREFIX__ | ||
48 | #define __REGISTER_PREFIX__ | ||
49 | #endif | ||
50 | |||
51 | #ifndef __IMMEDIATE_PREFIX__ | ||
52 | #define __IMMEDIATE_PREFIX__ # | ||
53 | #endif | ||
54 | |||
55 | /* ANSI concatenation macros. */ | ||
56 | |||
57 | #define CONCAT1(a, b) CONCAT2(a, b) | ||
58 | #define CONCAT2(a, b) a ## b | ||
59 | |||
60 | /* Use the right prefix for global labels. */ | ||
61 | |||
62 | #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) | ||
63 | |||
64 | /* Use the right prefix for registers. */ | ||
65 | |||
66 | #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) | ||
67 | |||
68 | /* Use the right prefix for immediate values. */ | ||
69 | |||
70 | #define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) | ||
71 | |||
72 | #define d0 REG (d0) | ||
73 | #define d1 REG (d1) | ||
74 | #define d2 REG (d2) | ||
75 | #define d3 REG (d3) | ||
76 | #define d4 REG (d4) | ||
77 | #define d5 REG (d5) | ||
78 | #define d6 REG (d6) | ||
79 | #define d7 REG (d7) | ||
80 | #define a0 REG (a0) | ||
81 | #define a1 REG (a1) | ||
82 | #define a2 REG (a2) | ||
83 | #define a3 REG (a3) | ||
84 | #define a4 REG (a4) | ||
85 | #define a5 REG (a5) | ||
86 | #define a6 REG (a6) | ||
87 | #define fp REG (fp) | ||
88 | #define sp REG (sp) | ||
89 | |||
90 | .text | ||
91 | .proc | ||
92 | .globl SYM (__udivsi3) | ||
93 | SYM (__udivsi3): | ||
94 | #if !(defined(__mcf5200__) || defined(__mcoldfire__)) | ||
95 | movel d2, sp@- | ||
96 | movel sp@(12), d1 /* d1 = divisor */ | ||
97 | movel sp@(8), d0 /* d0 = dividend */ | ||
98 | |||
99 | cmpl IMM (0x10000), d1 /* divisor >= 2 ^ 16 ? */ | ||
100 | jcc L3 /* then try next algorithm */ | ||
101 | movel d0, d2 | ||
102 | clrw d2 | ||
103 | swap d2 | ||
104 | divu d1, d2 /* high quotient in lower word */ | ||
105 | movew d2, d0 /* save high quotient */ | ||
106 | swap d0 | ||
107 | movew sp@(10), d2 /* get low dividend + high rest */ | ||
108 | divu d1, d2 /* low quotient */ | ||
109 | movew d2, d0 | ||
110 | jra L6 | ||
111 | |||
112 | L3: movel d1, d2 /* use d2 as divisor backup */ | ||
113 | L4: lsrl IMM (1), d1 /* shift divisor */ | ||
114 | lsrl IMM (1), d0 /* shift dividend */ | ||
115 | cmpl IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ? */ | ||
116 | jcc L4 | ||
117 | divu d1, d0 /* now we have 16 bit divisor */ | ||
118 | andl IMM (0xffff), d0 /* mask out divisor, ignore remainder */ | ||
119 | |||
120 | /* Multiply the 16 bit tentative quotient with the 32 bit divisor. Because of | ||
121 | the operand ranges, this might give a 33 bit product. If this product is | ||
122 | greater than the dividend, the tentative quotient was too large. */ | ||
123 | movel d2, d1 | ||
124 | mulu d0, d1 /* low part, 32 bits */ | ||
125 | swap d2 | ||
126 | mulu d0, d2 /* high part, at most 17 bits */ | ||
127 | swap d2 /* align high part with low part */ | ||
128 | tstw d2 /* high part 17 bits? */ | ||
129 | jne L5 /* if 17 bits, quotient was too large */ | ||
130 | addl d2, d1 /* add parts */ | ||
131 | jcs L5 /* if sum is 33 bits, quotient was too large */ | ||
132 | cmpl sp@(8), d1 /* compare the sum with the dividend */ | ||
133 | jls L6 /* if sum > dividend, quotient was too large */ | ||
134 | L5: subql IMM (1), d0 /* adjust quotient */ | ||
135 | |||
136 | L6: movel sp@+, d2 | ||
137 | rts | ||
138 | |||
139 | #else /* __mcf5200__ || __mcoldfire__ */ | ||
140 | |||
141 | /* Coldfire implementation of non-restoring division algorithm from | ||
142 | Hennessy & Patterson, Appendix A. */ | ||
143 | link a6,IMM (-12) | ||
144 | moveml d2-d4,sp@ | ||
145 | movel a6@(8),d0 | ||
146 | movel a6@(12),d1 | ||
147 | clrl d2 | clear p | ||
148 | moveq IMM (31),d4 | ||
149 | L1: addl d0,d0 | shift reg pair (p,a) one bit left | ||
150 | addxl d2,d2 | ||
151 | movl d2,d3 | subtract b from p, store in tmp. | ||
152 | subl d1,d3 | ||
153 | jcs L2 | if no carry, | ||
154 | bset IMM (0),d0 | set the low order bit of a to 1, | ||
155 | movl d3,d2 | and store tmp in p. | ||
156 | L2: subql IMM (1),d4 | ||
157 | jcc L1 | ||
158 | moveml sp@,d2-d4 | restore data registers | ||
159 | unlk a6 | and return | ||
160 | rts | ||
161 | #endif /* __mcf5200__ || __mcoldfire__ */ | ||
162 | |||
diff --git a/arch/m68k/lib/umodsi3.S b/arch/m68k/lib/umodsi3.S new file mode 100644 index 000000000000..5def5f626478 --- /dev/null +++ b/arch/m68k/lib/umodsi3.S | |||
@@ -0,0 +1,113 @@ | |||
1 | /* libgcc1 routines for 68000 w/o floating-point hardware. | ||
2 | Copyright (C) 1994, 1996, 1997, 1998 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 it | ||
7 | under the terms of the GNU General Public License as published by the | ||
8 | Free Software Foundation; either version 2, or (at your option) any | ||
9 | later version. | ||
10 | |||
11 | In addition to the permissions in the GNU General Public License, the | ||
12 | Free Software Foundation gives you unlimited permission to link the | ||
13 | compiled version of this file with other programs, and to distribute | ||
14 | those programs without any restriction coming from the use of this | ||
15 | file. (The General Public License restrictions do apply in other | ||
16 | respects; for example, they cover modification of the file, and | ||
17 | distribution when not linked into another program.) | ||
18 | |||
19 | This file is distributed in the hope that it will be useful, but | ||
20 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
22 | General Public License for more details. | ||
23 | |||
24 | You should have received a copy of the GNU General Public License | ||
25 | along with this program; see the file COPYING. If not, write to | ||
26 | the Free Software Foundation, 59 Temple Place - Suite 330, | ||
27 | Boston, MA 02111-1307, USA. */ | ||
28 | |||
29 | /* As a special exception, if you link this library with files | ||
30 | compiled with GCC to produce an executable, this does not cause | ||
31 | the resulting executable to be covered by the GNU General Public License. | ||
32 | This exception does not however invalidate any other reasons why | ||
33 | the executable file might be covered by the GNU General Public License. */ | ||
34 | |||
35 | /* Use this one for any 680x0; assumes no floating point hardware. | ||
36 | The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. | ||
37 | Some of this code comes from MINIX, via the folks at ericsson. | ||
38 | D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992 | ||
39 | */ | ||
40 | |||
41 | /* These are predefined by new versions of GNU cpp. */ | ||
42 | |||
43 | #ifndef __USER_LABEL_PREFIX__ | ||
44 | #define __USER_LABEL_PREFIX__ _ | ||
45 | #endif | ||
46 | |||
47 | #ifndef __REGISTER_PREFIX__ | ||
48 | #define __REGISTER_PREFIX__ | ||
49 | #endif | ||
50 | |||
51 | #ifndef __IMMEDIATE_PREFIX__ | ||
52 | #define __IMMEDIATE_PREFIX__ # | ||
53 | #endif | ||
54 | |||
55 | /* ANSI concatenation macros. */ | ||
56 | |||
57 | #define CONCAT1(a, b) CONCAT2(a, b) | ||
58 | #define CONCAT2(a, b) a ## b | ||
59 | |||
60 | /* Use the right prefix for global labels. */ | ||
61 | |||
62 | #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) | ||
63 | |||
64 | /* Use the right prefix for registers. */ | ||
65 | |||
66 | #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) | ||
67 | |||
68 | /* Use the right prefix for immediate values. */ | ||
69 | |||
70 | #define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) | ||
71 | |||
72 | #define d0 REG (d0) | ||
73 | #define d1 REG (d1) | ||
74 | #define d2 REG (d2) | ||
75 | #define d3 REG (d3) | ||
76 | #define d4 REG (d4) | ||
77 | #define d5 REG (d5) | ||
78 | #define d6 REG (d6) | ||
79 | #define d7 REG (d7) | ||
80 | #define a0 REG (a0) | ||
81 | #define a1 REG (a1) | ||
82 | #define a2 REG (a2) | ||
83 | #define a3 REG (a3) | ||
84 | #define a4 REG (a4) | ||
85 | #define a5 REG (a5) | ||
86 | #define a6 REG (a6) | ||
87 | #define fp REG (fp) | ||
88 | #define sp REG (sp) | ||
89 | |||
90 | .text | ||
91 | .proc | ||
92 | .globl SYM (__umodsi3) | ||
93 | SYM (__umodsi3): | ||
94 | movel sp@(8), d1 /* d1 = divisor */ | ||
95 | movel sp@(4), d0 /* d0 = dividend */ | ||
96 | movel d1, sp@- | ||
97 | movel d0, sp@- | ||
98 | jbsr SYM (__udivsi3) | ||
99 | addql IMM (8), sp | ||
100 | movel sp@(8), d1 /* d1 = divisor */ | ||
101 | #if !(defined(__mcf5200__) || defined(__mcoldfire__)) | ||
102 | movel d1, sp@- | ||
103 | movel d0, sp@- | ||
104 | jbsr SYM (__mulsi3) /* d0 = (a/b)*b */ | ||
105 | addql IMM (8), sp | ||
106 | #else | ||
107 | mulsl d1,d0 | ||
108 | #endif | ||
109 | movel sp@(4), d1 /* d1 = dividend */ | ||
110 | subl d0, d1 /* d1 = a - (a/b)*b */ | ||
111 | movel d1, d0 | ||
112 | rts | ||
113 | |||