/* 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(__udivsi3)67abi_entry_default8#if XCHAL_HAVE_DIV329quou a2, a2, a310#else11bltui a3, 2, .Lle_one /* check if the divisor <= 1 */1213mov a6, a2 /* keep dividend in a6 */14do_nsau a5, a6, a2, a7 /* dividend_shift = nsau (dividend) */15do_nsau a4, a3, a2, a7 /* divisor_shift = nsau (divisor) */16bgeu a5, a4, .Lspecial1718sub a4, a4, a5 /* count = divisor_shift - dividend_shift */19ssl a420sll a3, a3 /* divisor <<= count */21movi a2, 0 /* quotient = 0 */2223/* test-subtract-and-shift loop; one quotient bit on each iteration */24#if XCHAL_HAVE_LOOPS25loopnez a4, .Lloopend26#endif /* XCHAL_HAVE_LOOPS */27.Lloop:28bltu a6, a3, .Lzerobit29sub a6, a6, a330addi a2, a2, 131.Lzerobit:32slli a2, a2, 133srli a3, a3, 134#if !XCHAL_HAVE_LOOPS35addi a4, a4, -136bnez a4, .Lloop37#endif /* !XCHAL_HAVE_LOOPS */38.Lloopend:3940bltu a6, a3, .Lreturn41addi a2, a2, 1 /* increment quotient if dividend >= divisor */42.Lreturn:43abi_ret_default4445.Lle_one:46beqz a3, .Lerror /* if divisor == 1, return the dividend */47abi_ret_default4849.Lspecial:50/* return dividend >= divisor */51bltu a6, a3, .Lreturn052movi a2, 153abi_ret_default5455.Lerror:56/* Divide by zero: Use an illegal instruction to force an exception.57The subsequent "DIV0" string can be recognized by the exception58handler to identify the real cause of the exception. */59ill60.ascii "DIV0"6162.Lreturn0:63movi a2, 064#endif /* XCHAL_HAVE_DIV32 */65abi_ret_default6667ENDPROC(__udivsi3)68EXPORT_SYMBOL(__udivsi3)697071