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