Home | History | Annotate | Line # | Download | only in arm
      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-2024 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 
     38 FUNC_START aeabi_lcmp
     39 	cmp	xxh, yyh
     40 	beq	1f
     41 	bgt	2f
     42 	movs	r0, #1
     43 	negs	r0, r0
     44 	RET
     45 2:
     46 	movs	r0, #1
     47 	RET
     48 1:
     49 	subs	r0, xxl, yyl
     50 	beq	1f
     51 	bhi	2f
     52 	movs	r0, #1
     53 	negs	r0, r0
     54 	RET
     55 2:
     56 	movs	r0, #1
     57 1:
     58 	RET
     59 	FUNC_END aeabi_lcmp
     60 
     61 #endif /* L_aeabi_lcmp */
     62 
     63 #ifdef L_aeabi_ulcmp
     64 
     65 FUNC_START aeabi_ulcmp
     66 	cmp	xxh, yyh
     67 	bne	1f
     68 	subs	r0, xxl, yyl
     69 	beq	2f
     70 1:
     71 	bcs	1f
     72 	movs	r0, #1
     73 	negs	r0, r0
     74 	RET
     75 1:
     76 	movs	r0, #1
     77 2:
     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
     92 2:
     93 	beq	3f
     94 	movs	xxh, #0
     95 	mvns	xxh, xxh		@ 0xffffffff
     96 	movs	xxl, xxh
     97 3:
     98 	.else
     99 	blt	6f
    100 	bgt	4f
    101 	cmp	xxl, #0
    102 	beq	5f
    103 4:	movs	xxl, #0
    104 	mvns	xxl, xxl		@ 0xffffffff
    105 	lsrs	xxh, xxl, #1		@ 0x7fffffff
    106 	b	5f
    107 6:	movs	xxh, #0x80
    108 	lsls	xxh, xxh, #24		@ 0x80000000
    109 	movs	xxl, #0
    110 5:
    111 	.endif
    112 	@ tailcalls are tricky on v6-m.
    113 	push	{r0, r1, r2}
    114 	ldr	r0, 1f
    115 	adr	r1, 1f
    116 	adds	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
    121 1:
    122 	.word	__aeabi_ldiv0 - 1b
    123 7:
    124 .endm
    125 
    126 #ifdef L_aeabi_ldivmod
    127 
    128 FUNC_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 
    147 FUNC_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 
    166 FUNC_START aeabi_frsub
    167 
    168       push	{r4, lr}
    169       movs	r4, #1
    170       lsls	r4, #31
    171       eors	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 
    181 FUNC_START aeabi_cfrcmple
    182 
    183 	mov	ip, r0
    184 	movs	r0, r1
    185 	mov	r1, ip
    186 	b	6f
    187 
    188 FUNC_START aeabi_cfcmpeq
    189 FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
    190 
    191 	@ The status-returning routines are required to preserve all
    192 	@ registers except ip, lr, and cpsr.
    193 6:	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 	movs	r1, #0
    201 	cmn	r0, r1
    202 1:
    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 
    209 FUNC_START	aeabi_fcmpeq
    210 
    211 	push	{r4, lr}
    212 	bl	__eqsf2
    213 	negs	r0, r0
    214 	adds	r0, r0, #1
    215 	pop	{r4, pc}
    216 
    217 	FUNC_END aeabi_fcmpeq
    218 
    219 .macro COMPARISON cond, helper, mode=sf2
    220 FUNC_START	aeabi_fcmp\cond
    221 
    222 	push	{r4, lr}
    223 	bl	__\helper\mode
    224 	cmp	r0, #0
    225 	b\cond	1f
    226 	movs	r0, #0
    227 	pop	{r4, pc}
    228 1:
    229 	movs	r0, #1
    230 	pop	{r4, pc}
    231 
    232 	FUNC_END aeabi_fcmp\cond
    233 .endm
    234 
    235 COMPARISON lt, le
    236 COMPARISON le, le
    237 COMPARISON gt, ge
    238 COMPARISON ge, ge
    239 
    240 #endif /* L_arm_cmpsf2 */
    241 
    242 #ifdef L_arm_addsubdf3
    243 
    244 FUNC_START aeabi_drsub
    245 
    246       push	{r4, lr}
    247       movs	r4, #1
    248       lsls	r4, #31
    249       eors	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 
    259 FUNC_START aeabi_cdrcmple
    260 
    261 	mov	ip, r0
    262 	movs	r0, r2
    263 	mov	r2, ip
    264 	mov	ip, r1
    265 	movs	r1, r3
    266 	mov	r3, ip
    267 	b	6f
    268 
    269 FUNC_START aeabi_cdcmpeq
    270 FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
    271 
    272 	@ The status-returning routines are required to preserve all
    273 	@ registers except ip, lr, and cpsr.
    274 6:	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 	movs	r1, #0
    282 	cmn	r0, r1
    283 1:
    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 
    290 FUNC_START	aeabi_dcmpeq
    291 
    292 	push	{r4, lr}
    293 	bl	__eqdf2
    294 	negs	r0, r0
    295 	adds	r0, r0, #1
    296 	pop	{r4, pc}
    297 
    298 	FUNC_END aeabi_dcmpeq
    299 
    300 .macro COMPARISON cond, helper, mode=df2
    301 FUNC_START	aeabi_dcmp\cond
    302 
    303 	push	{r4, lr}
    304 	bl	__\helper\mode
    305 	cmp	r0, #0
    306 	b\cond	1f
    307 	movs	r0, #0
    308 	pop	{r4, pc}
    309 1:
    310 	movs	r0, #1
    311 	pop	{r4, pc}
    312 
    313 	FUNC_END aeabi_dcmp\cond
    314 .endm
    315 
    316 COMPARISON lt, le
    317 COMPARISON le, le
    318 COMPARISON gt, ge
    319 COMPARISON ge, ge
    320 
    321 #endif /* L_arm_cmpdf2 */
    322