xref: /linux/arch/microblaze/lib/udivsi3.S (revision a36e9f5cfe9eb3a1dce8769c7058251c42705357)
1/* SPDX-License-Identifier: GPL-2.0 */
2#include <linux/linkage.h>
3
4/*
5* Unsigned divide operation.
6*	Input :	Divisor in Reg r5
7*		Dividend in Reg r6
8*	Output: Result in Reg r3
9*/
10
11	.text
12	.globl	__udivsi3
13	.type __udivsi3, @function
14	.ent __udivsi3
15
16__udivsi3:
17
18	.frame	r1, 0, r15
19
20	addik	r1, r1, -12
21	swi	r29, r1, 0
22	swi	r30, r1, 4
23	swi	r31, r1, 8
24
25	beqi	r6, div_by_zero /* div_by_zero /* division error */
26	beqid	r5, result_is_zero /* result is zero */
27	addik	r30, r0, 0 /* clear mod */
28	addik	r29, r0, 32 /* initialize the loop count */
29
30/* check if r6 and r5 are equal - if yes, return 1 */
31	rsub	r18, r5, r6
32	beqid	r18, return_here
33	addik	r3, r0, 1
34
35/* check if (uns)r6 is greater than (uns)r5. in that case, just return 0 */
36	xor	r18, r5, r6
37	bgeid	r18, 16
38	add	r3, r0, r0 /* we would anyways clear r3 */
39	blti	r6, return_here /* r6[bit 31 = 1] hence is greater */
40	bri	checkr6
41	rsub	r18, r6, r5 /* microblazecmp */
42	blti	r18, return_here
43
44/* if r6 [bit 31] is set, then return result as 1 */
45checkr6:
46	bgti	r6, div0
47	brid	return_here
48	addik	r3, r0, 1
49
50/* first part try to find the first '1' in the r5 */
51div0:
52	blti	r5, div2
53div1:
54	add	r5, r5, r5 /* left shift logical r5 */
55	bgtid	r5, div1
56	addik	r29, r29, -1
57div2:
58/* left shift logical r5 get the '1' into the carry */
59	add	r5, r5, r5
60	addc	r30, r30, r30 /* move that bit into the mod register */
61	rsub	r31, r6, r30 /* try to subtract (r30 a r6) */
62	blti	r31, mod_too_small
63/* move the r31 to mod since the result was positive */
64	or	r30, r0, r31
65	addik	r3, r3, 1
66mod_too_small:
67	addik	r29, r29, -1
68	beqi	r29, loop_end
69	add	r3, r3, r3 /* shift in the '1' into div */
70	bri	div2 /* div2 */
71loop_end:
72	bri	return_here
73div_by_zero:
74result_is_zero:
75	or	r3, r0, r0 /* set result to 0 */
76return_here:
77/* restore values of csrs and that of r3 and the divisor and the dividend */
78	lwi	r29, r1, 0
79	lwi	r30, r1, 4
80	lwi	r31, r1, 8
81	rtsd	r15, 8
82	addik	r1, r1, 12
83
84.size __udivsi3, . - __udivsi3
85.end __udivsi3
86