^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 2010 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) ;; ABI considerations for the divide functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) ;; The following registers are call-used:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) ;; __c6xabi_divi A0,A1,A2,A4,A6,B0,B1,B2,B4,B5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) ;; __c6xabi_divu A0,A1,A2,A4,A6,B0,B1,B2,B4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) ;; __c6xabi_remi A1,A2,A4,A5,A6,B0,B1,B2,B4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) ;; __c6xabi_remu A1,A4,A5,A7,B0,B1,B2,B4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) ;;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) ;; In our implementation, divu and remu are leaf functions,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) ;; while both divi and remi call into divu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) ;; A0 is not clobbered by any of the functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) ;; divu does not clobber B2 either, which is taken advantage of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) ;; in remi.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) ;; divi uses B5 to hold the original return address during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) ;; the call to divu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) ;; remi uses B2 and A5 to hold the input values during the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) ;; call to divu. It stores B3 in on the stack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) .text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) ENTRY(__c6xabi_divu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) ;; We use a series of up to 31 subc instructions. First, we find
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) ;; out how many leading zero bits there are in the divisor. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ;; gives us both a shift count for aligning (shifting) the divisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) ;; to the, and the number of times we have to execute subc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) ;; At the end, we have both the remainder and most of the quotient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) ;; in A4. The top bit of the quotient is computed first and is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) ;; placed in A2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) ;; Return immediately if the dividend is zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) mv .s2x A4, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) [B1] lmbd .l2 1, B4, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) || [!B1] b .s2 B3 ; RETURN A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) || [!B1] mvk .d2 1, B4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) mv .l1x B1, A6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) || shl .s2 B4, B1, B4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ;; The loop performs a maximum of 28 steps, so we do the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ;; first 3 here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) cmpltu .l1x A4, B4, A2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) [!A2] sub .l1x A4, B4, A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) || shru .s2 B4, 1, B4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) || xor .s1 1, A2, A2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) shl .s1 A2, 31, A2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) || [B1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) || [B1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) [B1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) || [B1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ;; RETURN A may happen here (note: must happen before the next branch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) _divu_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) cmpgt .l2 B1, 7, B0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) || [B1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) || [B1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) [B1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) || [B1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) || [B0] b .s1 _divu_loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) [B1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) || [B1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) [B1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) || [B1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) [B1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) || [B1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) [B1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) || [B1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) [B1] subc .l1x A4,B4,A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) || [B1] add .s2 -1, B1, B1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ;; loop backwards branch happens here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ret .s2 B3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) || mvk .s1 32, A1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) sub .l1 A1, A6, A6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) shl .s1 A4, A6, A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) shru .s1 A4, 1, A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) || sub .l1 A6, 1, A6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) or .l1 A2, A4, A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) shru .s1 A4, A6, A4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) nop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ENDPROC(__c6xabi_divu)