aboutsummaryrefslogtreecommitdiff
path: root/compiler-rt/lib/builtins/arm/aeabi_cfcmp.S
blob: 5cb7d16042f429d3a5355908766e4d6460ca1f46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//===-- aeabi_cfcmp.S - EABI cfcmp* 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_cfcmpeq(float a, float b) {
//   if (isnan(a) || isnan(b)) {
//     Z = 0; C = 1;
//   } else {
//     __aeabi_cfcmple(a, b);
//   }
// }

        .syntax unified
        .p2align 2
DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmpeq)
        PACBTI_LANDING
#if defined(__ARM_FEATURE_PAC_DEFAULT)
        push {r0-r3, r12, lr}
#else
        push {r0-r3, lr}
#endif
        bl __aeabi_cfcmpeq_check_nan
        cmp r0, #1
#if defined(USE_THUMB_1)
        beq 1f
        // NaN has been ruled out, so __aeabi_cfcmple can't trap
        mov r0, sp
        ldm r0, {r0-r3}
        bl __aeabi_cfcmple
        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_cfcmple can't trap
        // Use "it ne" + unconditional branch to guarantee a supported relocation if
        // __aeabi_cfcmple is in a different section for some builds.
        IT(ne)
        bne __aeabi_cfcmple

#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_cfcmpeq)


// void __aeabi_cfcmple(float a, float b) {
//   if (__aeabi_fcmplt(a, b)) {
//     Z = 0; C = 0;
//   } else if (__aeabi_fcmpeq(a, b)) {
//     Z = 1; C = 1;
//   } else {
//     Z = 0; C = 1;
//   }
// }

        .syntax unified
        .p2align 2
DEFINE_COMPILERRT_FUNCTION(__aeabi_cfcmple)
        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_fcmplt
        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_fcmpeq
        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_fcmpeq
        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_cfcmple)

// int __aeabi_cfrcmple(float a, float b) {
//   return __aeabi_cfcmple(b, a);
// }

        .syntax unified
        .p2align 2
DEFINE_COMPILERRT_FUNCTION(__aeabi_cfrcmple)
#if defined(__ARM_FEATURE_BTI_DEFAULT)
        bti
#endif
        // Swap r0 and r1
        mov ip, r0
        mov r0, r1
        mov r1, ip

        b __aeabi_cfcmple
END_COMPILERRT_FUNCTION(__aeabi_cfrcmple)

NO_EXEC_STACK_DIRECTIVE