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 */
45 checkr6:
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 */
51 div0:
52 	blti	r5, div2
53 div1:
54 	add	r5, r5, r5 /* left shift logical r5 */
55 	bgtid	r5, div1
56 	addik	r29, r29, -1
57 div2:
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
66 mod_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 */
71 loop_end:
72 	bri	return_here
73 div_by_zero:
74 result_is_zero:
75 	or	r3, r0, r0 /* set result to 0 */
76 return_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