^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) ;; SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) ;; Copyright 2011 Free Software Foundation, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) ;; Contributed by Bernd Schmidt <bernds@codesourcery.com>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) ;;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) .text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) ENTRY(__c6xabi_divremu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) ;; We use a series of up to 31 subc instructions. First, we find
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) ;; out how many leading zero bits there are in the divisor. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) ;; gives us both a shift count for aligning (shifting) the divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) ;; to the, and the number of times we have to execute subc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) ;; At the end, we have both the remainder and most of the quotient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) ;; in A4. The top bit of the quotient is computed first and is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) ;; placed in A2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) ;; Return immediately if the dividend is zero. Setting B4 to 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) ;; is a trick to allow us to leave the following insns in the jump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) ;; delay slot without affecting the result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) mv .s2x A4, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) [b1] lmbd .l2 1, B4, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) ||[!b1] b .s2 B3 ; RETURN A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) ||[!b1] mvk .d2 1, B4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) ||[!b1] zero .s1 A5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) mv .l1x B1, A6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) || shl .s2 B4, B1, B4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) ;; The loop performs a maximum of 28 steps, so we do the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) ;; first 3 here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) cmpltu .l1x A4, B4, A2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) [!A2] sub .l1x A4, B4, A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) || shru .s2 B4, 1, B4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) || xor .s1 1, A2, A2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) shl .s1 A2, 31, A2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) || [b1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) || [b1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) [b1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) || [b1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ;; RETURN A may happen here (note: must happen before the next branch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) __divremu0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) cmpgt .l2 B1, 7, B0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) || [b1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) || [b1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) [b1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) || [b1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) || [b0] b .s1 __divremu0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) [b1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) || [b1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) [b1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) || [b1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) [b1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) || [b1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) [b1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) || [b1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) [b1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) || [b1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ;; loop backwards branch happens here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ret .s2 B3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) || mvk .s1 32, A1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) sub .l1 A1, A6, A6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) || extu .s1 A4, A6, A5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) shl .s1 A4, A6, A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) shru .s1 A4, 1, A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) || sub .l1 A6, 1, A6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) or .l1 A2, A4, A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) shru .s1 A4, A6, A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ENDPROC(__c6xabi_divremu)