//===-- aeabi_cdcmp.S - EABI cdcmp* implementation ------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "../assembly.h" #define APSR_Z (1 << 30) #define APSR_C (1 << 29) // void __aeabi_cdcmpeq(double a, double b) { // if (isnan(a) || isnan(b)) { // Z = 0; C = 1; // } else { // __aeabi_cdcmple(a, b); // } // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmpeq) PACBTI_LANDING #if defined(__ARM_FEATURE_PAC_DEFAULT) push {r0-r3, r12, lr} #else push {r0-r3, lr} #endif bl __aeabi_cdcmpeq_check_nan cmp r0, #1 #if defined(USE_THUMB_1) beq 1f // NaN has been ruled out, so __aeabi_cdcmple can't trap mov r0, sp ldm r0, {r0-r3} bl __aeabi_cdcmple pop {r0-r3, pc} 1: // Z = 0, C = 1 movs r0, #0xF lsls r0, r0, #31 pop {r0-r3, pc} #else #if defined(__ARM_FEATURE_PAC_DEFAULT) pop {r0-r3, r12, lr} aut r12, lr, sp #else pop {r0-r3, lr} #endif // NaN has been ruled out, so __aeabi_cdcmple can't trap // Use "it ne" + unconditional branch to guarantee a supported relocation if // __aeabi_cdcmple is in a different section for some builds. IT(ne) bne __aeabi_cdcmple #if defined(USE_THUMB_2) mov r12, #APSR_C msr APSR_nzcvq, r12 #else msr APSR_nzcvq, #APSR_C #endif JMP(lr) #endif END_COMPILERRT_FUNCTION(__aeabi_cdcmpeq) // void __aeabi_cdcmple(double a, double b) { // if (__aeabi_dcmplt(a, b)) { // Z = 0; C = 0; // } else if (__aeabi_dcmpeq(a, b)) { // Z = 1; C = 1; // } else { // Z = 0; C = 1; // } // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmple) PACBTI_LANDING // Per the RTABI, this function must preserve r0-r11. // Save lr in the same instruction for compactness #if defined(__ARM_FEATURE_PAC_DEFAULT) push {r0-r3, r12, lr} #else push {r0-r3, lr} #endif bl __aeabi_dcmplt cmp r0, #1 #if defined(USE_THUMB_1) bne 1f // Z = 0, C = 0 movs r0, #1 lsls r0, r0, #1 pop {r0-r3, pc} 1: mov r0, sp ldm r0, {r0-r3} bl __aeabi_dcmpeq cmp r0, #1 bne 2f // Z = 1, C = 1 movs r0, #2 lsls r0, r0, #31 pop {r0-r3, pc} 2: // Z = 0, C = 1 movs r0, #0xF lsls r0, r0, #31 pop {r0-r3, pc} #else ITT(eq) moveq ip, #0 beq 1f ldm sp, {r0-r3} bl __aeabi_dcmpeq cmp r0, #1 ITE(eq) moveq ip, #(APSR_C | APSR_Z) movne ip, #(APSR_C) 1: msr APSR_nzcvq, ip #if defined(__ARM_FEATURE_PAC_DEFAULT) pop {r0-r3, r12, lr} PAC_RETURN #else pop {r0-r3} POP_PC() #endif #endif END_COMPILERRT_FUNCTION(__aeabi_cdcmple) // int __aeabi_cdrcmple(double a, double b) { // return __aeabi_cdcmple(b, a); // } .syntax unified .p2align 2 DEFINE_COMPILERRT_FUNCTION(__aeabi_cdrcmple) #if defined(__ARM_FEATURE_BTI_DEFAULT) bti #endif // Swap r0 and r2 mov ip, r0 mov r0, r2 mov r2, ip // Swap r1 and r3 mov ip, r1 mov r1, r3 mov r3, ip #if defined(USE_THUMB_1) push {r0, lr} bl __aeabi_cdcmple pop {r0, pc} #else b __aeabi_cdcmple #endif END_COMPILERRT_FUNCTION(__aeabi_cdrcmple) NO_EXEC_STACK_DIRECTIVE