| /* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */ | |
| #include <linux/linkage.h> | |
| #include <asm/asmmacro.h> | |
| #include <asm/core.h> | |
| ENTRY(__modsi3) | |
| abi_entry_default | |
| #if XCHAL_HAVE_DIV32 | |
| rems a2, a2, a3 | |
| #else | |
| mov a7, a2 /* save original (signed) dividend */ | |
| do_abs a2, a2, a4 /* udividend = abs (dividend) */ | |
| do_abs a3, a3, a4 /* udivisor = abs (divisor) */ | |
| bltui a3, 2, .Lle_one /* check if udivisor <= 1 */ | |
| do_nsau a5, a2, a6, a8 /* udividend_shift = nsau (udividend) */ | |
| do_nsau a4, a3, a6, a8 /* udivisor_shift = nsau (udivisor) */ | |
| bgeu a5, a4, .Lspecial | |
| sub a4, a4, a5 /* count = udivisor_shift - udividend_shift */ | |
| ssl a4 | |
| sll a3, a3 /* udivisor <<= count */ | |
| /* test-subtract-and-shift loop */ | |
| #if XCHAL_HAVE_LOOPS | |
| loopnez a4, .Lloopend | |
| #endif /* XCHAL_HAVE_LOOPS */ | |
| .Lloop: | |
| bltu a2, a3, .Lzerobit | |
| sub a2, a2, a3 | |
| .Lzerobit: | |
| srli a3, a3, 1 | |
| #if !XCHAL_HAVE_LOOPS | |
| addi a4, a4, -1 | |
| bnez a4, .Lloop | |
| #endif /* !XCHAL_HAVE_LOOPS */ | |
| .Lloopend: | |
| .Lspecial: | |
| bltu a2, a3, .Lreturn | |
| sub a2, a2, a3 /* subtract again if udividend >= udivisor */ | |
| .Lreturn: | |
| bgez a7, .Lpositive | |
| neg a2, a2 /* if (dividend < 0), return -udividend */ | |
| .Lpositive: | |
| abi_ret_default | |
| .Lle_one: | |
| bnez a3, .Lreturn0 | |
| /* Divide by zero: Use an illegal instruction to force an exception. | |
| The subsequent "DIV0" string can be recognized by the exception | |
| handler to identify the real cause of the exception. */ | |
| ill | |
| .ascii "DIV0" | |
| .Lreturn0: | |
| movi a2, 0 | |
| #endif /* XCHAL_HAVE_DIV32 */ | |
| abi_ret_default | |
| ENDPROC(__modsi3) | |
| EXPORT_SYMBOL(__modsi3) | |
| #if !XCHAL_HAVE_NSA | |
| .section .rodata | |
| .align 4 | |
| .global __nsau_data | |
| .type __nsau_data, @object | |
| __nsau_data: | |
| .byte 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4 | |
| .byte 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 | |
| .byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 | |
| .byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 | |
| .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 | |
| .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 | |
| .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 | |
| .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 | |
| .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
| .size __nsau_data, . - __nsau_data | |
| #endif /* !XCHAL_HAVE_NSA */ |