18c2ecf20Sopenharmony_ci;; SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci;;  Copyright 2011  Free Software Foundation, Inc.
38c2ecf20Sopenharmony_ci;;  Contributed by Bernd Schmidt <bernds@codesourcery.com>.
48c2ecf20Sopenharmony_ci;;
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/linkage.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci	.text
98c2ecf20Sopenharmony_ciENTRY(__c6xabi_divremu)
108c2ecf20Sopenharmony_ci	;; We use a series of up to 31 subc instructions.  First, we find
118c2ecf20Sopenharmony_ci	;; out how many leading zero bits there are in the divisor.  This
128c2ecf20Sopenharmony_ci	;; gives us both a shift count for aligning (shifting) the divisor
138c2ecf20Sopenharmony_ci	;; to the, and the number of times we have to execute subc.
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci	;; At the end, we have both the remainder and most of the quotient
168c2ecf20Sopenharmony_ci	;; in A4.  The top bit of the quotient is computed first and is
178c2ecf20Sopenharmony_ci	;; placed in A2.
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	;; Return immediately if the dividend is zero.	Setting B4 to 1
208c2ecf20Sopenharmony_ci	;; is a trick to allow us to leave the following insns in the jump
218c2ecf20Sopenharmony_ci	;; delay slot without affecting the result.
228c2ecf20Sopenharmony_ci	mv	.s2x	A4, B1
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci  [b1]	lmbd	.l2	1, B4, B1
258c2ecf20Sopenharmony_ci||[!b1] b	.s2	B3	; RETURN A
268c2ecf20Sopenharmony_ci||[!b1] mvk	.d2	1, B4
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci||[!b1] zero	.s1	A5
298c2ecf20Sopenharmony_ci	mv	.l1x	B1, A6
308c2ecf20Sopenharmony_ci||	shl	.s2	B4, B1, B4
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	;; The loop performs a maximum of 28 steps, so we do the
338c2ecf20Sopenharmony_ci	;; first 3 here.
348c2ecf20Sopenharmony_ci	cmpltu	.l1x	A4, B4, A2
358c2ecf20Sopenharmony_ci  [!A2]	sub	.l1x	A4, B4, A4
368c2ecf20Sopenharmony_ci||	shru	.s2	B4, 1, B4
378c2ecf20Sopenharmony_ci||	xor	.s1	1, A2, A2
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	shl	.s1	A2, 31, A2
408c2ecf20Sopenharmony_ci|| [b1]	subc	.l1x	A4,B4,A4
418c2ecf20Sopenharmony_ci|| [b1]	add	.s2	-1, B1, B1
428c2ecf20Sopenharmony_ci   [b1]	subc	.l1x	A4,B4,A4
438c2ecf20Sopenharmony_ci|| [b1]	add	.s2	-1, B1, B1
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	;; RETURN A may happen here (note: must happen before the next branch)
468c2ecf20Sopenharmony_ci__divremu0:
478c2ecf20Sopenharmony_ci	cmpgt	.l2	B1, 7, B0
488c2ecf20Sopenharmony_ci|| [b1]	subc	.l1x	A4,B4,A4
498c2ecf20Sopenharmony_ci|| [b1]	add	.s2	-1, B1, B1
508c2ecf20Sopenharmony_ci   [b1]	subc	.l1x	A4,B4,A4
518c2ecf20Sopenharmony_ci|| [b1]	add	.s2	-1, B1, B1
528c2ecf20Sopenharmony_ci|| [b0] b	.s1	__divremu0
538c2ecf20Sopenharmony_ci   [b1]	subc	.l1x	A4,B4,A4
548c2ecf20Sopenharmony_ci|| [b1]	add	.s2	-1, B1, B1
558c2ecf20Sopenharmony_ci   [b1]	subc	.l1x	A4,B4,A4
568c2ecf20Sopenharmony_ci|| [b1]	add	.s2	-1, B1, B1
578c2ecf20Sopenharmony_ci   [b1]	subc	.l1x	A4,B4,A4
588c2ecf20Sopenharmony_ci|| [b1]	add	.s2	-1, B1, B1
598c2ecf20Sopenharmony_ci   [b1]	subc	.l1x	A4,B4,A4
608c2ecf20Sopenharmony_ci|| [b1]	add	.s2	-1, B1, B1
618c2ecf20Sopenharmony_ci   [b1]	subc	.l1x	A4,B4,A4
628c2ecf20Sopenharmony_ci|| [b1]	add	.s2	-1, B1, B1
638c2ecf20Sopenharmony_ci	;; loop backwards branch happens here
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	ret	.s2	B3
668c2ecf20Sopenharmony_ci||	mvk	.s1	32, A1
678c2ecf20Sopenharmony_ci	sub	.l1	A1, A6, A6
688c2ecf20Sopenharmony_ci||	extu	.s1	A4, A6, A5
698c2ecf20Sopenharmony_ci	shl	.s1	A4, A6, A4
708c2ecf20Sopenharmony_ci	shru	.s1	A4, 1, A4
718c2ecf20Sopenharmony_ci||	sub	.l1	A6, 1, A6
728c2ecf20Sopenharmony_ci	or	.l1	A2, A4, A4
738c2ecf20Sopenharmony_ci	shru	.s1	A4, A6, A4
748c2ecf20Sopenharmony_ci	nop
758c2ecf20Sopenharmony_ciENDPROC(__c6xabi_divremu)
76