1/* Miscellaneous BPABI functions.
2
3   Copyright (C) 2003-2015 Free Software Foundation, Inc.
4   Contributed by CodeSourcery, LLC.
5
6   This file is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published by the
8   Free Software Foundation; either version 3, or (at your option) any
9   later version.
10
11   This file is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   General Public License for more details.
15
16   Under Section 7 of GPL version 3, you are granted additional
17   permissions described in the GCC Runtime Library Exception, version
18   3.1, as published by the Free Software Foundation.
19
20   You should have received a copy of the GNU General Public License and
21   a copy of the GCC Runtime Library Exception along with this program;
22   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23   <http://www.gnu.org/licenses/>.  */
24
25	.cfi_sections .debug_frame
26
27#ifdef __ARM_EABI__
28/* Some attributes that are common to all routines in this file.  */
29	/* Tag_ABI_align_needed: This code does not require 8-byte
30	   alignment from the caller.  */
31	/* .eabi_attribute 24, 0  -- default setting.  */
32	/* Tag_ABI_align_preserved: This code preserves 8-byte
33	   alignment in any callee.  */
34	.eabi_attribute 25, 1
35#endif /* __ARM_EABI__ */
36
37#ifdef L_aeabi_lcmp
38
39ARM_FUNC_START aeabi_lcmp
40	cmp	xxh, yyh
41	do_it	lt
42	movlt	r0, #-1
43	do_it	gt
44	movgt	r0, #1
45	do_it	ne
46	RETc(ne)
47	subs	r0, xxl, yyl
48	do_it	lo
49	movlo	r0, #-1
50	do_it	hi
51	movhi	r0, #1
52	RET
53	FUNC_END aeabi_lcmp
54
55#endif /* L_aeabi_lcmp */
56
57#ifdef L_aeabi_ulcmp
58
59ARM_FUNC_START aeabi_ulcmp
60	cmp	xxh, yyh
61	do_it	lo
62	movlo	r0, #-1
63	do_it	hi
64	movhi	r0, #1
65	do_it	ne
66	RETc(ne)
67	cmp	xxl, yyl
68	do_it	lo
69	movlo	r0, #-1
70	do_it	hi
71	movhi	r0, #1
72	do_it	eq
73	moveq	r0, #0
74	RET
75	FUNC_END aeabi_ulcmp
76
77#endif /* L_aeabi_ulcmp */
78
79.macro test_div_by_zero signed
80/* Tail-call to divide-by-zero handlers which may be overridden by the user,
81   so unwinding works properly.  */
82#if defined(__thumb2__)
83	cbnz	yyh, 2f
84	cbnz	yyl, 2f
85	cmp	xxh, #0
86	.ifc \signed, unsigned
87	do_it	eq
88	cmpeq	xxl, #0
89	do_it	ne, t
90	movne	xxh, #0xffffffff
91	movne	xxl, #0xffffffff
92	.else
93	do_it	lt, tt
94	movlt	xxl, #0
95	movlt	xxh, #0x80000000
96	blt	1f
97	do_it	eq
98	cmpeq	xxl, #0
99	do_it	ne, t
100	movne	xxh, #0x7fffffff
101	movne	xxl, #0xffffffff
102	.endif
1031:
104	b	SYM (__aeabi_ldiv0) __PLT__
1052:
106#else
107	/* Note: Thumb-1 code calls via an ARM shim on processors which
108	   support ARM mode.  */
109	cmp	yyh, #0
110	cmpeq	yyl, #0
111	bne	2f
112	cmp	xxh, #0
113	.ifc \signed, unsigned
114	cmpeq	xxl, #0
115	movne	xxh, #0xffffffff
116	movne	xxl, #0xffffffff
117	.else
118	movlt	xxh, #0x80000000
119	movlt	xxl, #0
120	blt	1f
121	cmpeq	xxl, #0
122	movne	xxh, #0x7fffffff
123	movne	xxl, #0xffffffff
124	.endif
1251:
126	b	SYM (__aeabi_ldiv0) __PLT__
1272:
128#endif
129.endm
130
131/* we can use STRD/LDRD on v5TE and later, and any Thumb-2 architecture. */
132#if (defined(__ARM_EABI__)                                            \
133     && (defined(__thumb2__)                                          \
134         || (__ARM_ARCH >= 5 && defined(__TARGET_FEATURE_DSP))))
135#define CAN_USE_LDRD 1
136#else
137#define CAN_USE_LDRD 0
138#endif
139
140/* set up stack from for call to __udivmoddi4. At the end of the macro the
141   stack is arranged as follows:
142		sp+12	/ space for remainder
143		sp+8	\ (written by __udivmoddi4)
144		sp+4	lr
145		sp+0	sp+8 [rp (remainder pointer) argument for __udivmoddi4]
146
147 */
148.macro push_for_divide fname
149#if defined(__thumb2__) && CAN_USE_LDRD
150	sub	ip, sp, #8
151	strd	ip, lr, [sp, #-16]!
152#else
153	sub	sp, sp, #8
154	do_push	{sp, lr}
155#endif
156	.cfi_adjust_cfa_offset 16
157	.cfi_offset 14, -12
158.endm
159
160/* restore stack */
161.macro pop_for_divide
162	ldr	lr, [sp, #4]
163#if CAN_USE_LDRD
164	ldrd	r2, r3, [sp, #8]
165	add	sp, sp, #16
166#else
167	add	sp, sp, #8
168	do_pop	{r2, r3}
169#endif
170	.cfi_restore 14
171	.cfi_adjust_cfa_offset 0
172.endm
173
174#ifdef L_aeabi_ldivmod
175
176/* Perform 64 bit signed division.
177   Inputs:
178	r0:r1	numerator
179	r2:r3	denominator
180   Outputs:
181	r0:r1	quotient
182	r2:r3	remainder
183 */
184ARM_FUNC_START aeabi_ldivmod
185	.cfi_startproc
186	test_div_by_zero	signed
187
188	push_for_divide	__aeabi_ldivmod
189	cmp	xxh, #0
190	blt	1f
191	cmp	yyh, #0
192	blt	2f
193	/* arguments in (r0:r1), (r2:r3) and *sp */
194	bl	SYM(__udivmoddi4) __PLT__
195	.cfi_remember_state
196	pop_for_divide
197	RET
198
1991: /* xxh:xxl is negative */
200	.cfi_restore_state
201	negs	xxl, xxl
202	sbc	xxh, xxh, xxh, lsl #1	/* Thumb-2 has no RSC, so use X - 2X */
203	cmp	yyh, #0
204	blt	3f
205	/* arguments in (r0:r1), (r2:r3) and *sp */
206	bl	SYM(__udivmoddi4) __PLT__
207	.cfi_remember_state
208	pop_for_divide
209	negs	xxl, xxl
210	sbc	xxh, xxh, xxh, lsl #1	/* Thumb-2 has no RSC, so use X - 2X */
211	negs	yyl, yyl
212	sbc	yyh, yyh, yyh, lsl #1	/* Thumb-2 has no RSC, so use X - 2X */
213	RET
214
2152: /* only yyh:yyl is negative */
216	.cfi_restore_state
217	negs	yyl, yyl
218	sbc	yyh, yyh, yyh, lsl #1	/* Thumb-2 has no RSC, so use X - 2X */
219	/* arguments in (r0:r1), (r2:r3) and *sp */
220	bl	SYM(__udivmoddi4) __PLT__
221	.cfi_remember_state
222	pop_for_divide
223	negs	xxl, xxl
224	sbc	xxh, xxh, xxh, lsl #1	/* Thumb-2 has no RSC, so use X - 2X */
225	RET
226
2273: /* both xxh:xxl and yyh:yyl are negative */
228	.cfi_restore_state
229	negs	yyl, yyl
230	sbc	yyh, yyh, yyh, lsl #1	/* Thumb-2 has no RSC, so use X - 2X */
231	/* arguments in (r0:r1), (r2:r3) and *sp */
232	bl	SYM(__udivmoddi4) __PLT__
233	pop_for_divide
234	negs	yyl, yyl
235	sbc	yyh, yyh, yyh, lsl #1	/* Thumb-2 has no RSC, so use X - 2X */
236	RET
237
238	.cfi_endproc
239
240#endif /* L_aeabi_ldivmod */
241
242#ifdef L_aeabi_uldivmod
243
244/* Perform 64 bit signed division.
245   Inputs:
246	r0:r1	numerator
247	r2:r3	denominator
248   Outputs:
249	r0:r1	quotient
250	r2:r3	remainder
251 */
252ARM_FUNC_START aeabi_uldivmod
253	.cfi_startproc
254	test_div_by_zero	unsigned
255
256	push_for_divide	__aeabi_uldivmod
257	/* arguments in (r0:r1), (r2:r3) and *sp */
258	bl	SYM(__udivmoddi4) __PLT__
259	pop_for_divide
260	RET
261	.cfi_endproc
262
263#endif /* L_aeabi_divmod */
264
265