1/* Miscellaneous BPABI functions.  Thumb-1 implementation, suitable for ARMv4T,
2   ARMv6-M and ARMv8-M Baseline like ISA variants.
3
4   Copyright (C) 2006-2018 Free Software Foundation, Inc.
5   Contributed by CodeSourcery.
6
7   This file is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 3, or (at your option) any
10   later version.
11
12   This file is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   General Public License for more details.
16
17   Under Section 7 of GPL version 3, you are granted additional
18   permissions described in the GCC Runtime Library Exception, version
19   3.1, as published by the Free Software Foundation.
20
21   You should have received a copy of the GNU General Public License and
22   a copy of the GCC Runtime Library Exception along with this program;
23   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24   <http://www.gnu.org/licenses/>.  */
25
26#ifdef __ARM_EABI__
27/* Some attributes that are common to all routines in this file.  */
28	/* Tag_ABI_align_needed: This code does not require 8-byte
29	   alignment from the caller.  */
30	/* .eabi_attribute 24, 0  -- default setting.  */
31	/* Tag_ABI_align_preserved: This code preserves 8-byte
32	   alignment in any callee.  */
33	.eabi_attribute 25, 1
34#endif /* __ARM_EABI__ */
35
36#ifdef L_aeabi_lcmp
37
38FUNC_START aeabi_lcmp
39	cmp	xxh, yyh
40	beq	1f
41	bgt	2f
42	mov	r0, #1
43	neg	r0, r0
44	RET
452:
46	mov	r0, #1
47	RET
481:
49	sub	r0, xxl, yyl
50	beq	1f
51	bhi	2f
52	mov	r0, #1
53	neg	r0, r0
54	RET
552:
56	mov	r0, #1
571:
58	RET
59	FUNC_END aeabi_lcmp
60
61#endif /* L_aeabi_lcmp */
62
63#ifdef L_aeabi_ulcmp
64
65FUNC_START aeabi_ulcmp
66	cmp	xxh, yyh
67	bne	1f
68	sub	r0, xxl, yyl
69	beq	2f
701:
71	bcs	1f
72	mov	r0, #1
73	neg	r0, r0
74	RET
751:
76	mov	r0, #1
772:
78	RET
79	FUNC_END aeabi_ulcmp
80
81#endif /* L_aeabi_ulcmp */
82
83.macro test_div_by_zero signed
84	cmp	yyh, #0
85	bne	7f
86	cmp	yyl, #0
87	bne	7f
88	cmp	xxh, #0
89	.ifc	\signed, unsigned
90	bne	2f
91	cmp	xxl, #0
922:
93	beq	3f
94	mov	xxh, #0
95	mvn	xxh, xxh		@ 0xffffffff
96	mov	xxl, xxh
973:
98	.else
99	blt	6f
100	bgt	4f
101	cmp	xxl, #0
102	beq	5f
1034:	mov	xxl, #0
104	mvn	xxl, xxl		@ 0xffffffff
105	lsr	xxh, xxl, #1		@ 0x7fffffff
106	b	5f
1076:	mov	xxh, #0x80
108	lsl	xxh, xxh, #24		@ 0x80000000
109	mov	xxl, #0
1105:
111	.endif
112	@ tailcalls are tricky on v6-m.
113	push	{r0, r1, r2}
114	ldr	r0, 1f
115	adr	r1, 1f
116	add	r0, r1
117	str	r0, [sp, #8]
118	@ We know we are not on armv4t, so pop pc is safe.
119	pop	{r0, r1, pc}
120	.align	2
1211:
122	.word	__aeabi_ldiv0 - 1b
1237:
124.endm
125
126#ifdef L_aeabi_ldivmod
127
128FUNC_START aeabi_ldivmod
129	test_div_by_zero signed
130
131	push {r0, r1}
132	mov r0, sp
133	push {r0, lr}
134	ldr r0, [sp, #8]
135	bl SYM(__gnu_ldivmod_helper)
136	ldr r3, [sp, #4]
137	mov lr, r3
138	add sp, sp, #8
139	pop {r2, r3}
140	RET
141	FUNC_END aeabi_ldivmod
142
143#endif /* L_aeabi_ldivmod */
144
145#ifdef L_aeabi_uldivmod
146
147FUNC_START aeabi_uldivmod
148	test_div_by_zero unsigned
149
150	push {r0, r1}
151	mov r0, sp
152	push {r0, lr}
153	ldr r0, [sp, #8]
154	bl SYM(__udivmoddi4)
155	ldr r3, [sp, #4]
156	mov lr, r3
157	add sp, sp, #8
158	pop {r2, r3}
159	RET
160	FUNC_END aeabi_uldivmod
161
162#endif /* L_aeabi_uldivmod */
163
164#ifdef L_arm_addsubsf3
165
166FUNC_START aeabi_frsub
167
168      push	{r4, lr}
169      mov	r4, #1
170      lsl	r4, #31
171      eor	r0, r0, r4
172      bl	__aeabi_fadd
173      pop	{r4, pc}
174
175      FUNC_END aeabi_frsub
176
177#endif /* L_arm_addsubsf3 */
178
179#ifdef L_arm_cmpsf2
180
181FUNC_START aeabi_cfrcmple
182
183	mov	ip, r0
184	mov	r0, r1
185	mov	r1, ip
186	b	6f
187
188FUNC_START aeabi_cfcmpeq
189FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
190
191	@ The status-returning routines are required to preserve all
192	@ registers except ip, lr, and cpsr.
1936:	push	{r0, r1, r2, r3, r4, lr}
194	bl	__lesf2
195	@ Set the Z flag correctly, and the C flag unconditionally.
196	cmp	r0, #0
197	@ Clear the C flag if the return value was -1, indicating
198	@ that the first operand was smaller than the second.
199	bmi 1f
200	mov	r1, #0
201	cmn	r0, r1
2021:
203	pop	{r0, r1, r2, r3, r4, pc}
204
205	FUNC_END aeabi_cfcmple
206	FUNC_END aeabi_cfcmpeq
207	FUNC_END aeabi_cfrcmple
208
209FUNC_START	aeabi_fcmpeq
210
211	push	{r4, lr}
212	bl	__eqsf2
213	neg	r0, r0
214	add	r0, r0, #1
215	pop	{r4, pc}
216
217	FUNC_END aeabi_fcmpeq
218
219.macro COMPARISON cond, helper, mode=sf2
220FUNC_START	aeabi_fcmp\cond
221
222	push	{r4, lr}
223	bl	__\helper\mode
224	cmp	r0, #0
225	b\cond	1f
226	mov	r0, #0
227	pop	{r4, pc}
2281:
229	mov	r0, #1
230	pop	{r4, pc}
231
232	FUNC_END aeabi_fcmp\cond
233.endm
234
235COMPARISON lt, le
236COMPARISON le, le
237COMPARISON gt, ge
238COMPARISON ge, ge
239
240#endif /* L_arm_cmpsf2 */
241
242#ifdef L_arm_addsubdf3
243
244FUNC_START aeabi_drsub
245
246      push	{r4, lr}
247      mov	r4, #1
248      lsl	r4, #31
249      eor	xxh, xxh, r4
250      bl	__aeabi_dadd
251      pop	{r4, pc}
252
253      FUNC_END aeabi_drsub
254
255#endif /* L_arm_addsubdf3 */
256
257#ifdef L_arm_cmpdf2
258
259FUNC_START aeabi_cdrcmple
260
261	mov	ip, r0
262	mov	r0, r2
263	mov	r2, ip
264	mov	ip, r1
265	mov	r1, r3
266	mov	r3, ip
267	b	6f
268
269FUNC_START aeabi_cdcmpeq
270FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
271
272	@ The status-returning routines are required to preserve all
273	@ registers except ip, lr, and cpsr.
2746:	push	{r0, r1, r2, r3, r4, lr}
275	bl	__ledf2
276	@ Set the Z flag correctly, and the C flag unconditionally.
277	cmp	r0, #0
278	@ Clear the C flag if the return value was -1, indicating
279	@ that the first operand was smaller than the second.
280	bmi 1f
281	mov	r1, #0
282	cmn	r0, r1
2831:
284	pop	{r0, r1, r2, r3, r4, pc}
285
286	FUNC_END aeabi_cdcmple
287	FUNC_END aeabi_cdcmpeq
288	FUNC_END aeabi_cdrcmple
289
290FUNC_START	aeabi_dcmpeq
291
292	push	{r4, lr}
293	bl	__eqdf2
294	neg	r0, r0
295	add	r0, r0, #1
296	pop	{r4, pc}
297
298	FUNC_END aeabi_dcmpeq
299
300.macro COMPARISON cond, helper, mode=df2
301FUNC_START	aeabi_dcmp\cond
302
303	push	{r4, lr}
304	bl	__\helper\mode
305	cmp	r0, #0
306	b\cond	1f
307	mov	r0, #0
308	pop	{r4, pc}
3091:
310	mov	r0, #1
311	pop	{r4, pc}
312
313	FUNC_END aeabi_dcmp\cond
314.endm
315
316COMPARISON lt, le
317COMPARISON le, le
318COMPARISON gt, ge
319COMPARISON ge, ge
320
321#endif /* L_arm_cmpdf2 */
322