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