xref: /freebsd/sys/libkern/arm/divsi3.S (revision 9124ddeb4a551977cf6b2218291e7c666ce25f47)
1/*	$NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $	*/
2
3/*-
4 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
5 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
7 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
8 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
9 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
10 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
11 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14 * SUCH DAMAGE.
15 */
16
17#include <machine/asm.h>
18__FBSDID("$FreeBSD$");
19
20/*
21 * stack is aligned as there's a possibility of branching to L_overflow
22 * which makes a C call
23 */
24
25ENTRY_NP(__umodsi3)
26	stmfd	sp!, {lr}
27	sub	sp, sp, #4	/* align stack */
28	bl	.L_udivide
29	add	sp, sp, #4	/* unalign stack */
30	mov	r0, r1
31	ldmfd	sp!, {pc}
32
33ENTRY_NP(__modsi3)
34	stmfd	sp!, {lr}
35	sub	sp, sp, #4	/* align stack */
36	bl	.L_divide
37	add	sp, sp, #4	/* unalign stack */
38	mov	r0, r1
39	ldmfd	sp!, {pc}
40
41.L_overflow:
42#if !defined(_KERNEL) && !defined(_STANDALONE)
43	mov	r0, #8			/* SIGFPE */
44	bl	PIC_SYM(_C_LABEL(raise), PLT)	/* raise it */
45	mov	r0, #0
46#else
47	/* XXX should cause a fatal error */
48	mvn	r0, #0
49#endif
50	RET
51
52ENTRY_NP(__udivsi3)
53.L_udivide:				/* r0 = r0 / r1; r1 = r0 % r1 */
54	eor     r0, r1, r0
55	eor     r1, r0, r1
56	eor     r0, r1, r0
57					/* r0 = r1 / r0; r1 = r1 % r0 */
58	cmp	r0, #1
59	bcc	.L_overflow
60	beq	.L_divide_l0
61	mov	ip, #0
62	movs	r1, r1
63	bpl	.L_divide_l1
64	orr	ip, ip, #0x20000000	/* ip bit 0x20000000 = -ve r1 */
65	movs	r1, r1, lsr #1
66	orrcs	ip, ip, #0x10000000	/* ip bit 0x10000000 = bit 0 of r1 */
67	b	.L_divide_l1
68
69.L_divide_l0:				/* r0 == 1 */
70	mov	r0, r1
71	mov	r1, #0
72	RET
73
74ENTRY_NP(__divsi3)
75.L_divide:				/* r0 = r0 / r1; r1 = r0 % r1 */
76	eor     r0, r1, r0
77	eor     r1, r0, r1
78	eor     r0, r1, r0
79					/* r0 = r1 / r0; r1 = r1 % r0 */
80	cmp	r0, #1
81	bcc	.L_overflow
82	beq	.L_divide_l0
83	ands	ip, r0, #0x80000000
84	rsbmi	r0, r0, #0
85	ands	r2, r1, #0x80000000
86	eor	ip, ip, r2
87	rsbmi	r1, r1, #0
88	orr	ip, r2, ip, lsr #1	/* ip bit 0x40000000 = -ve division */
89					/* ip bit 0x80000000 = -ve remainder */
90
91.L_divide_l1:
92	mov	r2, #1
93	mov	r3, #0
94
95	/*
96	 * If the highest bit of the dividend is set, we have to be
97	 * careful when shifting the divisor. Test this.
98	 */
99	movs	r1,r1
100	bpl	.L_old_code
101
102	/*
103	 * At this point, the highest bit of r1 is known to be set.
104	 * We abuse this below in the tst instructions.
105	 */
106	tst	r1, r0 /*, lsl #0 */
107	bmi	.L_divide_b1
108	tst	r1, r0, lsl #1
109	bmi	.L_divide_b2
110	tst	r1, r0, lsl #2
111	bmi	.L_divide_b3
112	tst	r1, r0, lsl #3
113	bmi	.L_divide_b4
114	tst	r1, r0, lsl #4
115	bmi	.L_divide_b5
116	tst	r1, r0, lsl #5
117	bmi	.L_divide_b6
118	tst	r1, r0, lsl #6
119	bmi	.L_divide_b7
120	tst	r1, r0, lsl #7
121	bmi	.L_divide_b8
122	tst	r1, r0, lsl #8
123	bmi	.L_divide_b9
124	tst	r1, r0, lsl #9
125	bmi	.L_divide_b10
126	tst	r1, r0, lsl #10
127	bmi	.L_divide_b11
128	tst	r1, r0, lsl #11
129	bmi	.L_divide_b12
130	tst	r1, r0, lsl #12
131	bmi	.L_divide_b13
132	tst	r1, r0, lsl #13
133	bmi	.L_divide_b14
134	tst	r1, r0, lsl #14
135	bmi	.L_divide_b15
136	tst	r1, r0, lsl #15
137	bmi	.L_divide_b16
138	tst	r1, r0, lsl #16
139	bmi	.L_divide_b17
140	tst	r1, r0, lsl #17
141	bmi	.L_divide_b18
142	tst	r1, r0, lsl #18
143	bmi	.L_divide_b19
144	tst	r1, r0, lsl #19
145	bmi	.L_divide_b20
146	tst	r1, r0, lsl #20
147	bmi	.L_divide_b21
148	tst	r1, r0, lsl #21
149	bmi	.L_divide_b22
150	tst	r1, r0, lsl #22
151	bmi	.L_divide_b23
152	tst	r1, r0, lsl #23
153	bmi	.L_divide_b24
154	tst	r1, r0, lsl #24
155	bmi	.L_divide_b25
156	tst	r1, r0, lsl #25
157	bmi	.L_divide_b26
158	tst	r1, r0, lsl #26
159	bmi	.L_divide_b27
160	tst	r1, r0, lsl #27
161	bmi	.L_divide_b28
162	tst	r1, r0, lsl #28
163	bmi	.L_divide_b29
164	tst	r1, r0, lsl #29
165	bmi	.L_divide_b30
166	tst	r1, r0, lsl #30
167	bmi	.L_divide_b31
168/*
169 * instead of:
170 *	tst	r1, r0, lsl #31
171 *	bmi	.L_divide_b32
172 */
173	b	.L_divide_b32
174
175.L_old_code:
176	cmp	r1, r0
177	bcc	.L_divide_b0
178	cmp	r1, r0, lsl #1
179	bcc	.L_divide_b1
180	cmp	r1, r0, lsl #2
181	bcc	.L_divide_b2
182	cmp	r1, r0, lsl #3
183	bcc	.L_divide_b3
184	cmp	r1, r0, lsl #4
185	bcc	.L_divide_b4
186	cmp	r1, r0, lsl #5
187	bcc	.L_divide_b5
188	cmp	r1, r0, lsl #6
189	bcc	.L_divide_b6
190	cmp	r1, r0, lsl #7
191	bcc	.L_divide_b7
192	cmp	r1, r0, lsl #8
193	bcc	.L_divide_b8
194	cmp	r1, r0, lsl #9
195	bcc	.L_divide_b9
196	cmp	r1, r0, lsl #10
197	bcc	.L_divide_b10
198	cmp	r1, r0, lsl #11
199	bcc	.L_divide_b11
200	cmp	r1, r0, lsl #12
201	bcc	.L_divide_b12
202	cmp	r1, r0, lsl #13
203	bcc	.L_divide_b13
204	cmp	r1, r0, lsl #14
205	bcc	.L_divide_b14
206	cmp	r1, r0, lsl #15
207	bcc	.L_divide_b15
208	cmp	r1, r0, lsl #16
209	bcc	.L_divide_b16
210	cmp	r1, r0, lsl #17
211	bcc	.L_divide_b17
212	cmp	r1, r0, lsl #18
213	bcc	.L_divide_b18
214	cmp	r1, r0, lsl #19
215	bcc	.L_divide_b19
216	cmp	r1, r0, lsl #20
217	bcc	.L_divide_b20
218	cmp	r1, r0, lsl #21
219	bcc	.L_divide_b21
220	cmp	r1, r0, lsl #22
221	bcc	.L_divide_b22
222	cmp	r1, r0, lsl #23
223	bcc	.L_divide_b23
224	cmp	r1, r0, lsl #24
225	bcc	.L_divide_b24
226	cmp	r1, r0, lsl #25
227	bcc	.L_divide_b25
228	cmp	r1, r0, lsl #26
229	bcc	.L_divide_b26
230	cmp	r1, r0, lsl #27
231	bcc	.L_divide_b27
232	cmp	r1, r0, lsl #28
233	bcc	.L_divide_b28
234	cmp	r1, r0, lsl #29
235	bcc	.L_divide_b29
236	cmp	r1, r0, lsl #30
237	bcc	.L_divide_b30
238.L_divide_b32:
239	cmp	r1, r0, lsl #31
240	subhs	r1, r1,r0, lsl #31
241	addhs	r3, r3,r2, lsl #31
242.L_divide_b31:
243	cmp	r1, r0, lsl #30
244	subhs	r1, r1,r0, lsl #30
245	addhs	r3, r3,r2, lsl #30
246.L_divide_b30:
247	cmp	r1, r0, lsl #29
248	subhs	r1, r1,r0, lsl #29
249	addhs	r3, r3,r2, lsl #29
250.L_divide_b29:
251	cmp	r1, r0, lsl #28
252	subhs	r1, r1,r0, lsl #28
253	addhs	r3, r3,r2, lsl #28
254.L_divide_b28:
255	cmp	r1, r0, lsl #27
256	subhs	r1, r1,r0, lsl #27
257	addhs	r3, r3,r2, lsl #27
258.L_divide_b27:
259	cmp	r1, r0, lsl #26
260	subhs	r1, r1,r0, lsl #26
261	addhs	r3, r3,r2, lsl #26
262.L_divide_b26:
263	cmp	r1, r0, lsl #25
264	subhs	r1, r1,r0, lsl #25
265	addhs	r3, r3,r2, lsl #25
266.L_divide_b25:
267	cmp	r1, r0, lsl #24
268	subhs	r1, r1,r0, lsl #24
269	addhs	r3, r3,r2, lsl #24
270.L_divide_b24:
271	cmp	r1, r0, lsl #23
272	subhs	r1, r1,r0, lsl #23
273	addhs	r3, r3,r2, lsl #23
274.L_divide_b23:
275	cmp	r1, r0, lsl #22
276	subhs	r1, r1,r0, lsl #22
277	addhs	r3, r3,r2, lsl #22
278.L_divide_b22:
279	cmp	r1, r0, lsl #21
280	subhs	r1, r1,r0, lsl #21
281	addhs	r3, r3,r2, lsl #21
282.L_divide_b21:
283	cmp	r1, r0, lsl #20
284	subhs	r1, r1,r0, lsl #20
285	addhs	r3, r3,r2, lsl #20
286.L_divide_b20:
287	cmp	r1, r0, lsl #19
288	subhs	r1, r1,r0, lsl #19
289	addhs	r3, r3,r2, lsl #19
290.L_divide_b19:
291	cmp	r1, r0, lsl #18
292	subhs	r1, r1,r0, lsl #18
293	addhs	r3, r3,r2, lsl #18
294.L_divide_b18:
295	cmp	r1, r0, lsl #17
296	subhs	r1, r1,r0, lsl #17
297	addhs	r3, r3,r2, lsl #17
298.L_divide_b17:
299	cmp	r1, r0, lsl #16
300	subhs	r1, r1,r0, lsl #16
301	addhs	r3, r3,r2, lsl #16
302.L_divide_b16:
303	cmp	r1, r0, lsl #15
304	subhs	r1, r1,r0, lsl #15
305	addhs	r3, r3,r2, lsl #15
306.L_divide_b15:
307	cmp	r1, r0, lsl #14
308	subhs	r1, r1,r0, lsl #14
309	addhs	r3, r3,r2, lsl #14
310.L_divide_b14:
311	cmp	r1, r0, lsl #13
312	subhs	r1, r1,r0, lsl #13
313	addhs	r3, r3,r2, lsl #13
314.L_divide_b13:
315	cmp	r1, r0, lsl #12
316	subhs	r1, r1,r0, lsl #12
317	addhs	r3, r3,r2, lsl #12
318.L_divide_b12:
319	cmp	r1, r0, lsl #11
320	subhs	r1, r1,r0, lsl #11
321	addhs	r3, r3,r2, lsl #11
322.L_divide_b11:
323	cmp	r1, r0, lsl #10
324	subhs	r1, r1,r0, lsl #10
325	addhs	r3, r3,r2, lsl #10
326.L_divide_b10:
327	cmp	r1, r0, lsl #9
328	subhs	r1, r1,r0, lsl #9
329	addhs	r3, r3,r2, lsl #9
330.L_divide_b9:
331	cmp	r1, r0, lsl #8
332	subhs	r1, r1,r0, lsl #8
333	addhs	r3, r3,r2, lsl #8
334.L_divide_b8:
335	cmp	r1, r0, lsl #7
336	subhs	r1, r1,r0, lsl #7
337	addhs	r3, r3,r2, lsl #7
338.L_divide_b7:
339	cmp	r1, r0, lsl #6
340	subhs	r1, r1,r0, lsl #6
341	addhs	r3, r3,r2, lsl #6
342.L_divide_b6:
343	cmp	r1, r0, lsl #5
344	subhs	r1, r1,r0, lsl #5
345	addhs	r3, r3,r2, lsl #5
346.L_divide_b5:
347	cmp	r1, r0, lsl #4
348	subhs	r1, r1,r0, lsl #4
349	addhs	r3, r3,r2, lsl #4
350.L_divide_b4:
351	cmp	r1, r0, lsl #3
352	subhs	r1, r1,r0, lsl #3
353	addhs	r3, r3,r2, lsl #3
354.L_divide_b3:
355	cmp	r1, r0, lsl #2
356	subhs	r1, r1,r0, lsl #2
357	addhs	r3, r3,r2, lsl #2
358.L_divide_b2:
359	cmp	r1, r0, lsl #1
360	subhs	r1, r1,r0, lsl #1
361	addhs	r3, r3,r2, lsl #1
362.L_divide_b1:
363	cmp	r1, r0
364	subhs	r1, r1, r0
365	addhs	r3, r3, r2
366.L_divide_b0:
367
368	tst	ip, #0x20000000
369	bne	.L_udivide_l1
370	mov	r0, r3
371	cmp	ip, #0
372	rsbmi	r1, r1, #0
373	movs	ip, ip, lsl #1
374	bicmi	r0, r0, #0x80000000	/* Fix incase we divided 0x80000000 */
375	rsbmi	r0, r0, #0
376	RET
377
378.L_udivide_l1:
379	tst	ip, #0x10000000
380	mov	r1, r1, lsl #1
381	orrne	r1, r1, #1
382	mov	r3, r3, lsl #1
383	cmp	r1, r0
384	subhs	r1, r1, r0
385	addhs	r3, r3, r2
386	mov	r0, r3
387	RET
388