xref: /openbsd-src/gnu/usr.bin/gcc/gcc/config/arm/lib1funcs.asm (revision c87b03e512fc05ed6e0222f6fb0ae86264b1d05b)
1*c87b03e5Sespie@ libgcc routines for ARM cpu.
2*c87b03e5Sespie@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
3*c87b03e5Sespie
4*c87b03e5Sespie/* Copyright 1995, 1996, 1998, 1999, 2000 Free Software Foundation, Inc.
5*c87b03e5Sespie
6*c87b03e5SespieThis file 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
31*c87b03e5Sespie/* We need to know what prefix to add to function names.  */
32*c87b03e5Sespie
33*c87b03e5Sespie#ifndef __USER_LABEL_PREFIX__
34*c87b03e5Sespie#error  __USER_LABEL_PREFIX__ not defined
35*c87b03e5Sespie#endif
36*c87b03e5Sespie
37*c87b03e5Sespie/* ANSI concatenation macros.  */
38*c87b03e5Sespie
39*c87b03e5Sespie#define CONCAT1(a, b) CONCAT2(a, b)
40*c87b03e5Sespie#define CONCAT2(a, b) a ## b
41*c87b03e5Sespie
42*c87b03e5Sespie/* Use the right prefix for global labels.  */
43*c87b03e5Sespie
44*c87b03e5Sespie#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
45*c87b03e5Sespie
46*c87b03e5Sespie#ifdef __ELF__
47*c87b03e5Sespie#ifdef __thumb__
48*c87b03e5Sespie#define __PLT__  /* Not supported in Thumb assembler (for now).  */
49*c87b03e5Sespie#else
50*c87b03e5Sespie#define __PLT__ (PLT)
51*c87b03e5Sespie#endif
52*c87b03e5Sespie#define TYPE(x) .type SYM(x),function
53*c87b03e5Sespie#define SIZE(x) .size SYM(x), . - SYM(x)
54*c87b03e5Sespie#else
55*c87b03e5Sespie#define __PLT__
56*c87b03e5Sespie#define TYPE(x)
57*c87b03e5Sespie#define SIZE(x)
58*c87b03e5Sespie#endif
59*c87b03e5Sespie
60*c87b03e5Sespie/* Function end macros.  Variants for 26 bit APCS and interworking.  */
61*c87b03e5Sespie
62*c87b03e5Sespie#ifdef __APCS_26__
63*c87b03e5Sespie# define RET		movs	pc, lr
64*c87b03e5Sespie# define RETc(x)	mov##x##s	pc, lr
65*c87b03e5Sespie# define RETCOND 	^
66*c87b03e5Sespie.macro ARM_LDIV0
67*c87b03e5SespieLdiv0:
68*c87b03e5Sespie	str	lr, [sp, #-4]!
69*c87b03e5Sespie	bl	SYM (__div0) __PLT__
70*c87b03e5Sespie	mov	r0, #0			@ About as wrong as it could be.
71*c87b03e5Sespie	ldmia	sp!, {pc}^
72*c87b03e5Sespie.endm
73*c87b03e5Sespie#else
74*c87b03e5Sespie# ifdef __THUMB_INTERWORK__
75*c87b03e5Sespie#  define RET		bx	lr
76*c87b03e5Sespie#  define RETc(x)	bx##x	lr
77*c87b03e5Sespie.macro THUMB_LDIV0
78*c87b03e5SespieLdiv0:
79*c87b03e5Sespie	push	{ lr }
80*c87b03e5Sespie	bl	SYM (__div0)
81*c87b03e5Sespie	mov	r0, #0			@ About as wrong as it could be.
82*c87b03e5Sespie	pop	{ r1 }
83*c87b03e5Sespie	bx	r1
84*c87b03e5Sespie.endm
85*c87b03e5Sespie.macro ARM_LDIV0
86*c87b03e5SespieLdiv0:
87*c87b03e5Sespie	str	lr, [sp, #-4]!
88*c87b03e5Sespie	bl	SYM (__div0) __PLT__
89*c87b03e5Sespie	mov	r0, #0			@ About as wrong as it could be.
90*c87b03e5Sespie	ldr	lr, [sp], #4
91*c87b03e5Sespie	bx	lr
92*c87b03e5Sespie.endm
93*c87b03e5Sespie# else
94*c87b03e5Sespie#  define RET		mov	pc, lr
95*c87b03e5Sespie#  define RETc(x)	mov##x	pc, lr
96*c87b03e5Sespie.macro THUMB_LDIV0
97*c87b03e5SespieLdiv0:
98*c87b03e5Sespie	push	{ lr }
99*c87b03e5Sespie	bl	SYM (__div0)
100*c87b03e5Sespie	mov	r0, #0			@ About as wrong as it could be.
101*c87b03e5Sespie	pop	{ pc }
102*c87b03e5Sespie.endm
103*c87b03e5Sespie.macro ARM_LDIV0
104*c87b03e5SespieLdiv0:
105*c87b03e5Sespie	str	lr, [sp, #-4]!
106*c87b03e5Sespie	bl	SYM (__div0) __PLT__
107*c87b03e5Sespie	mov	r0, #0			@ About as wrong as it could be.
108*c87b03e5Sespie	ldmia	sp!, {pc}
109*c87b03e5Sespie.endm
110*c87b03e5Sespie# endif
111*c87b03e5Sespie# define RETCOND
112*c87b03e5Sespie#endif
113*c87b03e5Sespie
114*c87b03e5Sespie.macro FUNC_END name
115*c87b03e5SespieLdiv0:
116*c87b03e5Sespie#ifdef __thumb__
117*c87b03e5Sespie	THUMB_LDIV0
118*c87b03e5Sespie#else
119*c87b03e5Sespie	ARM_LDIV0
120*c87b03e5Sespie#endif
121*c87b03e5Sespie	SIZE (__\name)
122*c87b03e5Sespie.endm
123*c87b03e5Sespie
124*c87b03e5Sespie.macro THUMB_FUNC_START name
125*c87b03e5Sespie	.globl	SYM (\name)
126*c87b03e5Sespie	TYPE	(\name)
127*c87b03e5Sespie	.thumb_func
128*c87b03e5SespieSYM (\name):
129*c87b03e5Sespie.endm
130*c87b03e5Sespie
131*c87b03e5Sespie/* Function start macros.  Variants for ARM and Thumb.  */
132*c87b03e5Sespie
133*c87b03e5Sespie#ifdef __thumb__
134*c87b03e5Sespie#define THUMB_FUNC .thumb_func
135*c87b03e5Sespie#define THUMB_CODE .force_thumb
136*c87b03e5Sespie#else
137*c87b03e5Sespie#define THUMB_FUNC
138*c87b03e5Sespie#define THUMB_CODE
139*c87b03e5Sespie#endif
140*c87b03e5Sespie
141*c87b03e5Sespie.macro FUNC_START name
142*c87b03e5Sespie	.text
143*c87b03e5Sespie	.globl SYM (__\name)
144*c87b03e5Sespie	TYPE (__\name)
145*c87b03e5Sespie	.align 0
146*c87b03e5Sespie	THUMB_CODE
147*c87b03e5Sespie	THUMB_FUNC
148*c87b03e5SespieSYM (__\name):
149*c87b03e5Sespie.endm
150*c87b03e5Sespie
151*c87b03e5Sespie/* Register aliases.  */
152*c87b03e5Sespie
153*c87b03e5Sespiework		.req	r4	@ XXXX is this safe ?
154*c87b03e5Sespiedividend	.req	r0
155*c87b03e5Sespiedivisor		.req	r1
156*c87b03e5Sespieoverdone	.req	r2
157*c87b03e5Sespieresult		.req	r2
158*c87b03e5Sespiecurbit		.req	r3
159*c87b03e5Sespieip		.req	r12
160*c87b03e5Sespiesp		.req	r13
161*c87b03e5Sespielr		.req	r14
162*c87b03e5Sespiepc		.req	r15
163*c87b03e5Sespie
164*c87b03e5Sespie/* ------------------------------------------------------------------------ */
165*c87b03e5Sespie/*		Bodies of the divsion and modulo routines.		    */
166*c87b03e5Sespie/* ------------------------------------------------------------------------ */
167*c87b03e5Sespie.macro ARM_DIV_MOD_BODY modulo
168*c87b03e5SespieLoop1:
169*c87b03e5Sespie	@ Unless the divisor is very big, shift it up in multiples of
170*c87b03e5Sespie	@ four bits, since this is the amount of unwinding in the main
171*c87b03e5Sespie	@ division loop.  Continue shifting until the divisor is
172*c87b03e5Sespie	@ larger than the dividend.
173*c87b03e5Sespie	cmp	divisor, #0x10000000
174*c87b03e5Sespie	cmplo	divisor, dividend
175*c87b03e5Sespie	movlo	divisor, divisor, lsl #4
176*c87b03e5Sespie	movlo	curbit,  curbit,  lsl #4
177*c87b03e5Sespie	blo	Loop1
178*c87b03e5Sespie
179*c87b03e5SespieLbignum:
180*c87b03e5Sespie	@ For very big divisors, we must shift it a bit at a time, or
181*c87b03e5Sespie	@ we will be in danger of overflowing.
182*c87b03e5Sespie	cmp	divisor, #0x80000000
183*c87b03e5Sespie	cmplo	divisor, dividend
184*c87b03e5Sespie	movlo	divisor, divisor, lsl #1
185*c87b03e5Sespie	movlo	curbit,  curbit,  lsl #1
186*c87b03e5Sespie	blo	Lbignum
187*c87b03e5Sespie
188*c87b03e5SespieLoop3:
189*c87b03e5Sespie	@ Test for possible subtractions.  On the final pass, this may
190*c87b03e5Sespie	@ subtract too much from the dividend ...
191*c87b03e5Sespie
192*c87b03e5Sespie  .if \modulo
193*c87b03e5Sespie	@ ... so keep track of which subtractions are done in OVERDONE.
194*c87b03e5Sespie	@ We can fix them up afterwards.
195*c87b03e5Sespie	mov	overdone, #0
196*c87b03e5Sespie	cmp	dividend, divisor
197*c87b03e5Sespie	subhs	dividend, dividend, divisor
198*c87b03e5Sespie	cmp	dividend, divisor,  lsr #1
199*c87b03e5Sespie	subhs	dividend, dividend, divisor, lsr #1
200*c87b03e5Sespie	orrhs	overdone, overdone, curbit,  ror #1
201*c87b03e5Sespie	cmp	dividend, divisor,  lsr #2
202*c87b03e5Sespie	subhs	dividend, dividend, divisor, lsr #2
203*c87b03e5Sespie	orrhs	overdone, overdone, curbit,  ror #2
204*c87b03e5Sespie	cmp	dividend, divisor,  lsr #3
205*c87b03e5Sespie	subhs	dividend, dividend, divisor, lsr #3
206*c87b03e5Sespie	orrhs	overdone, overdone, curbit,  ror #3
207*c87b03e5Sespie	mov	ip,       curbit
208*c87b03e5Sespie  .else
209*c87b03e5Sespie	@ ... so keep track of which subtractions are done in RESULT.
210*c87b03e5Sespie	@ The result will be ok, since the "bit" will have been
211*c87b03e5Sespie	@ shifted out at the bottom.
212*c87b03e5Sespie	cmp	dividend, divisor
213*c87b03e5Sespie	subhs	dividend, dividend, divisor
214*c87b03e5Sespie	orrhs	result,   result,   curbit
215*c87b03e5Sespie	cmp	dividend, divisor,  lsr #1
216*c87b03e5Sespie	subhs	dividend, dividend, divisor, lsr #1
217*c87b03e5Sespie	orrhs	result,   result,   curbit,  lsr #1
218*c87b03e5Sespie	cmp	dividend, divisor,  lsr #2
219*c87b03e5Sespie	subhs	dividend, dividend, divisor, lsr #2
220*c87b03e5Sespie	orrhs	result,   result,   curbit,  lsr #2
221*c87b03e5Sespie	cmp	dividend, divisor,  lsr #3
222*c87b03e5Sespie	subhs	dividend, dividend, divisor, lsr #3
223*c87b03e5Sespie	orrhs	result,   result,   curbit,  lsr #3
224*c87b03e5Sespie  .endif
225*c87b03e5Sespie
226*c87b03e5Sespie	cmp	dividend, #0			@ Early termination?
227*c87b03e5Sespie	movnes	curbit,   curbit,  lsr #4	@ No, any more bits to do?
228*c87b03e5Sespie	movne	divisor,  divisor, lsr #4
229*c87b03e5Sespie	bne	Loop3
230*c87b03e5Sespie
231*c87b03e5Sespie  .if \modulo
232*c87b03e5SespieLfixup_dividend:
233*c87b03e5Sespie	@ Any subtractions that we should not have done will be recorded in
234*c87b03e5Sespie	@ the top three bits of OVERDONE.  Exactly which were not needed
235*c87b03e5Sespie	@ are governed by the position of the bit, stored in IP.
236*c87b03e5Sespie	ands	overdone, overdone, #0xe0000000
237*c87b03e5Sespie	@ If we terminated early, because dividend became zero, then the
238*c87b03e5Sespie	@ bit in ip will not be in the bottom nibble, and we should not
239*c87b03e5Sespie	@ perform the additions below.  We must test for this though
240*c87b03e5Sespie	@ (rather relying upon the TSTs to prevent the additions) since
241*c87b03e5Sespie	@ the bit in ip could be in the top two bits which might then match
242*c87b03e5Sespie	@ with one of the smaller RORs.
243*c87b03e5Sespie	tstne	ip, #0x7
244*c87b03e5Sespie	beq	Lgot_result
245*c87b03e5Sespie	tst	overdone, ip, ror #3
246*c87b03e5Sespie	addne	dividend, dividend, divisor, lsr #3
247*c87b03e5Sespie	tst	overdone, ip, ror #2
248*c87b03e5Sespie	addne	dividend, dividend, divisor, lsr #2
249*c87b03e5Sespie	tst	overdone, ip, ror #1
250*c87b03e5Sespie	addne	dividend, dividend, divisor, lsr #1
251*c87b03e5Sespie  .endif
252*c87b03e5Sespie
253*c87b03e5SespieLgot_result:
254*c87b03e5Sespie.endm
255*c87b03e5Sespie/* ------------------------------------------------------------------------ */
256*c87b03e5Sespie.macro THUMB_DIV_MOD_BODY modulo
257*c87b03e5Sespie	@ Load the constant 0x10000000 into our work register.
258*c87b03e5Sespie	mov	work, #1
259*c87b03e5Sespie	lsl	work, #28
260*c87b03e5SespieLoop1:
261*c87b03e5Sespie	@ Unless the divisor is very big, shift it up in multiples of
262*c87b03e5Sespie	@ four bits, since this is the amount of unwinding in the main
263*c87b03e5Sespie	@ division loop.  Continue shifting until the divisor is
264*c87b03e5Sespie	@ larger than the dividend.
265*c87b03e5Sespie	cmp	divisor, work
266*c87b03e5Sespie	bhs	Lbignum
267*c87b03e5Sespie	cmp	divisor, dividend
268*c87b03e5Sespie	bhs	Lbignum
269*c87b03e5Sespie	lsl	divisor, #4
270*c87b03e5Sespie	lsl	curbit,  #4
271*c87b03e5Sespie	b	Loop1
272*c87b03e5SespieLbignum:
273*c87b03e5Sespie	@ Set work to 0x80000000
274*c87b03e5Sespie	lsl	work, #3
275*c87b03e5SespieLoop2:
276*c87b03e5Sespie	@ For very big divisors, we must shift it a bit at a time, or
277*c87b03e5Sespie	@ we will be in danger of overflowing.
278*c87b03e5Sespie	cmp	divisor, work
279*c87b03e5Sespie	bhs	Loop3
280*c87b03e5Sespie	cmp	divisor, dividend
281*c87b03e5Sespie	bhs	Loop3
282*c87b03e5Sespie	lsl	divisor, #1
283*c87b03e5Sespie	lsl	curbit,  #1
284*c87b03e5Sespie	b	Loop2
285*c87b03e5SespieLoop3:
286*c87b03e5Sespie	@ Test for possible subtractions ...
287*c87b03e5Sespie  .if \modulo
288*c87b03e5Sespie	@ ... On the final pass, this may subtract too much from the dividend,
289*c87b03e5Sespie	@ so keep track of which subtractions are done, we can fix them up
290*c87b03e5Sespie	@ afterwards.
291*c87b03e5Sespie	mov	overdone, #0
292*c87b03e5Sespie	cmp	dividend, divisor
293*c87b03e5Sespie	blo	Lover1
294*c87b03e5Sespie	sub	dividend, dividend, divisor
295*c87b03e5SespieLover1:
296*c87b03e5Sespie	lsr	work, divisor, #1
297*c87b03e5Sespie	cmp	dividend, work
298*c87b03e5Sespie	blo	Lover2
299*c87b03e5Sespie	sub	dividend, dividend, work
300*c87b03e5Sespie	mov	ip, curbit
301*c87b03e5Sespie	mov	work, #1
302*c87b03e5Sespie	ror	curbit, work
303*c87b03e5Sespie	orr	overdone, curbit
304*c87b03e5Sespie	mov	curbit, ip
305*c87b03e5SespieLover2:
306*c87b03e5Sespie	lsr	work, divisor, #2
307*c87b03e5Sespie	cmp	dividend, work
308*c87b03e5Sespie	blo	Lover3
309*c87b03e5Sespie	sub	dividend, dividend, work
310*c87b03e5Sespie	mov	ip, curbit
311*c87b03e5Sespie	mov	work, #2
312*c87b03e5Sespie	ror	curbit, work
313*c87b03e5Sespie	orr	overdone, curbit
314*c87b03e5Sespie	mov	curbit, ip
315*c87b03e5SespieLover3:
316*c87b03e5Sespie	lsr	work, divisor, #3
317*c87b03e5Sespie	cmp	dividend, work
318*c87b03e5Sespie	blo	Lover4
319*c87b03e5Sespie	sub	dividend, dividend, work
320*c87b03e5Sespie	mov	ip, curbit
321*c87b03e5Sespie	mov	work, #3
322*c87b03e5Sespie	ror	curbit, work
323*c87b03e5Sespie	orr	overdone, curbit
324*c87b03e5Sespie	mov	curbit, ip
325*c87b03e5SespieLover4:
326*c87b03e5Sespie	mov	ip, curbit
327*c87b03e5Sespie  .else
328*c87b03e5Sespie	@ ... and note which bits are done in the result.  On the final pass,
329*c87b03e5Sespie	@ this may subtract too much from the dividend, but the result will be ok,
330*c87b03e5Sespie	@ since the "bit" will have been shifted out at the bottom.
331*c87b03e5Sespie	cmp	dividend, divisor
332*c87b03e5Sespie	blo	Lover1
333*c87b03e5Sespie	sub	dividend, dividend, divisor
334*c87b03e5Sespie	orr	result, result, curbit
335*c87b03e5SespieLover1:
336*c87b03e5Sespie	lsr	work, divisor, #1
337*c87b03e5Sespie	cmp	dividend, work
338*c87b03e5Sespie	blo	Lover2
339*c87b03e5Sespie	sub	dividend, dividend, work
340*c87b03e5Sespie	lsr	work, curbit, #1
341*c87b03e5Sespie	orr	result, work
342*c87b03e5SespieLover2:
343*c87b03e5Sespie	lsr	work, divisor, #2
344*c87b03e5Sespie	cmp	dividend, work
345*c87b03e5Sespie	blo	Lover3
346*c87b03e5Sespie	sub	dividend, dividend, work
347*c87b03e5Sespie	lsr	work, curbit, #2
348*c87b03e5Sespie	orr	result, work
349*c87b03e5SespieLover3:
350*c87b03e5Sespie	lsr	work, divisor, #3
351*c87b03e5Sespie	cmp	dividend, work
352*c87b03e5Sespie	blo	Lover4
353*c87b03e5Sespie	sub	dividend, dividend, work
354*c87b03e5Sespie	lsr	work, curbit, #3
355*c87b03e5Sespie	orr	result, work
356*c87b03e5SespieLover4:
357*c87b03e5Sespie  .endif
358*c87b03e5Sespie
359*c87b03e5Sespie	cmp	dividend, #0			@ Early termination?
360*c87b03e5Sespie	beq	Lover5
361*c87b03e5Sespie	lsr	curbit,  #4			@ No, any more bits to do?
362*c87b03e5Sespie	beq	Lover5
363*c87b03e5Sespie	lsr	divisor, #4
364*c87b03e5Sespie	b	Loop3
365*c87b03e5SespieLover5:
366*c87b03e5Sespie  .if \modulo
367*c87b03e5Sespie	@ Any subtractions that we should not have done will be recorded in
368*c87b03e5Sespie	@ the top three bits of "overdone".  Exactly which were not needed
369*c87b03e5Sespie	@ are governed by the position of the bit, stored in ip.
370*c87b03e5Sespie	mov	work, #0xe
371*c87b03e5Sespie	lsl	work, #28
372*c87b03e5Sespie	and	overdone, work
373*c87b03e5Sespie	beq	Lgot_result
374*c87b03e5Sespie
375*c87b03e5Sespie	@ If we terminated early, because dividend became zero, then the
376*c87b03e5Sespie	@ bit in ip will not be in the bottom nibble, and we should not
377*c87b03e5Sespie	@ perform the additions below.  We must test for this though
378*c87b03e5Sespie	@ (rather relying upon the TSTs to prevent the additions) since
379*c87b03e5Sespie	@ the bit in ip could be in the top two bits which might then match
380*c87b03e5Sespie	@ with one of the smaller RORs.
381*c87b03e5Sespie	mov	curbit, ip
382*c87b03e5Sespie	mov	work, #0x7
383*c87b03e5Sespie	tst	curbit, work
384*c87b03e5Sespie	beq	Lgot_result
385*c87b03e5Sespie
386*c87b03e5Sespie	mov	curbit, ip
387*c87b03e5Sespie	mov	work, #3
388*c87b03e5Sespie	ror	curbit, work
389*c87b03e5Sespie	tst	overdone, curbit
390*c87b03e5Sespie	beq	Lover6
391*c87b03e5Sespie	lsr	work, divisor, #3
392*c87b03e5Sespie	add	dividend, work
393*c87b03e5SespieLover6:
394*c87b03e5Sespie	mov	curbit, ip
395*c87b03e5Sespie	mov	work, #2
396*c87b03e5Sespie	ror	curbit, work
397*c87b03e5Sespie	tst	overdone, curbit
398*c87b03e5Sespie	beq	Lover7
399*c87b03e5Sespie	lsr	work, divisor, #2
400*c87b03e5Sespie	add	dividend, work
401*c87b03e5SespieLover7:
402*c87b03e5Sespie	mov	curbit, ip
403*c87b03e5Sespie	mov	work, #1
404*c87b03e5Sespie	ror	curbit, work
405*c87b03e5Sespie	tst	overdone, curbit
406*c87b03e5Sespie	beq	Lgot_result
407*c87b03e5Sespie	lsr	work, divisor, #1
408*c87b03e5Sespie	add	dividend, work
409*c87b03e5Sespie  .endif
410*c87b03e5SespieLgot_result:
411*c87b03e5Sespie.endm
412*c87b03e5Sespie/* ------------------------------------------------------------------------ */
413*c87b03e5Sespie/*		Start of the Real Functions				    */
414*c87b03e5Sespie/* ------------------------------------------------------------------------ */
415*c87b03e5Sespie#ifdef L_udivsi3
416*c87b03e5Sespie
417*c87b03e5Sespie	FUNC_START udivsi3
418*c87b03e5Sespie
419*c87b03e5Sespie#ifdef __thumb__
420*c87b03e5Sespie
421*c87b03e5Sespie	cmp	divisor, #0
422*c87b03e5Sespie	beq	Ldiv0
423*c87b03e5Sespie	mov	curbit, #1
424*c87b03e5Sespie	mov	result, #0
425*c87b03e5Sespie
426*c87b03e5Sespie	push	{ work }
427*c87b03e5Sespie	cmp	dividend, divisor
428*c87b03e5Sespie	blo	Lgot_result
429*c87b03e5Sespie
430*c87b03e5Sespie	THUMB_DIV_MOD_BODY 0
431*c87b03e5Sespie
432*c87b03e5Sespie	mov	r0, result
433*c87b03e5Sespie	pop	{ work }
434*c87b03e5Sespie	RET
435*c87b03e5Sespie
436*c87b03e5Sespie#else /* ARM version.  */
437*c87b03e5Sespie
438*c87b03e5Sespie	cmp	divisor, #0
439*c87b03e5Sespie	beq	Ldiv0
440*c87b03e5Sespie	mov	curbit, #1
441*c87b03e5Sespie	mov	result, #0
442*c87b03e5Sespie	cmp	dividend, divisor
443*c87b03e5Sespie	blo	Lgot_result
444*c87b03e5Sespie
445*c87b03e5Sespie	ARM_DIV_MOD_BODY 0
446*c87b03e5Sespie
447*c87b03e5Sespie	mov	r0, result
448*c87b03e5Sespie	RET
449*c87b03e5Sespie
450*c87b03e5Sespie#endif /* ARM version */
451*c87b03e5Sespie
452*c87b03e5Sespie	FUNC_END udivsi3
453*c87b03e5Sespie
454*c87b03e5Sespie#endif /* L_udivsi3 */
455*c87b03e5Sespie/* ------------------------------------------------------------------------ */
456*c87b03e5Sespie#ifdef L_umodsi3
457*c87b03e5Sespie
458*c87b03e5Sespie	FUNC_START umodsi3
459*c87b03e5Sespie
460*c87b03e5Sespie#ifdef __thumb__
461*c87b03e5Sespie
462*c87b03e5Sespie	cmp	divisor, #0
463*c87b03e5Sespie	beq	Ldiv0
464*c87b03e5Sespie	mov	curbit, #1
465*c87b03e5Sespie	cmp	dividend, divisor
466*c87b03e5Sespie	bhs	Lover10
467*c87b03e5Sespie	RET
468*c87b03e5Sespie
469*c87b03e5SespieLover10:
470*c87b03e5Sespie	push	{ work }
471*c87b03e5Sespie
472*c87b03e5Sespie	THUMB_DIV_MOD_BODY 1
473*c87b03e5Sespie
474*c87b03e5Sespie	pop	{ work }
475*c87b03e5Sespie	RET
476*c87b03e5Sespie
477*c87b03e5Sespie#else  /* ARM version.  */
478*c87b03e5Sespie
479*c87b03e5Sespie	cmp	divisor, #0
480*c87b03e5Sespie	beq	Ldiv0
481*c87b03e5Sespie	cmp     divisor, #1
482*c87b03e5Sespie	cmpne	dividend, divisor
483*c87b03e5Sespie	moveq   dividend, #0
484*c87b03e5Sespie	RETc(lo)
485*c87b03e5Sespie	mov	curbit, #1
486*c87b03e5Sespie
487*c87b03e5Sespie	ARM_DIV_MOD_BODY 1
488*c87b03e5Sespie
489*c87b03e5Sespie	RET
490*c87b03e5Sespie
491*c87b03e5Sespie#endif /* ARM version.  */
492*c87b03e5Sespie
493*c87b03e5Sespie	FUNC_END umodsi3
494*c87b03e5Sespie
495*c87b03e5Sespie#endif /* L_umodsi3 */
496*c87b03e5Sespie/* ------------------------------------------------------------------------ */
497*c87b03e5Sespie#ifdef L_divsi3
498*c87b03e5Sespie
499*c87b03e5Sespie	FUNC_START divsi3
500*c87b03e5Sespie
501*c87b03e5Sespie#ifdef __thumb__
502*c87b03e5Sespie	cmp	divisor, #0
503*c87b03e5Sespie	beq	Ldiv0
504*c87b03e5Sespie
505*c87b03e5Sespie	push	{ work }
506*c87b03e5Sespie	mov	work, dividend
507*c87b03e5Sespie	eor	work, divisor		@ Save the sign of the result.
508*c87b03e5Sespie	mov	ip, work
509*c87b03e5Sespie	mov	curbit, #1
510*c87b03e5Sespie	mov	result, #0
511*c87b03e5Sespie	cmp	divisor, #0
512*c87b03e5Sespie	bpl	Lover10
513*c87b03e5Sespie	neg	divisor, divisor	@ Loops below use unsigned.
514*c87b03e5SespieLover10:
515*c87b03e5Sespie	cmp	dividend, #0
516*c87b03e5Sespie	bpl	Lover11
517*c87b03e5Sespie	neg	dividend, dividend
518*c87b03e5SespieLover11:
519*c87b03e5Sespie	cmp	dividend, divisor
520*c87b03e5Sespie	blo	Lgot_result
521*c87b03e5Sespie
522*c87b03e5Sespie	THUMB_DIV_MOD_BODY 0
523*c87b03e5Sespie
524*c87b03e5Sespie	mov	r0, result
525*c87b03e5Sespie	mov	work, ip
526*c87b03e5Sespie	cmp	work, #0
527*c87b03e5Sespie	bpl	Lover12
528*c87b03e5Sespie	neg	r0, r0
529*c87b03e5SespieLover12:
530*c87b03e5Sespie	pop	{ work }
531*c87b03e5Sespie	RET
532*c87b03e5Sespie
533*c87b03e5Sespie#else /* ARM version.  */
534*c87b03e5Sespie
535*c87b03e5Sespie	eor	ip, dividend, divisor		@ Save the sign of the result.
536*c87b03e5Sespie	mov	curbit, #1
537*c87b03e5Sespie	mov	result, #0
538*c87b03e5Sespie	cmp	divisor, #0
539*c87b03e5Sespie	rsbmi	divisor, divisor, #0		@ Loops below use unsigned.
540*c87b03e5Sespie	beq	Ldiv0
541*c87b03e5Sespie	cmp	dividend, #0
542*c87b03e5Sespie	rsbmi	dividend, dividend, #0
543*c87b03e5Sespie	cmp	dividend, divisor
544*c87b03e5Sespie	blo	Lgot_result
545*c87b03e5Sespie
546*c87b03e5Sespie	ARM_DIV_MOD_BODY 0
547*c87b03e5Sespie
548*c87b03e5Sespie	mov	r0, result
549*c87b03e5Sespie	cmp	ip, #0
550*c87b03e5Sespie	rsbmi	r0, r0, #0
551*c87b03e5Sespie	RET
552*c87b03e5Sespie
553*c87b03e5Sespie#endif /* ARM version */
554*c87b03e5Sespie
555*c87b03e5Sespie	FUNC_END divsi3
556*c87b03e5Sespie
557*c87b03e5Sespie#endif /* L_divsi3 */
558*c87b03e5Sespie/* ------------------------------------------------------------------------ */
559*c87b03e5Sespie#ifdef L_modsi3
560*c87b03e5Sespie
561*c87b03e5Sespie	FUNC_START modsi3
562*c87b03e5Sespie
563*c87b03e5Sespie#ifdef __thumb__
564*c87b03e5Sespie
565*c87b03e5Sespie	mov	curbit, #1
566*c87b03e5Sespie	cmp	divisor, #0
567*c87b03e5Sespie	beq	Ldiv0
568*c87b03e5Sespie	bpl	Lover10
569*c87b03e5Sespie	neg	divisor, divisor		@ Loops below use unsigned.
570*c87b03e5SespieLover10:
571*c87b03e5Sespie	push	{ work }
572*c87b03e5Sespie	@ Need to save the sign of the dividend, unfortunately, we need
573*c87b03e5Sespie	@ work later on.  Must do this after saving the original value of
574*c87b03e5Sespie	@ the work register, because we will pop this value off first.
575*c87b03e5Sespie	push	{ dividend }
576*c87b03e5Sespie	cmp	dividend, #0
577*c87b03e5Sespie	bpl	Lover11
578*c87b03e5Sespie	neg	dividend, dividend
579*c87b03e5SespieLover11:
580*c87b03e5Sespie	cmp	dividend, divisor
581*c87b03e5Sespie	blo	Lgot_result
582*c87b03e5Sespie
583*c87b03e5Sespie	THUMB_DIV_MOD_BODY 1
584*c87b03e5Sespie
585*c87b03e5Sespie	pop	{ work }
586*c87b03e5Sespie	cmp	work, #0
587*c87b03e5Sespie	bpl	Lover12
588*c87b03e5Sespie	neg	dividend, dividend
589*c87b03e5SespieLover12:
590*c87b03e5Sespie	pop	{ work }
591*c87b03e5Sespie	RET
592*c87b03e5Sespie
593*c87b03e5Sespie#else /* ARM version.  */
594*c87b03e5Sespie
595*c87b03e5Sespie	cmp	divisor, #0
596*c87b03e5Sespie	rsbmi	divisor, divisor, #0		@ Loops below use unsigned.
597*c87b03e5Sespie	beq	Ldiv0
598*c87b03e5Sespie	@ Need to save the sign of the dividend, unfortunately, we need
599*c87b03e5Sespie	@ ip later on; this is faster than pushing lr and using that.
600*c87b03e5Sespie	str	dividend, [sp, #-4]!
601*c87b03e5Sespie	cmp	dividend, #0			@ Test dividend against zero
602*c87b03e5Sespie	rsbmi	dividend, dividend, #0		@ If negative make positive
603*c87b03e5Sespie	cmp	dividend, divisor		@ else if zero return zero
604*c87b03e5Sespie	blo	Lgot_result			@ if smaller return dividend
605*c87b03e5Sespie	mov	curbit, #1
606*c87b03e5Sespie
607*c87b03e5Sespie	ARM_DIV_MOD_BODY 1
608*c87b03e5Sespie
609*c87b03e5Sespie	ldr	ip, [sp], #4
610*c87b03e5Sespie	cmp	ip, #0
611*c87b03e5Sespie	rsbmi	dividend, dividend, #0
612*c87b03e5Sespie	RET
613*c87b03e5Sespie
614*c87b03e5Sespie#endif /* ARM version */
615*c87b03e5Sespie
616*c87b03e5Sespie	FUNC_END modsi3
617*c87b03e5Sespie
618*c87b03e5Sespie#endif /* L_modsi3 */
619*c87b03e5Sespie/* ------------------------------------------------------------------------ */
620*c87b03e5Sespie#ifdef L_dvmd_tls
621*c87b03e5Sespie
622*c87b03e5Sespie	FUNC_START div0
623*c87b03e5Sespie
624*c87b03e5Sespie	RET
625*c87b03e5Sespie
626*c87b03e5Sespie	SIZE	(__div0)
627*c87b03e5Sespie
628*c87b03e5Sespie#endif /* L_divmodsi_tools */
629*c87b03e5Sespie/* ------------------------------------------------------------------------ */
630*c87b03e5Sespie#ifdef L_dvmd_lnx
631*c87b03e5Sespie@ GNU/Linux division-by zero handler.  Used in place of L_dvmd_tls
632*c87b03e5Sespie
633*c87b03e5Sespie/* Constants taken from <asm/unistd.h> and <asm/signal.h> */
634*c87b03e5Sespie#define SIGFPE	8
635*c87b03e5Sespie#define __NR_SYSCALL_BASE	0x900000
636*c87b03e5Sespie#define __NR_getpid			(__NR_SYSCALL_BASE+ 20)
637*c87b03e5Sespie#define __NR_kill			(__NR_SYSCALL_BASE+ 37)
638*c87b03e5Sespie
639*c87b03e5Sespie	FUNC_START div0
640*c87b03e5Sespie
641*c87b03e5Sespie	stmfd	sp!, {r1, lr}
642*c87b03e5Sespie	swi	__NR_getpid
643*c87b03e5Sespie	cmn	r0, #1000
644*c87b03e5Sespie	ldmhsfd	sp!, {r1, pc}RETCOND	@ not much we can do
645*c87b03e5Sespie	mov	r1, #SIGFPE
646*c87b03e5Sespie	swi	__NR_kill
647*c87b03e5Sespie#ifdef __THUMB_INTERWORK__
648*c87b03e5Sespie	ldmfd	sp!, {r1, lr}
649*c87b03e5Sespie	bx	lr
650*c87b03e5Sespie#else
651*c87b03e5Sespie	ldmfd	sp!, {r1, pc}RETCOND
652*c87b03e5Sespie#endif
653*c87b03e5Sespie
654*c87b03e5Sespie	SIZE 	(__div0)
655*c87b03e5Sespie
656*c87b03e5Sespie#endif /* L_dvmd_lnx */
657*c87b03e5Sespie/* ------------------------------------------------------------------------ */
658*c87b03e5Sespie/* These next two sections are here despite the fact that they contain Thumb
659*c87b03e5Sespie   assembler because their presence allows interworked code to be linked even
660*c87b03e5Sespie   when the GCC library is this one.  */
661*c87b03e5Sespie
662*c87b03e5Sespie/* Do not build the interworking functions when the target architecture does
663*c87b03e5Sespie   not support Thumb instructions.  (This can be a multilib option).  */
664*c87b03e5Sespie#if defined L_call_via_rX && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
665*c87b03e5Sespie
666*c87b03e5Sespie/* These labels & instructions are used by the Arm/Thumb interworking code.
667*c87b03e5Sespie   The address of function to be called is loaded into a register and then
668*c87b03e5Sespie   one of these labels is called via a BL instruction.  This puts the
669*c87b03e5Sespie   return address into the link register with the bottom bit set, and the
670*c87b03e5Sespie   code here switches to the correct mode before executing the function.  */
671*c87b03e5Sespie
672*c87b03e5Sespie	.text
673*c87b03e5Sespie	.align 0
674*c87b03e5Sespie        .force_thumb
675*c87b03e5Sespie
676*c87b03e5Sespie.macro call_via register
677*c87b03e5Sespie	THUMB_FUNC_START _call_via_\register
678*c87b03e5Sespie
679*c87b03e5Sespie	bx	\register
680*c87b03e5Sespie	nop
681*c87b03e5Sespie
682*c87b03e5Sespie	SIZE	(_call_via_\register)
683*c87b03e5Sespie.endm
684*c87b03e5Sespie
685*c87b03e5Sespie	call_via r0
686*c87b03e5Sespie	call_via r1
687*c87b03e5Sespie	call_via r2
688*c87b03e5Sespie	call_via r3
689*c87b03e5Sespie	call_via r4
690*c87b03e5Sespie	call_via r5
691*c87b03e5Sespie	call_via r6
692*c87b03e5Sespie	call_via r7
693*c87b03e5Sespie	call_via r8
694*c87b03e5Sespie	call_via r9
695*c87b03e5Sespie	call_via sl
696*c87b03e5Sespie	call_via fp
697*c87b03e5Sespie	call_via ip
698*c87b03e5Sespie	call_via sp
699*c87b03e5Sespie	call_via lr
700*c87b03e5Sespie
701*c87b03e5Sespie#endif /* L_call_via_rX */
702*c87b03e5Sespie/* ------------------------------------------------------------------------ */
703*c87b03e5Sespie/* Do not build the interworking functions when the target architecture does
704*c87b03e5Sespie   not support Thumb instructions.  (This can be a multilib option).  */
705*c87b03e5Sespie#if defined L_interwork_call_via_rX && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
706*c87b03e5Sespie
707*c87b03e5Sespie/* These labels & instructions are used by the Arm/Thumb interworking code,
708*c87b03e5Sespie   when the target address is in an unknown instruction set.  The address
709*c87b03e5Sespie   of function to be called is loaded into a register and then one of these
710*c87b03e5Sespie   labels is called via a BL instruction.  This puts the return address
711*c87b03e5Sespie   into the link register with the bottom bit set, and the code here
712*c87b03e5Sespie   switches to the correct mode before executing the function.  Unfortunately
713*c87b03e5Sespie   the target code cannot be relied upon to return via a BX instruction, so
714*c87b03e5Sespie   instead we have to store the resturn address on the stack and allow the
715*c87b03e5Sespie   called function to return here instead.  Upon return we recover the real
716*c87b03e5Sespie   return address and use a BX to get back to Thumb mode.  */
717*c87b03e5Sespie
718*c87b03e5Sespie	.text
719*c87b03e5Sespie	.align 0
720*c87b03e5Sespie
721*c87b03e5Sespie	.code   32
722*c87b03e5Sespie	.globl _arm_return
723*c87b03e5Sespie_arm_return:
724*c87b03e5Sespie	ldmia 	r13!, {r12}
725*c87b03e5Sespie	bx 	r12
726*c87b03e5Sespie	.code   16
727*c87b03e5Sespie
728*c87b03e5Sespie.macro interwork register
729*c87b03e5Sespie	.code   16
730*c87b03e5Sespie
731*c87b03e5Sespie	THUMB_FUNC_START _interwork_call_via_\register
732*c87b03e5Sespie
733*c87b03e5Sespie	bx 	pc
734*c87b03e5Sespie	nop
735*c87b03e5Sespie
736*c87b03e5Sespie	.code   32
737*c87b03e5Sespie	.globl .Lchange_\register
738*c87b03e5Sespie.Lchange_\register:
739*c87b03e5Sespie	tst	\register, #1
740*c87b03e5Sespie	stmeqdb	r13!, {lr}
741*c87b03e5Sespie	adreq	lr, _arm_return
742*c87b03e5Sespie	bx	\register
743*c87b03e5Sespie
744*c87b03e5Sespie	SIZE	(_interwork_call_via_\register)
745*c87b03e5Sespie.endm
746*c87b03e5Sespie
747*c87b03e5Sespie	interwork r0
748*c87b03e5Sespie	interwork r1
749*c87b03e5Sespie	interwork r2
750*c87b03e5Sespie	interwork r3
751*c87b03e5Sespie	interwork r4
752*c87b03e5Sespie	interwork r5
753*c87b03e5Sespie	interwork r6
754*c87b03e5Sespie	interwork r7
755*c87b03e5Sespie	interwork r8
756*c87b03e5Sespie	interwork r9
757*c87b03e5Sespie	interwork sl
758*c87b03e5Sespie	interwork fp
759*c87b03e5Sespie	interwork ip
760*c87b03e5Sespie	interwork sp
761*c87b03e5Sespie
762*c87b03e5Sespie	/* The LR case has to be handled a little differently...  */
763*c87b03e5Sespie	.code 16
764*c87b03e5Sespie
765*c87b03e5Sespie	THUMB_FUNC_START _interwork_call_via_lr
766*c87b03e5Sespie
767*c87b03e5Sespie	bx 	pc
768*c87b03e5Sespie	nop
769*c87b03e5Sespie
770*c87b03e5Sespie	.code 32
771*c87b03e5Sespie	.globl .Lchange_lr
772*c87b03e5Sespie.Lchange_lr:
773*c87b03e5Sespie	tst	lr, #1
774*c87b03e5Sespie	stmeqdb	r13!, {lr}
775*c87b03e5Sespie	mov	ip, lr
776*c87b03e5Sespie	adreq	lr, _arm_return
777*c87b03e5Sespie	bx	ip
778*c87b03e5Sespie
779*c87b03e5Sespie	SIZE	(_interwork_call_via_lr)
780*c87b03e5Sespie
781*c87b03e5Sespie#endif /* L_interwork_call_via_rX */
782