1dbf4ed89SMax Filippov/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */ 2dbf4ed89SMax Filippov#include <linux/linkage.h> 3dbf4ed89SMax Filippov#include <asm/asmmacro.h> 4dbf4ed89SMax Filippov#include <asm/core.h> 5dbf4ed89SMax Filippov 6dbf4ed89SMax FilippovENTRY(__modsi3) 7dbf4ed89SMax Filippov 8dbf4ed89SMax Filippov abi_entry_default 9dbf4ed89SMax Filippov#if XCHAL_HAVE_DIV32 10dbf4ed89SMax Filippov rems a2, a2, a3 11dbf4ed89SMax Filippov#else 12dbf4ed89SMax Filippov mov a7, a2 /* save original (signed) dividend */ 13dbf4ed89SMax Filippov do_abs a2, a2, a4 /* udividend = abs (dividend) */ 14dbf4ed89SMax Filippov do_abs a3, a3, a4 /* udivisor = abs (divisor) */ 15dbf4ed89SMax Filippov bltui a3, 2, .Lle_one /* check if udivisor <= 1 */ 16dbf4ed89SMax Filippov do_nsau a5, a2, a6, a8 /* udividend_shift = nsau (udividend) */ 17dbf4ed89SMax Filippov do_nsau a4, a3, a6, a8 /* udivisor_shift = nsau (udivisor) */ 18dbf4ed89SMax Filippov bgeu a5, a4, .Lspecial 19dbf4ed89SMax Filippov 20dbf4ed89SMax Filippov sub a4, a4, a5 /* count = udivisor_shift - udividend_shift */ 21dbf4ed89SMax Filippov ssl a4 22dbf4ed89SMax Filippov sll a3, a3 /* udivisor <<= count */ 23dbf4ed89SMax Filippov 24dbf4ed89SMax Filippov /* test-subtract-and-shift loop */ 25dbf4ed89SMax Filippov#if XCHAL_HAVE_LOOPS 26dbf4ed89SMax Filippov loopnez a4, .Lloopend 27dbf4ed89SMax Filippov#endif /* XCHAL_HAVE_LOOPS */ 28dbf4ed89SMax Filippov.Lloop: 29dbf4ed89SMax Filippov bltu a2, a3, .Lzerobit 30dbf4ed89SMax Filippov sub a2, a2, a3 31dbf4ed89SMax Filippov.Lzerobit: 32dbf4ed89SMax Filippov srli a3, a3, 1 33dbf4ed89SMax Filippov#if !XCHAL_HAVE_LOOPS 34dbf4ed89SMax Filippov addi a4, a4, -1 35dbf4ed89SMax Filippov bnez a4, .Lloop 36dbf4ed89SMax Filippov#endif /* !XCHAL_HAVE_LOOPS */ 37dbf4ed89SMax Filippov.Lloopend: 38dbf4ed89SMax Filippov 39dbf4ed89SMax Filippov.Lspecial: 40dbf4ed89SMax Filippov bltu a2, a3, .Lreturn 41dbf4ed89SMax Filippov sub a2, a2, a3 /* subtract again if udividend >= udivisor */ 42dbf4ed89SMax Filippov.Lreturn: 43dbf4ed89SMax Filippov bgez a7, .Lpositive 44dbf4ed89SMax Filippov neg a2, a2 /* if (dividend < 0), return -udividend */ 45dbf4ed89SMax Filippov.Lpositive: 46dbf4ed89SMax Filippov abi_ret_default 47dbf4ed89SMax Filippov 48dbf4ed89SMax Filippov.Lle_one: 49dbf4ed89SMax Filippov bnez a3, .Lreturn0 50dbf4ed89SMax Filippov 51dbf4ed89SMax Filippov /* Divide by zero: Use an illegal instruction to force an exception. 52dbf4ed89SMax Filippov The subsequent "DIV0" string can be recognized by the exception 53dbf4ed89SMax Filippov handler to identify the real cause of the exception. */ 54dbf4ed89SMax Filippov ill 55dbf4ed89SMax Filippov .ascii "DIV0" 56dbf4ed89SMax Filippov 57dbf4ed89SMax Filippov.Lreturn0: 58dbf4ed89SMax Filippov movi a2, 0 59dbf4ed89SMax Filippov#endif /* XCHAL_HAVE_DIV32 */ 60dbf4ed89SMax Filippov abi_ret_default 61dbf4ed89SMax Filippov 62dbf4ed89SMax FilippovENDPROC(__modsi3) 63*338d9150SMax FilippovEXPORT_SYMBOL(__modsi3) 64dbf4ed89SMax Filippov 65dbf4ed89SMax Filippov#if !XCHAL_HAVE_NSA 66dbf4ed89SMax Filippov .section .rodata 67dbf4ed89SMax Filippov .align 4 68dbf4ed89SMax Filippov .global __nsau_data 69dbf4ed89SMax Filippov .type __nsau_data, @object 70dbf4ed89SMax Filippov__nsau_data: 71dbf4ed89SMax Filippov .byte 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4 72dbf4ed89SMax Filippov .byte 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 73dbf4ed89SMax Filippov .byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 74dbf4ed89SMax Filippov .byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 75dbf4ed89SMax Filippov .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 76dbf4ed89SMax Filippov .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 77dbf4ed89SMax Filippov .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 78dbf4ed89SMax Filippov .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 79dbf4ed89SMax Filippov .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 80dbf4ed89SMax Filippov .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 81dbf4ed89SMax Filippov .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 82dbf4ed89SMax Filippov .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 83dbf4ed89SMax Filippov .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 84dbf4ed89SMax Filippov .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 85dbf4ed89SMax Filippov .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 86dbf4ed89SMax Filippov .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 87dbf4ed89SMax Filippov .size __nsau_data, . - __nsau_data 88dbf4ed89SMax Filippov#endif /* !XCHAL_HAVE_NSA */ 89