xref: /freebsd/contrib/llvm-project/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
1//===-- aeabi_cfcmp.S - EABI cfcmp* implementation ------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "../assembly.h"
10
11#define APSR_Z (1 << 30)
12#define APSR_C (1 << 29)
13
14// void __aeabi_cfcmpeq(float a, float b) {
15//   if (isnan(a) || isnan(b)) {
16//     Z = 0; C = 1;
17//   } else {
18//     __aeabi_cfcmple(a, b);
19//   }
20// }
21
22        .syntax unified
23        .p2align 2
24DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmpeq)
25        push {r0-r3, lr}
26        bl __aeabi_cfcmpeq_check_nan
27        cmp r0, #1
28#if defined(USE_THUMB_1)
29        beq 1f
30        // NaN has been ruled out, so __aeabi_cfcmple can't trap
31        mov r0, sp
32        ldm r0, {r0-r3}
33        bl __aeabi_cfcmple
34        pop {r0-r3, pc}
351:
36        // Z = 0, C = 1
37        movs r0, #0xF
38        lsls r0, r0, #31
39        pop {r0-r3, pc}
40#else
41        pop {r0-r3, lr}
42
43        // NaN has been ruled out, so __aeabi_cfcmple can't trap
44        // Use "it ne" + unconditional branch to guarantee a supported relocation if
45        // __aeabi_cfcmple is in a different section for some builds.
46        IT(ne)
47        bne __aeabi_cfcmple
48
49#if defined(USE_THUMB_2)
50        mov ip, #APSR_C
51        msr APSR_nzcvq, ip
52#else
53        msr APSR_nzcvq, #APSR_C
54#endif
55        JMP(lr)
56#endif
57END_COMPILERRT_FUNCTION(__aeabi_cfcmpeq)
58
59
60// void __aeabi_cfcmple(float a, float b) {
61//   if (__aeabi_fcmplt(a, b)) {
62//     Z = 0; C = 0;
63//   } else if (__aeabi_fcmpeq(a, b)) {
64//     Z = 1; C = 1;
65//   } else {
66//     Z = 0; C = 1;
67//   }
68// }
69
70        .syntax unified
71        .p2align 2
72DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmple)
73        // Per the RTABI, this function must preserve r0-r11.
74        // Save lr in the same instruction for compactness
75        push {r0-r3, lr}
76
77        bl __aeabi_fcmplt
78        cmp r0, #1
79#if defined(USE_THUMB_1)
80        bne 1f
81        // Z = 0, C = 0
82        movs r0, #1
83        lsls r0, r0, #1
84        pop {r0-r3, pc}
851:
86        mov r0, sp
87        ldm r0, {r0-r3}
88        bl __aeabi_fcmpeq
89        cmp r0, #1
90        bne 2f
91        // Z = 1, C = 1
92        movs r0, #2
93        lsls r0, r0, #31
94        pop {r0-r3, pc}
952:
96        // Z = 0, C = 1
97        movs r0, #0xF
98        lsls r0, r0, #31
99        pop {r0-r3, pc}
100#else
101        ITT(eq)
102        moveq ip, #0
103        beq 1f
104
105        ldm sp, {r0-r3}
106        bl __aeabi_fcmpeq
107        cmp r0, #1
108        ITE(eq)
109        moveq ip, #(APSR_C | APSR_Z)
110        movne ip, #(APSR_C)
111
1121:
113        msr APSR_nzcvq, ip
114        pop {r0-r3}
115        POP_PC()
116#endif
117END_COMPILERRT_FUNCTION(__aeabi_cfcmple)
118
119// int __aeabi_cfrcmple(float a, float b) {
120//   return __aeabi_cfcmple(b, a);
121// }
122
123        .syntax unified
124        .p2align 2
125DEFINE_COMPILERRT_FUNCTION(__aeabi_cfrcmple)
126        // Swap r0 and r1
127        mov ip, r0
128        mov r0, r1
129        mov r1, ip
130
131        b __aeabi_cfcmple
132END_COMPILERRT_FUNCTION(__aeabi_cfrcmple)
133
134NO_EXEC_STACK_DIRECTIVE
135
136