summaryrefslogtreecommitdiff
path: root/lib/builtins/arm/aeabi_cfcmp.S
blob: 4b1de997687f0a6dc1c18c635a9a604000c7273c (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
//===-- aeabi_cfcmp.S - EABI cfcmp* implementation ------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "../assembly.h"

#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
#error big endian support not implemented
#endif

#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)
        push {r0-r3, lr}
        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
        pop {r0-r3, lr}

        // 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 ip, #APSR_C
        msr APSR_nzcvq, ip
#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)
        // Per the RTABI, this function must preserve r0-r11.
        // Save lr in the same instruction for compactness
        push {r0-r3, lr}

        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
        pop {r0-r3}
        POP_PC()
#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)
        // 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