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