Commit | Line | Data |
---|---|---|
dbf4ed89 MF |
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(__modsi3) | |
7 | ||
8 | abi_entry_default | |
9 | #if XCHAL_HAVE_DIV32 | |
10 | rems a2, a2, a3 | |
11 | #else | |
12 | mov a7, a2 /* save original (signed) dividend */ | |
13 | do_abs a2, a2, a4 /* udividend = abs (dividend) */ | |
14 | do_abs a3, a3, a4 /* udivisor = abs (divisor) */ | |
15 | bltui a3, 2, .Lle_one /* check if udivisor <= 1 */ | |
16 | do_nsau a5, a2, a6, a8 /* udividend_shift = nsau (udividend) */ | |
17 | do_nsau a4, a3, a6, a8 /* udivisor_shift = nsau (udivisor) */ | |
18 | bgeu a5, a4, .Lspecial | |
19 | ||
20 | sub a4, a4, a5 /* count = udivisor_shift - udividend_shift */ | |
21 | ssl a4 | |
22 | sll a3, a3 /* udivisor <<= count */ | |
23 | ||
24 | /* test-subtract-and-shift loop */ | |
25 | #if XCHAL_HAVE_LOOPS | |
26 | loopnez a4, .Lloopend | |
27 | #endif /* XCHAL_HAVE_LOOPS */ | |
28 | .Lloop: | |
29 | bltu a2, a3, .Lzerobit | |
30 | sub a2, a2, a3 | |
31 | .Lzerobit: | |
32 | srli a3, a3, 1 | |
33 | #if !XCHAL_HAVE_LOOPS | |
34 | addi a4, a4, -1 | |
35 | bnez a4, .Lloop | |
36 | #endif /* !XCHAL_HAVE_LOOPS */ | |
37 | .Lloopend: | |
38 | ||
39 | .Lspecial: | |
40 | bltu a2, a3, .Lreturn | |
41 | sub a2, a2, a3 /* subtract again if udividend >= udivisor */ | |
42 | .Lreturn: | |
43 | bgez a7, .Lpositive | |
44 | neg a2, a2 /* if (dividend < 0), return -udividend */ | |
45 | .Lpositive: | |
46 | abi_ret_default | |
47 | ||
48 | .Lle_one: | |
49 | bnez a3, .Lreturn0 | |
50 | ||
51 | /* Divide by zero: Use an illegal instruction to force an exception. | |
52 | The subsequent "DIV0" string can be recognized by the exception | |
53 | handler to identify the real cause of the exception. */ | |
54 | ill | |
55 | .ascii "DIV0" | |
56 | ||
57 | .Lreturn0: | |
58 | movi a2, 0 | |
59 | #endif /* XCHAL_HAVE_DIV32 */ | |
60 | abi_ret_default | |
61 | ||
62 | ENDPROC(__modsi3) | |
63 | ||
64 | #if !XCHAL_HAVE_NSA | |
65 | .section .rodata | |
66 | .align 4 | |
67 | .global __nsau_data | |
68 | .type __nsau_data, @object | |
69 | __nsau_data: | |
70 | .byte 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4 | |
71 | .byte 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 | |
72 | .byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 | |
73 | .byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 | |
74 | .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 | |
75 | .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 | |
76 | .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 | |
77 | .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 | |
78 | .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
79 | .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
80 | .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
81 | .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
82 | .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
83 | .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
84 | .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
85 | .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
86 | .size __nsau_data, . - __nsau_data | |
87 | #endif /* !XCHAL_HAVE_NSA */ |