1@ libgcc1 routines for ARM cpu.
2@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
3
4/* Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
5
6This file is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11In addition to the permissions in the GNU General Public License, the
12Free Software Foundation gives you unlimited permission to link the
13compiled version of this file with other programs, and to distribute
14those programs without any restriction coming from the use of this
15file.  (The General Public License restrictions do apply in other
16respects; for example, they cover modification of the file, and
17distribution when not linked into another program.)
18
19This file is distributed in the hope that it will be useful, but
20WITHOUT ANY WARRANTY; without even the implied warranty of
21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22General Public License for more details.
23
24You should have received a copy of the GNU General Public License
25along with this program; see the file COPYING.  If not, write to
26the Free Software Foundation, 59 Temple Place - Suite 330,
27Boston, MA 02111-1307, USA.  */
28
29/* As a special exception, if you link this library with other files,
30   some of which are compiled with GCC, to produce an executable,
31   this library does not by itself cause the resulting executable
32   to be covered by the GNU General Public License.
33   This exception does not however invalidate any other reasons why
34   the executable file might be covered by the GNU General Public License.
35 */
36/* This code is derived from gcc 2.95.3 */
37/* I Molton     29/07/01 */
38
39#include <linux/linkage.h>
40#include <asm/assembler.h>
41#include <asm/hardware.h>
42
43#define RET	movs
44#define RETc(x)	mov##x##s
45#define RETCOND ^
46
47dividend	.req	r0
48divisor		.req	r1
49result		.req	r2
50overdone        .req    r2
51curbit		.req	r3
52ip		.req	r12
53sp		.req	r13
54lr		.req	r14
55pc		.req	r15
56
57ENTRY(__udivsi3)
58	cmp	divisor, #0
59	beq	Ldiv0
60	mov	curbit, #1
61	mov	result, #0
62	cmp	dividend, divisor
63	bcc	Lgot_result_udivsi3
641:
65	@ Unless the divisor is very big, shift it up in multiples of
66	@ four bits, since this is the amount of unwinding in the main
67	@ division loop.  Continue shifting until the divisor is
68	@ larger than the dividend.
69	cmp	divisor, #0x10000000
70	cmpcc	divisor, dividend
71	movcc	divisor, divisor, lsl #4
72	movcc	curbit, curbit, lsl #4
73	bcc	1b
74
752:
76	@ For very big divisors, we must shift it a bit at a time, or
77	@ we will be in danger of overflowing.
78	cmp	divisor, #0x80000000
79	cmpcc	divisor, dividend
80	movcc	divisor, divisor, lsl #1
81	movcc	curbit, curbit, lsl #1
82	bcc	2b
83
843:
85	@ Test for possible subtractions, and note which bits
86	@ are done in the result.  On the final pass, this may subtract
87	@ too much from the dividend, but the result will be ok, since the
88	@ "bit" will have been shifted out at the bottom.
89	cmp	dividend, divisor
90	subcs	dividend, dividend, divisor
91	orrcs	result, result, curbit
92	cmp	dividend, divisor, lsr #1
93	subcs	dividend, dividend, divisor, lsr #1
94	orrcs	result, result, curbit, lsr #1
95	cmp	dividend, divisor, lsr #2
96	subcs	dividend, dividend, divisor, lsr #2
97	orrcs	result, result, curbit, lsr #2
98	cmp	dividend, divisor, lsr #3
99	subcs	dividend, dividend, divisor, lsr #3
100	orrcs	result, result, curbit, lsr #3
101	cmp	dividend, #0			@ Early termination?
102	movnes	curbit, curbit, lsr #4		@ No, any more bits to do?
103	movne	divisor, divisor, lsr #4
104	bne	3b
105Lgot_result_udivsi3:
106	mov	r0, result
107	RET	pc, lr
108
109Ldiv0:
110	str	lr, [sp, #-4]!
111	bl	__div0
112	mov	r0, #0			@ about as wrong as it could be
113	ldmia	sp!, {pc}RETCOND
114
115/* __umodsi3 ----------------------- */
116
117ENTRY(__umodsi3)
118	cmp	divisor, #0
119	beq	Ldiv0
120	mov	curbit, #1
121	cmp	dividend, divisor
122	RETc(cc)	pc, lr
1231:
124	@ Unless the divisor is very big, shift it up in multiples of
125	@ four bits, since this is the amount of unwinding in the main
126	@ division loop.  Continue shifting until the divisor is
127	@ larger than the dividend.
128	cmp	divisor, #0x10000000
129	cmpcc	divisor, dividend
130	movcc	divisor, divisor, lsl #4
131	movcc	curbit, curbit, lsl #4
132	bcc	1b
133
1342:
135	@ For very big divisors, we must shift it a bit at a time, or
136	@ we will be in danger of overflowing.
137	cmp	divisor, #0x80000000
138	cmpcc	divisor, dividend
139	movcc	divisor, divisor, lsl #1
140	movcc	curbit, curbit, lsl #1
141	bcc	2b
142
1433:
144	@ Test for possible subtractions.  On the final pass, this may
145	@ subtract too much from the dividend, so keep track of which
146	@ subtractions are done, we can fix them up afterwards...
147	mov	overdone, #0
148	cmp	dividend, divisor
149	subcs	dividend, dividend, divisor
150	cmp	dividend, divisor, lsr #1
151	subcs	dividend, dividend, divisor, lsr #1
152	orrcs	overdone, overdone, curbit, ror #1
153	cmp	dividend, divisor, lsr #2
154	subcs	dividend, dividend, divisor, lsr #2
155	orrcs	overdone, overdone, curbit, ror #2
156	cmp	dividend, divisor, lsr #3
157	subcs	dividend, dividend, divisor, lsr #3
158	orrcs	overdone, overdone, curbit, ror #3
159	mov	ip, curbit
160	cmp	dividend, #0			@ Early termination?
161	movnes	curbit, curbit, lsr #4		@ No, any more bits to do?
162	movne	divisor, divisor, lsr #4
163	bne	3b
164
165	@ Any subtractions that we should not have done will be recorded in
166	@ the top three bits of "overdone".  Exactly which were not needed
167	@ are governed by the position of the bit, stored in ip.
168	@ If we terminated early, because dividend became zero,
169	@ then none of the below will match, since the bit in ip will not be
170	@ in the bottom nibble.
171	ands	overdone, overdone, #0xe0000000
172	RETc(eq)	pc, lr				@ No fixups needed
173	tst	overdone, ip, ror #3
174	addne	dividend, dividend, divisor, lsr #3
175	tst	overdone, ip, ror #2
176	addne	dividend, dividend, divisor, lsr #2
177	tst	overdone, ip, ror #1
178	addne	dividend, dividend, divisor, lsr #1
179	RET	pc, lr
180
181ENTRY(__divsi3)
182	eor	ip, dividend, divisor		@ Save the sign of the result.
183	mov	curbit, #1
184	mov	result, #0
185	cmp	divisor, #0
186	rsbmi	divisor, divisor, #0		@ Loops below use unsigned.
187	beq	Ldiv0
188	cmp	dividend, #0
189	rsbmi	dividend, dividend, #0
190	cmp	dividend, divisor
191	bcc	Lgot_result_divsi3
192
1931:
194	@ Unless the divisor is very big, shift it up in multiples of
195	@ four bits, since this is the amount of unwinding in the main
196	@ division loop.  Continue shifting until the divisor is
197	@ larger than the dividend.
198	cmp	divisor, #0x10000000
199	cmpcc	divisor, dividend
200	movcc	divisor, divisor, lsl #4
201	movcc	curbit, curbit, lsl #4
202	bcc	1b
203
2042:
205	@ For very big divisors, we must shift it a bit at a time, or
206	@ we will be in danger of overflowing.
207	cmp	divisor, #0x80000000
208	cmpcc	divisor, dividend
209	movcc	divisor, divisor, lsl #1
210	movcc	curbit, curbit, lsl #1
211	bcc	2b
212
2133:
214	@ Test for possible subtractions, and note which bits
215	@ are done in the result.  On the final pass, this may subtract
216	@ too much from the dividend, but the result will be ok, since the
217	@ "bit" will have been shifted out at the bottom.
218	cmp	dividend, divisor
219	subcs	dividend, dividend, divisor
220	orrcs	result, result, curbit
221	cmp	dividend, divisor, lsr #1
222	subcs	dividend, dividend, divisor, lsr #1
223	orrcs	result, result, curbit, lsr #1
224	cmp	dividend, divisor, lsr #2
225	subcs	dividend, dividend, divisor, lsr #2
226	orrcs	result, result, curbit, lsr #2
227	cmp	dividend, divisor, lsr #3
228	subcs	dividend, dividend, divisor, lsr #3
229	orrcs	result, result, curbit, lsr #3
230	cmp	dividend, #0			@ Early termination?
231	movnes	curbit, curbit, lsr #4		@ No, any more bits to do?
232	movne	divisor, divisor, lsr #4
233	bne	3b
234Lgot_result_divsi3:
235	mov	r0, result
236	cmp	ip, #0
237	rsbmi	r0, r0, #0
238	RET	pc, lr
239
240ENTRY(__modsi3)
241	mov	curbit, #1
242	cmp	divisor, #0
243	rsbmi	divisor, divisor, #0		@ Loops below use unsigned.
244	beq	Ldiv0
245	@ Need to save the sign of the dividend, unfortunately, we need
246	@ ip later on; this is faster than pushing lr and using that.
247	str	dividend, [sp, #-4]!
248	cmp	dividend, #0
249	rsbmi	dividend, dividend, #0
250	cmp	dividend, divisor
251	bcc	Lgot_result_modsi3
252
2531:
254	@ Unless the divisor is very big, shift it up in multiples of
255	@ four bits, since this is the amount of unwinding in the main
256	@ division loop.  Continue shifting until the divisor is
257	@ larger than the dividend.
258	cmp	divisor, #0x10000000
259	cmpcc	divisor, dividend
260	movcc	divisor, divisor, lsl #4
261	movcc	curbit, curbit, lsl #4
262	bcc	1b
263
2642:
265	@ For very big divisors, we must shift it a bit at a time, or
266	@ we will be in danger of overflowing.
267	cmp	divisor, #0x80000000
268	cmpcc	divisor, dividend
269	movcc	divisor, divisor, lsl #1
270	movcc	curbit, curbit, lsl #1
271	bcc	2b
272
2733:
274	@ Test for possible subtractions.  On the final pass, this may
275	@ subtract too much from the dividend, so keep track of which
276	@ subtractions are done, we can fix them up afterwards...
277	mov	overdone, #0
278	cmp	dividend, divisor
279	subcs	dividend, dividend, divisor
280	cmp	dividend, divisor, lsr #1
281	subcs	dividend, dividend, divisor, lsr #1
282	orrcs	overdone, overdone, curbit, ror #1
283	cmp	dividend, divisor, lsr #2
284	subcs	dividend, dividend, divisor, lsr #2
285	orrcs	overdone, overdone, curbit, ror #2
286	cmp	dividend, divisor, lsr #3
287	subcs	dividend, dividend, divisor, lsr #3
288	orrcs	overdone, overdone, curbit, ror #3
289	mov	ip, curbit
290	cmp	dividend, #0			@ Early termination?
291	movnes	curbit, curbit, lsr #4		@ No, any more bits to do?
292	movne	divisor, divisor, lsr #4
293	bne	3b
294
295	@ Any subtractions that we should not have done will be recorded in
296	@ the top three bits of "overdone".  Exactly which were not needed
297	@ are governed by the position of the bit, stored in ip.
298	@ If we terminated early, because dividend became zero,
299	@ then none of the below will match, since the bit in ip will not be
300	@ in the bottom nibble.
301	ands	overdone, overdone, #0xe0000000
302	beq	Lgot_result_modsi3
303	tst	overdone, ip, ror #3
304	addne	dividend, dividend, divisor, lsr #3
305	tst	overdone, ip, ror #2
306	addne	dividend, dividend, divisor, lsr #2
307	tst	overdone, ip, ror #1
308	addne	dividend, dividend, divisor, lsr #1
309Lgot_result_modsi3:
310	ldr	ip, [sp], #4
311	cmp	ip, #0
312	rsbmi	dividend, dividend, #0
313	RET	pc, lr
314