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
24DEFINE_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}
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_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
57END_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
72DEFINE_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}
851:
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}
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_dcmpeq
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_cdcmple)
118
119// int __aeabi_cdrcmple(double a, double b) {
120//   return __aeabi_cdcmple(b, a);
121// }
122
123        .syntax unified
124        .p2align 2
125DEFINE_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
137END_COMPILERRT_FUNCTION(__aeabi_cdrcmple)
138
139NO_EXEC_STACK_DIRECTIVE
140
141