WIP FPC-III support
[linux/fpc-iii.git] / arch / microblaze / lib / udivsi3.S
blobacdc667235c4747eaf4ce01921e1e5ee2fdb2330
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include <linux/linkage.h>
4 /*
5 * Unsigned divide operation.
6 *       Input : Divisor in Reg r5
7 *               Dividend in Reg r6
8 *       Output: Result in Reg r3
9 */
11         .text
12         .globl  __udivsi3
13         .type __udivsi3, @function
14         .ent __udivsi3
16 __udivsi3:
18         .frame  r1, 0, r15
20         addik   r1, r1, -12
21         swi     r29, r1, 0
22         swi     r30, r1, 4
23         swi     r31, r1, 8
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 */
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
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
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
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
84 .size __udivsi3, . - __udivsi3
85 .end __udivsi3