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