162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */ 262306a36Sopenharmony_ci#include <linux/linkage.h> 362306a36Sopenharmony_ci#include <asm/asmmacro.h> 462306a36Sopenharmony_ci#include <asm/core.h> 562306a36Sopenharmony_ci 662306a36Sopenharmony_ciENTRY(__modsi3) 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci abi_entry_default 962306a36Sopenharmony_ci#if XCHAL_HAVE_DIV32 1062306a36Sopenharmony_ci rems a2, a2, a3 1162306a36Sopenharmony_ci#else 1262306a36Sopenharmony_ci mov a7, a2 /* save original (signed) dividend */ 1362306a36Sopenharmony_ci do_abs a2, a2, a4 /* udividend = abs (dividend) */ 1462306a36Sopenharmony_ci do_abs a3, a3, a4 /* udivisor = abs (divisor) */ 1562306a36Sopenharmony_ci bltui a3, 2, .Lle_one /* check if udivisor <= 1 */ 1662306a36Sopenharmony_ci do_nsau a5, a2, a6, a8 /* udividend_shift = nsau (udividend) */ 1762306a36Sopenharmony_ci do_nsau a4, a3, a6, a8 /* udivisor_shift = nsau (udivisor) */ 1862306a36Sopenharmony_ci bgeu a5, a4, .Lspecial 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci sub a4, a4, a5 /* count = udivisor_shift - udividend_shift */ 2162306a36Sopenharmony_ci ssl a4 2262306a36Sopenharmony_ci sll a3, a3 /* udivisor <<= count */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci /* test-subtract-and-shift loop */ 2562306a36Sopenharmony_ci#if XCHAL_HAVE_LOOPS 2662306a36Sopenharmony_ci loopnez a4, .Lloopend 2762306a36Sopenharmony_ci#endif /* XCHAL_HAVE_LOOPS */ 2862306a36Sopenharmony_ci.Lloop: 2962306a36Sopenharmony_ci bltu a2, a3, .Lzerobit 3062306a36Sopenharmony_ci sub a2, a2, a3 3162306a36Sopenharmony_ci.Lzerobit: 3262306a36Sopenharmony_ci srli a3, a3, 1 3362306a36Sopenharmony_ci#if !XCHAL_HAVE_LOOPS 3462306a36Sopenharmony_ci addi a4, a4, -1 3562306a36Sopenharmony_ci bnez a4, .Lloop 3662306a36Sopenharmony_ci#endif /* !XCHAL_HAVE_LOOPS */ 3762306a36Sopenharmony_ci.Lloopend: 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci.Lspecial: 4062306a36Sopenharmony_ci bltu a2, a3, .Lreturn 4162306a36Sopenharmony_ci sub a2, a2, a3 /* subtract again if udividend >= udivisor */ 4262306a36Sopenharmony_ci.Lreturn: 4362306a36Sopenharmony_ci bgez a7, .Lpositive 4462306a36Sopenharmony_ci neg a2, a2 /* if (dividend < 0), return -udividend */ 4562306a36Sopenharmony_ci.Lpositive: 4662306a36Sopenharmony_ci abi_ret_default 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci.Lle_one: 4962306a36Sopenharmony_ci bnez a3, .Lreturn0 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /* Divide by zero: Use an illegal instruction to force an exception. 5262306a36Sopenharmony_ci The subsequent "DIV0" string can be recognized by the exception 5362306a36Sopenharmony_ci handler to identify the real cause of the exception. */ 5462306a36Sopenharmony_ci ill 5562306a36Sopenharmony_ci .ascii "DIV0" 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci.Lreturn0: 5862306a36Sopenharmony_ci movi a2, 0 5962306a36Sopenharmony_ci#endif /* XCHAL_HAVE_DIV32 */ 6062306a36Sopenharmony_ci abi_ret_default 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciENDPROC(__modsi3) 6362306a36Sopenharmony_ciEXPORT_SYMBOL(__modsi3) 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci#if !XCHAL_HAVE_NSA 6662306a36Sopenharmony_ci .section .rodata 6762306a36Sopenharmony_ci .align 4 6862306a36Sopenharmony_ci .global __nsau_data 6962306a36Sopenharmony_ci .type __nsau_data, @object 7062306a36Sopenharmony_ci__nsau_data: 7162306a36Sopenharmony_ci .byte 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4 7262306a36Sopenharmony_ci .byte 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 7362306a36Sopenharmony_ci .byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 7462306a36Sopenharmony_ci .byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 7562306a36Sopenharmony_ci .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 7662306a36Sopenharmony_ci .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 7762306a36Sopenharmony_ci .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 7862306a36Sopenharmony_ci .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 7962306a36Sopenharmony_ci .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 8062306a36Sopenharmony_ci .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 8162306a36Sopenharmony_ci .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 8262306a36Sopenharmony_ci .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 8362306a36Sopenharmony_ci .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 8462306a36Sopenharmony_ci .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 8562306a36Sopenharmony_ci .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 8662306a36Sopenharmony_ci .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 8762306a36Sopenharmony_ci .size __nsau_data, . - __nsau_data 8862306a36Sopenharmony_ci#endif /* !XCHAL_HAVE_NSA */ 89