|
| 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 | + |
| 6 | +ENTRY(__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 | + |
| 62 | +ENDPROC(__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 */ |
0 commit comments