1/* Miscellaneous BPABI functions.  ARMv6M implementation
2
3   Copyright (C) 2006-2015 Free Software Foundation, Inc.
4   Contributed by CodeSourcery.
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#ifdef __ARM_EABI__
26/* Some attributes that are common to all routines in this file.  */
27	/* Tag_ABI_align_needed: This code does not require 8-byte
28	   alignment from the caller.  */
29	/* .eabi_attribute 24, 0  -- default setting.  */
30	/* Tag_ABI_align_preserved: This code preserves 8-byte
31	   alignment in any callee.  */
32	.eabi_attribute 25, 1
33#endif /* __ARM_EABI__ */
34
35#ifdef L_aeabi_lcmp
36
37FUNC_START aeabi_lcmp
38	cmp	xxh, yyh
39	beq	1f
40	bgt	2f
41	mov	r0, #1
42	neg	r0, r0
43	RET
442:
45	mov	r0, #1
46	RET
471:
48	sub	r0, xxl, yyl
49	beq	1f
50	bhi	2f
51	mov	r0, #1
52	neg	r0, r0
53	RET
542:
55	mov	r0, #1
561:
57	RET
58	FUNC_END aeabi_lcmp
59
60#endif /* L_aeabi_lcmp */
61
62#ifdef L_aeabi_ulcmp
63
64FUNC_START aeabi_ulcmp
65	cmp	xxh, yyh
66	bne	1f
67	sub	r0, xxl, yyl
68	beq	2f
691:
70	bcs	1f
71	mov	r0, #1
72	neg	r0, r0
73	RET
741:
75	mov	r0, #1
762:
77	RET
78	FUNC_END aeabi_ulcmp
79
80#endif /* L_aeabi_ulcmp */
81
82.macro test_div_by_zero signed
83	cmp	yyh, #0
84	bne	7f
85	cmp	yyl, #0
86	bne	7f
87	cmp	xxh, #0
88	.ifc	\signed, unsigned
89	bne	2f
90	cmp	xxl, #0
912:
92	beq	3f
93	mov	xxh, #0
94	mvn	xxh, xxh		@ 0xffffffff
95	mov	xxl, xxh
963:
97	.else
98	blt	6f
99	bgt	4f
100	cmp	xxl, #0
101	beq	5f
1024:	mov	xxl, #0
103	mvn	xxl, xxl		@ 0xffffffff
104	lsr	xxh, xxl, #1		@ 0x7fffffff
105	b	5f
1066:	mov	xxh, #0x80
107	lsl	xxh, xxh, #24		@ 0x80000000
108	mov	xxl, #0
1095:
110	.endif
111	@ tailcalls are tricky on v6-m.
112	push	{r0, r1, r2}
113	ldr	r0, 1f
114	adr	r1, 1f
115	add	r0, r1
116	str	r0, [sp, #8]
117	@ We know we are not on armv4t, so pop pc is safe.
118	pop	{r0, r1, pc}
119	.align	2
1201:
121	.word	__aeabi_ldiv0 - 1b
1227:
123.endm
124
125#ifdef L_aeabi_ldivmod
126
127FUNC_START aeabi_ldivmod
128	test_div_by_zero signed
129
130	push {r0, r1}
131	mov r0, sp
132	push {r0, lr}
133	ldr r0, [sp, #8]
134	bl SYM(__gnu_ldivmod_helper)
135	ldr r3, [sp, #4]
136	mov lr, r3
137	add sp, sp, #8
138	pop {r2, r3}
139	RET
140	FUNC_END aeabi_ldivmod
141
142#endif /* L_aeabi_ldivmod */
143
144#ifdef L_aeabi_uldivmod
145
146FUNC_START aeabi_uldivmod
147	test_div_by_zero unsigned
148
149	push {r0, r1}
150	mov r0, sp
151	push {r0, lr}
152	ldr r0, [sp, #8]
153	bl SYM(__udivmoddi4)
154	ldr r3, [sp, #4]
155	mov lr, r3
156	add sp, sp, #8
157	pop {r2, r3}
158	RET
159	FUNC_END aeabi_uldivmod
160
161#endif /* L_aeabi_uldivmod */
162
163#ifdef L_arm_addsubsf3
164
165FUNC_START aeabi_frsub
166
167      push	{r4, lr}
168      mov	r4, #1
169      lsl	r4, #31
170      eor	r0, r0, r4
171      bl	__aeabi_fadd
172      pop	{r4, pc}
173
174      FUNC_END aeabi_frsub
175
176#endif /* L_arm_addsubsf3 */
177
178#ifdef L_arm_cmpsf2
179
180FUNC_START aeabi_cfrcmple
181
182	mov	ip, r0
183	mov	r0, r1
184	mov	r1, ip
185	b	6f
186
187FUNC_START aeabi_cfcmpeq
188FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
189
190	@ The status-returning routines are required to preserve all
191	@ registers except ip, lr, and cpsr.
1926:	push	{r0, r1, r2, r3, r4, lr}
193	bl	__lesf2
194	@ Set the Z flag correctly, and the C flag unconditionally.
195	cmp	r0, #0
196	@ Clear the C flag if the return value was -1, indicating
197	@ that the first operand was smaller than the second.
198	bmi 1f
199	mov	r1, #0
200	cmn	r0, r1
2011:
202	pop	{r0, r1, r2, r3, r4, pc}
203
204	FUNC_END aeabi_cfcmple
205	FUNC_END aeabi_cfcmpeq
206	FUNC_END aeabi_cfrcmple
207
208FUNC_START	aeabi_fcmpeq
209
210	push	{r4, lr}
211	bl	__eqsf2
212	neg	r0, r0
213	add	r0, r0, #1
214	pop	{r4, pc}
215
216	FUNC_END aeabi_fcmpeq
217
218.macro COMPARISON cond, helper, mode=sf2
219FUNC_START	aeabi_fcmp\cond
220
221	push	{r4, lr}
222	bl	__\helper\mode
223	cmp	r0, #0
224	b\cond	1f
225	mov	r0, #0
226	pop	{r4, pc}
2271:
228	mov	r0, #1
229	pop	{r4, pc}
230
231	FUNC_END aeabi_fcmp\cond
232.endm
233
234COMPARISON lt, le
235COMPARISON le, le
236COMPARISON gt, ge
237COMPARISON ge, ge
238
239#endif /* L_arm_cmpsf2 */
240
241#ifdef L_arm_addsubdf3
242
243FUNC_START aeabi_drsub
244
245      push	{r4, lr}
246      mov	r4, #1
247      lsl	r4, #31
248      eor	xxh, xxh, r4
249      bl	__aeabi_dadd
250      pop	{r4, pc}
251
252      FUNC_END aeabi_drsub
253
254#endif /* L_arm_addsubdf3 */
255
256#ifdef L_arm_cmpdf2
257
258FUNC_START aeabi_cdrcmple
259
260	mov	ip, r0
261	mov	r0, r2
262	mov	r2, ip
263	mov	ip, r1
264	mov	r1, r3
265	mov	r3, ip
266	b	6f
267
268FUNC_START aeabi_cdcmpeq
269FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
270
271	@ The status-returning routines are required to preserve all
272	@ registers except ip, lr, and cpsr.
2736:	push	{r0, r1, r2, r3, r4, lr}
274	bl	__ledf2
275	@ Set the Z flag correctly, and the C flag unconditionally.
276	cmp	r0, #0
277	@ Clear the C flag if the return value was -1, indicating
278	@ that the first operand was smaller than the second.
279	bmi 1f
280	mov	r1, #0
281	cmn	r0, r1
2821:
283	pop	{r0, r1, r2, r3, r4, pc}
284
285	FUNC_END aeabi_cdcmple
286	FUNC_END aeabi_cdcmpeq
287	FUNC_END aeabi_cdrcmple
288
289FUNC_START	aeabi_dcmpeq
290
291	push	{r4, lr}
292	bl	__eqdf2
293	neg	r0, r0
294	add	r0, r0, #1
295	pop	{r4, pc}
296
297	FUNC_END aeabi_dcmpeq
298
299.macro COMPARISON cond, helper, mode=df2
300FUNC_START	aeabi_dcmp\cond
301
302	push	{r4, lr}
303	bl	__\helper\mode
304	cmp	r0, #0
305	b\cond	1f
306	mov	r0, #0
307	pop	{r4, pc}
3081:
309	mov	r0, #1
310	pop	{r4, pc}
311
312	FUNC_END aeabi_dcmp\cond
313.endm
314
315COMPARISON lt, le
316COMPARISON le, le
317COMPARISON gt, ge
318COMPARISON ge, ge
319
320#endif /* L_arm_cmpdf2 */
321