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