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