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 6ENTRY(__umodsi3) 7 8 abi_entry_default 9#if XCHAL_HAVE_DIV32 10 remu a2, a2, a3 11#else 12 bltui a3, 2, .Lle_one /* check if the divisor is <= 1 */ 13 14 do_nsau a5, a2, a6, a7 /* dividend_shift = nsau (dividend) */ 15 do_nsau a4, a3, a6, a7 /* divisor_shift = nsau (divisor) */ 16 bgeu a5, a4, .Lspecial 17 18 sub a4, a4, a5 /* count = divisor_shift - dividend_shift */ 19 ssl a4 20 sll a3, a3 /* divisor <<= count */ 21 22 /* test-subtract-and-shift loop */ 23#if XCHAL_HAVE_LOOPS 24 loopnez a4, .Lloopend 25#endif /* XCHAL_HAVE_LOOPS */ 26.Lloop: 27 bltu a2, a3, .Lzerobit 28 sub a2, a2, a3 29.Lzerobit: 30 srli a3, a3, 1 31#if !XCHAL_HAVE_LOOPS 32 addi a4, a4, -1 33 bnez a4, .Lloop 34#endif /* !XCHAL_HAVE_LOOPS */ 35.Lloopend: 36 37.Lspecial: 38 bltu a2, a3, .Lreturn 39 sub a2, a2, a3 /* subtract once more if dividend >= divisor */ 40.Lreturn: 41 abi_ret_default 42 43.Lle_one: 44 bnez a3, .Lreturn0 45 46 /* Divide by zero: Use an illegal instruction to force an exception. 47 The subsequent "DIV0" string can be recognized by the exception 48 handler to identify the real cause of the exception. */ 49 ill 50 .ascii "DIV0" 51 52.Lreturn0: 53 movi a2, 0 54#endif /* XCHAL_HAVE_DIV32 */ 55 abi_ret_default 56 57ENDPROC(__umodsi3) 58EXPORT_SYMBOL(__umodsi3) 59