/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */1#include <linux/linkage.h>2#include <asm/asmmacro.h>3#include <asm/core.h>45ENTRY(__umodsi3)67abi_entry_default8#if XCHAL_HAVE_DIV329remu a2, a2, a310#else11bltui a3, 2, .Lle_one /* check if the divisor is <= 1 */1213do_nsau a5, a2, a6, a7 /* dividend_shift = nsau (dividend) */14do_nsau a4, a3, a6, a7 /* divisor_shift = nsau (divisor) */15bgeu a5, a4, .Lspecial1617sub a4, a4, a5 /* count = divisor_shift - dividend_shift */18ssl a419sll a3, a3 /* divisor <<= count */2021/* test-subtract-and-shift loop */22#if XCHAL_HAVE_LOOPS23loopnez a4, .Lloopend24#endif /* XCHAL_HAVE_LOOPS */25.Lloop:26bltu a2, a3, .Lzerobit27sub a2, a2, a328.Lzerobit:29srli a3, a3, 130#if !XCHAL_HAVE_LOOPS31addi a4, a4, -132bnez a4, .Lloop33#endif /* !XCHAL_HAVE_LOOPS */34.Lloopend:3536.Lspecial:37bltu a2, a3, .Lreturn38sub a2, a2, a3 /* subtract once more if dividend >= divisor */39.Lreturn:40abi_ret_default4142.Lle_one:43bnez a3, .Lreturn04445/* Divide by zero: Use an illegal instruction to force an exception.46The subsequent "DIV0" string can be recognized by the exception47handler to identify the real cause of the exception. */48ill49.ascii "DIV0"5051.Lreturn0:52movi a2, 053#endif /* XCHAL_HAVE_DIV32 */54abi_ret_default5556ENDPROC(__umodsi3)57EXPORT_SYMBOL(__umodsi3)585960