GNU Linux-libre 6.1.91-gnu
[releases.git] / arch / xtensa / lib / udivsi3.S
1 /* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */
2 #include <linux/linkage.h>
3 #include <asm/asmmacro.h>
4 #include <asm/core.h>
5
6 ENTRY(__udivsi3)
7
8         abi_entry_default
9 #if XCHAL_HAVE_DIV32
10         quou    a2, a2, a3
11 #else
12         bltui   a3, 2, .Lle_one /* check if the divisor <= 1 */
13
14         mov     a6, a2          /* keep dividend in a6 */
15         do_nsau a5, a6, a2, a7  /* dividend_shift = nsau (dividend) */
16         do_nsau a4, a3, a2, a7  /* divisor_shift = nsau (divisor) */
17         bgeu    a5, a4, .Lspecial
18
19         sub     a4, a4, a5      /* count = divisor_shift - dividend_shift */
20         ssl     a4
21         sll     a3, a3          /* divisor <<= count */
22         movi    a2, 0           /* quotient = 0 */
23
24         /* test-subtract-and-shift loop; one quotient bit on each iteration */
25 #if XCHAL_HAVE_LOOPS
26         loopnez a4, .Lloopend
27 #endif /* XCHAL_HAVE_LOOPS */
28 .Lloop:
29         bltu    a6, a3, .Lzerobit
30         sub     a6, a6, a3
31         addi    a2, a2, 1
32 .Lzerobit:
33         slli    a2, a2, 1
34         srli    a3, a3, 1
35 #if !XCHAL_HAVE_LOOPS
36         addi    a4, a4, -1
37         bnez    a4, .Lloop
38 #endif /* !XCHAL_HAVE_LOOPS */
39 .Lloopend:
40
41         bltu    a6, a3, .Lreturn
42         addi    a2, a2, 1       /* increment quotient if dividend >= divisor */
43 .Lreturn:
44         abi_ret_default
45
46 .Lle_one:
47         beqz    a3, .Lerror     /* if divisor == 1, return the dividend */
48         abi_ret_default
49
50 .Lspecial:
51         /* return dividend >= divisor */
52         bltu    a6, a3, .Lreturn0
53         movi    a2, 1
54         abi_ret_default
55
56 .Lerror:
57         /* Divide by zero: Use an illegal instruction to force an exception.
58            The subsequent "DIV0" string can be recognized by the exception
59            handler to identify the real cause of the exception.  */
60         ill
61         .ascii  "DIV0"
62
63 .Lreturn0:
64         movi    a2, 0
65 #endif /* XCHAL_HAVE_DIV32 */
66         abi_ret_default
67
68 ENDPROC(__udivsi3)