1/* Copyright (C) 2018-2021 Free Software Foundation, Inc.
2
3This file is free software; you can redistribute it and/or modify it
4under the terms of the GNU General Public License as published by the
5Free Software Foundation; either version 3, or (at your option) any
6later version.
7
8This file is distributed in the hope that it will be useful, but
9WITHOUT ANY WARRANTY; without even the implied warranty of
10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11General Public License for more details.
12
13Under Section 7 of GPL version 3, you are granted additional
14permissions described in the GCC Runtime Library Exception, version
153.1, as published by the Free Software Foundation.
16
17You should have received a copy of the GNU General Public License and
18a copy of the GCC Runtime Library Exception along with this program;
19see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
20<http://www.gnu.org/licenses/>.  */
21
22
23#ifdef L__mulsi3
24	.balign 4
25	.globl	__mulsi3
26	.type	__mulsi3, @function
27__mulsi3:
28	l.movhi		r11, 0			/* initial r */
29
30	/* Given R = X * Y ... */
311:	l.sfeq		r4, r0			/* while (y != 0) */
32	l.bf		2f
33	 l.andi		r5, r4, 1		/* if (y & 1) ... */
34	l.add		r12, r11, r3
35	l.sfne		r5, r0
36#if defined(__or1k_cmov__)
37	l.cmov		r11, r12, r11		/* ... r += x. */
38	l.srli		r4, r4, 1		/* y >>= 1 */
39#else
40	l.bnf		3f
41	 l.srli		r4, r4, 1		/* y >>= 1 */
42	l.ori		r11, r12, 0
433:
44#endif
45	l.j		1b
46	 l.add		r3, r3, r3		/* x <<= 1 */
47
482:	l.jr		r9
49	 l.nop
50
51	.size	__mulsi3, . - __mulsi3
52#endif
53
54#if defined(L__udivsi3) || defined(L__umodsi3) \
55    || defined(L__divsi3) || defined(L__modsi3)
56	.global	__udivmodsi3_internal
57	.hidden	__udivmodsi3_internal
58	.type	__udivmodsi3_internal, @function
59#endif
60
61#ifdef L__udivsi3
62	.balign	4
63	.global	__udivsi3
64	.type	__udivsi3, @function
65__udivsi3:
66__udivmodsi3_internal:
67	/* Note that the other division routines assume that r13
68	   is not clobbered by this routine, and use that as to
69	   save a return address without creating a stack frame.  */
70
71	l.sfeq		r4, r0		/* division by zero; return 0.  */
72	l.ori		r11, r0, 0	/* initial quotient */
73	l.bf		9f
74	 l.ori		r12, r3, 0	/* initial remainder */
75
76	/* Given X/Y, shift Y left until Y >= X.  */
77	l.ori		r6, r0, 1	/* mask = 1 */
781:	l.sflts		r4, r0		/* y has msb set */
79	l.bf		2f
80	 l.sfltu	r4, r12		/* y < x */
81	l.add		r4, r4, r4	/* y <<= 1 */
82	l.bf		1b
83	 l.add		r6, r6, r6	/* mask <<= 1 */
84
85	/* Shift Y back to the right again, subtracting from X.  */
862:	l.add		r7, r11, r6	/* tmp1 = quot + mask */
873:	l.srli		r6, r6, 1	/* mask >>= 1 */
88	l.sub		r8, r12, r4	/* tmp2 = x - y */
89	l.sfleu		r4, r12		/* y <= x */
90	l.srli		r4, r4, 1	/* y >>= 1 */
91#if defined(__or1k_cmov__)
92	l.cmov		r11, r7, r11	/* if (y <= x) quot = tmp1 */
93	l.cmov		r12, r8, r12	/* if (y <= x) x = tmp2 */
94#else
95	l.bnf		4f
96	 l.nop
97	l.ori		r11, r7, 0
98	l.ori		r12, r8, 0
994:
100#endif
101	l.sfne		r6, r0		/* loop until mask == 0 */
102	l.bf		3b
103	 l.add		r7, r11, r6	/* delay fill from loop start */
104
1059:	l.jr		r9
106	 l.nop
107
108	.size	__udivsi3, . - __udivsi3
109	.size	__udivmodsi3_internal, . - __udivmodsi3_internal
110#endif
111
112#ifdef L__umodsi3
113	.balign	4
114	.global	__umodsi3
115	.type	__umodsi3, @function
116	.cfi_startproc
117__umodsi3:
118	/* Know that __udivmodsi3_internal does not clobber r13.  */
119	l.ori		r13, r9, 0
120	.cfi_register	9, 13
121	l.jal		__udivmodsi3_internal
122	 l.nop
123	l.jr		r13		/* return to saved lr */
124	 l.ori		r11, r12, 0	/* move remainder to rv */
125
126	.cfi_endproc
127	.size	__umodsi3, . - __umodsi3
128#endif
129
130/* For signed division we do:
131
132     -x / y = x / -y = -(x / y)
133     -x % y = -(x % y)
134      x % -y = x % y
135
136   which has the property that (x/y)*y + (x%y) = x.  */
137
138#ifdef L__divsi3
139	.balign	4
140	.global	__divsi3
141	.type	__divsi3, @function
142	.cfi_startproc
143__divsi3:
144	l.xor		r6, r3, r4	/* need result negate?  */
145
146	l.sflts		r3, r0		/* abs(x) */
147#if defined(__or1k_cmov__)
148	l.sub		r5, r0, r3
149	l.cmov		r3, r5, r3
150#else
151	l.bnf		1f
152	 l.sub		r5, r0, r3
153	l.ori		r3, r5, 0
1541:
155#endif
156	l.sflts		r4, r0		/* abs(y) */
157#if defined(__or1k_cmov__)
158	l.sub		r5, r0, r4
159	l.cmov		r4, r5, r4
160#else
161	l.bnf		2f
162	 l.sub		r5, r0, r4
163	l.ori		r4, r5, 0
1642:
165#endif
166
167	/* If the result will not require sign flip, tail call.  */
168	l.sflts		r6, r0
169	l.bnf		__udivmodsi3_internal
170	 l.ori		r13, r9, 0	/* save lr */
171
172	/* Otherwise, know that __udivmodsi3_internal does not clobber r13.
173	   Perform a normal call, then negate and return via saved lr.  */
174	.cfi_register	9, 13
175	l.jal		__udivmodsi3_internal
176	 l.nop
177	l.jr		r13
178	 l.sub		r11, r0, r11
179
180	.cfi_endproc
181	.size	__divsi3, . - __divsi3
182#endif
183
184#ifdef L__modsi3
185	.balign	4
186	.global	__modsi3
187	.type	__modsi3, @function
188	.cfi_startproc
189__modsi3:
190	l.sflts		r4, r0		/* abs(y) */
191#if defined(__or1k_cmov__)
192	l.sub		r5, r0, r4
193	l.cmov		r4, r5, r4
194#else
195	l.bnf		2f
196	 l.sub		r5, r0, r4
197	l.ori		r4, r5, 0
1982:
199#endif
200
201	l.sflts		r3, r0		/* x negative? */
202	l.bf		1f
203	 l.ori		r13, r9, 0	/* save lr */
204
205	/* Know that __udivmodsi3_internal does not clobber r13.  */
206	.cfi_register	9, 13
207
208	/* X positive; no negate of the result required.  */
209	l.jal		__udivmodsi3_internal
210	 l.nop
211	l.jr		r13		/* return to saved lr */
212	 l.ori		r11, r12, 0	/* move remainder to rv */
213
214	/* X negative; negate both X and the result.  */
2151:	l.jal		__udivmodsi3_internal
216	 l.sub		r3, r0, r3
217	l.jr		r13		/* return to saved lr */
218	 l.sub		r11, r0, r12	/* negate remainder to rv */
219
220	.cfi_endproc
221	.size __modsi3, .- __modsi3
222#endif
223