]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/compiler-rt/lib/builtins/arm/aeabi_cdcmp.S
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / compiler-rt / lib / builtins / arm / aeabi_cdcmp.S
1 //===-- aeabi_cdcmp.S - EABI cdcmp* 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 #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
12 #error big endian support not implemented
13 #endif
14
15 #define APSR_Z (1 << 30)
16 #define APSR_C (1 << 29)
17
18 // void __aeabi_cdcmpeq(double a, double b) {
19 //   if (isnan(a) || isnan(b)) {
20 //     Z = 0; C = 1;
21 //   } else {
22 //     __aeabi_cdcmple(a, b);
23 //   }
24 // }
25
26         .syntax unified
27         .p2align 2
28 DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmpeq)
29         push {r0-r3, lr}
30         bl __aeabi_cdcmpeq_check_nan
31         cmp r0, #1
32 #if defined(USE_THUMB_1)
33         beq 1f
34         // NaN has been ruled out, so __aeabi_cdcmple can't trap
35         mov r0, sp
36         ldm r0, {r0-r3}
37         bl __aeabi_cdcmple
38         pop {r0-r3, pc}
39 1:
40         // Z = 0, C = 1
41         movs r0, #0xF
42         lsls r0, r0, #31
43         pop {r0-r3, pc}
44 #else
45         pop {r0-r3, lr}
46
47         // NaN has been ruled out, so __aeabi_cdcmple can't trap
48         // Use "it ne" + unconditional branch to guarantee a supported relocation if
49         // __aeabi_cdcmple is in a different section for some builds.
50         IT(ne)
51         bne __aeabi_cdcmple
52
53 #if defined(USE_THUMB_2)
54         mov ip, #APSR_C
55         msr APSR_nzcvq, ip
56 #else
57         msr APSR_nzcvq, #APSR_C
58 #endif
59         JMP(lr)
60 #endif
61 END_COMPILERRT_FUNCTION(__aeabi_cdcmpeq)
62
63
64 // void __aeabi_cdcmple(double a, double b) {
65 //   if (__aeabi_dcmplt(a, b)) {
66 //     Z = 0; C = 0;
67 //   } else if (__aeabi_dcmpeq(a, b)) {
68 //     Z = 1; C = 1;
69 //   } else {
70 //     Z = 0; C = 1;
71 //   }
72 // }
73
74         .syntax unified
75         .p2align 2
76 DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmple)
77         // Per the RTABI, this function must preserve r0-r11.
78         // Save lr in the same instruction for compactness
79         push {r0-r3, lr}
80
81         bl __aeabi_dcmplt
82         cmp r0, #1
83 #if defined(USE_THUMB_1)
84         bne 1f
85         // Z = 0, C = 0
86         movs r0, #1
87         lsls r0, r0, #1
88         pop {r0-r3, pc}
89 1:
90         mov r0, sp
91         ldm r0, {r0-r3}
92         bl __aeabi_dcmpeq
93         cmp r0, #1
94         bne 2f
95         // Z = 1, C = 1
96         movs r0, #2
97         lsls r0, r0, #31
98         pop {r0-r3, pc}
99 2:
100         // Z = 0, C = 1
101         movs r0, #0xF
102         lsls r0, r0, #31
103         pop {r0-r3, pc}
104 #else
105         ITT(eq)
106         moveq ip, #0
107         beq 1f
108
109         ldm sp, {r0-r3}
110         bl __aeabi_dcmpeq
111         cmp r0, #1
112         ITE(eq)
113         moveq ip, #(APSR_C | APSR_Z)
114         movne ip, #(APSR_C)
115
116 1:
117         msr APSR_nzcvq, ip
118         pop {r0-r3}
119         POP_PC()
120 #endif
121 END_COMPILERRT_FUNCTION(__aeabi_cdcmple)
122
123 // int __aeabi_cdrcmple(double a, double b) {
124 //   return __aeabi_cdcmple(b, a);
125 // }
126
127         .syntax unified
128         .p2align 2
129 DEFINE_COMPILERRT_FUNCTION(__aeabi_cdrcmple)
130         // Swap r0 and r2
131         mov ip, r0
132         mov r0, r2
133         mov r2, ip
134
135         // Swap r1 and r3
136         mov ip, r1
137         mov r1, r3
138         mov r3, ip
139
140         b __aeabi_cdcmple
141 END_COMPILERRT_FUNCTION(__aeabi_cdrcmple)
142
143 NO_EXEC_STACK_DIRECTIVE
144