1/* libgcc routines for the MCore.
2   Copyright (C) 1993, 1999, 2000 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11In addition to the permissions in the GNU General Public License, the
12Free Software Foundation gives you unlimited permission to link the
13compiled version of this file into combinations with other programs,
14and to distribute those combinations without any restriction coming
15from the use of this file.  (The General Public License restrictions
16do apply in other respects; for example, they cover modification of
17the file, and distribution when not linked into a combine
18executable.)
19
20This file is distributed in the hope that it will be useful, but
21WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23General Public License for more details.
24
25You should have received a copy of the GNU General Public License
26along with this program; see the file COPYING.  If not, write to
27the Free Software Foundation, 51 Franklin Street, Fifth Floor,
28Boston, MA 02110-1301, USA.  */
29
30#define CONCAT1(a, b) CONCAT2(a, b)
31#define CONCAT2(a, b) a ## b
32
33/* Use the right prefix for global labels.  */
34
35#define SYM(x) CONCAT1 (__, x)
36
37#ifdef __ELF__
38#define TYPE(x) .type SYM (x),@function
39#define SIZE(x) .size SYM (x), . - SYM (x)
40#else
41#define TYPE(x)
42#define SIZE(x)
43#endif
44
45.macro FUNC_START name
46	.text
47	.globl SYM (\name)
48	TYPE (\name)
49SYM (\name):
50.endm
51
52.macro FUNC_END name
53	SIZE (\name)
54.endm
55
56#ifdef	L_udivsi3
57FUNC_START udiv32
58FUNC_START udivsi32
59
60	movi	r1,0		// r1-r2 form 64 bit dividend
61	movi	r4,1		// r4 is quotient (1 for a sentinel)
62
63	cmpnei	r3,0		// look for 0 divisor
64	bt	9f
65	trap	3		// divide by 0
669:
67	// control iterations; skip across high order 0 bits in dividend
68	mov	r7,r2
69	cmpnei	r7,0
70	bt	8f
71	movi	r2,0		// 0 dividend
72	jmp	r15		// quick return
738:
74	ff1	r7		// figure distance to skip
75	lsl	r4,r7		// move the sentinel along (with 0's behind)
76	lsl	r2,r7		// and the low 32 bits of numerator
77
78// appears to be wrong...
79// tested out incorrectly in our OS work...
80//	mov	r7,r3		// looking at divisor
81//	ff1	r7		// I can move 32-r7 more bits to left.
82//	addi	r7,1		// ok, one short of that...
83//	mov	r1,r2
84//	lsr	r1,r7		// bits that came from low order...
85//	rsubi	r7,31		// r7 == "32-n" == LEFT distance
86//	addi	r7,1		// this is (32-n)
87//	lsl	r4,r7		// fixes the high 32 (quotient)
88//	lsl	r2,r7
89//	cmpnei	r4,0
90//	bf	4f		// the sentinel went away...
91
92	// run the remaining bits
93
941:	lslc	r2,1		// 1 bit left shift of r1-r2
95	addc	r1,r1
96	cmphs	r1,r3		// upper 32 of dividend >= divisor?
97	bf	2f
98	sub	r1,r3		// if yes, subtract divisor
992:	addc	r4,r4		// shift by 1 and count subtracts
100	bf	1b		// if sentinel falls out of quotient, stop
101
1024:	mov	r2,r4		// return quotient
103	mov	r3,r1		// and piggyback the remainder
104	jmp	r15
105FUNC_END udiv32
106FUNC_END udivsi32
107#endif
108
109#ifdef	L_umodsi3
110FUNC_START urem32
111FUNC_START umodsi3
112	movi	r1,0		// r1-r2 form 64 bit dividend
113	movi	r4,1		// r4 is quotient (1 for a sentinel)
114	cmpnei	r3,0		// look for 0 divisor
115	bt	9f
116	trap	3		// divide by 0
1179:
118	// control iterations; skip across high order 0 bits in dividend
119	mov	r7,r2
120	cmpnei	r7,0
121	bt	8f
122	movi	r2,0		// 0 dividend
123	jmp	r15		// quick return
1248:
125	ff1	r7		// figure distance to skip
126	lsl	r4,r7		// move the sentinel along (with 0's behind)
127	lsl	r2,r7		// and the low 32 bits of numerator
128
1291:	lslc	r2,1		// 1 bit left shift of r1-r2
130	addc	r1,r1
131	cmphs	r1,r3		// upper 32 of dividend >= divisor?
132	bf	2f
133	sub	r1,r3		// if yes, subtract divisor
1342:	addc	r4,r4		// shift by 1 and count subtracts
135	bf	1b		// if sentinel falls out of quotient, stop
136	mov	r2,r1		// return remainder
137	jmp	r15
138FUNC_END urem32
139FUNC_END umodsi3
140#endif
141
142#ifdef	L_divsi3
143FUNC_START div32
144FUNC_START divsi3
145	mov	r5,r2		// calc sign of quotient
146	xor	r5,r3
147	abs	r2		// do unsigned divide
148	abs	r3
149	movi	r1,0		// r1-r2 form 64 bit dividend
150	movi	r4,1		// r4 is quotient (1 for a sentinel)
151	cmpnei	r3,0		// look for 0 divisor
152	bt	9f
153	trap	3		// divide by 0
1549:
155	// control iterations; skip across high order 0 bits in dividend
156	mov	r7,r2
157	cmpnei	r7,0
158	bt	8f
159	movi	r2,0		// 0 dividend
160	jmp	r15		// quick return
1618:
162	ff1	r7		// figure distance to skip
163	lsl	r4,r7		// move the sentinel along (with 0's behind)
164	lsl	r2,r7		// and the low 32 bits of numerator
165
166// tested out incorrectly in our OS work...
167//	mov	r7,r3		// looking at divisor
168//	ff1	r7		// I can move 32-r7 more bits to left.
169//	addi	r7,1		// ok, one short of that...
170//	mov	r1,r2
171//	lsr	r1,r7		// bits that came from low order...
172//	rsubi	r7,31		// r7 == "32-n" == LEFT distance
173//	addi	r7,1		// this is (32-n)
174//	lsl	r4,r7		// fixes the high 32 (quotient)
175//	lsl	r2,r7
176//	cmpnei	r4,0
177//	bf	4f		// the sentinel went away...
178
179	// run the remaining bits
1801:	lslc	r2,1		// 1 bit left shift of r1-r2
181	addc	r1,r1
182	cmphs	r1,r3		// upper 32 of dividend >= divisor?
183	bf	2f
184	sub	r1,r3		// if yes, subtract divisor
1852:	addc	r4,r4		// shift by 1 and count subtracts
186	bf	1b		// if sentinel falls out of quotient, stop
187
1884:	mov	r2,r4		// return quotient
189	mov	r3,r1		// piggyback the remainder
190	btsti	r5,31		// after adjusting for sign
191	bf	3f
192	rsubi	r2,0
193	rsubi	r3,0
1943:	jmp	r15
195FUNC_END div32
196FUNC_END divsi3
197#endif
198
199#ifdef	L_modsi3
200FUNC_START rem32
201FUNC_START modsi3
202	mov	r5,r2		// calc sign of remainder
203	abs	r2		// do unsigned divide
204	abs	r3
205	movi	r1,0		// r1-r2 form 64 bit dividend
206	movi	r4,1		// r4 is quotient (1 for a sentinel)
207	cmpnei	r3,0		// look for 0 divisor
208	bt	9f
209	trap	3		// divide by 0
2109: 
211	// control iterations; skip across high order 0 bits in dividend
212	mov	r7,r2
213	cmpnei	r7,0
214	bt	8f
215	movi	r2,0		// 0 dividend
216	jmp	r15		// quick return
2178:
218	ff1	r7		// figure distance to skip
219	lsl	r4,r7		// move the sentinel along (with 0's behind)
220	lsl	r2,r7		// and the low 32 bits of numerator
221
2221:	lslc	r2,1		// 1 bit left shift of r1-r2
223	addc	r1,r1
224	cmphs	r1,r3		// upper 32 of dividend >= divisor?
225	bf	2f
226	sub	r1,r3		// if yes, subtract divisor
2272:	addc	r4,r4		// shift by 1 and count subtracts
228	bf	1b		// if sentinel falls out of quotient, stop
229	mov	r2,r1		// return remainder
230	btsti	r5,31		// after adjusting for sign
231	bf	3f
232	rsubi	r2,0
2333:	jmp	r15
234FUNC_END rem32
235FUNC_END modsi3
236#endif
237
238
239/* GCC expects that {__eq,__ne,__gt,__ge,__le,__lt}{df2,sf2}
240   will behave as __cmpdf2. So, we stub the implementations to
241   jump on to __cmpdf2 and __cmpsf2.
242 
243   All of these shortcircuit the return path so that __cmp{sd}f2
244   will go directly back to the caller.  */
245
246.macro  COMPARE_DF_JUMP name
247	.import SYM (cmpdf2)
248FUNC_START \name
249	jmpi SYM (cmpdf2)
250FUNC_END \name
251.endm
252		
253#ifdef  L_eqdf2
254COMPARE_DF_JUMP eqdf2
255#endif /* L_eqdf2 */
256
257#ifdef  L_nedf2
258COMPARE_DF_JUMP nedf2
259#endif /* L_nedf2 */
260
261#ifdef  L_gtdf2
262COMPARE_DF_JUMP gtdf2
263#endif /* L_gtdf2 */
264
265#ifdef  L_gedf2
266COMPARE_DF_JUMP gedf2
267#endif /* L_gedf2 */
268
269#ifdef  L_ltdf2
270COMPARE_DF_JUMP ltdf2
271#endif /* L_ltdf2 */
272	
273#ifdef  L_ledf2
274COMPARE_DF_JUMP ledf2
275#endif /* L_ledf2 */
276
277/* SINGLE PRECISION FLOATING POINT STUBS */
278
279.macro  COMPARE_SF_JUMP name
280	.import SYM (cmpsf2)
281FUNC_START \name
282	jmpi SYM (cmpsf2)
283FUNC_END \name
284.endm
285		
286#ifdef  L_eqsf2
287COMPARE_SF_JUMP eqsf2
288#endif /* L_eqsf2 */
289	
290#ifdef  L_nesf2
291COMPARE_SF_JUMP nesf2
292#endif /* L_nesf2 */
293	
294#ifdef  L_gtsf2
295COMPARE_SF_JUMP gtsf2
296#endif /* L_gtsf2 */
297	
298#ifdef  L_gesf2
299COMPARE_SF_JUMP __gesf2
300#endif /* L_gesf2 */
301	
302#ifdef  L_ltsf2
303COMPARE_SF_JUMP __ltsf2
304#endif /* L_ltsf2 */
305	
306#ifdef  L_lesf2
307COMPARE_SF_JUMP lesf2
308#endif /* L_lesf2 */
309