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 | #define APSR_Z (1 << 30) |
12 | #define APSR_C (1 << 29) |
13 | |
14 | // void __aeabi_cdcmpeq(double a, double b) { |
15 | // if (isnan(a) || isnan(b)) { |
16 | // Z = 0; C = 1; |
17 | // } else { |
18 | // __aeabi_cdcmple(a, b); |
19 | // } |
20 | // } |
21 | |
22 | .syntax unified |
23 | .p2align 2 |
24 | DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmpeq) |
25 | push {r0-r3, lr} |
26 | bl __aeabi_cdcmpeq_check_nan |
27 | cmp r0, #1 |
28 | #if defined(USE_THUMB_1) |
29 | beq 1f |
30 | // NaN has been ruled out, so __aeabi_cdcmple can't trap |
31 | mov r0, sp |
32 | ldm r0, {r0-r3} |
33 | bl __aeabi_cdcmple |
34 | pop {r0-r3, pc} |
35 | 1: |
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_cdcmple can't trap |
44 | // Use "it ne" + unconditional branch to guarantee a supported relocation if |
45 | // __aeabi_cdcmple is in a different section for some builds. |
46 | IT(ne) |
47 | bne __aeabi_cdcmple |
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 |
57 | END_COMPILERRT_FUNCTION(__aeabi_cdcmpeq) |
58 | |
59 | |
60 | // void __aeabi_cdcmple(double a, double b) { |
61 | // if (__aeabi_dcmplt(a, b)) { |
62 | // Z = 0; C = 0; |
63 | // } else if (__aeabi_dcmpeq(a, b)) { |
64 | // Z = 1; C = 1; |
65 | // } else { |
66 | // Z = 0; C = 1; |
67 | // } |
68 | // } |
69 | |
70 | .syntax unified |
71 | .p2align 2 |
72 | DEFINE_COMPILERRT_FUNCTION(__aeabi_cdcmple) |
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_dcmplt |
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} |
85 | 1: |
86 | mov r0, sp |
87 | ldm r0, {r0-r3} |
88 | bl __aeabi_dcmpeq |
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} |
95 | 2: |
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_dcmpeq |
107 | cmp r0, #1 |
108 | ITE(eq) |
109 | moveq ip, #(APSR_C | APSR_Z) |
110 | movne ip, #(APSR_C) |
111 | |
112 | 1: |
113 | msr APSR_nzcvq, ip |
114 | pop {r0-r3} |
115 | POP_PC() |
116 | #endif |
117 | END_COMPILERRT_FUNCTION(__aeabi_cdcmple) |
118 | |
119 | // int __aeabi_cdrcmple(double a, double b) { |
120 | // return __aeabi_cdcmple(b, a); |
121 | // } |
122 | |
123 | .syntax unified |
124 | .p2align 2 |
125 | DEFINE_COMPILERRT_FUNCTION(__aeabi_cdrcmple) |
126 | // Swap r0 and r2 |
127 | mov ip, r0 |
128 | mov r0, r2 |
129 | mov r2, ip |
130 | |
131 | // Swap r1 and r3 |
132 | mov ip, r1 |
133 | mov r1, r3 |
134 | mov r3, ip |
135 | |
136 | b __aeabi_cdcmple |
137 | END_COMPILERRT_FUNCTION(__aeabi_cdrcmple) |
138 | |
139 | NO_EXEC_STACK_DIRECTIVE |
140 | |
141 | |